// Main app — V2: senior repositioning
const { useState, useEffect, useRef } = React;

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "accent": "#4a6cf7",
  "parallaxIntensity": 1,
  "grainEnabled": true
} /*EDITMODE-END*/;

/* ============ NAV ============ */
function Nav({ lang, setLang }) {
  const [scrolled, setScrolled] = useState(false);
  useEffect(() => {
    const onScroll = () => setScrolled(window.scrollY > 40);
    window.addEventListener("scroll", onScroll, { passive: true });
    return () => window.removeEventListener("scroll", onScroll);
  }, []);

  return (
    <nav className={`nav ${scrolled ? "scrolled" : ""}`}>
      <div className="wrap nav-inner">
        <div className="brand">
          <span className="brand-dot" />
          <span>NATHAN PICHON · SENIOR BACKEND ENGINEER</span>
        </div>
        <div className="nav-links">
          <a href="#proof">{lang === "fr" ? "Repères" : "Numbers"}</a>
          <a href="#manifesto">{lang === "fr" ? "Approche" : "Approach"}</a>
          <a href="#engagements">{lang === "fr" ? "Ce que je fais" : "What I do"}</a>
          <a href="#cases">{lang === "fr" ? "Réalisations" : "Track record"}</a>
          <a href="#timeline">{lang === "fr" ? "Parcours" : "Career"}</a>
          <a href="#internal">{lang === "fr" ? "En interne" : "In-house"}</a>
          <a href="#contact">Contact</a>
        </div>
        <div className="nav-right">
          <span className="status-dot"><span className="pulse" /> {lang === "fr" ? "Disponible Q3 2026" : "Available Q3 2026"}</span>
          <div className="lang-toggle">
            <button className={lang === "fr" ? "active" : ""} onClick={() => setLang("fr")}>FR</button>
            <button className={lang === "en" ? "active" : ""} onClick={() => setLang("en")}>EN</button>
          </div>
        </div>
      </div>
    </nav>);

}

/* ============ HERO ============ */
function Hero({ lang, scrollY, parallaxIntensity }) {
  const py = scrollY * 0.15 * parallaxIntensity;
  const headlineY = scrollY * -0.06 * parallaxIntensity;
  const reveal = Math.min(1, scrollY / 600);
  const clip = `inset(${(1 - reveal) * 8}% ${(1 - reveal) * 8}% ${(1 - reveal) * 8}% ${(1 - reveal) * 8}%)`;
  const greyscale = 1 - reveal;

  return (
    <section className="hero">
      <div className="wrap hero-grid">
        <div style={{ transform: `translateY(${headlineY}px)` }}>
          <span className="eyebrow">
            {lang === "fr" ? "SENIOR BACKEND ENGINEER · NODE.JS / TYPESCRIPT" : "SENIOR BACKEND ENGINEER · NODE.JS / TYPESCRIPT"}
          </span>
          <h1 className="hero-headline">
            {lang === "fr" ?
            <>Des backends qui <em>tiennent</em>.</> :

            <>Backends that <em>hold</em>.</>
            }
          </h1>
          <p className="hero-sub">
            {lang === "fr" ?
            "10 ans à concevoir, faire évoluer et stabiliser des systèmes Node.js / TypeScript, de l'ESN à la scale-up produit. J'aime le code propre, la bonne décision technique au bon moment, et les équipes où on s'entraide pour livrer un produit de qualité." :
            "10 years designing, evolving and stabilising Node.js / TypeScript systems, from large consultancies to product scale-ups. I like clean code, the right technical call at the right time, and teams that help each other ship a quality product."}
          </p>

          <div className="hero-actions">
            <a className="btn-primary" href="https://calendly.com/contact-npichon/30min" target="_blank" rel="noopener">
              {lang === "fr" ? "Réserver 30 min" : "Book 30 min"}
              <svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M2 12 L12 2 M5 2 H12 V9" stroke="currentColor" strokeWidth="1.4" /></svg>
            </a>
            <a className="btn-ghost" href="#cases">
              {lang === "fr" ? "Voir les réalisations" : "See track record"}
            </a>
          </div>

          <div className="hero-meta">
            <span><b>10 ans</b> {lang === "fr" ? "de Node.js en prod" : "of Node.js in prod"}</span>
            <span><b>ESN → produit</b> {lang === "fr" ? "jusqu'à la scale-up" : "to scale-up"}</span>
            <span><b>{lang === "fr" ? "Backend," : "Backend,"}</b> {lang === "fr" ? "mais pas que" : "but not only"}</span>
          </div>
        </div>

        <div className="hero-portrait" style={{ transform: `translateY(${-py}px)` }}>
          <div className="portrait-frame">
            <img
              src="assets/portrait.png"
              alt="Nathan Pichon"
              className="portrait-img"
              style={{
                clipPath: clip,
                filter: `grayscale(${greyscale * 100}%) contrast(${1 + reveal * 0.05})`
              }} />
            
            <div className="portrait-coords">
              N. PICHON<br />BACKEND ENGINEER<br />FR · 2026
            </div>
            <div className="portrait-tag">
              {lang === "fr" ? "10+ ANS · NODE.JS" : "10+ YRS · NODE.JS"}
            </div>
          </div>
        </div>
      </div>
    </section>);

}

/* ============ PROOF BAR (logos + numbers) ============ */
function Proof({ lang }) {
  const stats = lang === "fr" ? [
  { n: "10+", l: "ans de Node.js en production" },
  { n: "200×", l: "gain mesuré sur une requête MongoDB" },
  { n: "2,5 ans", l: "Senior Backend chez Strapi" },
  { n: "3 équipes", l: "accompagnées et montées en compétence" }] :
  [
  { n: "10+", l: "years of Node.js in production" },
  { n: "200×", l: "measured speedup on one MongoDB query" },
  { n: "2.5 yrs", l: "Senior Backend at Strapi" },
  { n: "3 teams", l: "coached and levelled up" }];


  const companies = ["STRAPI", "SIMPLIFIELD", "SOPRA STERIA", "BANQUE DE FRANCE", "SNCF"];

  return (
    <section id="proof" className="proof">
      <div className="wrap">
        <div className="proof-companies">
          <span className="proof-label">{lang === "fr" ? "DÉJÀ VU CHEZ" : "PREVIOUSLY AT"}</span>
          <div className="proof-companies-list">
            {companies.map((c, i) => <span key={i}>{c}</span>)}
          </div>
        </div>

        <div className="proof-stats">
          {stats.map((s, i) =>
          <div className="proof-stat" key={i}>
              <div className="proof-stat-num">{s.n}</div>
              <div className="proof-stat-label">{s.l}</div>
            </div>
          )}
        </div>
      </div>
    </section>);

}

/* ============ MANIFESTO ============ */
function Manifesto({ lang }) {
  const lines = lang === "fr" ? [
  "Le bon outil pour le besoin. Monolithe, microservices, DDD ou pas : ça dépend du produit, jamais de la mode.",
  "Le code maintenable bat le code malin. C'est l'équipe qui vivra avec, pas mon ego.",
  "Backend engineer, mais pas que. Si le PO galère sur sa roadmap ou le devops sur un déploiement, je donne un coup de main.",
  "On ne refait pas une stack pour le plaisir. On y touche quand elle bloque vraiment le produit.",
  "Rendre les autres autonomes vaut mieux que devenir indispensable.",
  "Une base mal pensée n'est pas un souci de perf, c'est un souci de design — et ça se règle ensemble."] :
  [
  "The right tool for the job. Monolith, microservices, DDD or not: it depends on the product, never the trend.",
  "Maintainable code beats clever code. The team lives with it, not my ego.",
  "Backend engineer, but not only. If the PO is stuck on a roadmap or devops on a deploy, I pitch in.",
  "You don't rewrite a stack for fun. You touch it when it's genuinely blocking the product.",
  "Making others autonomous beats becoming indispensable.",
  "A badly designed database isn't a perf problem, it's a design problem — and we fix it together."];


  return (
    <section id="manifesto" className="manifesto">
      <div className="wrap">
        <div className="section-head reveal">
          <span className="section-tag">§ 02 / {lang === "fr" ? "APPROCHE" : "APPROACH"}</span>
          <div>
            <h2 className="section-title">
              {lang === "fr" ? <>Comment <em>je bosse</em>.</> : <>How <em>I work</em>.</>}
            </h2>
            <p className="section-lede">
              {lang === "fr" ?
              "Quelques principes appris en dix ans de prod. Aucun n'est une religion." :
              "A few principles picked up over ten years in production. None of them is a religion."}
            </p>
          </div>
        </div>

        <ol className="manifesto-list reveal">
          {lines.map((line, i) =>
          <li key={i}>
              <span className="m-num">{String(i + 1).padStart(2, "0")}</span>
              <span className="m-line">{line}</span>
            </li>
          )}
        </ol>
      </div>
    </section>);

}

/* ============ ENGAGEMENTS (services, but framed as missions) ============ */
function Engagements({ lang }) {
  const items = lang === "fr" ? [
  {
    tag: "01",
    title: "Construire & faire évoluer",
    desc: "Concevoir et coder des features et des services backend Node.js / TypeScript. Le quotidien : des API propres, testées, qui tiennent en prod — et que l'équipe peut reprendre sans moi.",
    deliverables: ["Features de bout en bout", "API propres et testées", "Code que l'équipe reprend", "Revue de code utile"]
  },
  {
    tag: "02",
    title: "Stabiliser & débloquer",
    desc: "Quand le backend grince — couplage, lenteurs, déploiements anxiogènes — je trouve les vrais points de blocage et je les traite avec l'équipe. Sans tout casser ni tout réécrire pour autant.",
    deliverables: ["Diagnostic honnête", "Corrections incrémentales", "Zéro big bang risqué", "Équipe embarquée"]
  },
  {
    tag: "03",
    title: "Audit MongoDB / Node.js",
    desc: "Vos requêtes ralentissent, vos index ne suivent plus. J'audite schéma, requêtes et patterns d'accès, je livre des gains mesurés — et j'explique chaque correctif pour que l'équipe sache reproduire.",
    deliverables: ["Audit chiffré", "Quick wins priorisés", "Atelier de restitution", "Anti-patterns documentés"]
  },
  {
    tag: "04",
    title: "Aider l'équipe à monter",
    desc: "Pair-coding, revue de design, onboarding, un coup de main au PO ou au devops. Pas pour apprendre dans le vide — pour devenir autonomes sur les bonnes décisions.",
    deliverables: ["Pair-coding", "Revue de design", "Onboarding", "Coup de main transverse"]
  }] :
  [
  {
    tag: "01",
    title: "Build & evolve",
    desc: "Designing and coding backend features and services in Node.js / TypeScript. The day-to-day: clean, tested APIs that hold in production — and that the team can pick up without me.",
    deliverables: ["End-to-end features", "Clean, tested APIs", "Code the team owns", "Useful code review"]
  },
  {
    tag: "02",
    title: "Stabilise & unblock",
    desc: "When the backend creaks — coupling, slowness, scary deploys — I find the real blockers and tackle them with the team. Without breaking or rewriting everything in the process.",
    deliverables: ["Honest diagnosis", "Incremental fixes", "No risky big bang", "Team on board"]
  },
  {
    tag: "03",
    title: "MongoDB / Node.js audit",
    desc: "Queries are slowing, indexes can't keep up. I audit schema, queries and access patterns, ship measured gains — and explain every fix so the team can reproduce it.",
    deliverables: ["Quantified audit", "Prioritised quick wins", "Debrief workshop", "Documented anti-patterns"]
  },
  {
    tag: "04",
    title: "Help the team level up",
    desc: "Pair-coding, design review, onboarding, a hand to the PO or devops. Not learning for its own sake — becoming autonomous on the right calls.",
    deliverables: ["Pair-coding", "Design review", "Onboarding", "Cross-team help"]
  }];


  return (
    <section id="engagements">
      <div className="wrap">
        <div className="section-head reveal">
          <span className="section-tag">§ 03 / {lang === "fr" ? "CE QUE JE FAIS" : "WHAT I DO"}</span>
          <div>
            <h2 className="section-title">
              {lang === "fr" ? <>Là où je suis <em>utile</em>.</> : <>Where I'm <em>useful</em>.</>}
            </h2>
            <p className="section-lede">
              {lang === "fr" ?
              "En freelance comme en interne, c'est le même métier : du backend solide, et un coup de main partout où ça coince." :
              "Freelance or in-house, it's the same job: solid backend work, and a hand wherever things get stuck."}
            </p>
          </div>
        </div>

        <div className="engagements reveal">
          {items.map((it, i) =>
          <article className="engagement" key={i}>
              <header className="engagement-head">
                <span className="engagement-tag">{it.tag}</span>
              </header>
              <h3 className="engagement-title">{it.title}</h3>
              <p className="engagement-desc">{it.desc}</p>
              <div className="engagement-deliv">
                <span className="engagement-deliv-label">{lang === "fr" ? "Concrètement" : "In practice"}</span>
                <ul>{it.deliverables.map((d, j) => <li key={j}>{d}</li>)}</ul>
              </div>
            </article>
          )}
        </div>
      </div>
    </section>);

}

/* ============ FIT (when to call / when not) ============ */
function Fit({ lang }) {
  const yes = lang === "fr" ? [
  "Vous voulez un senior qui code vraiment, pas seulement qui fait des slides.",
  "Vous tenez à un produit de qualité et à une équipe qui s'entraide.",
  "Vous êtes sur du Node.js / TypeScript, avec du Mongo et/ou du Postgres.",
  "Vous aimez les gens qui expliquent leurs décisions et font monter les autres.",
  "Vous préférez le pragmatisme aux dogmes d'architecture."] :
  [
  "You want a senior who actually codes, not just makes slides.",
  "You care about a quality product and a team that helps each other.",
  "You're on Node.js / TypeScript, with Mongo and/or Postgres.",
  "You like people who explain their decisions and level others up.",
  "You prefer pragmatism over architecture dogma."];

  const no = lang === "fr" ? [
  "Vous cherchez le TJM le plus bas pour de l'exécution pure.",
  "Vous voulez quelqu'un qui code seul dans son coin, sans parler à personne.",
  "Votre stack principale n'est pas JavaScript / TypeScript.",
  "Vous attendez qu'on valide une décision déjà prise, sans discussion.",
  "Vous voulez du microservices partout, surtout parce que c'est moderne."] :
  [
  "You're after the lowest day-rate for pure execution.",
  "You want someone who codes alone in a corner, talking to no one.",
  "Your main stack isn't JavaScript / TypeScript.",
  "You expect a decision already made to be rubber-stamped, no debate.",
  "You want microservices everywhere, mostly because it's modern."];


  return (
    <section id="fit" className="fit">
      <div className="wrap">
        <div className="section-head reveal">
          <span className="section-tag">§ 04 / {lang === "fr" ? "FRANCHEMENT" : "HONESTLY"}</span>
          <div>
            <h2 className="section-title">
              {lang === "fr" ? <>Où ça <em>matche</em> —<br />où ce n'est <em>pas moi</em>.</> : <>Where it <em>clicks</em> —<br />where it <em>won't</em>.</>}
            </h2>
            <p className="section-lede">
              {lang === "fr" ?
              "Autant être clair tout de suite. Ça évite de perdre du temps des deux côtés." :
              "Better be clear upfront. Saves everyone's time."}
            </p>
          </div>
        </div>

        <div className="fit-grid reveal">
          <div className="fit-col fit-yes">
            <h4>{lang === "fr" ? "↗ ON VA BIEN S'ENTENDRE SI" : "↗ WE'LL GET ALONG IF"}</h4>
            <ul>{yes.map((y, i) => <li key={i}>{y}</li>)}</ul>
          </div>
          <div className="fit-col fit-no">
            <h4>{lang === "fr" ? "↘ PASSEZ VOTRE CHEMIN SI" : "↘ LOOK ELSEWHERE IF"}</h4>
            <ul>{no.map((y, i) => <li key={i}>{y}</li>)}</ul>
          </div>
        </div>
      </div>
    </section>);

}

/* ============ TRACK RECORD (real cases, context/action/result) ============ */
function Cases({ lang }) {
  const cases = lang === "fr" ? [
  {
    id: "01",
    company: "STRAPI",
    duration: "2.5 ans · Senior Backend Engineer",
    title: "Refonte du backend Strapi Cloud",
    context: "Strapi Cloud, produit clé du groupe, montait en charge avec un backend hérité difficile à faire évoluer. Patterns inconsistants, modèle de relations utilisateur/projet sous-dimensionné pour les besoins B2B.",
    action: "Réécriture du modèle utilisateur/projet, standardisation des patterns d'architecture, lead technique sur le développement de la Cloud CLI, mentorat de plusieurs nouveaux arrivants.",
    result: "Modèle de relations refondu, Cloud CLI livrée et adoptée, vélocité de l'équipe Experience stabilisée. Participation active au recrutement (tests techniques, entretiens)."
  },
  {
    id: "02",
    company: "SIMPLIFIELD",
    duration: "1.7 an · Chapter Lead Backend",
    title: "Refonte de la stack backend",
    context: "Stack backend monolithique Node.js arrivée à la limite de ses capacités d'évolution. Couplage fort, difficulté à introduire de nouveaux domaines métiers, contraintes opérationnelles croissantes.",
    action: "Conception et pilotage de la refonte vers DDD + architecture hexagonale + micro-services NestJS. Conduite de l'intégration Auth0 (planification, conception, intégration). Encadrement des développeurs backend.",
    result: "Première architecture hexagonale de l'entreprise. Auth0 livré en production. Équipe formée aux patterns DDD pendant la mission."
  },
  {
    id: "03",
    company: "INDÉPENDANT",
    duration: "Forfait · Audit MongoDB",
    title: "Package Audit MongoDB",
    context: "Application Node.js / MongoDB en production présentant des temps de réponse dégradés sur les requêtes critiques. Soupçon d'anti-patterns côté schéma et indexation.",
    action: "Audit complet : schéma, requêtes, indexation, patterns d'accès depuis Node.js. Restitution sous forme de rapport écrit + atelier de discussion avec l'équipe pour expliquer chaque optimisation.",
    result: "Optimisations livrées avec gains mesurés jusqu'à deux ordres de grandeur sur certaines requêtes. Anti-patterns documentés pour usage interne futur."
  },
  {
    id: "04",
    company: "SOPRA STERIA · BANQUE DE FRANCE",
    duration: "1 an · Lead Tech AngularJS",
    title: "Lead technique grand compte",
    context: "Projet réglementaire Banque de France, environnement à forte exigence de sécurité et de conformité, équipe de développement pluridisciplinaire.",
    action: "Encadrement technique, revue de code systématique, mise en place de bonnes pratiques, coordination avec les équipes QA et DevOps.",
    result: "Bonnes pratiques industrialisées sur l'équipe, montée en compétence des juniors, transition fluide en fin de mission."
  }] :
  [
  {
    id: "01",
    company: "STRAPI",
    duration: "2.5 yrs · Senior Backend Engineer",
    title: "Strapi Cloud backend rearchitecture",
    context: "Strapi Cloud, a strategic product, was scaling on a legacy backend that was hard to evolve. Inconsistent patterns, undersized user/project relationship model for B2B needs.",
    action: "Rewrote the user/project model, standardised architecture patterns, tech-led the Cloud CLI development, mentored several new joiners.",
    result: "Relationship model rebuilt, Cloud CLI shipped and adopted, Experience team velocity stabilised. Active in hiring (technical tests, interviews)."
  },
  {
    id: "02",
    company: "SIMPLIFIELD",
    duration: "1.7 yrs · Backend Chapter Lead",
    title: "Backend stack overhaul",
    context: "Node.js monolith reaching the limit of its evolution capacity. High coupling, hard to introduce new business domains, growing operational pressure.",
    action: "Designed and led the move to DDD + hexagonal architecture + NestJS micro-services. Drove the Auth0 integration (planning, design, rollout). Coached the backend team.",
    result: "Company's first hexagonal architecture project. Auth0 shipped to production. Team trained on DDD patterns during the engagement."
  },
  {
    id: "03",
    company: "INDEPENDENT",
    duration: "Fixed-fee · MongoDB Audit",
    title: "MongoDB Audit Package",
    context: "Node.js / MongoDB application in production with degraded latency on critical queries. Suspected schema and indexing anti-patterns.",
    action: "Full audit: schema, queries, indexing, access patterns from Node.js. Written report + debrief workshop for the team, explaining each optimisation.",
    result: "Optimisations shipped with measured gains up to two orders of magnitude on key queries. Anti-patterns documented for internal reuse."
  },
  {
    id: "04",
    company: "SOPRA STERIA · BANQUE DE FRANCE",
    duration: "1 yr · AngularJS Tech Lead",
    title: "Enterprise tech lead",
    context: "Regulatory project at Banque de France, high security and compliance bar, cross-disciplinary delivery team.",
    action: "Technical mentoring, systematic code review, best-practice rollout, coordination with QA and DevOps teams.",
    result: "Best practices institutionalised across the team, junior devs levelled up, smooth handover at the end of the engagement."
  }];


  return (
    <section id="cases">
      <div className="wrap">
        <div className="section-head reveal">
          <span className="section-tag">§ 05 / {lang === "fr" ? "RÉALISATIONS" : "TRACK RECORD"}</span>
          <div>
            <h2 className="section-title">
              {lang === "fr" ? <>Ce qui a été <em>livré</em>.</> : <>What was <em>shipped</em>.</>}
            </h2>
            <p className="section-lede">
              {lang === "fr" ? "Format senior : contexte, action, résultat. Sans superlatif." : "Senior format: context, action, result. No superlatives."}
            </p>
          </div>
        </div>

        <div className="cases-list reveal">
          {cases.map((c) =>
          <article className="case-row" key={c.id}>
              <div className="case-row-head">
                <span className="case-row-id">CASE {c.id}</span>
                <span className="case-row-company">{c.company}</span>
                <span className="case-row-duration">{c.duration}</span>
              </div>
              <h3 className="case-row-title">{c.title}</h3>
              <div className="case-row-grid">
                <div>
                  <h5>{lang === "fr" ? "CONTEXTE" : "CONTEXT"}</h5>
                  <p>{c.context}</p>
                </div>
                <div>
                  <h5>{lang === "fr" ? "ACTION" : "ACTION"}</h5>
                  <p>{c.action}</p>
                </div>
                <div>
                  <h5>{lang === "fr" ? "RÉSULTAT" : "OUTCOME"}</h5>
                  <p>{c.result}</p>
                </div>
              </div>
            </article>
          )}
        </div>
      </div>
    </section>);

}

/* ============ TIMELINE — kept horizontal as before, condensed ============ */
function Timeline({ lang }) {
  const items = lang === "fr" ? [
  { period: "2025 — PRÉSENT", company: "Indépendant", role: "Senior Backend Engineer · Freelance", desc: "Audits MongoDB, accompagnement d'équipes, renforts backend Node.js.", featured: true },
  { period: "2022 — 2025", company: "Strapi", role: "Senior Backend Engineer", desc: "Refonte technique du backend Cloud, lead Cloud CLI, mentorat, recrutement." },
  { period: "2021 — 2022", company: "SimpliField", role: "Chapter Lead Backend", desc: "Pilotage de la refonte (DDD, hexagonal, micro-services NestJS, Auth0)." },
  { period: "2019 — 2022", company: "SimpliField", role: "Développeur Web", desc: "Modules tâches, newsfeed, statistiques. Sprints, support P1/P2." },
  { period: "2015 — 2019", company: "Sopra Steria", role: "Ingénieur études & développement", desc: "Banque de France, SNCF. Lead technique en fin de mission." }] :
  [
  { period: "2025 — NOW", company: "Independent", role: "Senior Backend Engineer · Freelance", desc: "MongoDB audits, team coaching, Node.js backend reinforcement.", featured: true },
  { period: "2022 — 2025", company: "Strapi", role: "Senior Backend Engineer", desc: "Cloud backend rearchitecture, Cloud CLI lead, mentoring, hiring." },
  { period: "2021 — 2022", company: "SimpliField", role: "Backend Chapter Lead", desc: "Led the refactor (DDD, hexagonal, NestJS micro-services, Auth0)." },
  { period: "2019 — 2022", company: "SimpliField", role: "Web Developer", desc: "Tasks, newsfeed, stats modules. Sprints, P1/P2 support." },
  { period: "2015 — 2019", company: "Sopra Steria", role: "Studies & Development Engineer", desc: "Banque de France, SNCF. Tech lead by end of tenure." }];


  return (
    <section id="timeline">
      <div className="wrap">
        <div className="section-head reveal">
          <span className="section-tag">§ 06 / {lang === "fr" ? "PARCOURS" : "CAREER"}</span>
          <div>
            <h2 className="section-title">
              {lang === "fr" ? <>Dix ans, <em>trois</em> employeurs,<br />une trajectoire.</> : <>Ten years, <em>five</em> employers,<br />one trajectory.</>}
            </h2>
            <p className="section-lede">
              {lang === "fr" ? "ESN grand compte → produit → scale-up → indépendant. Faites glisser →" : "Enterprise consultancy → product → scale-up → independent. Drag →"}
            </p>
          </div>
        </div>
      </div>
      <div className="timeline-wrap reveal">
        <div className="timeline-scroll">
          <div className="timeline-track">
            {items.map((it, i) =>
            <div key={i} className={`t-item ${it.featured ? "featured" : ""}`}>
                <div className="t-dot" />
                <div className="t-period">{it.period}</div>
                <div className="t-company">{it.company}</div>
                <div className="t-role">{it.role}</div>
                <div className="t-desc">{it.desc}</div>
              </div>
            )}
          </div>
        </div>
      </div>
    </section>);

}

/* ============ INTERNAL PATH (Engineering Manager ambition) ============ */
function InternalPath({ lang }) {
  const content = lang === "fr" ? {
    tag: "§ 07 / EN INTERNE",
    title: <>Je cherche une <em>équipe</em>, pas un poste.</>,
    lede: "Le freelance répond à un besoin précis. Si un jour je rejoins une entreprise en interne, ce n'est pas pour un titre — c'est pour une équipe et un produit.",
    note: "Section destinée aux entreprises qui m'envisagent en interne. Si vous me cherchez en prestation, le reste de la page est plus pertinent.",
    paragraphs: [
    {
      label: "CE QUE JE CHERCHE",
      text: "Pas un titre précis. J'aime naviguer entre Senior Backend Engineer et Lead Backend selon les besoins de l'équipe — coder quand c'est utile, prendre du recul quand il faut structurer. Ce qui compte, c'est la qualité du produit et l'équipe qui le fait."
    },
    {
      label: "COMMENT JE TRAVAILLE",
      text: "Mon périmètre suit le besoin, pas la fiche de poste. Aider le Product Owner à dégrossir sa roadmap, monter avec le devops un bot Slack pour déployer des environnements à la demande — si ça fait avancer le produit, j'y vais."
    },
    {
      label: "MA POSITION TECHNIQUE",
      text: "Le bon outil pour le bon besoin, point. Je ne suis pas un ayatollah du microservice, du DDD ou de l'hexagonal. Si un monolithe répond au besoin — ou existe déjà et coûterait trop cher à migrer — je ne pousse pas une refonte risquée pour la beauté du pattern."
    },
    {
      label: "OÙ JE VEUX ALLER",
      text: "Un jour, CTO. Pas demain — c'est une trajectoire longue, qui se construit en comprenant vraiment le produit, l'équipe et le business. Le freelance m'apprend beaucoup, mais c'est en interne, dans la durée, qu'on peut construire ça sérieusement."
    }]

  } : {
    tag: "§ 07 / IN-HOUSE",
    title: <>I'm after a <em>team</em>, not a title.</>,
    lede: "Freelancing answers a specific need. If I ever join a company in-house, it won't be for a title — it'll be for a team and a product.",
    note: "This section is for companies considering me in-house. If you're looking at me for contract work, the rest of the page is more relevant.",
    paragraphs: [
    {
      label: "WHAT I'M LOOKING FOR",
      text: "No specific title. I like moving between Senior Backend Engineer and Lead Backend depending on what the team needs — coding when it helps, stepping back when structure is needed. What matters is the quality of the product and the people building it."
    },
    {
      label: "HOW I WORK",
      text: "My scope follows the product need, not the job description. Helping the Product Owner shape their roadmap, building a Slack bot with devops to spin up environments on demand — if it moves the product forward, I'm in."
    },
    {
      label: "MY TECHNICAL STANCE",
      text: "The right tool for the right need, full stop. I'm no zealot for microservices, DDD or hexagonal architecture. If a monolith fits the need — or already exists and would cost too much to migrate — I won't push a risky rewrite for the elegance of the pattern."
    },
    {
      label: "WHERE I WANT TO GO",
      text: "CTO, one day. Not tomorrow — it's a long trajectory, built by genuinely understanding the product, the team and the business. Freelancing teaches me a lot, but it's in-house, over the long term, that you can build that seriously."
    }]

  };

  return (
    <section id="internal" className="internal">
      <div className="wrap">
        <div className="section-head reveal">
          <span className="section-tag">{content.tag}</span>
          <div>
            <h2 className="section-title">{content.title}</h2>
            <p className="section-lede">{content.lede}</p>
            <p className="internal-note">{content.note}</p>
          </div>
        </div>

        <div className="internal-grid reveal">
          {content.paragraphs.map((p, i) =>
          <div className="internal-card" key={i}>
              <span className="internal-label">{p.label}</span>
              <p>{p.text}</p>
            </div>
          )}
        </div>
      </div>
    </section>);

}

/* ============ ARCHITECTURE SCHEMA (kept) ============ */
function ArchitectureBlock({ lang }) {
  return (
    <section id="architecture">
      <div className="wrap">
        <div className="section-head reveal">
          <span className="section-tag">§ 08 / {lang === "fr" ? "VISION TECHNIQUE" : "TECHNICAL VIEW"}</span>
          <div>
            <h2 className="section-title">
              {lang === "fr" ? <>Une <em>architecture</em> qui se défend.</> : <>An <em>architecture</em> that holds up.</>}
            </h2>
            <p className="section-lede">
              {lang === "fr" ?
              "Le schéma ci-dessous est un exemple parmi d'autres : un découpage en domaines isolés qui avait du sens pour ce produit-là. Sur un autre projet, un monolithe bien rangé ferait tout aussi bien l'affaire. La bonne architecture, c'est celle qui colle au besoin — pas la plus à la mode." :
              "The diagram below is one example among many: a split into isolated domains that made sense for that particular product. On another project, a tidy monolith would do the job just as well. The right architecture is the one that fits the need — not the trendiest one."}
            </p>
          </div>
        </div>
        <div className="schema-block reveal">
          <span className="schema-label">{lang === "fr" ? "EXEMPLE — DÉCOUPAGE DDD / HEXAGONAL" : "EXAMPLE — DDD / HEXAGONAL SPLIT"}</span>
          <SchemaArchitecture />
        </div>
      </div>
    </section>);

}

/* ============ CONTACT ============ */
function Contact({ lang }) {
  return (
    <section id="contact" className="contact">
      <div className="wrap">
        <span className="section-tag">§ 09 / CONTACT</span>
        <h2 className="contact-headline" style={{ marginTop: 24 }}>
          {lang === "fr" ? <>On en <em>discute</em> ?</> : <>Let's <em>talk</em>?</>}
        </h2>
        <p className="contact-lede">
          {lang === "fr" ?
          "Réservez 30 minutes sur mon Calendly. On parle de votre contexte, je pose mes questions, et je vous dis franchement si je peux aider — ou pas. Pas de baratin commercial." :
          "Book 30 minutes on my Calendly. We talk through your context, I ask my questions, and I tell you honestly whether I can help — or not. No sales pitch."}
        </p>

        <a className="contact-cta" href="https://calendly.com/contact-npichon/30min" target="_blank" rel="noopener">
          {lang === "fr" ? "RÉSERVER 30 MIN AVEC NATHAN" : "BOOK 30 MIN WITH NATHAN"}
          <span className="arrow">
            <svg width="14" height="14" viewBox="0 0 14 14" fill="none">
              <path d="M2 12 L12 2 M5 2 H12 V9" stroke="currentColor" strokeWidth="1.4" />
            </svg>
          </span>
        </a>

        <div className="contact-meta">
          <div>
            <h5>{lang === "fr" ? "Réserver" : "Book"}</h5>
            <a href="https://calendly.com/contact-npichon/30min" target="_blank" rel="noopener">Calendly ↗</a><br />
            <a href="mailto:contact@npichon.eu">contact@npichon.eu</a>
          </div>
          <div>
            <h5>{lang === "fr" ? "Plateformes" : "Platforms"}</h5>
            <a href="https://www.linkedin.com/in/nathan-pichon" target="_blank" rel="noopener">LinkedIn ↗</a><br />
            <a href="https://www.malt.fr/profile/nathanpichon" target="_blank" rel="noopener">Malt ↗</a><br />
            <a href="https://github.com/nathan-pichon/" target="_blank" rel="noopener">GitHub ↗</a>
          </div>
          <div>
            <h5>{lang === "fr" ? "Disponibilité" : "Availability"}</h5>
            <p>{lang === "fr" ? "Q3 2026 — engagement long ou forfait court" : "Q3 2026 — long engagement or short fixed-fee"}</p>
          </div>
          <div>
            <h5>{lang === "fr" ? "Modalités" : "Terms"}</h5>
            <p>{lang === "fr" ? "Remote-first · ponctuel sur site · FR / EN" : "Remote-first · occasional onsite · FR / EN"}</p>
          </div>
        </div>

        <footer>
          <span>© 2026 Nathan Pichon · {lang === "fr" ? "Tous droits réservés" : "All rights reserved"}</span>
          <span>{lang === "fr" ? "Réponse sous 24h ouvrées" : "Reply within one business day"}</span>
        </footer>
      </div>
    </section>);

}

/* ============ TWEAKS ============ */
function PortfolioTweaks({ tweaks, setTweak }) {
  return (
    <TweaksPanel title="Tweaks">
      <TweakSection title="Couleur d'accent">
        <TweakColor value={tweaks.accent} onChange={(v) => setTweak("accent", v)} />
      </TweakSection>
      <TweakSection title="Parallax">
        <TweakSlider label="Intensité" min={0} max={2} step={0.1}
        value={tweaks.parallaxIntensity}
        onChange={(v) => setTweak("parallaxIntensity", v)} />
      </TweakSection>
      <TweakSection title="Détails">
        <TweakToggle label="Grain de fond" value={tweaks.grainEnabled} onChange={(v) => setTweak("grainEnabled", v)} />
      </TweakSection>
    </TweaksPanel>);

}

/* ============ APP ============ */
function App() {
  const [lang, setLang] = useState("fr");
  const [scrollY, setScrollY] = useState(0);
  const [tweaks, setTweak] = useTweaks(TWEAK_DEFAULTS);

  useEffect(() => {document.body.className = `lang-${lang}`;}, [lang]);

  useEffect(() => {
    const onScroll = () => setScrollY(window.scrollY);
    window.addEventListener("scroll", onScroll, { passive: true });
    return () => window.removeEventListener("scroll", onScroll);
  }, []);

  useEffect(() => {
    document.documentElement.style.setProperty("--accent", tweaks.accent);
    document.documentElement.style.setProperty("--accent-soft", tweaks.accent + "1f");
  }, [tweaks.accent]);

  useEffect(() => {
    const observer = new IntersectionObserver((entries) => {
      entries.forEach((e) => {if (e.isIntersecting) e.target.classList.add("in");});
    }, { threshold: 0.12 });
    document.querySelectorAll(".reveal").forEach((el) => observer.observe(el));
    return () => observer.disconnect();
  }, [lang]);

  const bgY = scrollY * 0.3 * tweaks.parallaxIntensity;
  const blob1Y = scrollY * 0.5 * tweaks.parallaxIntensity;
  const blob2Y = scrollY * 0.25 * tweaks.parallaxIntensity;

  return (
    <>
      <div className="bg-grid" style={{ transform: `translateY(${-bgY}px)` }} />
      <div className="bg-blob b1" style={{ transform: `translateY(${blob1Y}px)` }} />
      <div className="bg-blob b2" style={{ transform: `translateY(${-blob2Y}px)` }} />
      {tweaks.grainEnabled &&
      <div style={{
        position: "fixed", inset: 0, pointerEvents: "none", zIndex: 2,
        backgroundImage: `url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='200' height='200'><filter id='n'><feTurbulence baseFrequency='0.9' numOctaves='2'/><feColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.06 0'/></filter><rect width='200' height='200' filter='url(%23n)'/></svg>")`,
        opacity: 0.5,
        mixBlendMode: "multiply"
      }} />
      }

      <Nav lang={lang} setLang={setLang} />
      <main>
        <Hero lang={lang} scrollY={scrollY} parallaxIntensity={tweaks.parallaxIntensity} />
        <Proof lang={lang} />
        <Manifesto lang={lang} />
        <Engagements lang={lang} />
        <Fit lang={lang} />
        <Cases lang={lang} />
        <Timeline lang={lang} />
        <InternalPath lang={lang} />
        <ArchitectureBlock lang={lang} />
        <Contact lang={lang} />
      </main>

      <PortfolioTweaks tweaks={tweaks} setTweak={setTweak} />
    </>);

}

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