const { useState, useEffect, useRef, useMemo } = React;

// ----- Theme hook -----
function useTheme() {
  const [theme, setTheme] = useState(() => document.documentElement.getAttribute('data-theme') || 'light');
  useEffect(() => {
    document.documentElement.setAttribute('data-theme', theme);
    try { localStorage.setItem('lk-theme', theme); } catch(e) {}
  }, [theme]);
  return [theme, () => setTheme(t => t === 'light' ? 'dark' : 'light')];
}

// ----- Scroll reveal -----
function useReveal() {
  useEffect(() => {
    const els = document.querySelectorAll('[data-reveal]');
    // Immediately mark any element already in the viewport so nothing gets stuck invisible.
    const markIfVisible = (el) => {
      const r = el.getBoundingClientRect();
      if (r.top < window.innerHeight && r.bottom > 0) el.classList.add('is-in');
    };
    els.forEach(markIfVisible);
    const io = new IntersectionObserver((entries) => {
      entries.forEach(e => {
        if (e.isIntersecting) {
          e.target.classList.add('is-in');
          io.unobserve(e.target);
        }
      });
    }, { threshold: 0, rootMargin: '0px 0px 200px 0px' });
    els.forEach(el => { if (!el.classList.contains('is-in')) io.observe(el); });
    // Safety: anything still hidden after a couple seconds gets revealed.
    const safety = setTimeout(() => {
      document.querySelectorAll('[data-reveal]:not(.is-in)').forEach(el => {
        const r = el.getBoundingClientRect();
        if (r.top < window.innerHeight * 1.5) el.classList.add('is-in');
      });
    }, 1200);
    return () => { io.disconnect(); clearTimeout(safety); };
  }, []);
}

// ----- Data -----
const EXPERIENCE = [
  {
    range: '2026 · Present',
    company: 'AMD',
    role: 'Senior Full-Stack Engineer',
    location: 'Austin, TX',
    featured: true,
    color: 'amd',
    summary: 'Building a full-stack platform to manage and track CPU and GPU manufacturing requests.',
    bullets: [
      'Design and develop a full-stack application using Python, FastAPI, and Svelte to manage and track CPU and GPU manufacturing requests.',
      'Maintain and provide ongoing support for two legacy PHP applications, including an internal budget management tool.',
    ],
    stack: ['Python', 'FastAPI', 'Svelte', 'PHP'],
  },
  {
    range: '2023 · 2025',
    company: 'Apple',
    role: 'Software Development Engineer, Full-Stack',
    location: 'Austin, TX',
    featured: true,
    color: 'apple',
    summary: 'Shipped internal tooling, observability, and AI-assisted workflows across multiple Apple teams.',
    bullets: [
      'Built a React + TypeScript frontend for a test-case orchestration app, which cut average deployment time by 30%.',
      'Maintained and extended a Ruby on Rails application used to schedule music events.',
      'Integrated with backends via Apollo GraphQL and Hasura.',
      'Improved product observability and support to reduce time-to-diagnosis during outages.',
      'Led training sessions on Prometheus, OpenLens, Grafana, Datadog, Kubernetes and Helm.',
      'Used Claude and Copilot to streamline dev processes and increase productivity.',
      'Built a VS Code extension that publishes automated code reviews via OpenAI.',
      'Built a TypeScript + React chatbot for end-user support, powered by Gemini.',
      'Used Java + Spring Boot to build a backend for an internal song-tagging tool that improved Apple Music UX.',
    ],
    stack: ['React', 'TypeScript', 'Ruby on Rails', 'GraphQL', 'Java', 'Spring Boot', 'Kubernetes'],
  },
  {
    range: '2020 · 2023',
    company: 'Amazon',
    role: 'Software Development Engineer II',
    location: 'Austin, TX',
    featured: true,
    color: 'amazon',
    summary: 'Scaled Amazon Payments infrastructure and helped launch Amazon in two new countries.',
    bullets: [
      'Automated dashboards to monitor key Amazon services.',
      'Mentored two interns in React UI development best practices.',
      'Built event-driven applications using Kafka and AWS SNS.',
      'Helped launch Amazon in Sweden and Poland.',
      'Moved key Amazon payment services to native AWS, which brought overall IMR down by 40%.',
      'Implemented Redis caching to improve application load time.',
    ],
    stack: ['React', 'AWS', 'Kafka', 'SNS', 'Redis'],
  },
  {
    range: '2017 · 2020',
    company: 'Amazon',
    role: 'Software Development Engineer II',
    location: 'Seattle, WA',
    color: 'amazon',
    summary: 'Broke Amazon Payments’ dependency on Oracle by migrating to DynamoDB.',
    bullets: [
      'Migrated key software systems from Oracle to DynamoDB, finally breaking Amazon Payments’ long-running Oracle dependency and cutting costs.',
      'Refactored key systems to be more extensible and testable.',
      'Used DevOps and build tools such as Ant for CI/CD.',
      'Designed reliable, resilient systems on AWS.',
    ],
    stack: ['Java', 'AWS', 'DynamoDB', 'Ant'],
  },
  {
    range: '2016 · 2017',
    company: 'Texas Biomedical Research Institute',
    role: 'Java Programmer',
    location: 'San Antonio, TX',
    color: 'neutral',
    summary: 'Modeled research business processes and built BI tooling for a biomedical lab.',
    bullets: [
      'Coded business processes for animal demographics, care, and fee schedules in Java.',
      'Customized LabKey with additional views and input screens via JSP and ExtJS.',
      'Developed XML schemas to model business entities.',
      'Built BI dashboards with Metabase.',
      'Designed Jenkins pipelines to automate testing and deployment to Docker.',
    ],
    stack: ['Java', 'JSP', 'ExtJS', 'Jenkins', 'Docker'],
  },
  {
    range: '2015 · 2016',
    company: 'PIC Business Systems',
    role: 'PHP & Web Developer',
    location: 'San Antonio, TX',
    color: 'neutral',
    summary: 'Built REST APIs, EDI integrations, and web front-ends for B2B retail partners.',
    bullets: [
      'Designed and developed REST APIs with RAML and CodeIgniter.',
      'Developed a PHP EDI library to improve business processes with retailers such as Home Depot.',
      'Built APIs to consume SOAP services.',
      'Developed front-ends using HTML5 APIs, JavaScript and jQuery.',
      'Developed MapQuest integration modules.',
    ],
    stack: ['PHP', 'CodeIgniter', 'jQuery', 'SOAP'],
  },
];

const SkillIcon = ({ kind }) => {
  const p = { width: 22, height: 22, viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', strokeWidth: 1.6, strokeLinecap: 'round', strokeLinejoin: 'round' };
  const m = {
    lang: <svg {...p}><path d="M8 6l-6 6 6 6M16 6l6 6-6 6M14 4l-4 16"/></svg>,
    front: <svg {...p}><rect x="3" y="4" width="18" height="14" rx="2"/><path d="M8 20h8M12 18v2"/></svg>,
    back: <svg {...p}><rect x="3" y="4" width="18" height="5" rx="1"/><rect x="3" y="12" width="18" height="5" rx="1"/><circle cx="7" cy="6.5" r="0.8" fill="currentColor"/><circle cx="7" cy="14.5" r="0.8" fill="currentColor"/></svg>,
    data: <svg {...p}><ellipse cx="12" cy="5" rx="8" ry="2.5"/><path d="M4 5v6c0 1.4 3.6 2.5 8 2.5s8-1.1 8-2.5V5M4 11v6c0 1.4 3.6 2.5 8 2.5s8-1.1 8-2.5v-6"/></svg>,
    cloud: <svg {...p}><path d="M7 18a4 4 0 0 1-1-7.9A6 6 0 0 1 17.8 10 4.5 4.5 0 0 1 17 19H7z"/></svg>,
    obs: <svg {...p}><path d="M3 12h4l2-6 4 12 2-6h6"/></svg>,
    ai: <svg {...p}><path d="M12 3v2M12 19v2M4.2 6.2l1.4 1.4M18.4 16.4l1.4 1.4M3 12h2M19 12h2M4.2 17.8l1.4-1.4M18.4 7.6l1.4-1.4"/><circle cx="12" cy="12" r="4"/><path d="M10.5 12h3M12 10.5v3"/></svg>,
  };
  return m[kind] || null;
};

const SKILLS = [
  { group: 'Languages', icon: 'lang', items: ['Python', 'Java', 'PHP', 'TypeScript', 'JavaScript', 'Ruby', 'VBA', 'SQL'] },
  { group: 'Frontend', icon: 'front', items: ['React', 'Svelte', 'TypeScript', 'HTML5', 'CSS'] },
  { group: 'Backend', icon: 'back', items: ['FastAPI', 'Spring Boot', 'Rails', 'CodeIgniter', 'GraphQL', 'REST'] },
  { group: 'Data', icon: 'data', items: ['PostgreSQL', 'DynamoDB', 'Redis', 'Hasura', 'Oracle'] },
  { group: 'AI / ML', icon: 'ai', items: ['OpenAI API', 'Anthropic Claude', 'LangChain', 'RAG pipelines', 'Vector DBs', 'Prompt engineering', 'LLM evals', 'Embeddings'] },
  { group: 'Cloud & DevOps', icon: 'cloud', items: ['AWS', 'Kubernetes', 'Helm', 'Docker', 'Jenkins', 'Kafka', 'SNS'] },
  { group: 'Observability', icon: 'obs', items: ['Prometheus', 'Grafana', 'Datadog', 'OpenLens'] },
];

const WorkIcon = ({ kind }) => {
  const p = { width: 44, height: 44, viewBox: '0 0 48 48', fill: 'none', stroke: 'currentColor', strokeWidth: 1.3, strokeLinecap: 'round', strokeLinejoin: 'round' };
  if (kind === 'book') return <svg {...p}><path d="M10 8h20a4 4 0 0 1 4 4v28H14a4 4 0 0 1-4-4V8z"/><path d="M10 34h24M16 14h12M16 20h10"/></svg>;
  if (kind === 'shield') return <svg {...p}><path d="M24 6l14 4v12c0 10-7 16-14 20-7-4-14-10-14-20V10l14-4z"/><path d="M17 24l5 5 9-10"/></svg>;
  if (kind === 'house') return <svg {...p}><path d="M8 22L24 8l16 14v18a2 2 0 0 1-2 2H10a2 2 0 0 1-2-2V22z"/><path d="M19 42V28h10v14"/></svg>;
  if (kind === 'chart') return <svg {...p}><path d="M8 40V8M8 40h32"/><path d="M14 32l6-8 6 5 10-14"/><circle cx="14" cy="32" r="1.5" fill="currentColor"/><circle cx="20" cy="24" r="1.5" fill="currentColor"/><circle cx="26" cy="29" r="1.5" fill="currentColor"/><circle cx="36" cy="15" r="1.5" fill="currentColor"/></svg>;
  if (kind === 'mic') return <svg {...p}><rect x="19" y="6" width="10" height="22" rx="5"/><path d="M12 22a12 12 0 0 0 24 0M24 34v8M18 42h12"/></svg>;
  if (kind === 'doc') return <svg {...p}><path d="M12 6h16l8 8v28a2 2 0 0 1-2 2H12a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2z"/><path d="M28 6v8h8M16 22h16M16 28h16M16 34h10"/></svg>;
  if (kind === 'eye') return <svg {...p}><path d="M4 24s7-12 20-12 20 12 20 12-7 12-20 12S4 24 4 24z"/><circle cx="24" cy="24" r="5"/></svg>;
  if (kind === 'chip') return <svg {...p}><rect x="12" y="12" width="24" height="24" rx="2"/><rect x="18" y="18" width="12" height="12" rx="1"/><path d="M16 8v4M24 8v4M32 8v4M16 36v4M24 36v4M32 36v4M8 16h4M8 24h4M8 32h4M36 16h4M36 24h4M36 32h4"/></svg>;
  if (kind === 'flask') return <svg {...p}><path d="M18 8h12M20 8v12l-8 16a3 3 0 0 0 3 4h18a3 3 0 0 0 3-4l-8-16V8"/><path d="M15 28h18"/></svg>;
  if (kind === 'ai') return <svg {...p}><rect x="10" y="14" width="28" height="20" rx="3"/><circle cx="18" cy="24" r="2" fill="currentColor"/><circle cx="30" cy="24" r="2" fill="currentColor"/></svg>;
  if (kind === 'db') return <svg {...p}><ellipse cx="24" cy="12" rx="12" ry="4"/><path d="M12 12v10c0 2.2 5.4 4 12 4s12-1.8 12-4V12M12 22v10c0 2.2 5.4 4 12 4s12-1.8 12-4V22"/></svg>;
  return null;
};

const SELECTED_WORK = [
  {
    tag: 'AI Agents · 2025',
    title: 'AgentLoop',
    body: 'A platform for teams who ship real AI agents to production. I built the agent orchestration layer, the eval tooling, and the developer dashboard that ties it all together.',
    metric: 'agentloopio.com',
    url: 'https://agentloopio.com/',
    icon: 'ai',
    shot: 'assets/proj-agentloop.jpg',
    stack: ['LangGraph', 'LangChain', 'OpenAI', 'Claude', 'Next.js', 'Python'],
  },
  {
    tag: 'Voice AI · 2025',
    title: 'Voitech',
    body: 'Voice AI that actually sounds like a human on the phone. I worked on the real time speech pipeline, the conversational flows, and the dashboard teams use to tune agent behavior.',
    metric: 'voitech.ai',
    url: 'https://www.voitech.ai/',
    icon: 'mic',
    shot: 'assets/proj-voitech.jpg',
    stack: ['OpenAI Realtime', 'Deepgram', 'ElevenLabs', 'LiveKit', 'WebRTC', 'Node.js'],
  },
  {
    tag: 'RegTech · Life Sciences',
    title: 'Ritivel',
    body: 'Regulatory drafting for pharma and biotech teams. The product turns weeks of FDA submission work into minutes, with word level traceability so reviewers always know where a claim came from. Backed by Y Combinator.',
    metric: 'ritivel.com',
    url: 'https://www.ritivel.com/',
    icon: 'doc',
    shot: 'assets/proj-ritivel.jpg',
    stack: ['RAG', 'Vector DB', 'Next.js', 'FastAPI', 'PostgreSQL', 'Local LLM'],
  },
  {
    tag: 'Industrial AI · Vision',
    title: 'Zetamotion',
    body: 'A quality control platform for factory lines. Real time defect detection running on the edge, with a synthetic data pipeline so teams can train new models even when real defects are rare. Deployed across aerospace and automotive customers.',
    metric: 'zetamotion.com',
    url: 'https://zetamotion.com/',
    icon: 'eye',
    shot: 'assets/proj-zetamotion.jpg',
    stack: ['PyTorch', 'CUDA', 'Computer Vision', 'Synthetic Data', 'MQTT', 'Edge ML'],
  },
  {
    tag: 'Fiction · Publishing',
    title: 'Author Amy Harmon',
    body: 'The marketing and book catalog site for a New York Times bestselling author. I built the whole front end, from her catalog of novels to the tour dates and press page.',
    metric: 'authoramyharmon.com',
    url: 'http://authoramyharmon.com/',
    icon: 'book',
    shot: 'assets/proj-amy.jpg',
    stack: ['WordPress', 'PHP', 'SCSS', 'Responsive'],
  },
  {
    tag: 'Insurance · France',
    title: 'Assurances Expatrié',
    body: 'An insurance quote platform for French expats living abroad. A multi step questionnaire on the front, partner APIs and lead routing on the back.',
    metric: 'assurances-expatrie.com',
    url: 'http://assurances-expatrie.com/',
    icon: 'shield',
    shot: 'assets/proj-assurances.jpg',
    stack: ['PHP', 'MySQL', 'jQuery', 'REST APIs'],
  },
  {
    tag: 'Fintech · France',
    title: 'Crédit Expatrié',
    body: 'A credit and mortgage brokerage site for French citizens buying property abroad. Simulation calculators up front, document intake and CRM integration running the pipeline behind the scenes.',
    metric: 'credit-expatrie.com',
    url: 'http://www.credit-expatrie.com/',
    icon: 'chart',
    shot: 'assets/proj-credit.jpg',
    stack: ['PHP', 'MySQL', 'JavaScript', 'CRM integration'],
  },
];

// ----- Components -----
function ThemeToggle({ theme, onToggle }) {
  return (
    <button className="theme-toggle" onClick={onToggle} aria-label="Toggle theme" title={theme === 'dark' ? 'Switch to light' : 'Switch to dark'}>
      <span className="tt-track">
        <span className="tt-thumb" data-on={theme === 'dark'}>
          {theme === 'dark' ? (
            <svg width="14" height="14" viewBox="0 0 24 24" fill="none"><path d="M21 12.8A9 9 0 1 1 11.2 3a7 7 0 0 0 9.8 9.8z" fill="currentColor"/></svg>
          ) : (
            <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round"><circle cx="12" cy="12" r="4" fill="currentColor"/><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>
          )}
        </span>
      </span>
    </button>
  );
}

function Nav({ theme, toggleTheme }) {
  const [scrolled, setScrolled] = useState(false);
  useEffect(() => {
    const on = () => setScrolled(window.scrollY > 20);
    on();
    window.addEventListener('scroll', on, { passive: true });
    return () => window.removeEventListener('scroll', on);
  }, []);
  return (
    <nav className={`nav ${scrolled ? 'scrolled' : ''}`}>
      <a href="#top" className="nav-brand">
        <span className="brand-mark"><span>LK</span></span>
        <span className="brand-name">Lamine Kacimi</span>
      </a>
      <div className="nav-links">
        <a href="#work">Work</a>
        <a href="#experience">Experience</a>
        <a href="#skills">Skills</a>
        <a href="#testimonials">Praise</a>
        <a href="#contact">Contact</a>
      </div>
      <div className="nav-right">
        <ThemeToggle theme={theme} onToggle={toggleTheme} />
      </div>
    </nav>
  );
}

function Hero() {
  const blobRef = useRef(null);
  useEffect(() => {
    let raf = 0;
    let mx = 0, my = 0, cx = 0, cy = 0;
    const onMove = (e) => {
      mx = (e.clientX / window.innerWidth - 0.5) * 40;
      my = (e.clientY / window.innerHeight - 0.5) * 40;
    };
    const tick = () => {
      cx += (mx - cx) * 0.06;
      cy += (my - cy) * 0.06;
      if (blobRef.current) blobRef.current.style.transform = `translate(${cx}px, ${cy}px)`;
      raf = requestAnimationFrame(tick);
    };
    window.addEventListener('mousemove', onMove);
    raf = requestAnimationFrame(tick);
    return () => { window.removeEventListener('mousemove', onMove); cancelAnimationFrame(raf); };
  }, []);

  return (
    <section className="hero" id="top">
      <div className="hero-blob" ref={blobRef} aria-hidden="true" />
      <div className="hero-grid" aria-hidden="true" />

      <div className="hero-layout">
        <div className="hero-left">
          <div className="hero-meta">
            <span className="dot" /> Available · Georgetown, TX
          </div>

          <h1 className="hero-title">
            <span className="line">I design &amp; build</span>
            <span className="line"><span className="serif italic">resilient</span> full-stack</span>
            <span className="line">software, <span className="serif italic">at scale</span>.</span>
          </h1>

          <div className="hero-foot">
            <p className="hero-lede">
              Senior full-stack engineer with <strong>15+ years</strong> designing,
              building and shipping systems for <em>AMD, Apple, Amazon</em> and more.
              Python, TypeScript, Java, and the clouds they run on.
            </p>
            <div className="hero-actions">
              <a href="#work" className="btn btn-primary">Selected work <Arrow /></a>
              <a href="#contact" className="btn btn-ghost">Get in touch</a>
            </div>
          </div>
        </div>

        <div className="hero-right">
          <div className="portrait-wrap">
            <div className="portrait-frame">
              <img src="assets/lamine-portrait.jpg" alt="Lamine Kacimi" className="portrait-img" />
              <div className="portrait-badge mono">
                <span className="dot" /> LK · EST. 2010
              </div>
            </div>
            <div className="portrait-caption">
              <span className="serif italic">“Ship the boring parts first. The rest is easy.”</span>
              <span className="pc-sig mono">Lamine Kacimi</span>
            </div>
            <div className="portrait-ticker mono">
              <div className="ticker-track">
                <div className="ticker-group">
                  <span>AMD</span><span className="tdot">●</span>
                  <span>APPLE</span><span className="tdot">●</span>
                  <span>AMAZON</span><span className="tdot">●</span>
                  <span>15 YRS</span><span className="tdot">●</span>
                  <span>FULL-STACK</span><span className="tdot">●</span>
                  <span>PYTHON</span><span className="tdot">●</span>
                  <span>REACT</span><span className="tdot">●</span>
                  <span>AWS</span><span className="tdot">●</span>
                </div>
                <div className="ticker-group" aria-hidden="true">
                  <span>AMD</span><span className="tdot">●</span>
                  <span>APPLE</span><span className="tdot">●</span>
                  <span>AMAZON</span><span className="tdot">●</span>
                  <span>15 YRS</span><span className="tdot">●</span>
                  <span>FULL-STACK</span><span className="tdot">●</span>
                  <span>PYTHON</span><span className="tdot">●</span>
                  <span>REACT</span><span className="tdot">●</span>
                  <span>AWS</span><span className="tdot">●</span>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>

      <div className="hero-stats">
        <Stat n="15+" l="Years shipping" />
        <Stat n="6" l="Companies" />
        <Stat n="2" l="New Amazon launches" />
        <Stat n="40%" l="IMR reduction" />
      </div>

      <div className="scroll-hint"><span>scroll</span><span className="scroll-line" /></div>
    </section>
  );
}

function Stat({ n, l }) {
  return (
    <div className="stat">
      <div className="stat-n serif">{n}</div>
      <div className="stat-l">{l}</div>
    </div>
  );
}

function Arrow() {
  return <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M5 12h14M13 6l6 6-6 6"/></svg>;
}

function About() {
  return (
    <section className="about" id="about" data-reveal>
      <div className="section-head">
        <span className="eyebrow"><span className="eb-num">01</span> About</span>
      </div>
      <div className="about-grid">
        <div className="about-copy">
          <p className="lead serif">
            I'm a full-stack engineer who likes the whole stack. Schemas and <em>Svelte</em>,
            Helm charts and hover states. I've spent the last decade and a half
            turning messy problems into systems that don't wake anyone at 3am.
          </p>
          <p>
            I cut my teeth writing PHP and Java for retailers, then spent nearly six
            years at <strong>Amazon</strong> hardening the payments stack. That meant
            migrating services off Oracle, moving workloads to native AWS, and
            helping launch Amazon in Sweden and Poland. At <strong>Apple</strong> I focused on internal
            developer tooling, observability, and weaving AI into the day-to-day:
            a VS Code extension that drafts code reviews, a Gemini-backed support
            chatbot, dashboards in Grafana and Datadog. Now at <strong>AMD</strong> I'm
            building new platform tooling with Python, FastAPI and Svelte.
          </p>
          <p>
            I hold a CS degree from the National Institute of Technology in Algiers
            and distributed-systems coursework from UIUC. I care about small teams,
            tight feedback loops, and code that reads like prose.
          </p>
        </div>
        <aside className="about-card">
          <div className="ac-row"><span className="ac-k">Based in</span><span className="ac-v">Georgetown, TX</span></div>
          <div className="ac-row"><span className="ac-k">Focus</span><span className="ac-v">Full-stack · Platform</span></div>
          <div className="ac-row"><span className="ac-k">Languages</span><span className="ac-v">English, French, Arabic</span></div>
          <div className="ac-row"><span className="ac-k">Education</span><span className="ac-v">NIT Algiers · UIUC</span></div>
          <div className="ac-row"><span className="ac-k">Status</span><span className="ac-v"><span className="dot" /> Open to collaborations</span></div>
        </aside>
      </div>
    </section>
  );
}

function SelectedWork() {
  return (
    <section className="work" id="work">
      <div className="ambient-orb a" aria-hidden="true" />
      <div className="ambient-orb b" aria-hidden="true" />
      <div className="section-head" data-reveal>
        <span className="eyebrow"><span className="eb-num">02</span> Selected work</span>
        <h2 className="section-title serif">
          Things I've shipped that <span className="italic">moved numbers</span>.
        </h2>
      </div>
      <div className="work-list">
        {SELECTED_WORK.map((w, i) => (
          <a href={w.url} target="_blank" rel="noreferrer" className={`work-row ${i % 2 ? 'flip' : ''}`} key={i} data-reveal>
            <div className="wr-media">
              <div className="wr-frame">
                <div className="wr-browser">
                  <span /><span /><span />
                  <div className="wr-url mono">{w.metric}</div>
                </div>
                {w.shot && <img src={w.shot} alt={w.title} loading="lazy" />}
              </div>
              <div className="wr-index mono">{String(i + 1).padStart(2, '0')}</div>
            </div>
            <div className="wr-content">
              <div className="wr-head">
                <span className="wr-tag mono">{w.tag}</span>
                <span className="wr-icon"><WorkIcon kind={w.icon} /></span>
              </div>
              <h3 className="wr-title serif">{w.title}</h3>
              <p className="wr-body">{w.body}</p>
              {w.stack && (
                <ul className="wr-stack mono">
                  {w.stack.map((s, j) => <li key={j}>{s}</li>)}
                </ul>
              )}
              <div className="wr-foot">
                <span className="wr-link mono">Visit {w.metric}</span>
                <span className="wr-arrow"><Arrow /></span>
              </div>
            </div>
          </a>
        ))}
      </div>
    </section>
  );
}

function LogoMark({ color }) {
  // Simple abstract marks, original and not branded
  const common = { width: 28, height: 28, viewBox: '0 0 32 32' };
  if (color === 'amd') return <svg {...common}><rect x="4" y="4" width="24" height="24" rx="4" fill="none" stroke="currentColor" strokeWidth="1.5"/><rect x="10" y="10" width="12" height="12" rx="2" fill="currentColor"/></svg>;
  if (color === 'apple') return <svg {...common}><circle cx="16" cy="16" r="10" fill="none" stroke="currentColor" strokeWidth="1.5"/><circle cx="16" cy="16" r="4" fill="currentColor"/></svg>;
  if (color === 'amazon') return <svg {...common}><path d="M6 20 L16 8 L26 20" stroke="currentColor" strokeWidth="1.5" fill="none"/><circle cx="16" cy="22" r="2" fill="currentColor"/></svg>;
  return <svg {...common}><rect x="6" y="6" width="20" height="20" rx="2" stroke="currentColor" strokeWidth="1.5" fill="none"/><line x1="6" y1="16" x2="26" y2="16" stroke="currentColor" strokeWidth="1.5"/></svg>;
}

function ExperienceRow({ job, isOpen, onToggle, index }) {
  const innerRef = useRef(null);
  const bodyRef = useRef(null);

  useEffect(() => {
    const inner = innerRef.current;
    const body = bodyRef.current;
    if (!inner || !body) return;
    if (isOpen) {
      // Set to measured height, then after transition end, release to auto so nested resizes work
      const h = inner.offsetHeight;
      body.style.maxHeight = h + 'px';
      const onEnd = (e) => {
        if (e.propertyName !== 'max-height') return;
        if (bodyRef.current) bodyRef.current.style.maxHeight = 'none';
        body.removeEventListener('transitionend', onEnd);
      };
      body.addEventListener('transitionend', onEnd);
      return () => body.removeEventListener('transitionend', onEnd);
    } else {
      // From auto, re-clamp to current height, force reflow, then to 0
      const h = inner.offsetHeight;
      body.style.maxHeight = h + 'px';
      // force reflow
      void body.offsetHeight;
      requestAnimationFrame(() => {
        if (bodyRef.current) bodyRef.current.style.maxHeight = '0px';
      });
    }
  }, [isOpen]);

  return (
    <div className={`xp-row ${isOpen ? 'open' : ''} ${job.featured ? 'featured' : ''}`}>
      <button className="xp-head" onClick={onToggle} aria-expanded={isOpen}>
        <div className="xp-range mono">{job.range}</div>
        <div className="xp-mark"><LogoMark color={job.color} /></div>
        <div className="xp-core">
          <div className="xp-company serif">{job.company}</div>
          <div className="xp-role">{job.role} · <span className="xp-loc">{job.location}</span></div>
        </div>
        <div className="xp-toggle" aria-hidden="true">
          <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M6 9l6 6 6-6"/></svg>
        </div>
      </button>
      <div className="xp-body" ref={bodyRef} style={{ maxHeight: isOpen ? 'none' : '0px' }}>
        <div className="xp-body-inner" ref={innerRef}>
          <p className="xp-summary">{job.summary}</p>
          <ul className="xp-bullets">
            {job.bullets.map((b, i) => <li key={i}>{b}</li>)}
          </ul>
          <div className="xp-stack">
            {job.stack.map((s, i) => <span className="chip" key={i}>{s}</span>)}
          </div>
        </div>
      </div>
    </div>
  );
}

function Experience() {
  const [open, setOpen] = useState(new Set([0, 1, 2]));
  const toggle = (i) => {
    setOpen(prev => {
      const n = new Set(prev);
      n.has(i) ? n.delete(i) : n.add(i);
      return n;
    });
  };
  return (
    <section className="experience" id="experience">
      <div className="ambient-orb b" aria-hidden="true" />
      <div className="section-head" data-reveal>
        <span className="eyebrow"><span className="eb-num">03</span> Experience</span>
        <h2 className="section-title serif">
          A decade and change of <span className="italic">shipping.</span>
        </h2>
      </div>
      <div className="xp-list">
        {EXPERIENCE.map((job, i) => (
          <ExperienceRow key={i} job={job} index={i} isOpen={open.has(i)} onToggle={() => toggle(i)} />
        ))}
      </div>
    </section>
  );
}

function Skills() {
  return (
    <section className="skills" id="skills">
      <div className="ambient-orb a" aria-hidden="true" />
      <div className="section-head" data-reveal>
        <span className="eyebrow"><span className="eb-num">04</span> Toolkit</span>
        <h2 className="section-title serif">
          Tools I reach for, <span className="italic">often.</span>
        </h2>
        <p className="section-sub">
          A working set, not a dumping ground. Grouped by where they live in the stack.
        </p>
      </div>
      <div className="skills-stack">
        {SKILLS.map((s, i) => (
          <div className="skill-row" key={i} data-reveal style={{ transitionDelay: `${i * 50}ms` }}>
            <div className="skill-row-head">
              <div className="skill-row-num mono">{String(i + 1).padStart(2, '0')}</div>
              <div className="skill-row-icon"><SkillIcon kind={s.icon} /></div>
              <div className="skill-row-label">
                <div className="skill-row-title serif">{s.group}</div>
                <div className="skill-row-count mono">{s.items.length} tools</div>
              </div>
            </div>
            <div className="skill-row-tags">
              {s.items.map((it, j) => (
                <span className="skill-tag" key={j}>{it}</span>
              ))}
            </div>
          </div>
        ))}
      </div>
    </section>
  );
}

const TESTIMONIALS = [
  {
    quote: "Lamine is an exceptional Cloud Architect. We brought him in to integrate AWS SNS into our ASP.NET Core 8 application and fix a stubborn IAM permission issue between our local and staging environments. He jumped into our repo immediately, diagnosed the credential chain issue within minutes, and delivered a clean, interface-driven publisher service in under two hours. He even hopped on a call to walk our lead developer through the exact Dependency Injection setup. Fast, highly communicative, and deeply knowledgeable about enterprise AWS architecture. We will absolutely hire him again as we continue our microservices transition.",
    name: "Clara Tracy",
    role: "CEO, Stealth Startup",
    context: "AWS Solutions Architect · ASP.NET Core API",
    photo: "assets/clara.jpg",
    lang: "en",
  },
  {
    quote: "Lamine is a team player, a hard worker and a great person to collaborate with. We had to deliver a big responsive project together and we did it on deadline even if the amount of problems we had to face was quite huge. I recommend him without a doubt for any project.",
    name: "Pierre Ragois",
    role: "Designer & Entrepreneur",
    context: "Client · August 2013",
    photo: "assets/pierre.jpg",
    lang: "en",
  },
  {
    quote: "Je recommande M. Kacimi pour sa parfaite maîtrise du langage Java ainsi que le J2EE. C'est un formateur chevronné avec un potentiel de développement hors normes; il peut aussi bien travailler solo ou diriger une équipe en tant que collaborateur ou instructeur. Je suivrais sans doute n'importe quelle formation avec lui.",
    name: "Salim Zaouagui",
    role: "Chef cellule Support et Médiation, Algérie Télécom",
    context: "Direct report · August 2016",
    photo: "assets/salim.jpg",
    lang: "fr",
  },
];

function Testimonials() {
  return (
    <section className="testimonials" id="testimonials">
      <div className="section-head" data-reveal>
        <span className="eyebrow"><span className="eb-num">05</span> Testimonials</span>
        <h2 className="section-title serif">
          What people I've worked with <span className="italic">say.</span>
        </h2>
      </div>
      <div className="testimonial-grid">
        {TESTIMONIALS.map((t, i) => (
          <article className="testimonial-card" key={i} data-reveal style={{ transitionDelay: `${i * 80}ms` }}>
            <div className="t-quote-mark serif">"</div>
            <p className="t-quote">{t.quote}</p>
            <div className="t-author">
              <img src={t.photo} alt={t.name} className="t-avatar" />
              <div className="t-meta">
                <div className="t-name">{t.name}</div>
                <div className="t-role">{t.role}</div>
                <div className="t-context mono">{t.context}{t.lang === 'fr' ? ' · FR' : ''}</div>
              </div>
            </div>
          </article>
        ))}
      </div>
    </section>
  );
}

function Contact() {
  const [copied, setCopied] = useState(false);
  const email = 'me@laminekacimi.com';
  const copy = async () => {
    try {
      await navigator.clipboard.writeText(email);
      setCopied(true);
      setTimeout(() => setCopied(false), 1800);
    } catch(e) {}
  };
  return (
    <section className="contact" id="contact">
      <div className="contact-inner" data-reveal>
        <span className="eyebrow"><span className="eb-num">06</span> Contact</span>
        <h2 className="contact-title serif">
          Got something worth <span className="italic">building</span>?
        </h2>
        <p className="contact-lede">
          I'm open to senior IC and staff-level opportunities, interesting consulting work,
          and the occasional late-night architecture rant. Reach out.
        </p>
        <div className="contact-actions">
          <button className="email-pill" onClick={copy}>
            <span className="ep-at">@</span>
            <span className="ep-email">{email}</span>
            <span className="ep-copy mono">{copied ? 'copied' : 'copy'}</span>
          </button>
        </div>
        <div className="contact-links">
          <a href="mailto:me@laminekacimi.com" className="c-link">
            <span className="cl-k mono">email</span>
            <span className="cl-v">me@laminekacimi.com</span>
            <Arrow />
          </a>
          <a href="https://github.com/lkacimi" target="_blank" rel="noreferrer" className="c-link">
            <span className="cl-k mono">github</span>
            <span className="cl-v">/lkacimi</span>
            <Arrow />
          </a>
          <a href="https://www.linkedin.com/in/lamine-kacimi/" target="_blank" rel="noreferrer" className="c-link">
            <span className="cl-k mono">linkedin</span>
            <span className="cl-v">/in/lamine-kacimi</span>
            <Arrow />
          </a>
          <a href="https://www.upwork.com/freelancers/laminekacimi" target="_blank" rel="noreferrer" className="c-link">
            <span className="cl-k mono">upwork</span>
            <span className="cl-v">/laminekacimi</span>
            <Arrow />
          </a>
          <a href="tel:+12105487450" className="c-link">
            <span className="cl-k mono">phone</span>
            <span className="cl-v">+1 (210) 548-7450</span>
            <Arrow />
          </a>
        </div>
      </div>
    </section>
  );
}

function Footer() {
  return (
    <footer className="footer">
      <div className="footer-main serif italic">Lamine Kacimi</div>
      <div className="footer-row">
        <span className="mono">© {new Date().getFullYear()} · Georgetown, TX</span>
        <span className="mono">designed &amp; built with care</span>
      </div>
    </footer>
  );
}

function BackToTop() {
  const [show, setShow] = useState(false);
  useEffect(() => {
    const on = () => setShow(window.scrollY > 600);
    on();
    window.addEventListener('scroll', on, { passive: true });
    return () => window.removeEventListener('scroll', on);
  }, []);
  return (
    <button
      className={`back-top ${show ? 'visible' : ''}`}
      onClick={() => window.scrollTo({ top: 0, behavior: 'smooth' })}
      aria-label="Back to top"
    >
      <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
        <path d="M12 19V5M5 12l7-7 7 7"/>
      </svg>
      <span className="bt-label mono">top</span>
    </button>
  );
}

function App() {
  const [theme, toggleTheme] = useTheme();
  useReveal();
  // Smooth scroll for anchor clicks
  useEffect(() => {
    const onClick = (e) => {
      const a = e.target.closest('a[href^="#"]');
      if (!a) return;
      const id = a.getAttribute('href').slice(1);
      if (!id) return;
      const el = document.getElementById(id);
      if (!el) return;
      e.preventDefault();
      window.scrollTo({ top: el.getBoundingClientRect().top + window.scrollY - 60, behavior: 'smooth' });
    };
    document.addEventListener('click', onClick);
    return () => document.removeEventListener('click', onClick);
  }, []);

  return (
    <div className="page">
      <Nav theme={theme} toggleTheme={toggleTheme} />
      <Hero />
      <About />
      <SelectedWork />
      <Experience />
      <Skills />
      <Testimonials />
      <Contact />
      <Footer />
      <BackToTop />
    </div>
  );
}

ReactDOM.createRoot(document.getElementById('root')).render(<App />);
