/* global React */
const { useState: useLavState, useEffect: useLavEffect, useRef: useLavRef } = React;

/* -----------------------------------------------------------------------------
   page-lavora.jsx — Lavora con noi (Tecnolife site-2026)
   -----------------------------------------------------------------------------
   Componenti:
   - LavoraHero      hero gradient + headline
   - LavoraValues    4 valori "Perché Tecnolife"
   - LavoraRoles     griglia posizioni aperte (anchor → #candidati)
   - LavoraForm      form candidatura — FCE end-to-end (no mailto)
   - LavoraPrivacy   informativa GDPR completa con TOC sticky

   FORM FLOW (v0.9.0 — backend FCE multipart-aware):
   1) Validazione client-side completa (campi + CV file PDF/DOC/DOCX max 5MB)
   2) Upload del CV via POST multipart /api/forms/upload-attachment
      → riceviamo { signedUrl, path, filename, sizeKb, contentType, expiresAt }
   3) Submit JSON dei metadati al backend FCE (Turnstile + honeypot inclusi)
      includendo _attachments: [{ url: signedUrl, filename, contentType, sizeKb }]
      → il server ri-firma l'URL con TTL breve e lo passa a Resend
        come attachments[].path. Resend scarica e include il file nell'email
        verso i recipients configurati in form_configs.recipients di Supabase
        (al 2026-05-11: {job@tecnolife.com, p.liuzzi@tecnolife.com}, vedi
        docs/fce-recipient-update-cv-2026-05-11.sql).
   4) Schermata di success "puro": niente mailto, candidato chiude la pagina.

   Storia:
   - v0.4.0 introdusse il form con CV ma il backend FCE non aveva supporto
     multipart, quindi si usava un mailto handoff post-success.
   - v0.9.0 (questa) sostituisce il flusso con upload diretto. Richiede
     che il backend gamma_extensions abbia rilasciato il supporto attachments
     (commit "feat(forms): supporto attachments end-to-end via Resend") e che
     la migration 003_form_attachments.sql sia stata eseguita su Supabase.
   - v0.12.5 — 2026-05-11. Aggiornato il commento per riflettere i nuovi
     recipients dopo la UPDATE Supabase, e il nuovo display name del
     mittente Resend "Horis <noreply@updates.horis.cloud>" (rebranding
     globale lato backend FCE, repo NBN-WEST/gamma_extensions). Stesso
     commit backend ha sistemato l'interpolazione del subject template
     (precedentemente sostituiva solo {{site_name}}, {{form_name}}; ora
     interpola anche {{ruolo}}, {{nome}}, {{cognome}} ecc.).

   v0.9.0 — 2026-05-07 · v0.12.5 — 2026-05-11
   ----------------------------------------------------------------------------- */

window.LavoraHero = function LavoraHero({ lang }) {
  const t = lang === "it" ? {
    eyebrow: "Lavora con noi",
    h1a: "Costruiamo insieme",
    h1b: "il futuro digitale delle aziende italiane.",
    lead: "Cerchiamo persone curiose, rigorose e appassionate di tecnologia. In Tecnolife troverai progetti enterprise, formazione continua e un team che mette al centro la qualità del lavoro.",
  } : {
    eyebrow: "Careers",
    h1a: "Let's build",
    h1b: "the digital future of Italian companies.",
    lead: "We look for curious, rigorous people who are passionate about technology. At Tecnolife you'll find enterprise projects, continuous learning and a team that puts the quality of the work first.",
  };
  return (
    <div style={{ position: "relative", overflow: "hidden", color: "#fff", paddingTop: 160, paddingBottom: 110 }}>
      <div style={{ position: "absolute", inset: 0, background: "var(--tl-gradient-mesh)", zIndex: 0 }} />
      <window.Container style={{ position: "relative", zIndex: 2, maxWidth: 880 }}>
        <window.Eyebrow light>{t.eyebrow}</window.Eyebrow>
        <h1 style={{ fontSize: "clamp(40px, 6vw, 76px)", fontWeight: 800, lineHeight: 1.04, letterSpacing: "-0.03em", margin: 0 }}>
          <span style={{ display: "block", color: "#fff" }}>{t.h1a}</span>
          <span style={{ display: "block", background: "linear-gradient(135deg,#7EE3FF 0%,#28D1FE 40%,#1E8BFF 100%)", WebkitBackgroundClip: "text", backgroundClip: "text", color: "transparent", paddingBottom: "0.12em" }}>{t.h1b}</span>
        </h1>
        <p style={{ fontSize: "clamp(16px, 1.4vw, 20px)", lineHeight: 1.55, color: "rgba(255,255,255,0.78)", maxWidth: 640, marginTop: 28 }}>{t.lead}</p>
      </window.Container>
    </div>
  );
};

window.LavoraValues = function LavoraValues({ lang }) {
  const items = lang === "it" ? [
    { icon: "rocket", t: "Progetti enterprise", d: "Lavoriamo con aziende italiane e internazionali su piattaforme Adobe Commerce, Microsoft Dynamics 365, Microsoft Power Platform, Liferay e soluzioni custom." },
    { icon: "spark", t: "Formazione continua", d: "Certificazioni ufficiali, percorsi tecnici interni e tempo dedicato all'aggiornamento — l'AI evolve, e noi con lei." },
    { icon: "users", t: "Team multidisciplinare", d: "UX/UI Designer, Solution Architect, sviluppatori certificati: tutti contribuiscono fin dal primo giorno alla soluzione." },
    { icon: "shield-check", t: "Equilibrio e qualità", d: "Smart working ibrido, processi snelli e attenzione concreta al benessere delle persone. Niente cultura del lavoro infinito." },
  ] : [
    { icon: "rocket", t: "Enterprise projects", d: "We work with Italian and international clients on Adobe Commerce, Microsoft Dynamics 365, Microsoft Power Platform, Liferay and custom solutions." },
    { icon: "spark", t: "Continuous learning", d: "Official certifications, internal tech tracks and time dedicated to learning — AI moves fast, and so do we." },
    { icon: "users", t: "Cross-functional team", d: "UX/UI designers, Solution Architects, certified developers — everyone contributes to the solution from day one." },
    { icon: "shield-check", t: "Balance and quality", d: "Hybrid smart working, lean processes and real care for people. No always-on culture." },
  ];
  return (
    <window.Section style={{ background: "var(--bg)" }}>
      <window.Container>
        <div style={{ maxWidth: 720, marginBottom: 44 }}>
          <window.Eyebrow>{lang === "it" ? "Perché Tecnolife" : "Why Tecnolife"}</window.Eyebrow>
          <h2 style={{ fontSize: "clamp(28px,3.5vw,44px)", fontWeight: 700, letterSpacing: "-0.02em", lineHeight: 1.15, margin: 0 }}>
            {lang === "it" ? "Un ambiente progettato per crescere." : "An environment designed to help you grow."}
          </h2>
          <p style={{ fontSize: 17, color: "var(--fg-2)", marginTop: 16, maxWidth: 640 }}>
            {lang === "it"
              ? "Quattro cose che ci stanno a cuore e che ritroverai in ogni progetto."
              : "Four things we care about, that you'll find in every project."}
          </p>
        </div>
        <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(240px, 1fr))", gap: 16 }}>
          {items.map((v) => (
            <div key={v.t} style={{ background: "#fff", border: "1px solid var(--border)", borderRadius: 16, padding: 24, boxShadow: "var(--shadow-sm)" }}>
              <div style={{ width: 44, height: 44, borderRadius: 11, background: "linear-gradient(135deg,#0228A3,#1E8BFF)", color: "#fff", display: "inline-flex", alignItems: "center", justifyContent: "center", marginBottom: 18 }}>
                <window.Icon name={v.icon} size={20} />
              </div>
              <div style={{ fontSize: 17, fontWeight: 700, color: "var(--fg-1)", marginBottom: 8, letterSpacing: "-0.005em" }}>{v.t}</div>
              <div style={{ fontSize: 14, color: "var(--fg-2)", lineHeight: 1.55 }}>{v.d}</div>
            </div>
          ))}
        </div>
      </window.Container>
    </window.Section>
  );
};

window.LavoraRoles = function LavoraRoles({ lang }) {
  const roles = lang === "it" ? [
    { tag: "AI / ML", t: "AI / Machine Learning Engineer", l: "Roma · Ibrido", d: "Progettazione e training di modelli ML, fine-tuning di LLM, integrazione di soluzioni AI nei processi di business dei clienti." },
    { tag: "Sviluppo", t: "Full-Stack Developer (Java / PHP)", l: "Roma · Ibrido", d: "Sviluppo end-to-end di applicazioni enterprise: API, microservizi e interfacce moderne con framework Java, PHP e JavaScript." },
    { tag: "Sviluppo", t: "Sviluppatore Adobe Commerce / Magento", l: "Roma · Ibrido", d: "Progettazione e sviluppo back-end di e-Commerce B2B/B2C su piattaforma Magento 2." },
    { tag: "Dati", t: "Data Engineer", l: "Roma · Ibrido", d: "Costruzione di pipeline ETL/ELT, modellazione dati e data platform a supporto dei progetti di AI e analytics." },
    { tag: "Cloud", t: "DevOps / Cloud Engineer", l: "Roma · Ibrido", d: "CI/CD, Infrastructure as Code, gestione di ambienti Azure e AWS, observability e sicurezza per applicazioni in produzione." },
    { tag: "Design", t: "UX/UI Designer", l: "Roma · Ibrido", d: "Progettazione di interfacce per e-Commerce, portali e applicazioni enterprise basate su AI." },
    { tag: "Architettura", t: "Solution Architect", l: "Roma · Ibrido", d: "Definizione dell'architettura tecnica end-to-end e interfaccia con tutti gli stakeholder di progetto." },
    { tag: "Spontanea", t: "Candidatura spontanea", l: "Tutte le sedi", d: "Non hai trovato il ruolo giusto? Inviaci comunque il tuo CV: i talenti ci interessano sempre." },
  ] : [
    { tag: "AI / ML", t: "AI / Machine Learning Engineer", l: "Rome · Hybrid", d: "Design and training of ML models, fine-tuning of LLMs, integration of AI into clients' business processes." },
    { tag: "Engineering", t: "Full-Stack Developer (Java / PHP)", l: "Rome · Hybrid", d: "End-to-end development of enterprise applications: APIs, microservices and modern interfaces with Java, PHP and JavaScript frameworks." },
    { tag: "Engineering", t: "Adobe Commerce / Magento Developer", l: "Rome · Hybrid", d: "Design and back-end development of B2B/B2C e-Commerce on Magento 2." },
    { tag: "Data", t: "Data Engineer", l: "Rome · Hybrid", d: "ETL/ELT pipelines, data modelling and data platforms supporting AI and analytics projects." },
    { tag: "Cloud", t: "DevOps / Cloud Engineer", l: "Rome · Hybrid", d: "CI/CD, Infrastructure as Code, management of Azure and AWS environments, observability and security for production applications." },
    { tag: "Design", t: "UX/UI Designer", l: "Rome · Hybrid", d: "Interface design for e-Commerce, portals and AI-driven enterprise applications." },
    { tag: "Architecture", t: "Solution Architect", l: "Rome · Hybrid", d: "Define the end-to-end technical architecture and act as interface with all stakeholders." },
    { tag: "Open", t: "Spontaneous application", l: "All offices", d: "Didn't find the right role? Send your CV anyway — we're always interested in talent." },
  ];
  return (
    <window.Section style={{ background: "var(--bg-subtle)" }}>
      <window.Container>
        <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 40, alignItems: "end", marginBottom: 36 }} className="lav-head">
          <div>
            <window.Eyebrow>{lang === "it" ? "Posizioni aperte" : "Open positions"}</window.Eyebrow>
            <h2 style={{ fontSize: "clamp(28px,3.5vw,44px)", fontWeight: 700, letterSpacing: "-0.02em", lineHeight: 1.1, margin: 0 }}>
              {lang === "it" ? "Posizioni che stiamo cercando." : "Roles we're hiring for."}
            </h2>
          </div>
          <p style={{ fontSize: 16, color: "var(--fg-2)", lineHeight: 1.6, margin: 0 }}>
            {lang === "it"
              ? "Compila il form qui sotto indicando il ruolo per cui ti candidi. Rispondiamo a tutte le candidature entro 10 giorni lavorativi."
              : "Fill in the form below specifying the role you are applying for. We respond to all applications within 10 business days."}
          </p>
        </div>
        <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(300px, 1fr))", gap: 14 }}>
          {roles.map((r) => (
            <a key={r.t} href="#candidati" style={{
              display: "block", background: "#fff", border: "1px solid var(--border)", borderRadius: 16,
              padding: 22, textDecoration: "none", color: "inherit", transition: "all 220ms cubic-bezier(.22,1,.36,1)",
              boxShadow: "var(--shadow-xs)",
            }}
            onMouseEnter={(e) => { e.currentTarget.style.transform = "translateY(-2px)"; e.currentTarget.style.boxShadow = "var(--shadow-md)"; e.currentTarget.style.borderColor = "var(--tl-blue-primary)"; }}
            onMouseLeave={(e) => { e.currentTarget.style.transform = "translateY(0)"; e.currentTarget.style.boxShadow = "var(--shadow-xs)"; e.currentTarget.style.borderColor = "var(--border)"; }}>
              <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 10 }}>
                <window.Tag color={r.tag === "Spontanea" || r.tag === "Open" ? "cyan" : "blue"}>{r.tag}</window.Tag>
                <window.Icon name="arrow-up-right" size={16} color="var(--tl-blue-primary)" />
              </div>
              <div style={{ fontSize: 17, fontWeight: 700, color: "var(--fg-1)", letterSpacing: "-0.01em", marginBottom: 6 }}>{r.t}</div>
              <div style={{ fontSize: 12, fontFamily: "var(--font-mono)", color: "var(--tl-blue-primary)", letterSpacing: ".05em", marginBottom: 10, textTransform: "uppercase" }}>{r.l}</div>
              <div style={{ fontSize: 13.5, color: "var(--fg-2)", lineHeight: 1.55 }}>{r.d}</div>
            </a>
          ))}
        </div>
        <style>{`
          @media (max-width: 880px) { .lav-head { grid-template-columns: 1fr !important; gap: 16px !important; } }
        `}</style>
      </window.Container>
    </window.Section>
  );
};

/* -----------------------------------------------------------------------------
   LavoraForm — candidatura HR con FCE end-to-end (upload CV + submit unificato)
   -----------------------------------------------------------------------------
   - Stato controllato (immutable spread).
   - CV: validazione client-side (estensione + MIME + size ≤5MB) prima del submit;
     poi upload reale via /api/forms/upload-attachment, signed URL passato come
     _attachments[] al successivo /api/forms/submit. Niente mailto.
   - Honeypot anti-bot (`_hp` invisibile) + Cloudflare Turnstile sul submit.
   - Field name allineati a form_configs.fields[].name su Supabase
     (vedi docs/fce-supabase-inserts-v0.4.0.sql).
   ----------------------------------------------------------------------------- */
const LAV_INITIAL = Object.freeze({
  nome: "", cognome: "", email: "", telefono: "",
  ruolo: "", seniority: "",
  linkedin: "", portfolio: "",
  messaggio: "",
  consensoSel: false, consensoArchivio: false, consensoArt9: false,
});
const LAV_EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/;
const LAV_URL_RE = /^https?:\/\/[^\s]+$/i;
const LAV_MAX_CV_BYTES = 5 * 1024 * 1024; /* 5 MB */
const LAV_ALLOWED_CV_EXT = [".pdf", ".doc", ".docx"];
const LAV_ALLOWED_CV_MIME = [
  "application/pdf",
  "application/msword",
  "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
];

function lavValidateCv(file, lang) {
  if (!file) return null;
  const name = file.name || "";
  const ext = name.toLowerCase().slice(name.lastIndexOf("."));
  const okExt = LAV_ALLOWED_CV_EXT.indexOf(ext) >= 0;
  /* MIME può essere vuoto su alcuni browser/OS — affidabilità maggiore sull'estensione. */
  const okMime = !file.type || LAV_ALLOWED_CV_MIME.indexOf(file.type) >= 0;
  if (!okExt || !okMime) {
    return lang === "it"
      ? "Formato non valido. Sono accettati solo PDF, DOC o DOCX."
      : "Invalid format. Only PDF, DOC or DOCX are accepted.";
  }
  if (file.size > LAV_MAX_CV_BYTES) {
    return lang === "it"
      ? "Il file supera i 5MB. Riduci la dimensione o invia un PDF compresso."
      : "File exceeds 5MB. Reduce the size or send a compressed PDF.";
  }
  return null;
}

/* Upload del CV via multipart al backend FCE. Ritorna la promise che risolve
   con { signedUrl, path, filename, sizeKb, contentType, expiresAt } oppure
   reject con { code, message }. */
async function lavUploadCv({ apiBase, siteId, formId, file }) {
  const fd = new FormData();
  fd.append("siteId", siteId);
  fd.append("formId", formId);
  fd.append("file", file, file.name);
  let res;
  try {
    res = await fetch(apiBase + "/api/forms/upload-attachment", {
      method: "POST",
      body: fd,
    });
  } catch (e) {
    throw { code: "network", message: e && e.message };
  }
  if (res.ok) {
    const body = await res.json().catch(() => ({}));
    if (body && body.success && body.attachment) return body.attachment;
    throw { code: "generic", message: (body && body.error) || "" };
  }
  if (res.status === 429) throw { code: "ratelimit" };
  if (res.status === 404) throw { code: "form-not-found" };
  if (res.status === 403) throw { code: "turnstile-failed" };
  if (res.status === 400) {
    const body = await res.json().catch(() => ({}));
    throw { code: body && body.code ? body.code : "validation", message: body && body.error };
  }
  throw { code: "generic" };
}

window.LavoraForm = function LavoraForm({ lang }) {
  const [values, setValues] = useLavState(LAV_INITIAL);
  const [honeypot, setHoneypot] = useLavState("");
  const [cvFile, setCvFile] = useLavState(null);
  const [cvError, setCvError] = useLavState("");
  /* status: idle | uploading | submitting | success | error */
  const [status, setStatus] = useLavState("idle");
  const [errorMsg, setErrorMsg] = useLavState("");
  const [fieldErrors, setFieldErrors] = useLavState({});
  const fileRef = useLavRef(null);
  const turnstileTokenRef = useLavRef(null);
  const turnstileWidgetIdRef = useLavRef(null);
  const turnstileContainerRef = useLavRef(null);

  const t = lang === "it" ? {
    eyebrow: "Candidati",
    h2: "Inviaci la tua candidatura.",
    sub: "Compila il form, allega il tuo CV (PDF, DOC o DOCX, max 5MB) e ti ricontatteremo. Tutti i dati sono trattati nel rispetto del GDPR.",
    f1: "Nome", f2: "Cognome", f3: "Email", f4: "Telefono",
    role: "Ruolo per cui ti candidi",
    rolePlaceholder: "Seleziona un ruolo",
    roles: [
      "AI / Machine Learning Engineer",
      "Full-Stack Developer (Java / PHP)",
      "Sviluppatore Adobe Commerce / Magento",
      "Data Engineer",
      "DevOps / Cloud Engineer",
      "UX/UI Designer",
      "Solution Architect",
      "Candidatura spontanea",
    ],
    seniority: "Seniority",
    seniorityPlaceholder: "Seleziona",
    seniorityOpts: ["Junior (0-2 anni)", "Mid (2-5 anni)", "Senior (5-10 anni)", "Lead (10+ anni)"],
    linkedin: "Profilo LinkedIn (opzionale)",
    portfolio: "Portfolio o GitHub (opzionale)",
    cv: "Curriculum Vitae",
    cvHelper: "Formati accettati: PDF, DOC, DOCX. Dimensione massima: 5 MB. Solo file in italiano o inglese.",
    cvBtn: "Scegli file",
    cvNoFile: "Nessun file selezionato",
    cvHandoffNotice: "Il tuo CV viene caricato in modo sicuro sui nostri server e allegato direttamente all'email che ricevono i nostri recruiter. Non serve alcun client email locale: una volta inviata la candidatura, il flusso è completo.",
    msg: "Messaggio (opzionale)",
    msgPlaceholder: "Raccontaci qualcosa di te, dei progetti che hai realizzato, di cosa ti motiva.",
    consent1Title: "Trattamento dei dati per la candidatura",
    consent1: "Acconsento al trattamento dei miei dati personali (inclusi quelli contenuti nel CV) ai sensi del Regolamento UE 2016/679 (GDPR) e del D.Lgs. 196/2003, per le finalità di selezione del personale.",
    consent2Title: "Conservazione del CV per opportunità future",
    consent2: "Acconsento, in via facoltativa, alla conservazione del mio CV per un periodo massimo di 24 mesi, per essere considerato in future opportunità di selezione anche per posizioni diverse da quella per cui mi candido.",
    consent3Title: "Dati particolari",
    consent3: "Confermo di non includere nel mio CV o nei messaggi dati personali appartenenti a categorie particolari ai sensi dell'art. 9 GDPR (origine etnica, opinioni politiche, convinzioni religiose, dati sanitari, ecc.) salvo che siano strettamente necessari alla valutazione della candidatura.",
    privacyLink: "Leggi l'informativa privacy completa",
    cta: "Invia candidatura",
    uploadingCv: "Caricamento CV…",
    sending: "Invio in corso…",
    success: "Candidatura ricevuta.",
    successSub: "Grazie. La tua candidatura è stata registrata insieme al CV. Ti risponderemo entro 10 giorni lavorativi all'indirizzo email indicato.",
    err: {
      required: "Campo obbligatorio.",
      email: "Indirizzo email non valido.",
      url: "URL non valido (deve iniziare con http:// o https://).",
      privacy: "È necessario accettare l'informativa.",
      cv: "Allega il tuo CV.",
      generic: "Si è verificato un errore. Riprova tra qualche istante.",
      ratelimit: "Hai inviato troppe richieste. Riprova tra un minuto.",
      validation: "Alcuni campi non sono stati compilati correttamente.",
      network: "Connessione non riuscita. Verifica la tua rete e riprova.",
      config: "Form non ancora configurato. Contatta l'amministratore.",
      turnstileMissing: "Completa la verifica anti-bot e riprova.",
      turnstileFailed: "Verifica anti-bot fallita. Ricarica la pagina e riprova.",
      uploadFailed: "Caricamento del CV non riuscito. Riprova o usa un file più piccolo.",
      uploadMime: "Formato CV non valido. Sono accettati solo PDF, DOC o DOCX.",
      uploadSize: "Il CV supera la dimensione massima consentita.",
      uploadMagic: "Il file CV sembra corrotto o non corrisponde all'estensione. Riprova con un altro file.",
    },
  } : {
    eyebrow: "Apply",
    h2: "Send us your application.",
    sub: "Fill in the form, attach your CV (PDF, DOC or DOCX, max 5MB) and we'll get back to you. All data is processed in compliance with GDPR.",
    f1: "First name", f2: "Last name", f3: "Email", f4: "Phone",
    role: "Role you are applying for",
    rolePlaceholder: "Select a role",
    roles: [
      "AI / Machine Learning Engineer",
      "Full-Stack Developer (Java / PHP)",
      "Adobe Commerce / Magento Developer",
      "Data Engineer",
      "DevOps / Cloud Engineer",
      "UX/UI Designer",
      "Solution Architect",
      "Spontaneous application",
    ],
    seniority: "Seniority",
    seniorityPlaceholder: "Select",
    seniorityOpts: ["Junior (0-2 years)", "Mid (2-5 years)", "Senior (5-10 years)", "Lead (10+ years)"],
    linkedin: "LinkedIn profile (optional)",
    portfolio: "Portfolio or GitHub (optional)",
    cv: "CV",
    cvHelper: "Accepted formats: PDF, DOC, DOCX. Max size: 5 MB. Files in Italian or English only.",
    cvBtn: "Choose file",
    cvNoFile: "No file selected",
    cvHandoffNotice: "Your CV is uploaded securely to our servers and attached directly to the email our recruiters receive. No local email client is needed: once you submit, the flow is complete.",
    msg: "Message (optional)",
    msgPlaceholder: "Tell us about yourself, the projects you've worked on, what motivates you.",
    consent1Title: "Data processing for the application",
    consent1: "I consent to the processing of my personal data (including the data contained in the CV) under EU Regulation 2016/679 (GDPR) and Italian Legislative Decree 196/2003 for personnel selection purposes.",
    consent2Title: "CV retention for future opportunities",
    consent2: "I optionally consent to the retention of my CV for a maximum period of 24 months, to be considered for future selection opportunities, including roles other than the one I'm applying for.",
    consent3Title: "Special category data",
    consent3: "I confirm that my CV and messages do not include personal data belonging to special categories under art. 9 GDPR (ethnic origin, political opinions, religious beliefs, health data, etc.) unless strictly necessary to assess the application.",
    privacyLink: "Read the full privacy notice",
    cta: "Submit application",
    uploadingCv: "Uploading CV…",
    sending: "Submitting…",
    success: "Application received.",
    successSub: "Thanks. Your application is registered together with the CV. We'll get back to you within 10 business days at the email address provided.",
    err: {
      required: "Required field.",
      email: "Invalid email address.",
      url: "Invalid URL (must start with http:// or https://).",
      privacy: "You must accept the notice.",
      cv: "Attach your CV.",
      generic: "Something went wrong. Please try again shortly.",
      ratelimit: "Too many requests. Please retry in a minute.",
      validation: "Some fields were not filled in correctly.",
      network: "Network error. Check your connection and retry.",
      config: "Form not yet configured. Please contact the administrator.",
      turnstileMissing: "Complete the anti-bot verification and retry.",
      turnstileFailed: "Anti-bot verification failed. Reload the page and retry.",
      uploadFailed: "CV upload failed. Try again or use a smaller file.",
      uploadMime: "Invalid CV format. Only PDF, DOC or DOCX are accepted.",
      uploadSize: "CV exceeds the maximum allowed size.",
      uploadMagic: "The CV file looks corrupted or doesn't match the extension. Try another file.",
    },
  };

  /* Turnstile render. */
  useLavEffect(function () {
    const cfg = (typeof window !== "undefined" && window.FCE_CONFIG) || null;
    const helper = (typeof window !== "undefined" && window.FCE_HELPER) || null;
    if (!cfg || !cfg.turnstileSiteKey || !helper || !turnstileContainerRef.current) return;
    let cancelled = false;
    helper.ensureTurnstileScript()
      .then(function () {
        if (cancelled || !turnstileContainerRef.current || turnstileWidgetIdRef.current) return;
        turnstileWidgetIdRef.current = helper.renderTurnstile(turnstileContainerRef.current, {
          onToken: function (tok) { turnstileTokenRef.current = tok; },
          onError: function () { turnstileTokenRef.current = null; },
          onExpired: function () { turnstileTokenRef.current = null; },
        });
      })
      .catch(function () { /* fallback gestito a submit */ });
    return function () { cancelled = true; };
  }, []);

  function setField(name, val) {
    setValues({ ...values, [name]: val });
    if (fieldErrors[name]) {
      const next = { ...fieldErrors };
      delete next[name];
      setFieldErrors(next);
    }
  }

  function onFile(e) {
    const f = e.target.files && e.target.files[0];
    if (!f) { setCvFile(null); setCvError(""); return; }
    const err = lavValidateCv(f, lang);
    if (err) { setCvFile(null); setCvError(err); e.target.value = ""; return; }
    setCvFile(f);
    setCvError("");
  }

  function validate() {
    const errs = {};
    if (!values.nome.trim()) errs.nome = t.err.required;
    if (!values.cognome.trim()) errs.cognome = t.err.required;
    if (!values.email.trim()) errs.email = t.err.required;
    else if (!LAV_EMAIL_RE.test(values.email.trim())) errs.email = t.err.email;
    if (!values.telefono.trim()) errs.telefono = t.err.required;
    if (!values.ruolo) errs.ruolo = t.err.required;
    if (!values.seniority) errs.seniority = t.err.required;
    if (values.linkedin && !LAV_URL_RE.test(values.linkedin.trim())) errs.linkedin = t.err.url;
    if (values.portfolio && !LAV_URL_RE.test(values.portfolio.trim())) errs.portfolio = t.err.url;
    if (!values.consensoSel) errs.consensoSel = t.err.privacy;
    if (!values.consensoArt9) errs.consensoArt9 = t.err.privacy;
    return errs;
  }

  function resetTurnstile() {
    const helper = window.FCE_HELPER;
    if (helper && turnstileWidgetIdRef.current) {
      helper.resetTurnstile(turnstileWidgetIdRef.current);
      turnstileTokenRef.current = null;
    }
  }

  function mapUploadErrorCode(code) {
    if (code === "ratelimit") return t.err.ratelimit;
    if (code === "form-not-found") return t.err.config;
    if (code === "turnstile-failed") return t.err.turnstileFailed;
    if (code === "size") return t.err.uploadSize;
    if (code === "mime" || code === "extension") return t.err.uploadMime;
    if (code === "magic") return t.err.uploadMagic;
    if (code === "empty") return t.err.uploadFailed;
    if (code === "network") return t.err.network;
    return t.err.uploadFailed;
  }

  async function handleSubmit(e) {
    e.preventDefault();
    if (status === "uploading" || status === "submitting") return;

    const errs = validate();
    if (!cvFile) errs.cv = t.err.cv;
    if (Object.keys(errs).length > 0) {
      setFieldErrors(errs); setStatus("error"); setErrorMsg(t.err.validation);
      return;
    }

    const cfg = window.FCE_CONFIG || null;
    const helper = window.FCE_HELPER || null;
    if (!cfg || !helper || !cfg.formIdLavora || /^TODO_/.test(cfg.formIdLavora)) {
      setStatus("error"); setErrorMsg(t.err.config);
      return;
    }
    if (cfg.turnstileSiteKey && !turnstileTokenRef.current) {
      setStatus("error"); setErrorMsg(t.err.turnstileMissing);
      return;
    }

    /* STEP 1 — upload del CV (multipart). */
    setStatus("uploading"); setErrorMsg(""); setFieldErrors({});
    let attachment;
    try {
      attachment = await lavUploadCv({
        apiBase: cfg.apiBase,
        siteId: cfg.siteId,
        formId: cfg.formIdLavora,
        file: cvFile,
      });
    } catch (err) {
      setStatus("error");
      setErrorMsg(mapUploadErrorCode(err && err.code));
      return;
    }

    /* STEP 2 — submit JSON con _attachments. */
    setStatus("submitting");

    const payload = {
      siteId: cfg.siteId,
      formId: cfg.formIdLavora,
      data: {
        nome: values.nome.trim(),
        cognome: values.cognome.trim(),
        email: values.email.trim(),
        telefono: values.telefono.trim(),
        ruolo: values.ruolo,
        seniority: values.seniority,
        linkedin: values.linkedin.trim(),
        portfolio: values.portfolio.trim(),
        messaggio: values.messaggio.trim(),
        cvFileName: attachment.filename,
        cvFileSizeKb: String(attachment.sizeKb || 0),
        consensoSel: values.consensoSel,
        consensoArchivio: values.consensoArchivio,
        consensoArt9: values.consensoArt9,
      },
      _honeypot: honeypot,
      turnstileToken: turnstileTokenRef.current || "",
      _attachments: [
        {
          url: attachment.signedUrl,
          filename: attachment.filename,
          contentType: attachment.contentType,
          sizeKb: attachment.sizeKb,
        },
      ],
    };

    const res = await helper.submitForm(payload);
    if (res.ok) {
      setStatus("success");
      return;
    }
    const code = res.code;
    let msg = t.err.generic;
    if (code === "config") msg = t.err.config;
    else if (code === "turnstile-missing") msg = t.err.turnstileMissing;
    else if (code === "turnstile-failed") msg = t.err.turnstileFailed;
    else if (code === "ratelimit") msg = t.err.ratelimit;
    else if (code === "validation") msg = (res.body && res.body.error) || t.err.validation;
    else if (code === "network") msg = t.err.network;
    setStatus("error"); setErrorMsg(msg); resetTurnstile();
  }

  const isUploading = status === "uploading";
  const isSubmitting = status === "submitting";
  const isBusy = isUploading || isSubmitting;
  const isSuccess = status === "success";

  let ctaLabel = t.cta;
  if (isUploading) ctaLabel = t.uploadingCv;
  else if (isSubmitting) ctaLabel = t.sending;

  return (
    <window.Section id="candidati" style={{ background: "var(--bg)" }}>
      <window.Container>
        <div style={{ maxWidth: 760, marginBottom: 36 }}>
          <window.Eyebrow>{t.eyebrow}</window.Eyebrow>
          <h2 style={{ fontSize: "clamp(28px,3.5vw,44px)", fontWeight: 700, letterSpacing: "-0.02em", lineHeight: 1.1, margin: 0 }}>{t.h2}</h2>
          <p style={{ fontSize: 17, color: "var(--fg-2)", marginTop: 16, lineHeight: 1.6 }}>{t.sub}</p>
        </div>

        <form onSubmit={handleSubmit} noValidate style={{
          background: "#fff", border: "1px solid var(--border)",
          borderRadius: 24, padding: "clamp(28px, 4vw, 44px)",
          boxShadow: "var(--shadow-md)",
          maxWidth: 920,
        }}>
          {isSuccess ? (
            <div style={{ padding: "60px 14px", textAlign: "center" }}>
              <div style={{ width: 72, height: 72, borderRadius: 20, margin: "0 auto 24px", background: "linear-gradient(135deg,#0B57E0,#28D1FE)", color: "#fff", display: "inline-flex", alignItems: "center", justifyContent: "center", boxShadow: "0 12px 30px rgba(40,209,254,.4)" }}>
                <window.Icon name="check-simple" size={36} strokeWidth={2.5} />
              </div>
              <div style={{ fontSize: 22, fontWeight: 700, color: "var(--fg-1)", marginBottom: 8, letterSpacing: "-0.01em" }}>{t.success}</div>
              <div style={{ fontSize: 14, color: "var(--fg-2)", maxWidth: 520, margin: "0 auto", lineHeight: 1.55 }}>{t.successSub}</div>
            </div>
          ) : (
            <div style={{ display: "flex", flexDirection: "column", gap: 16 }}>
              {/* Honeypot anti-bot — non visibile, deve restare vuoto. */}
              <div aria-hidden="true" style={{ position: "absolute", left: "-9999px", height: 0, width: 0, overflow: "hidden" }}>
                <label>
                  Do not fill this field
                  <input type="text" name="_hp" tabIndex={-1} autoComplete="off" value={honeypot} onChange={(e) => setHoneypot(e.target.value)} />
                </label>
              </div>

              <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12 }} className="lav-fields">
                <LavField label={t.f1} name="nome" value={values.nome} onChange={setField} error={fieldErrors.nome} disabled={isBusy} required autoComplete="given-name" />
                <LavField label={t.f2} name="cognome" value={values.cognome} onChange={setField} error={fieldErrors.cognome} disabled={isBusy} required autoComplete="family-name" />
              </div>
              <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12 }} className="lav-fields">
                <LavField label={t.f3} name="email" type="email" value={values.email} onChange={setField} error={fieldErrors.email} disabled={isBusy} required autoComplete="email" />
                <LavField label={t.f4} name="telefono" type="tel" value={values.telefono} onChange={setField} error={fieldErrors.telefono} disabled={isBusy} required autoComplete="tel" />
              </div>
              <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12 }} className="lav-fields">
                <LavSelect label={t.role} name="ruolo" value={values.ruolo} onChange={setField} placeholder={t.rolePlaceholder} options={t.roles} error={fieldErrors.ruolo} disabled={isBusy} required />
                <LavSelect label={t.seniority} name="seniority" value={values.seniority} onChange={setField} placeholder={t.seniorityPlaceholder} options={t.seniorityOpts} error={fieldErrors.seniority} disabled={isBusy} required />
              </div>
              <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12 }} className="lav-fields">
                <LavField label={t.linkedin} name="linkedin" type="url" value={values.linkedin} onChange={setField} error={fieldErrors.linkedin} disabled={isBusy} placeholder="https://linkedin.com/in/..." />
                <LavField label={t.portfolio} name="portfolio" type="url" value={values.portfolio} onChange={setField} error={fieldErrors.portfolio} disabled={isBusy} placeholder="https://github.com/..." />
              </div>

              {/* CV Upload */}
              <div>
                <div style={{ fontSize: 12, fontWeight: 600, color: "var(--fg-2)", letterSpacing: "0.04em", marginBottom: 6 }}>{t.cv} *</div>
                <div style={{
                  display: "flex", alignItems: "center", gap: 14,
                  padding: "14px 16px",
                  border: "1.5px dashed " + (cvError || fieldErrors.cv ? "var(--tl-danger)" : "var(--border)"),
                  borderRadius: 12,
                  background: "var(--bg-subtle)",
                }}>
                  <input
                    ref={fileRef}
                    type="file"
                    accept=".pdf,.doc,.docx,application/pdf,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document"
                    onChange={onFile}
                    disabled={isBusy}
                    style={{ display: "none" }}
                  />
                  <button type="button" onClick={() => fileRef.current && fileRef.current.click()} disabled={isBusy} style={{
                    fontFamily: "var(--font-sans)", fontSize: 13, fontWeight: 600,
                    padding: "9px 16px", borderRadius: 10, cursor: isBusy ? "not-allowed" : "pointer",
                    border: "1px solid var(--border)", background: "#fff", color: "var(--tl-blue-deep)",
                    display: "inline-flex", alignItems: "center", gap: 8,
                    opacity: isBusy ? 0.6 : 1,
                  }}>
                    <window.Icon name="layers" size={14} />
                    {t.cvBtn}
                  </button>
                  <div style={{ fontSize: 13, color: cvFile ? "var(--fg-1)" : "var(--fg-3, #6B7280)", flex: 1, minWidth: 0, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>
                    {cvFile ? (cvFile.name + " · " + Math.round(cvFile.size / 1024) + " KB") : t.cvNoFile}
                  </div>
                </div>
                <div style={{ fontSize: 12, color: "var(--fg-3, #6B7280)", marginTop: 6 }}>{t.cvHelper}</div>
                {(cvError || fieldErrors.cv) && (
                  <div role="alert" style={{ fontSize: 12, color: "var(--tl-danger)", marginTop: 4 }}>{cvError || fieldErrors.cv}</div>
                )}
                <div style={{
                  marginTop: 10, padding: "10px 12px",
                  background: "rgba(11,87,224,.06)",
                  border: "1px solid rgba(11,87,224,.18)",
                  borderRadius: 10,
                  display: "flex", gap: 10, alignItems: "flex-start",
                }}>
                  <span style={{ color: "var(--tl-blue-primary)", flexShrink: 0, marginTop: 1 }}>
                    <window.Icon name="info" size={14} />
                  </span>
                  <div style={{ fontSize: 12, color: "var(--fg-2)", lineHeight: 1.5 }}>{t.cvHandoffNotice}</div>
                </div>
              </div>

              <LavField label={t.msg} name="messaggio" multiline value={values.messaggio} onChange={setField} disabled={isBusy} placeholder={t.msgPlaceholder} />

              {/* Privacy / Consents block */}
              <div style={{
                marginTop: 8, padding: 22, borderRadius: 14,
                background: "var(--bg-subtle)", border: "1px solid var(--border)",
                display: "flex", flexDirection: "column", gap: 14,
              }}>
                <Consent name="consensoSel" required title={t.consent1Title} body={t.consent1} checked={values.consensoSel} onChange={setField} error={fieldErrors.consensoSel} />
                <Consent name="consensoArchivio" title={t.consent2Title} body={t.consent2} checked={values.consensoArchivio} onChange={setField} />
                <Consent name="consensoArt9" required title={t.consent3Title} body={t.consent3} checked={values.consensoArt9} onChange={setField} error={fieldErrors.consensoArt9} />
                <a href="privacy.html" target="_blank" rel="noopener" style={{ fontSize: 12, fontWeight: 600, color: "var(--tl-blue-primary)", display: "inline-flex", alignItems: "center", gap: 6, marginTop: 4 }}>
                  <window.Icon name="external" size={12} />
                  {t.privacyLink}
                </a>
              </div>

              {/* Cloudflare Turnstile widget — anti-bot HARD sul submit. */}
              <div ref={turnstileContainerRef} aria-label="Verifica anti-bot" style={{ display: "flex", justifyContent: "flex-start", marginTop: 6 }} />

              {status === "error" && errorMsg && (
                <div role="alert" style={{ fontSize: 13, color: "#7A1F22", background: "rgba(229,72,77,.08)", border: "1px solid rgba(229,72,77,.25)", borderRadius: 10, padding: "10px 14px", marginTop: 4 }}>{errorMsg}</div>
              )}

              <div style={{ marginTop: 6 }}>
                <window.Button size="lg" type="submit" icon={!isBusy ? <window.Icon name="arrow" size={16} /> : null}>
                  {ctaLabel}
                </window.Button>
              </div>
            </div>
          )}
        </form>

        <style>{`
          @media (max-width: 720px) { .lav-fields { grid-template-columns: 1fr !important; } }
        `}</style>
      </window.Container>
    </window.Section>
  );
};

function Consent({ name, title, body, required = false, checked, onChange, error }) {
  return (
    <label style={{ display: "flex", gap: 12, alignItems: "flex-start", cursor: "pointer" }}>
      <input
        type="checkbox"
        name={name}
        required={required}
        checked={!!checked}
        onChange={(e) => onChange(name, e.target.checked)}
        aria-invalid={!!error}
        style={{ marginTop: 4, flexShrink: 0, width: 16, height: 16, accentColor: "#0B57E0" }}
      />
      <div>
        <div style={{ fontSize: 13, fontWeight: 600, color: error ? "var(--tl-danger)" : "var(--fg-1)", marginBottom: 3 }}>
          {title} {required && <span style={{ color: error ? "var(--tl-danger)" : "var(--tl-blue-primary)" }}>*</span>}
        </div>
        <div style={{ fontSize: 12.5, color: error ? "var(--tl-danger)" : "var(--fg-2)", lineHeight: 1.55 }}>{body}</div>
      </div>
    </label>
  );
}

function LavField({ label, name, type = "text", multiline = false, placeholder, value, onChange, error, disabled = false, required = false, autoComplete }) {
  const [focus, setFocus] = useLavState(false);
  const borderColor = error ? "var(--tl-danger)" : (focus ? "var(--tl-blue-primary)" : "var(--border)");
  const common = {
    fontFamily: "var(--font-sans)", fontSize: 14,
    padding: "12px 14px", borderRadius: 10,
    border: `1px solid ${borderColor}`,
    background: "#fff", color: "var(--fg-1)",
    outline: "none", width: "100%", boxSizing: "border-box",
    transition: "all 140ms",
    boxShadow: focus && !error ? "0 0 0 4px rgba(11,87,224,.12)" : "none",
    opacity: disabled ? 0.6 : 1,
  };
  const handleChange = (e) => onChange(name, e.target.value);
  return (
    <label style={{ display: "flex", flexDirection: "column", gap: 6 }}>
      <span style={{ fontSize: 12, fontWeight: 600, color: "var(--fg-2)", letterSpacing: "0.04em" }}>{label}{required && " *"}</span>
      {multiline
        ? <textarea name={name} rows={4} placeholder={placeholder} value={value} onChange={handleChange} required={required} disabled={disabled} aria-invalid={!!error} onFocus={() => setFocus(true)} onBlur={() => setFocus(false)} style={common} />
        : <input type={type} name={name} placeholder={placeholder} value={value} onChange={handleChange} required={required} disabled={disabled} autoComplete={autoComplete} aria-invalid={!!error} onFocus={() => setFocus(true)} onBlur={() => setFocus(false)} style={common} />}
      {error && (<span role="alert" style={{ fontSize: 11, color: "var(--tl-danger)", marginTop: 2 }}>{error}</span>)}
    </label>
  );
}

function LavSelect({ label, name, options, placeholder, value, onChange, error, disabled = false, required = false }) {
  const [focus, setFocus] = useLavState(false);
  const borderColor = error ? "var(--tl-danger)" : (focus ? "var(--tl-blue-primary)" : "var(--border)");
  return (
    <label style={{ display: "flex", flexDirection: "column", gap: 6 }}>
      <span style={{ fontSize: 12, fontWeight: 600, color: "var(--fg-2)", letterSpacing: "0.04em" }}>{label}{required && " *"}</span>
      <select
        name={name}
        value={value}
        onChange={(e) => onChange(name, e.target.value)}
        required={required}
        disabled={disabled}
        aria-invalid={!!error}
        onFocus={() => setFocus(true)}
        onBlur={() => setFocus(false)}
        style={{
          fontFamily: "var(--font-sans)", fontSize: 14,
          padding: "12px 14px", borderRadius: 10,
          border: `1px solid ${borderColor}`,
          background: "#fff", color: value ? "var(--fg-1)" : "var(--fg-3, #6B7280)",
          outline: "none", width: "100%", boxSizing: "border-box",
          transition: "all 140ms",
          boxShadow: focus && !error ? "0 0 0 4px rgba(11,87,224,.12)" : "none",
          opacity: disabled ? 0.6 : 1,
          appearance: "none",
          backgroundImage: "url(\"data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'><path d='M1 1l5 5 5-5' fill='none' stroke='%236B7280' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/></svg>\")",
          backgroundRepeat: "no-repeat",
          backgroundPosition: "right 14px center",
          paddingRight: 36,
        }}>
        <option value="" disabled>{placeholder}</option>
        {options.map((o) => <option key={o} value={o}>{o}</option>)}
      </select>
      {error && (<span role="alert" style={{ fontSize: 11, color: "var(--tl-danger)", marginTop: 2 }}>{error}</span>)}
    </label>
  );
}

window.LavoraPrivacy = function LavoraPrivacy({ lang }) {
  const t = lang === "it" ? {
    eyebrow: "Informativa privacy",
    h2: "Come trattiamo i tuoi dati.",
    sub: "Informativa ai sensi degli artt. 13 e 14 del Regolamento UE 2016/679 (GDPR).",
    blocks: [
      { h: "Titolare del trattamento", p: "Il Titolare del trattamento è Tecnolife IT Consulting S.r.l., con sede in Via del Serafico 200, 00142 Roma (RM), Italia. P.IVA 11747341003. Per contatti: privacy@tecnolife.com." },
      { h: "Categorie di dati trattati", p: "Trattiamo i dati anagrafici e di contatto (nome, cognome, email, telefono), i dati professionali (CV, esperienze, formazione, certificazioni) e i dati che spontaneamente includi nel messaggio. Non sono richiesti né incoraggiati dati appartenenti a categorie particolari (art. 9 GDPR)." },
      { h: "Finalità e base giuridica", p: "I dati vengono trattati per (a) gestire la tua candidatura per la posizione indicata — base giuridica: misure precontrattuali (art. 6.1.b GDPR); (b) per opportunità future, previo consenso (art. 6.1.a GDPR), per un massimo di 24 mesi; (c) per adempiere a obblighi di legge (art. 6.1.c GDPR)." },
      { h: "Periodo di conservazione", p: "I dati relativi a candidature per posizioni specifiche sono conservati per 12 mesi dalla chiusura del processo di selezione. Con il consenso facoltativo, il CV può essere conservato fino a 24 mesi per future selezioni. Decorsi tali termini i dati sono cancellati o resi anonimi." },
      { h: "Destinatari dei dati", p: "I dati possono essere trattati da personale autorizzato di Tecnolife (HR e responsabili tecnici delle aree professionali) e da fornitori che agiscono come responsabili del trattamento (servizi cloud, posta elettronica, ATS). I dati non sono diffusi né trasferiti al di fuori dello Spazio Economico Europeo, salvo eventuali trasferimenti garantiti dalle Clausole Contrattuali Standard della Commissione Europea." },
      { h: "I tuoi diritti", p: "In qualunque momento puoi esercitare i diritti di accesso, rettifica, cancellazione, limitazione, portabilità e opposizione (artt. 15-22 GDPR), nonché revocare il consenso facoltativo prestato. Puoi farlo scrivendo a privacy@tecnolife.com. Hai inoltre diritto di proporre reclamo al Garante per la protezione dei dati personali (www.garanteprivacy.it)." },
      { h: "Conferimento dei dati", p: "Il conferimento dei dati richiesti come obbligatori è necessario per valutare la candidatura: il rifiuto comporta l'impossibilità di considerare la tua application. Il conferimento di dati ulteriori (LinkedIn, portfolio, messaggio) è facoltativo." },
    ],
  } : {
    eyebrow: "Privacy notice",
    h2: "How we handle your data.",
    sub: "Notice pursuant to artt. 13 and 14 of EU Regulation 2016/679 (GDPR).",
    blocks: [
      { h: "Data controller", p: "The data controller is Tecnolife IT Consulting S.r.l., headquartered at Via del Serafico 200, 00142 Rome (RM), Italy. VAT 11747341003. Contact: privacy@tecnolife.com." },
      { h: "Categories of data processed", p: "We process identity and contact data (first name, last name, email, phone), professional data (CV, experiences, education, certifications) and data you spontaneously include in your message. Special category data (art. 9 GDPR) is not requested or encouraged." },
      { h: "Purposes and legal basis", p: "Data is processed to (a) manage your application for the indicated role — legal basis: pre-contractual measures (art. 6.1.b GDPR); (b) for future opportunities, subject to consent (art. 6.1.a GDPR), for a maximum of 24 months; (c) to comply with legal obligations (art. 6.1.c GDPR)." },
      { h: "Retention period", p: "Data related to specific applications is retained for 12 months from the end of the selection process. With optional consent, the CV may be retained for up to 24 months for future selections. After these terms, data is deleted or anonymised." },
      { h: "Data recipients", p: "Data may be processed by authorised Tecnolife personnel (HR and technical leads) and by providers acting as data processors (cloud services, email, ATS). Data is not disclosed or transferred outside the European Economic Area, except where guaranteed by the European Commission's Standard Contractual Clauses." },
      { h: "Your rights", p: "You may exercise the rights of access, rectification, erasure, restriction, portability and objection (artt. 15-22 GDPR) at any time, as well as withdraw any optional consent. You can do so by writing to privacy@tecnolife.com. You also have the right to lodge a complaint with the Italian Data Protection Authority (www.garanteprivacy.it)." },
      { h: "Provision of data", p: "Providing the data marked as required is necessary to assess your application: refusal makes it impossible to consider it. Providing additional data (LinkedIn, portfolio, message) is optional." },
    ],
  };
  return (
    <window.Section style={{ background: "var(--bg-subtle)" }}>
      <window.Container>
        <div style={{ display: "grid", gridTemplateColumns: "1fr 1.6fr", gap: 56 }} className="lav-priv">
          <div className="lav-priv-sticky" style={{ position: "sticky", top: 100, alignSelf: "start" }}>
            <window.Eyebrow>{t.eyebrow}</window.Eyebrow>
            <h2 style={{ fontSize: "clamp(24px,3vw,36px)", fontWeight: 700, letterSpacing: "-0.02em", lineHeight: 1.15, margin: 0 }}>{t.h2}</h2>
            <p style={{ fontSize: 14, color: "var(--fg-2)", marginTop: 14, lineHeight: 1.6 }}>{t.sub}</p>
            <a href="mailto:privacy@tecnolife.com" style={{ display: "inline-flex", alignItems: "center", gap: 8, marginTop: 18, fontSize: 13, fontWeight: 600, color: "var(--tl-blue-primary)" }}>
              <window.Icon name="mail" size={14} />
              privacy@tecnolife.com
            </a>
          </div>
          <div style={{ display: "flex", flexDirection: "column", gap: 24 }}>
            {t.blocks.map((b, i) => (
              <div key={b.h} style={{ display: "grid", gridTemplateColumns: "auto 1fr", gap: 18, paddingBottom: 22, borderBottom: i < t.blocks.length - 1 ? "1px solid var(--border)" : "none" }}>
                <div style={{ fontFamily: "var(--font-mono)", fontSize: 12, fontWeight: 600, color: "var(--tl-blue-primary)", letterSpacing: ".05em" }}>{String(i + 1).padStart(2, "0")}</div>
                <div>
                  <div style={{ fontSize: 16, fontWeight: 700, color: "var(--fg-1)", marginBottom: 8, letterSpacing: "-0.005em" }}>{b.h}</div>
                  <div style={{ fontSize: 14, color: "var(--fg-2)", lineHeight: 1.65 }}>{b.p}</div>
                </div>
              </div>
            ))}
          </div>
        </div>
        <style>{`
          @media (max-width: 880px) { .lav-priv { grid-template-columns: 1fr !important; gap: 28px !important; } .lav-priv-sticky { position: static !important; top: auto !important; } }
        `}</style>
      </window.Container>
    </window.Section>
  );
};
