/* i18n — lightweight dictionary + useLang hook + t() helper.
   Loaded before other components so window.t / window.useLang are defined.
   RULE: every user-visible string in New/ must come from this dict. */

const DICT = {
  en: {
    nav: {
      about: "about",
      experience: "experience",
      work: "work",
      services: "services",
      contact: "contact",
      docs: "docs",
      letsTalk: "let's talk",
    },
    hero: {
      available: "Available for work · Q1 2026",
      location: "Nice, France",
      version: "v0.25.11",
      verbs: ["building", "shipping", "scaling", "crafting"],
      verbSuffix: " solutions.",
      ctaPrimary: "Selected work",
      ctaGhost: "Start a project",
      codeComment: "// 2026 — currently",
      codeRole: "fullstack dev",
      codeFocus: "ai + infra",
      stats: {
        shipped: "Shipped projects",
        years: "Years building",
        clients: "Happy clients",
        tech: "Tech & languages",
      },
      scroll: "scroll",
    },
    about: {
      label: "About",
      tagline: "/bio",
      city: "Nice · FR",
      p1: "I'm a fullstack developer working at the seams of AI, product engineering, and infrastructure. I like the whole stack — from database query plans to the last 2px of a button's hover state.",
      p2: "Two years in, I've shipped AI-native products, Rust backends pushing LLM tokens under heavy concurrency, and polished client work that actually converts. I care about craft, clarity, and shipping things that feel right.",
      p3: "Right now I'm freelancing from the south of France, working with founders and teams that need someone who can own a feature end-to-end — from architecture decisions to the UI details users won't consciously notice.",
      facts: {
        basedInLabel: "Based in",
        basedInValue: "Nice, France (CET)",
        languagesLabel: "Languages",
        languagesValue: "FR (native) · EN (fluent)",
        workingAsLabel: "Working as",
        workingAsValue: "Freelance / Contract",
        openToLabel: "Open to",
        openToValue: "AI internships · outside France",
      },
      skills: {
        heading: "Toolbox",
        sub: "what I reach for",
        frontend: "Frontend",
        backend: "Backend",
        aiData: "AI & Data",
        infra: "Infra & DX",
      },
    },
    curriculum: {
      label: "Curriculum",
      tagline: "/education",
      sectionTitle: {
        before: "Where I learned to ",
        em: "think",
        after: " like an engineer.",
      },
      lede: "My academic path — from the French Baccalauréat to 42Nice's project-based curriculum.",
      journeyTitle: "Academic Journey",
      journeyDesc:
        "A commitment to continuous learning and excellence in software development and artificial intelligence.",
      items: {
        school42Label: "42Nice",
        school42Value:
          "Innovative peer-to-peer learning in software development",
        previousLabel: "Previous education",
        previousValue:
          "Building strong foundations in technology and problem-solving",
        baccalaureatLabel: "French Baccalauréat",
        baccalaureatValue: "Specialties: Mathematics, Physics, Biology",
      },
      transcriptTitle: "Official Transcript",
      transcriptFilename: "Transcript_Bonnard",
      transcriptDate: "05-04-2026.pdf",
      viewAction: "View transcript",
      downloadAction: "Download PDF",
      lastUpdated: "Last updated: April 5, 2026",
    },
    skills: {
      label: "Skills",
      tagline: "/toolbox",
      sectionTitle: { before: "The stack I ", em: "stand behind", after: "." },
      lede: "The tech I reach for first — plus the human skills that make the tech land.",
      technicalGroup: "Technical",
      technicalSub: "languages, frameworks, databases",
      softGroup: "Soft skills",
      softSub: "the human side of shipping",
      toolsGroup: "Tools & Platforms",
      toolsSub: "what I use day to day",
      favoriteHint: "favorite",
      soft: {
        fastLearner: "Fast-learner",
        creativity: "Creativity",
        problemSolving: "Problem solving",
        communication: "Communication",
        optimization: "Optimization",
        adaptability: "Adaptability",
        teamwork: "Teamwork",
      },
    },
    experience: {
      label: "Experience",
      tagline: "/cv",
      sectionTitle: {
        before: "From school to ",
        em: "shipping",
        after: " — in parallel.",
      },
      lede: "Three tracks running at once: 42Nice for the fundamentals, personal projects for the exploration, and freelance clients for the real stakes.",
      at: "at",
      items: {
        freelance: {
          period: "December 2025 — now",
          role: "Freelance Fullstack Developer",
          company: "BloomSkills · GaIa",
          desc: "Freelance work alongside my studies, focused on AI integrations and patented solutions. On BloomSkills, an AI-powered soft-skills assessment platform — fullstack delivery from ingestion pipeline to operator dashboards. On GaIa, a retrieval-augmented assistant for industrial documentation — prompt orchestration, vector search, and evaluation harness.",
        },
        personal: {
          period: "2024 — now",
          role: "Personal projects",
          company: "Open-source & experiments",
          desc: "Tools and experiments I build in the gaps — from a Rust LLM gateway (SwiftLLM) unifying OpenAI, Anthropic, Gemini, Mistral & Ollama behind one API, to a browser-based 3D rendering studio (Raybox). Where most of my learning actually happens.",
        },
        school42: {
          period: "July 2024 — now",
          role: "Student",
          company: "42Nice",
          desc: "Innovative peer-to-peer learning in software development. Strengthening my foundations in C, C++, algorithms, and systems programming through a project-based curriculum with no courses, no teachers — just code and peer review.",
        },
      },
    },
    projects: {
      label: "Selected Work",
      tagline: "2024—2026",
      sectionTitle: {
        before: "Products that ",
        em: "ship",
        after: ", not slides that impress.",
      },
      lede: "A handful of recent projects across professional and personal work. Each one taught me something different.",
      tags: {
        professionalFeatured: "Professional · Featured",
        personal: "Personal",
        professional: "Professional",
        personalWip: "Personal · WIP",
        studio: "Studio · Various",
      },
      bloom: {
        titleBefore: "BloomSkills",
        titleEm: "— AI assessments",
        desc: "AI-powered skills assessment platform. Candidates take adaptive tests; the engine evaluates free-form answers via LLM chains and generates detailed competency reports. I led fullstack development.",
      },
      swiftllm: {
        title: "SwiftLLM",
        desc: "High-throughput Rust gateway for LLM inference. Rate limiting, streaming, caching, and multi-provider routing.",
      },
      gaia: {
        title: "GaIa",
        desc: "RAG-powered assistant for industrial documentation. Vector search, prompt orchestration, evaluation harness.",
      },
      raybox: {
        title: "Raybox",
        desc: "Experimental 3D portfolio shader playground. Three.js, custom GLSL, and real-time post-processing.",
      },
      inputmuxd: {
        title: "inputmuxd",
        desc: "Cross-platform userspace driver for the Valve Steam Controller (2026). Gyro mouse, trackpad modes, action layers, dual-stage triggers — replicated outside Steam, so the controller works in any launcher, emulator, or on the desktop. Pre-hardware: protocol reverse-engineering in progress.",
      },
      studio: {
        title: "Client work",
        desc: "Cybersecurity audits, internal tools, marketing sites. Tight deadlines, real users, real outcomes.",
      },
    },
    services: {
      title: "Services",
      subtitle: "What I can do for you",
      sectionLabel: "/what I offer",
      webDev: {
        title: "Web Development",
        desc: "Production-grade web apps, built from scratch or on top of an existing codebase. React, Next.js, Vue, TypeScript, Node.js — the whole stack, with obsessive attention to performance, accessibility, and the details users feel even when they can't name them.",
      },
      mobile: {
        title: "AI Integration",
        desc: "Real LLM features — not demos. RAG pipelines, agent orchestration, fine-tuning, prompt hygiene, cost discipline, and the evaluation harnesses that keep AI reliable in production. Pretrained APIs or your own models.",
      },
      cloud: {
        title: "Cloud",
        desc: "Cloud infrastructure that scales sideways and costs sensibly. AWS, Vercel, Railway, GCP. Serverless or containers, single-region or multi-region — sized to your actual traffic and budget, not someone else's reference architecture.",
      },
      devops: {
        title: "DevOps",
        desc: "CI/CD that catches real regressions, IaC you can review, observability that pages the right person. GitHub Actions, Docker, Terraform, Prometheus — the glue that lets small teams ship like bigger ones without burning out.",
      },
      database: {
        title: "Database",
        desc: "Schema design, query optimization, and migrations you can sleep through. PostgreSQL as a default, Redis for caching, pgvector/Pinecone for retrieval. GraphQL or REST — whichever actually fits the product.",
      },
      softwareDev: {
        title: "Software Development",
        desc: "Custom tools, internal platforms, CLIs, desktop apps, automation. When nothing off-the-shelf fits, I build the exact tool your team needs — well-typed, well-tested, and easy to hand off when you're ready.",
      },
    },
    contact: {
      label: "Contact",
      tagline: "/let's talk",
      headline: { before: "Got a ", em: "brief", after: "?\nLet's ship it." },
      socials: {
        github: "01 — GitHub",
        linkedin: "02 — LinkedIn",
        resumeAI: "03 — Resume (AI)",
        resumeAIMeta: "pdf · ai engineer",
        resumeCyber: "04 — Resume (Cyber)",
        resumeCyberMeta: "pdf · cybersecurity",
      },
      card: {
        available: "● Currently available",
        title: "Booking Q1 2026",
        desc: "Typical response under 24h. I take on 1–2 engagements at a time to keep focus high. Timezone-friendly across EU.",
        localTime: "Local time",
        response: "Response",
        responseValue: "< 24h",
        minEngagement: "Min. engagement",
        minEngagementValue: "2 weeks",
        rate: "Rate",
        rateValue: "On request",
      },
    },
    docs: {
      label: "Documentation",
      tagline: "/projects",
      sectionTitle: {
        before: "Deep dives into ",
        em: "what I build",
        after: ".",
      },
      lede: "Technical docs for select personal projects — build notes, architecture, and the reasoning behind the tradeoffs.",
      viewDocs: "View docs",
      comingSoon: "Coming soon",
      moreSoon: "// more projects coming soon...",
      types: {
        personal: "Personal",
        professional: "Professional",
      },
      projects: {
        swiftllm:
          "A blazing-fast universal LLM gateway in Rust, unifying OpenAI, Anthropic, Gemini, Mistral & Ollama behind a single API.",
        raybox:
          "A browser-based 3D rendering studio — import models, apply materials, set up lighting, and render. No installs, no complexity.",
        inputmuxd:
          "Cross-platform userspace driver for the Valve Steam Controller (2026). Steam Input replicated outside Steam — gyro mouse, trackpad modes, action layers, dual-stage triggers.",
      },
    },
    swiftllm: {
      back: "Back to docs",
      eyebrow: "Project · Documentation",
      title: "SwiftLLM Docs",
      description:
        "A blazing-fast universal LLM gateway in Rust. Unify OpenAI, Anthropic, Gemini, Mistral, Ollama, Groq, Together AI & AWS Bedrock behind a single API.",
      freeBadge: "100% Free & Open Source",
      mitBadge: "MIT Licensed",
      githubLink: "GitHub",
      sidebarHeading: "Navigation",
      copy: "Copy",
      copied: "Copied",
    },
    notfound: {
      badge: "404",
      title: "Lost in the web..",
      message:
        "The page you're looking for drifted off into the void. Let's get you back on track.",
      action: "Back to safety",
    },
    raybox: {
      back: "Back to docs",
      eyebrow: "Project · Documentation",
      title: "Raybox",
      subtitle: {
        before: "A browser-based ",
        em: "3D rendering",
        after: " studio.",
      },
      description:
        "Import models, apply materials, set up lighting, and render — all in the browser. No installs, no complexity. Three.js under the hood, custom GLSL shaders, real-time post-processing.",
      upcomingBadge: "Upcoming",
      upcomingTitle: "Documentation coming soon",
      upcomingBody:
        "Raybox is still in active development. Full documentation — the architecture, the shader pipeline, the UX decisions — will land when the project leaves WIP. Follow along or reach out if you want early access.",
      ctaContact: "Get in touch",
      stackTitle: "Stack",
      stack: ["Next.js", "React", "Three.js", "TypeScript", "GLSL", "WebGL 2"],
    },
    inputmuxd: {
      back: "Back to docs",
      eyebrow: "Project · Documentation",
      title: "inputmuxd",
      subtitle: {
        before: "A cross-platform ",
        em: "userspace driver",
        after: " for the Steam Controller.",
      },
      description:
        "Steam Input replicated outside Steam — gyro mouse, trackpad modes, action layers, dual-stage triggers, full controller support in any context. Written in Rust, runs on Linux and Windows.",
      meta: {
        status: "Status · pre-hardware",
        workspace: "Rust workspace · 6 crates",
        platforms: "Linux · Windows",
      },
      wipBadge: "In development",
      wipTitle: "Not ready for use yet",
      wipBody:
        "The plumbing — discovery, virtual devices, remap engine, config parsing, packet dumper — is complete and tested. But the Steam Controller 2 hasn't shipped: every decoder constant is marked TODO(RE) and decode() currently returns no events. The driver becomes functional the day I get hardware to point the dump tool at.",
      goalTitle: "The goal",
      goalP1:
        "Steam Input is good but tightly coupled to the Steam client. inputmuxd exists to run the controller without launching Steam, work in non-game contexts (window managers, DAWs, image editors, BIOS-adjacent tools), and stay inspectable — Steam Input is closed source.",
      goalP2:
        "The driver lives in userspace as a daemon. One blocking worker per controller decodes HID reports at 250 Hz, runs them through a configurable remap engine, and emits to virtual mouse / keyboard / gamepad devices via uinput (Linux) or ViGEm (Windows). It can run alongside Steam Input — they share the device with HID contention, not driver contention.",
      scopeTitle: "What's in scope",
      scopeLede:
        "Feature targets for v1. ✅ means the decoder and event plumbing are implemented but unverified against real hardware — the structure is complete, only the byte map is pending.",
      scopeItems: [
        { label: "Full digital button decoding", status: "✅  R3 deferred" },
        { label: "Analog triggers", status: "✅" },
        { label: "Trackpad X/Y/pressure/touch", status: "✅" },
        { label: "Gyro + accelerometer", status: "✅  calibrated" },
        { label: "Trackpad clicks", status: "Deferred" },
        { label: "Stick X/Y", status: "Deferred · firmware HID" },
        { label: "Grip sense", status: "Pending capture" },
        { label: "Haptic output", status: "Pending RE" },
        { label: "Battery / connection", status: "Pending RE" },
        { label: "Puck dongle", status: "Detected, not driven" },
      ],
      missingTitle: "What's missing",
      missingLede: "Hardware-blocked or out of scope by design.",
      missingItems: [
        "Confirmed SC2 byte map — every protocol constant stays TODO(RE) until I can capture real packets",
        "Haptic encoder — the path back to the controller is plumbed, the encoding itself is reverse-engineering homework",
        "GUI configuration tool — TOML by hand for now",
        "Kernel module — userspace driver only, deliberately",
        "macOS support — not a target",
        "Steam VDF binding import/export — write your own config",
        "Firmware updates — out of scope",
      ],
      archTitle: "Architecture",
      archLede:
        "Six small crates. The split is deliberate: core is pure data, I/O is isolated, the remap engine never talks to the OS, and the binaries are thin glue.",
      archItems: [
        {
          name: "inputmuxd-core",
          desc: "Protocol decode, input model, config schema · no OS deps",
        },
        {
          name: "inputmuxd-hid",
          desc: "Device discovery and packet I/O via hidapi",
        },
        {
          name: "inputmuxd-output",
          desc: "Virtual mouse / keyboard / gamepad via uinput or ViGEm",
        },
        {
          name: "inputmuxd-remap",
          desc: "Trackpad modes, gyro, triggers, action layers, bindings",
        },
        {
          name: "inputmuxd-daemon",
          desc: "The inputmuxd binary · one async worker per controller",
        },
        {
          name: "inputmuxd-dump",
          desc: "Packet capture / debug tool for reverse engineering",
        },
      ],
      stackTitle: "Stack",
      stack: [
        "Rust",
        "Tokio",
        "hidapi",
        "evdev / uinput",
        "ViGEm",
        "serde + TOML",
      ],
      ctaTitle: "Want to track progress?",
      ctaBody:
        "inputmuxd ships when the hardware lands. Reach out if you want a heads-up when it leaves WIP, or if you have a Steam Controller 2 dev kit and want to help with protocol capture.",
      ctaContact: "Get in touch",
    },
    footer: {
      copy: "© {year} Alexis Bonnard — Built with care in Nice, FR.",
      tag: "No trackers · No cookies · Just code",
    },
  },

  fr: {
    nav: {
      about: "à propos",
      experience: "expérience",
      work: "projets",
      services: "services",
      contact: "contact",
      docs: "docs",
      letsTalk: "discutons",
    },
    hero: {
      available: "Disponible pour travailler · T1 2026",
      location: "Nice, France",
      version: "v0.25.11",
      verbs: ["construisant", "livrant", "faisant évoluer", "façonnant"],
      verbSuffix: " des solutions.",
      ctaPrimary: "Projets sélectionnés",
      ctaGhost: "Démarrer un projet",
      codeComment: "// 2026 — actuellement",
      codeRole: "dev fullstack",
      codeFocus: "ia + infra",
      stats: {
        shipped: "Projets livrés",
        years: "Années à construire",
        clients: "Clients satisfaits",
        tech: "Techs & langages",
      },
      scroll: "défiler",
    },
    about: {
      label: "À propos",
      tagline: "/bio",
      city: "Nice · FR",
      p1: "Je suis développeur fullstack, entre IA, ingénierie produit et infrastructure. J'aime toute la stack — du plan d'exécution d'une requête SQL aux deux derniers pixels d'un état hover.",
      p2: "Après deux ans, j'ai livré des produits AI-native, des backends Rust qui poussent des tokens LLM sous forte concurrence, et du travail client soigné qui convertit vraiment. J'ai de l'attention pour l'artisanat, la clarté, et les choses qui sonnent juste.",
      p3: "En ce moment je suis en freelance depuis le sud de la France, avec des fondateurs et des équipes qui ont besoin de quelqu'un capable de porter une fonctionnalité de bout en bout — des choix d'architecture aux détails d'UI que l'utilisateur ne remarquera pas consciemment.",
      facts: {
        basedInLabel: "Basé à",
        basedInValue: "Nice, France (CET)",
        languagesLabel: "Langues",
        languagesValue: "FR (natif) · EN (courant)",
        workingAsLabel: "Statut",
        workingAsValue: "Freelance / Contrat",
        openToLabel: "Ouvert à",
        openToValue: "Stages IA · hors de France",
      },
      skills: {
        heading: "Boîte à outils",
        sub: "ce que je sors du tiroir",
        frontend: "Frontend",
        backend: "Backend",
        aiData: "IA & Data",
        infra: "Infra & DX",
      },
    },
    curriculum: {
      label: "Curriculum",
      tagline: "/études",
      sectionTitle: {
        before: "Où j'ai appris à ",
        em: "penser",
        after: " comme un ingénieur.",
      },
      lede: "Mon parcours académique — du Baccalauréat français au cursus par projets de 42Nice.",
      journeyTitle: "Parcours académique",
      journeyDesc:
        "Un engagement envers l'apprentissage continu et l'excellence en développement logiciel et intelligence artificielle.",
      items: {
        school42Label: "42Nice",
        school42Value:
          "Apprentissage innovant en peer-to-peer en développement logiciel",
        previousLabel: "Formation antérieure",
        previousValue:
          "Construction de bases solides en technologie et résolution de problèmes",
        baccalaureatLabel: "Baccalauréat français",
        baccalaureatValue: "Spécialités : Mathématiques, Physique, Biologie",
      },
      transcriptTitle: "Relevé officiel",
      transcriptFilename: "Transcript_Bonnard",
      transcriptDate: "05-04-2026.pdf",
      viewAction: "Voir le relevé",
      downloadAction: "Télécharger PDF",
      lastUpdated: "Dernière mise à jour : 5 avril 2026",
    },
    skills: {
      label: "Skills",
      tagline: "/boîte à outils",
      sectionTitle: {
        before: "La stack sur laquelle je ",
        em: "m'engage",
        after: ".",
      },
      lede: "La tech que j'attrape en premier — et les skills humains qui font atterrir la tech.",
      technicalGroup: "Technique",
      technicalSub: "langages, frameworks, bases de données",
      softGroup: "Soft skills",
      softSub: "le côté humain de l'expédition",
      toolsGroup: "Outils & Plateformes",
      toolsSub: "ce que j'utilise au quotidien",
      favoriteHint: "favori",
      soft: {
        fastLearner: "Apprentissage rapide",
        creativity: "Créativité",
        problemSolving: "Résolution de problèmes",
        communication: "Communication",
        optimization: "Optimisation",
        adaptability: "Adaptabilité",
        teamwork: "Travail en équipe",
      },
    },
    experience: {
      label: "Expérience",
      tagline: "/cv",
      sectionTitle: {
        before: "De l'école aux ",
        em: "livraisons",
        after: " — en parallèle.",
      },
      lede: "Trois rails en même temps : 42Nice pour les fondamentaux, les projets personnels pour l'exploration, et le freelance pour les vrais enjeux.",
      at: "chez",
      items: {
        freelance: {
          period: "Décembre 2025 — auj.",
          role: "Développeur Fullstack Freelance",
          company: "BloomSkills · GaIa",
          desc: "Missions freelance en parallèle des études, centrées sur les intégrations IA et les solutions brevetées. Sur BloomSkills, plateforme d'évaluation des soft skills propulsée par IA — livraison fullstack, du pipeline d'ingestion aux dashboards opérateurs. Sur GaIa, assistant RAG pour la documentation industrielle — orchestration de prompts, recherche vectorielle, harnais d'évaluation.",
        },
        personal: {
          period: "2024 — auj.",
          role: "Projets personnels",
          company: "Open-source & expérimentations",
          desc: "Outils et expérimentations construits en marge — d'une passerelle LLM en Rust (SwiftLLM) qui unifie OpenAI, Anthropic, Gemini, Mistral & Ollama derrière une seule API, à un studio de rendu 3D dans le navigateur (Raybox). C'est là que la plupart de mon apprentissage se passe vraiment.",
        },
        school42: {
          period: "Juillet 2024 — auj.",
          role: "Étudiant",
          company: "42Nice",
          desc: "Apprentissage innovant en peer-to-peer en développement logiciel. Renforcement de mes bases en C, C++, algorithmique et programmation système via un cursus par projets — sans cours, sans profs, juste du code et de la relecture entre pairs.",
        },
      },
    },
    projects: {
      label: "Projets sélectionnés",
      tagline: "2024—2026",
      sectionTitle: {
        before: "Des produits qui ",
        em: "sortent",
        after: ", pas des slides qui impressionnent.",
      },
      lede: "Une poignée de projets récents, professionnels et personnels. Chacun m'a appris quelque chose de différent.",
      tags: {
        professionalFeatured: "Professionnel · À la une",
        personal: "Personnel",
        professional: "Professionnel",
        personalWip: "Personnel · En cours",
        studio: "Studio · Divers",
      },
      bloom: {
        titleBefore: "BloomSkills",
        titleEm: "— évaluations IA",
        desc: "Plateforme d'évaluation des compétences propulsée par IA. Les candidats passent des tests adaptatifs ; le moteur évalue les réponses libres via des chaînes LLM et génère des rapports de compétences détaillés. J'ai piloté le développement fullstack.",
      },
      swiftllm: {
        title: "SwiftLLM",
        desc: "Passerelle Rust à haut débit pour l'inférence LLM. Rate limiting, streaming, cache, et routage multi-providers.",
      },
      gaia: {
        title: "GaIa",
        desc: "Assistant RAG pour la documentation industrielle. Recherche vectorielle, orchestration de prompts, harnais d'évaluation.",
      },
      raybox: {
        title: "Raybox",
        desc: "Terrain de jeu expérimental de shaders pour portfolio 3D. Three.js, GLSL sur mesure, post-processing en temps réel.",
      },
      inputmuxd: {
        title: "inputmuxd",
        desc: "Driver userspace cross-platform pour la Valve Steam Controller (2026). Souris gyroscopique, modes du trackpad, couches d'actions, gâchettes deux étages — répliqués hors de Steam, pour faire fonctionner la manette dans n'importe quel launcher, émulateur, ou sur le bureau. Pré-matériel : rétro-ingénierie du protocole en cours.",
      },
      studio: {
        title: "Travail client",
        desc: "Audits de cybersecurité, outils internes, sites marketing. Délais serrés, vrais utilisateurs, vrais résultats.",
      },
    },
    services: {
      title: "Services",
      subtitle: "Ce que je peux faire pour vous",
      sectionLabel: "/ce que je propose",
      webDev: {
        title: "Développement Web",
        desc: "Applications web de qualité production, construites de zéro ou sur une base existante. React, Next.js, Vue, TypeScript, Node.js — toute la stack, avec une attention obsessionnelle à la performance, l'accessibilité, et les détails que les utilisateurs ressentent sans savoir les nommer.",
      },
      mobile: {
        title: "Intégration IA",
        desc: "De vraies fonctionnalités LLM — pas des démos. Pipelines RAG, orchestration d'agents, fine-tuning, propreté des prompts, maîtrise des coûts, et les harnais d'évaluation qui rendent l'IA fiable en production. APIs pré-entraînées ou modèles sur mesure.",
      },
      cloud: {
        title: "Cloud",
        desc: "Infrastructure cloud qui passe à l'échelle horizontalement et coûte raisonnablement. AWS, Vercel, Railway, GCP. Serverless ou conteneurs, mono ou multi-région — dimensionnée à votre trafic réel et votre budget, pas à l'architecture de référence de quelqu'un d'autre.",
      },
      devops: {
        title: "DevOps",
        desc: "CI/CD qui attrape les vraies régressions, IaC relisible, observabilité qui alerte la bonne personne. GitHub Actions, Docker, Terraform, Prometheus — la colle qui permet aux petites équipes d'expédier comme les grandes, sans s'épuiser.",
      },
      database: {
        title: "Base de Données",
        desc: "Conception de schéma, optimisation de requêtes, et migrations sur lesquelles vous pouvez dormir tranquille. PostgreSQL par défaut, Redis pour le cache, pgvector/Pinecone pour la recherche vectorielle. GraphQL ou REST — celui qui convient vraiment au produit.",
      },
      softwareDev: {
        title: "Développement Logiciel",
        desc: "Outils sur mesure, plateformes internes, CLIs, applications desktop, automatisations. Quand rien d'existant ne colle, je construis l'outil exact dont votre équipe a besoin — bien typé, bien testé, et facile à reprendre en main le moment venu.",
      },
    },
    contact: {
      label: "Contact",
      tagline: "/discutons",
      headline: { before: "Un ", em: "brief", after: " ?\nOn l'expédie." },
      socials: {
        github: "01 — GitHub",
        linkedin: "02 — LinkedIn",
        resumeAI: "03 — CV (IA)",
        resumeAIMeta: "pdf · ingénieur ia",
        resumeCyber: "04 — CV (Cyber)",
        resumeCyberMeta: "pdf · cybersécurité",
      },
      card: {
        available: "● Actuellement disponible",
        title: "Réservations T1 2026",
        desc: "Réponse typique sous 24h. Je prends 1–2 missions à la fois pour garder une vraie concentration. Compatible avec les fuseaux horaires européens.",
        localTime: "Heure locale",
        response: "Réponse",
        responseValue: "< 24h",
        minEngagement: "Mission minimum",
        minEngagementValue: "2 semaines",
        rate: "Tarif",
        rateValue: "Sur demande",
      },
    },
    docs: {
      label: "Documentation",
      tagline: "/projets",
      sectionTitle: {
        before: "Plongées dans ",
        em: "ce que je construis",
        after: ".",
      },
      lede: "Documentation technique pour certains projets personnels — notes de build, architecture et la réflexion derrière les arbitrages.",
      viewDocs: "Voir la doc",
      comingSoon: "Bientôt",
      moreSoon: "// plus de projets bientôt...",
      types: {
        personal: "Personnel",
        professional: "Professionnel",
      },
      projects: {
        swiftllm:
          "Une passerelle LLM universelle ultra-rapide en Rust, unifiant OpenAI, Anthropic, Gemini, Mistral & Ollama derrière une seule API.",
        raybox:
          "Un studio de rendu 3D dans le navigateur — importez vos modèles, appliquez des matériaux, configurez l'éclairage et rendez. Sans installation, sans complexité.",
        inputmuxd:
          "Driver userspace cross-platform pour la Valve Steam Controller (2026). Steam Input répliqué hors de Steam — souris gyroscopique, modes du trackpad, couches d'actions, gâchettes deux étages.",
      },
    },
    swiftllm: {
      back: "Retour à la doc",
      eyebrow: "Projet · Documentation",
      title: "SwiftLLM Docs",
      description:
        "Une passerelle LLM universelle ultra-rapide en Rust. Unifie OpenAI, Anthropic, Gemini, Mistral, Ollama, Groq, Together AI & AWS Bedrock derrière une seule API.",
      freeBadge: "100% Libre & Open Source",
      mitBadge: "Licence MIT",
      githubLink: "GitHub",
      sidebarHeading: "Navigation",
      copy: "Copier",
      copied: "Copié",
    },
    notfound: {
      badge: "404",
      title: "Vous vous êtes perdu dans le web..",
      message:
        "La page que vous cherchez a dérivé dans le vide. On vous remet sur les rails.",
      action: "Revenir en lieu sûr",
    },
    raybox: {
      back: "Retour à la doc",
      eyebrow: "Projet · Documentation",
      title: "Raybox",
      subtitle: {
        before: "Un studio de ",
        em: "rendu 3D",
        after: " dans le navigateur.",
      },
      description:
        "Importez vos modèles, appliquez des matériaux, configurez l'éclairage et rendez — le tout dans le navigateur. Sans installation, sans complexité. Three.js sous le capot, shaders GLSL sur mesure, post-processing en temps réel.",
      upcomingBadge: "À venir",
      upcomingTitle: "Documentation bientôt disponible",
      upcomingBody:
        "Raybox est encore en développement actif. La documentation complète — l'architecture, le pipeline de shaders, les décisions UX — arrivera quand le projet sortira du WIP. Suivez l'avancée, ou contactez-moi si vous voulez un accès anticipé.",
      ctaContact: "Me contacter",
      stackTitle: "Stack",
      stack: ["Next.js", "React", "Three.js", "TypeScript", "GLSL", "WebGL 2"],
    },
    inputmuxd: {
      back: "Retour à la doc",
      eyebrow: "Projet · Documentation",
      title: "inputmuxd",
      subtitle: {
        before: "Un driver ",
        em: "userspace",
        after: " cross-platform pour la Steam Controller.",
      },
      description:
        "Steam Input répliqué hors de Steam — souris gyroscopique, modes du trackpad, couches d'actions, gâchettes deux étages, support complet de la manette dans n'importe quel contexte. Écrit en Rust, tourne sous Linux et Windows.",
      meta: {
        status: "Statut · pré-matériel",
        workspace: "Workspace Rust · 6 crates",
        platforms: "Linux · Windows",
      },
      wipBadge: "En développement",
      wipTitle: "Pas encore prêt à l'usage",
      wipBody:
        "La plomberie — découverte, périphériques virtuels, moteur de remap, parsing de config, capture de paquets — est complète et testée. Mais la Steam Controller 2 n'est pas encore sortie : chaque constante du décodeur est marquée TODO(RE) et decode() ne renvoie aucun événement pour l'instant. Le driver deviendra fonctionnel le jour où j'aurai du matériel à pointer avec l'outil de dump.",
      goalTitle: "L'objectif",
      goalP1:
        "Steam Input fonctionne bien, mais reste étroitement couplé au client Steam. inputmuxd existe pour faire tourner la manette sans lancer Steam, fonctionner hors-jeu (gestionnaires de fenêtres, DAW, éditeurs d'image, outils proches du BIOS), et rester inspectable — Steam Input est closed source.",
      goalP2:
        "Le driver vit en userspace, sous forme de daemon. Un worker bloquant par manette décode les rapports HID à 250 Hz, les passe dans un moteur de remap configurable, et émet vers des périphériques virtuels souris / clavier / manette via uinput (Linux) ou ViGEm (Windows). Il peut tourner en parallèle de Steam Input — ils partagent le périphérique avec contention HID, pas contention driver.",
      scopeTitle: "Ce qui est dans le scope",
      scopeLede:
        "Cibles de fonctionnalités pour la v1. ✅ signifie que le décodeur et la plomberie événementielle sont implémentés mais non vérifiés contre du vrai matériel — la structure est complète, seule la byte map reste à confirmer.",
      scopeItems: [
        { label: "Décodage complet des boutons numériques", status: "✅  R3 reporté" },
        { label: "Gâchettes analogiques",                   status: "✅" },
        { label: "Trackpad X/Y/pression/contact",           status: "✅" },
        { label: "Gyro + accéléromètre",                    status: "✅  calibré" },
        { label: "Clics du trackpad",                       status: "Reporté" },
        { label: "Stick X/Y",                               status: "Reporté · HID firmware" },
        { label: "Détection de prise",                      status: "Capture à faire" },
        { label: "Sortie haptique",                         status: "RE en attente" },
        { label: "Batterie / connexion",                    status: "RE en attente" },
        { label: "Dongle puck",                             status: "Détecté, non piloté" },
      ],
      missingTitle: "Ce qui manque",
      missingLede: "Bloqué par le matériel, ou hors-scope par choix.",
      missingItems: [
        "Byte map SC2 confirmée — chaque constante du protocole reste TODO(RE) tant que je ne peux pas capturer de vrais paquets",
        "Encodeur haptique — le chemin de retour vers la manette est plombé, l'encodage lui-même est du devoir de rétro-ingénierie",
        "Outil de configuration graphique — TOML à la main pour l'instant",
        "Module noyau — driver userspace uniquement, volontairement",
        "Support macOS — pas une cible",
        "Import/export de bindings Steam VDF — écrivez votre config",
        "Mises à jour de firmware — hors-scope",
      ],
      archTitle: "Architecture",
      archLede:
        "Six petits crates. Le découpage est volontaire : core est de la donnée pure, les I/O sont isolées, le moteur de remap ne parle jamais à l'OS, et les binaires sont juste de la colle fine.",
      archItems: [
        { name: "inputmuxd-core",   desc: "Décodage du protocole, modèle d'entrées, schéma de config · zéro dépendance OS" },
        { name: "inputmuxd-hid",    desc: "Découverte de périphériques et I/O paquets via hidapi" },
        { name: "inputmuxd-output", desc: "Souris / clavier / manette virtuels via uinput ou ViGEm" },
        { name: "inputmuxd-remap",  desc: "Modes du trackpad, gyro, gâchettes, couches d'actions, bindings" },
        { name: "inputmuxd-daemon", desc: "Le binaire inputmuxd · un worker async par manette" },
        { name: "inputmuxd-dump",   desc: "Outil de capture / debug pour la rétro-ingénierie" },
      ],
      stackTitle: "Stack",
      stack: ["Rust", "Tokio", "hidapi", "evdev / uinput", "ViGEm", "serde + TOML"],
      ctaTitle: "Envie de suivre l'avancée ?",
      ctaBody:
        "inputmuxd sort quand le matériel arrive. Contactez-moi si vous voulez être prévenu quand le projet sort du WIP, ou si vous avez un dev kit Steam Controller 2 et voulez aider à la capture de protocole.",
      ctaContact: "Me contacter",
    },
    footer: {
      copy: "© {year} Alexis Bonnard — Conçu avec soin à Nice, FR.",
      tag: "Aucun tracker · Aucun cookie · Juste du code",
    },
  },
};

const listeners = new Set();
let currentLang = "en";
try {
  const stored = localStorage.getItem("lang");
  if (stored && DICT[stored]) currentLang = stored;
} catch (_) {}

function t(key, lang) {
  const l = lang || currentLang;
  const parts = key.split(".");
  let v = DICT[l] || DICT.en;
  for (const p of parts) {
    if (v && typeof v === "object" && p in v) v = v[p];
    else return key;
  }
  return v;
}

function setLang(lang) {
  if (!DICT[lang] || lang === currentLang) return;
  currentLang = lang;
  try {
    localStorage.setItem("lang", lang);
  } catch (_) {}
  document.documentElement.setAttribute("data-lang", lang);
  listeners.forEach((fn) => fn(lang));
}

function useLang() {
  const [lang, set] = React.useState(currentLang);
  React.useEffect(() => {
    const fn = (l) => set(l);
    listeners.add(fn);
    return () => listeners.delete(fn);
  }, []);
  return [lang, setLang];
}

document.documentElement.setAttribute("data-lang", currentLang);

window.I18N_DICT = DICT;
window.t = t;
window.setLang = setLang;
window.useLang = useLang;
