// careers.jsx
// Martes AI - "Lavora con noi": Typeform-style hiring form.
// Cover + role overview, then a role picker that branches into role-specific
// questions, then contact + free message. Submits to the CRM base
// (Hiring Requests Martes AI) via /api/submit. Mounted by index.html.
// Design/animations ported from the assessment app (code/apps/assessment).

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

// ─────────────────────────────────────────────────────────────────────────────
// ROLE KEYS - the single-select label maps to a stable key used for branching
// and for the per-role question segments below.
// ─────────────────────────────────────────────────────────────────────────────
const ROLES = ['Formatore AI', 'Editor', 'Developer', 'Sales', 'Media Buyer'];

// Shared contact block, asked right after the role is picked.
const CONTACT = [
  { id: 'nome', kind: 'text', input: 'text', section: 'Chi sei', title: 'Come ti chiami?', placeholder: 'Nome e cognome' },
  { id: 'email', kind: 'text', input: 'email', validate: 'email', section: 'Chi sei', title: 'La tua email', placeholder: 'nome@esempio.com' },
  { id: 'numero', kind: 'text', input: 'tel', validate: 'tel', section: 'Chi sei', title: 'Un numero dove possiamo sentirti', placeholder: 'Con prefisso, es. +39 333 1234567' },
  { id: 'linkedin', kind: 'text', input: 'url', section: 'Chi sei', title: 'Il tuo profilo LinkedIn', placeholder: 'Incolla il link', optional: true },
  { id: 'citta', kind: 'text', input: 'text', section: 'Chi sei', title: 'Da dove ci scrivi?', placeholder: 'Città', optional: true },
  {
    id: 'esperienza', kind: 'single', section: 'Chi sei',
    title: 'Da quanto fai questo lavoro?',
    options: ['Meno di 1 anno', '1-3 anni', '3-5 anni', { label: 'Più di 5 anni', value: 'Piu di 5 anni' }],
  },
  {
    id: 'disponibilita', kind: 'single', section: 'Chi sei',
    title: 'Come ti piacerebbe collaborare con noi?',
    options: ['Full-time', 'Part-time', 'Freelance / P.IVA', 'A progetto / percentuale'],
  },
];

// Per-role question segments. Only the picked role's segment enters the flow.
const ROLE_QUESTIONS = {
  'Formatore AI': [
    {
      id: 'fa_claude', kind: 'single', section: 'Formatore AI',
      title: 'Quanto conosci Claude Code?',
      hint: 'È lo strumento con cui lavoriamo in aula ogni giorno',
      options: ['Mai usato', "L'ho provato", 'Lo uso spesso', 'Ci lavoro ogni giorno'],
    },
    {
      id: 'fa_speaking', kind: 'single', section: 'Formatore AI',
      title: 'Quanto sei a tuo agio a parlare in pubblico?',
      hint: 'Le nostre formazioni sono dal vivo e molto pratiche',
      options: ['Poco, meglio dietro le quinte', 'Me la cavo con piccoli gruppi', 'Sto bene anche davanti a una platea', 'È già il mio mestiere'],
    },
    {
      id: 'fa_docenza', kind: 'single', section: 'Formatore AI',
      title: 'Hai già formato o insegnato ad altri?',
      options: ['Sì, con continuità', 'Qualche volta', 'Non ancora'],
    },
    {
      id: 'fa_video', kind: 'text', section: 'Formatore AI',
      title: 'Un link dove ti si vede parlare o insegnare',
      placeholder: 'Un talk, un webinar, un video, anche informale',
      optional: true,
    },
  ],
  'Editor': [
    {
      id: 'ed_tipo', kind: 'multi', section: 'Editor',
      title: 'Che tipo di montaggio sai fare?',
      hint: "Puoi selezionare più di un'opzione",
      options: ['Short form', 'Long form', 'Vlog'],
    },
    {
      id: 'ed_software', kind: 'multi', section: 'Editor',
      title: 'Con cosa monti?',
      hint: "Puoi selezionare più di un'opzione",
      options: ['Premiere Pro', 'DaVinci Resolve', 'Final Cut', 'CapCut', 'After Effects', 'Altro'],
    },
    {
      id: 'ed_showreel', kind: 'text', section: 'Editor',
      title: 'Linkaci il tuo showreel o portfolio',
      placeholder: 'Reel, canale YouTube, cartella Drive, sito…',
    },
    {
      id: 'ed_motion', kind: 'single', section: 'Editor',
      title: 'Te la cavi con animazioni e motion graphics?',
      options: ['No, solo montaggio', 'Le basi', 'Sì, è un mio punto forte'],
      optional: true,
    },
  ],
  'Developer': [
    {
      id: 'dev_claude', kind: 'single', section: 'Developer',
      title: 'Quanto conosci Claude Code?',
      options: ['Mai usato', "L'ho provato", 'Lo uso spesso', 'Ci lavoro ogni giorno'],
    },
    {
      id: 'dev_livello', kind: 'single', section: 'Developer',
      title: 'Come ti descriveresti?',
      options: ['Junior', 'Mid', 'Senior'],
    },
    {
      id: 'dev_stack', kind: 'text', section: 'Developer',
      title: 'Il tuo stack principale',
      placeholder: 'Linguaggi, framework, strumenti con cui sei più veloce…',
    },
    {
      id: 'dev_github', kind: 'text', section: 'Developer',
      title: 'GitHub o un progetto di cui vai fiero',
      placeholder: 'Incolla il link',
      optional: true,
    },
    {
      id: 'dev_percorso', kind: 'single', section: 'Developer',
      title: 'Su cosa ti vedi meglio?',
      hint: 'Chi è forte entra nei progetti veri, altrimenti si affianca ai clienti che sviluppano',
      options: ['Progetti di engineering as a service', 'Coaching ai clienti che sviluppano', 'Entrambe le cose'],
    },
  ],
  'Sales': [
    {
      id: 'sa_esperienza', kind: 'single', section: 'Sales',
      title: 'Che esperienza hai nella vendita?',
      options: ['Poca, sto iniziando', "Un po'", 'Sì, vendo con continuità', 'Vendo high-ticket da anni'],
    },
    {
      id: 'sa_percentuale', kind: 'single', section: 'Sales',
      title: 'Il ruolo è a percentuale sul venduto. Come lo vivi?',
      options: ['Perfetto, mi motiva', 'Va bene se i numeri tornano', 'Preferirei anche un fisso'],
    },
    {
      id: 'sa_settore', kind: 'text', section: 'Sales',
      title: 'Cosa hai venduto finora?',
      placeholder: 'Prodotto o servizio, settore, ticket medio…',
    },
    {
      id: 'sa_risultato', kind: 'text', section: 'Sales',
      title: 'Un risultato di vendita di cui vai fiero',
      placeholder: 'Con qualche numero, se puoi',
      optional: true,
    },
  ],
  'Media Buyer': [
    {
      id: 'mb_piattaforme', kind: 'multi', section: 'Media Buyer',
      title: 'Su quali piattaforme lanci le ads?',
      hint: "Puoi selezionare più di un'opzione",
      options: ['Meta Ads', 'Google Ads', 'TikTok Ads', 'YouTube Ads', 'LinkedIn Ads', 'Altro'],
    },
    {
      id: 'mb_budget', kind: 'single', section: 'Media Buyer',
      title: 'Qual è il budget mensile più alto che hai gestito?',
      options: ['Meno di 5k', '5-20k', '20-50k', 'Oltre 50k'],
    },
    {
      id: 'mb_risultato', kind: 'text', section: 'Media Buyer',
      title: 'Un risultato di cui vai fiero',
      placeholder: 'Una campagna, i numeri, il ROAS…',
    },
    {
      id: 'mb_link', kind: 'text', section: 'Media Buyer',
      title: 'Un case study o un account da mostrarci',
      placeholder: 'Incolla il link',
      optional: true,
    },
  ],
};

// Portfolio upload + free closing message, shared across roles.
const ALLEGATO = {
  id: 'allegato', kind: 'file', section: 'Ci siamo',
  title: 'Allega un assaggio dei tuoi lavori migliori',
  hint: 'PDF, immagini o un documento col tuo portfolio. Max 5 MB. Per i video meglio un link nelle domande sopra.',
  optional: true,
};

const MESSAGGIO = {
  id: 'messaggio', kind: 'text', section: 'Ci siamo',
  title: 'Vuoi aggiungere qualcosa?',
  placeholder: 'Perché vuoi lavorare con noi, cosa ti rende la persona giusta…',
  optional: true,
};

const INTRO = [
  {
    id: 'cover',
    kind: 'info',
    section: 'Lavora con noi',
    eyebrow: 'Martes AI · Lavora con noi',
    title: 'Stiamo cercando giocatori di Serie A. E tu potresti essere uno di loro.',
    body:
      "Stiamo costruendo la realtà numero uno in Italia, e ci servono i talenti più forti del Paese. Raccontaci chi sei: due minuti, poi ci pensiamo noi.",
    cta: 'Vediamo i ruoli',
  },
  {
    id: 'ruoli',
    kind: 'info',
    section: 'Lavora con noi',
    eyebrow: 'Le figure che cerchiamo',
    title: 'Cinque ruoli, una squadra',
    body: 'Scegli quello più tuo. Le domande dopo cambiano in base al ruolo.',
    bullets: [
      { n: '01', text: "Formatore AI: porti l'AI in aula. Le nostre formazioni sono pratiche e dal vivo, quindi servono esperienza vera con Claude Code e la disinvoltura di chi sa tenere una sala." },
      { n: '02', text: 'Editor: monti i nostri contenuti. Short form, long form e vlog, dal taglio del parlato al ritmo giusto.' },
      { n: '03', text: 'Developer: costruisci sul serio. Se sei forte entri nei progetti di engineering as a service, altrimenti fai da coach ai clienti che sviluppano con noi.' },
      { n: '04', text: 'Sales: chiudi. Prendi le nostre chiamate commerciali, porti a casa i clienti e lavori a percentuale sul venduto.' },
      { n: '05', text: 'Media Buyer: gestisci le campagne. Pianifichi, lanci e ottimizzi le ads che portano lead a noi e ai nostri clienti.' },
    ],
    cta: 'Mi candido',
  },
  {
    id: 'posizione',
    kind: 'single',
    section: 'Candidatura',
    title: 'Per quale ruolo ti candidi?',
    options: ROLES,
  },
];

const THANKS = {
  id: 'thanks',
  kind: 'thanks',
  section: 'Fatto',
  title: 'Grazie, ci abbiamo messo la faccia anche noi.',
  body: 'Abbiamo ricevuto la tua candidatura. Se c\'è un match ti scriviamo noi, di solito nel giro di qualche giorno.',
};

// ─────────────────────────────────────────────────────────────────────────────
// buildFlow - intro + (once a role is picked) contact + role questions + close.
// Rebuilds when the picked role changes.
// ─────────────────────────────────────────────────────────────────────────────
function buildFlow(role) {
  const flow = INTRO.map((s) => ({ ...s }));
  if (role && ROLE_QUESTIONS[role]) {
    CONTACT.forEach((s) => flow.push({ ...s }));
    ROLE_QUESTIONS[role].forEach((s) => flow.push({ ...s }));
    flow.push({ ...ALLEGATO });
    flow.push({ ...MESSAGGIO });
    flow.push({ ...THANKS });
  }
  let n = 0;
  for (const s of flow) {
    if (s.kind === 'single' || s.kind === 'multi' || s.kind === 'text' || s.kind === 'file') {
      n += 1;
      s.qNum = n;
    }
  }
  return flow;
}

// Inline validation for text inputs that declare screen.validate.
// Returns an error string when the (non-empty) value is malformed, else null.
function fieldError(screen, value) {
  if (!screen || !screen.validate) return null;
  const v = (value || '').trim();
  if (!v) return null;
  if (screen.validate === 'email') {
    return /^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/.test(v) ? null : "Controlla l'email, sembra incompleta";
  }
  if (screen.validate === 'tel') {
    const digits = v.replace(/\D/g, '');
    const ok = /^\+?[\d\s().\-]{6,}$/.test(v) && digits.length >= 8 && digits.length <= 15;
    return ok ? null : 'Inserisci un numero di telefono valido';
  }
  return null;
}

// Rough total for the progress bar before a role is picked (keeps the bar from
// jumping to 100% on the role screen). Real length is used once branched.
const EST_STEPS = 16;

// ─────────────────────────────────────────────────────────────────────────────
// THEME
// ─────────────────────────────────────────────────────────────────────────────
function buildTheme(t) {
  const dark = t.dark;
  const accent = t.accent;
  return {
    bg: dark ? '#050505' : '#FAFAF7',
    cardBg: dark ? '#0A0A0A' : '#FFFFFF',
    fg: dark ? '#F5F5F4' : '#0A0A0A',
    fgMuted: dark ? 'rgba(245,245,244,0.55)' : 'rgba(10,10,10,0.55)',
    fgDim: dark ? 'rgba(245,245,244,0.35)' : 'rgba(10,10,10,0.4)',
    border: dark ? 'rgba(255,255,255,0.08)' : 'rgba(0,0,0,0.08)',
    borderStrong: dark ? 'rgba(255,255,255,0.18)' : 'rgba(0,0,0,0.18)',
    accent,
    accentDim: accent + '22',
    accentInk: '#050505',
    fontFamily: "'Manrope', ui-sans-serif, system-ui, sans-serif",
    questionFontFamily: "'Manrope', ui-sans-serif, system-ui, sans-serif",
  };
}

// ─────────────────────────────────────────────────────────────────────────────
// MAIN COMPONENT
// ─────────────────────────────────────────────────────────────────────────────
function CareersForm({ tweaks }) {
  const [idx, setIdx] = useState(0);
  const [dir, setDir] = useState(1);
  const [answers, setAnswers] = useState({});
  const [submitState, setSubmitState] = useState('idle');

  const role = answers.posizione;
  const FLOW = useMemo(() => buildFlow(role), [role]);
  const PROGRESS_IDS = useMemo(
    () => FLOW.filter((s) => ['single', 'multi', 'text', 'file'].includes(s.kind)).map((s) => s.id),
    [FLOW]
  );
  const containerRef = useRef(null);

  const theme = useMemo(() => buildTheme(tweaks), [tweaks]);
  const screen = FLOW[Math.min(idx, FLOW.length - 1)];

  const goNext = useCallback(() => {
    setDir(1);
    setIdx((i) => Math.min(i + 1, FLOW.length - 1));
  }, [FLOW.length]);
  const goPrev = useCallback(() => {
    setDir(-1);
    setIdx((i) => Math.max(i - 1, 0));
  }, []);

  const setAnswer = (id, val) => setAnswers((a) => ({ ...a, [id]: val }));
  const getAnswer = (id) => answers[id];

  const isAnswered = (s) => {
    if (!s) return true;
    if (s.kind === 'info' || s.kind === 'thanks') return true;
    if (s.optional) return true;
    const v = answers[s.id];
    if (s.kind === 'multi') return Array.isArray(v) && v.length > 0;
    if (s.kind === 'text') return typeof v === 'string' && v.trim().length > 0;
    if (s.kind === 'file') return v != null;
    return v !== undefined && v !== null && v !== '';
  };

  const canAdvance = isAnswered(screen) && !fieldError(screen, answers[screen && screen.id]);

  const handleSingleSelect = (s, opt) => setAnswer(s.id, opt);

  useEffect(() => {
    const onKey = (e) => {
      const tag = (e.target.tagName || '').toLowerCase();
      const inField = tag === 'input' || tag === 'textarea';
      if (e.key === 'Enter') {
        if (inField && tag === 'textarea' && e.shiftKey) return;
        if (canAdvance) {
          e.preventDefault();
          if (screen.kind === 'thanks') submit();
          else goNext();
        }
        return;
      }
      if (inField) return;
      if (e.key === 'ArrowDown' || e.key === 'ArrowRight') {
        if (canAdvance) goNext();
      } else if (e.key === 'ArrowUp' || e.key === 'ArrowLeft') {
        goPrev();
      } else if (screen.kind === 'single' && /^[1-9]$/.test(e.key)) {
        const n = parseInt(e.key, 10) - 1;
        if (screen.options[n]) handleSingleSelect(screen, optValue(screen.options[n]));
      } else if (screen.kind === 'multi' && /^[a-z]$/i.test(e.key)) {
        const n = e.key.toLowerCase().charCodeAt(0) - 97;
        if (screen.options[n]) toggleMulti(screen, optValue(screen.options[n]));
      }
    };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [screen, canAdvance, goNext, goPrev]);

  const toggleMulti = (s, opt) => {
    setAnswers((a) => {
      const cur = Array.isArray(a[s.id]) ? a[s.id] : [];
      const next = cur.includes(opt) ? cur.filter((x) => x !== opt) : [...cur, opt];
      return { ...a, [s.id]: next };
    });
  };

  const submit = async () => {
    if (submitState === 'sending' || submitState === 'sent') return;
    setSubmitState('sending');
    try {
      const { allegato, ...rest } = answers;
      const payload = { answers: rest, file: allegato || null, timestamp: new Date().toISOString() };
      const res = await fetch('/api/submit', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(payload),
      });
      if (!res.ok) throw new Error(await res.text());
      setSubmitState('sent');
    } catch (err) {
      console.error('[Careers] submit error:', err);
      setSubmitState('error');
    }
  };

  const totalSteps = role ? FLOW.length : EST_STEPS;
  const progressPct = useMemo(() => {
    if (totalSteps <= 1) return 0;
    return Math.min(100, (idx / (totalSteps - 1)) * 100);
  }, [idx, totalSteps]);

  const qTotal = role ? PROGRESS_IDS.length : 12;

  return (
    <div
      ref={containerRef}
      className="mt-root"
      style={{
        '--bg': theme.bg,
        '--card': theme.cardBg,
        '--fg': theme.fg,
        '--fg-muted': theme.fgMuted,
        '--fg-dim': theme.fgDim,
        '--border': theme.border,
        '--border-strong': theme.borderStrong,
        '--accent': theme.accent,
        '--accent-dim': theme.accentDim,
        '--accent-ink': theme.accentInk,
        '--font': theme.fontFamily,
        '--font-q': theme.questionFontFamily,
        '--transition': tweaks.transition,
      }}
    >
      {tweaks.showProgress && (
        <div className="mt-progress-wrap">
          <div className="mt-progress-track">
            <div className="mt-progress-fill" style={{ width: `${progressPct}%` }} />
          </div>
          <div className="mt-progress-meta">
            {screen.qNum && <span>{screen.qNum} / {qTotal}</span>}
          </div>
        </div>
      )}

      <div className="mt-stage">
        <CrossFadeStage screenKey={screen.id} dir={dir} transition={tweaks.transition}>
          <ScreenRenderer
            screen={screen}
            answer={getAnswer(screen.id)}
            onSelect={(opt) => handleSingleSelect(screen, opt)}
            onToggle={(opt) => toggleMulti(screen, opt)}
            onText={(v) => setAnswer(screen.id, v)}
            onSetAnswer={(v) => setAnswer(screen.id, v)}
            onSubmit={submit}
            submitState={submitState}
            answers={answers}
          />
        </CrossFadeStage>
      </div>

      {screen.kind !== 'thanks' && (
        <InlineCTA
          label={screen.cta || 'Avanti'}
          onClick={goNext}
          disabled={!canAdvance}
          onBack={goPrev}
          canBack={idx > 0}
        />
      )}

      {screen.kind !== 'thanks' && (
        <div className="mt-footer">
          <div className="mt-footer-left">
            <button className="mt-nav-btn" onClick={goPrev} disabled={idx === 0} aria-label="Indietro" title="Indietro (↑)">
              <svg width="16" height="16" viewBox="0 0 16 16" fill="none">
                <path d="M4 10l4-4 4 4" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
              </svg>
            </button>
            <button className="mt-nav-btn" onClick={goNext} disabled={!canAdvance || idx === FLOW.length - 1} aria-label="Avanti" title="Avanti (↓)">
              <svg width="16" height="16" viewBox="0 0 16 16" fill="none">
                <path d="M4 6l4 4 4-4" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
              </svg>
            </button>
          </div>
          <div className="mt-footer-meta">
            <kbd>↵</kbd> per andare avanti
          </div>
        </div>
      )}
    </div>
  );
}

// ─────────────────────────────────────────────────────────────────────────────
// helpers for {label, value} options
// ─────────────────────────────────────────────────────────────────────────────
function optValue(o) { return typeof o === 'string' ? o : o.value; }
function optLabel(o) { return typeof o === 'string' ? o : o.label; }

// ─────────────────────────────────────────────────────────────────────────────
// SLIDE / STAGE
// ─────────────────────────────────────────────────────────────────────────────
function CrossFadeStage({ screenKey, transition, children }) {
  return <div key={screenKey} className={`mt-slide mt-slide-${transition} mt-slide-enter`}>{children}</div>;
}

// ─────────────────────────────────────────────────────────────────────────────
// SCREEN RENDERER
// ─────────────────────────────────────────────────────────────────────────────
function ScreenRenderer({ screen, answer, onSelect, onToggle, onText, onSetAnswer, onSubmit, submitState, answers }) {
  if (screen.kind === 'info') return <InfoScreen screen={screen} />;
  if (screen.kind === 'single') return <SingleScreen screen={screen} answer={answer} onSelect={onSelect} />;
  if (screen.kind === 'multi') return <MultiScreen screen={screen} answer={answer} onToggle={onToggle} onSetAnswer={onSetAnswer} />;
  if (screen.kind === 'text') return <TextScreen screen={screen} answer={answer} onText={onText} />;
  if (screen.kind === 'file') return <FileScreen screen={screen} answer={answer} onSetAnswer={onSetAnswer} />;
  if (screen.kind === 'thanks') return <ThanksScreen screen={screen} onSubmit={onSubmit} submitState={submitState} answers={answers} />;
  return null;
}

function InlineCTA({ label, onClick, disabled, onBack, canBack }) {
  return (
    <div className="mt-inline-cta-row">
      {canBack && (
        <button className="mt-inline-back" onClick={onBack} type="button" aria-label="Indietro">
          <svg width="14" height="14" viewBox="0 0 14 14" fill="none" aria-hidden="true">
            <path d="M9 3l-4 4 4 4" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" />
          </svg>
          <span>Indietro</span>
        </button>
      )}
      <button className="mt-inline-cta" onClick={onClick} disabled={disabled}>
        <span>{label}</span>
        <svg width="18" height="18" viewBox="0 0 18 18" fill="none" aria-hidden="true">
          <path d="M3 9h11M10 4l5 5-5 5" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
        </svg>
      </button>
    </div>
  );
}

// ── ASCII SPHERE (cover background) ──
function AsciiSphere() {
  const canvasRef = useRef(null);
  const frameRef = useRef(0);
  useEffect(() => {
    const canvas = canvasRef.current;
    if (!canvas) return;
    const ctx = canvas.getContext('2d');
    if (!ctx) return;
    const reduce = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
    const chars = '░▒▓█▀▄▌▐│─┤├┴┬╭╮╰╯';
    let time = 0;
    const resize = () => {
      const dpr = window.devicePixelRatio || 1;
      const rect = canvas.getBoundingClientRect();
      canvas.width = rect.width * dpr;
      canvas.height = rect.height * dpr;
      ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
    };
    resize();
    window.addEventListener('resize', resize);
    const render = () => {
      const rect = canvas.getBoundingClientRect();
      ctx.clearRect(0, 0, rect.width, rect.height);
      const centerX = rect.width / 2;
      const centerY = rect.height / 2;
      const radius = Math.min(rect.width, rect.height) * 0.46;
      ctx.font = '13px monospace';
      ctx.textAlign = 'center';
      ctx.textBaseline = 'middle';
      const points = [];
      for (let phi = 0; phi < Math.PI * 2; phi += 0.13) {
        for (let theta = 0; theta < Math.PI; theta += 0.13) {
          const x = Math.sin(theta) * Math.cos(phi + time * 0.5);
          const y = Math.sin(theta) * Math.sin(phi + time * 0.5);
          const z = Math.cos(theta);
          const rotY = time * 0.3;
          const newX = x * Math.cos(rotY) - z * Math.sin(rotY);
          const newZ = x * Math.sin(rotY) + z * Math.cos(rotY);
          const rotX = time * 0.2;
          const newY = y * Math.cos(rotX) - newZ * Math.sin(rotX);
          const finalZ = y * Math.sin(rotX) + newZ * Math.cos(rotX);
          const depth = (finalZ + 1) / 2;
          const charIndex = Math.floor(depth * (chars.length - 1));
          points.push({ x: centerX + newX * radius, y: centerY + newY * radius, z: finalZ, char: chars[charIndex] });
        }
      }
      points.sort((a, b) => a.z - b.z);
      points.forEach((point) => {
        const depth = (point.z + 1) / 2;
        const alpha = 0.15 + depth * 0.7;
        const r = Math.round(243 - (243 - 74) * depth);
        const g = Math.round(243 - (243 - 222) * depth);
        const b = Math.round(243 - (243 - 128) * depth);
        ctx.fillStyle = `rgba(${r}, ${g}, ${b}, ${alpha})`;
        ctx.fillText(point.char, point.x, point.y);
      });
      time += reduce ? 0 : 0.02;
      frameRef.current = requestAnimationFrame(render);
    };
    render();
    return () => {
      window.removeEventListener('resize', resize);
      cancelAnimationFrame(frameRef.current);
    };
  }, []);
  return <canvas ref={canvasRef} className="mt-cover-sphere" />;
}

// ── INFO ──
function InfoScreen({ screen }) {
  const [visibleCount, setVisibleCount] = useState(0);
  const hasBullets = screen.bullets && screen.bullets.length > 0;
  useEffect(() => {
    if (!hasBullets || visibleCount >= screen.bullets.length) return;
    const t = setTimeout(() => setVisibleCount((c) => c + 1), 150 + visibleCount * 120);
    return () => clearTimeout(t);
  }, [visibleCount, hasBullets, screen.bullets]);
  const isCover = screen.id === 'cover';
  return (
    <div className={`mt-screen mt-screen-info${isCover ? ' mt-screen-cover' : ''}`}>
      {isCover && (
        <div className="mt-cover-bg" aria-hidden="true">
          <AsciiSphere />
          <div className="mt-cover-scrim" />
        </div>
      )}
      {isCover && <img className="mt-cover-logo" src="/martes-logo.png" alt="Martes AI" />}
      {screen.eyebrow && <div className="mt-eyebrow">{screen.eyebrow}</div>}
      <h1 className="mt-title">{screen.title}</h1>
      {screen.body && <p className="mt-body">{screen.body}</p>}
      {hasBullets && (
        <ol className="mt-bullets">
          {screen.bullets.map((b, i) => (
            <li key={b.n} className="mt-bullet"
              style={{
                opacity: i < visibleCount ? 1 : 0,
                transform: i < visibleCount ? 'translateX(0)' : 'translateX(16px)',
                transition: 'opacity 300ms ease, transform 300ms ease',
              }}>
              <span className="mt-bullet-n">{b.n}</span>
              <span className="mt-bullet-t">{b.text}</span>
            </li>
          ))}
        </ol>
      )}
    </div>
  );
}

// ── SINGLE ──
function SingleScreen({ screen, answer, onSelect }) {
  const [altroText, setAltroText] = useState('');
  const handleSelect = (val) => {
    if (val === 'Altro') onSelect(altroText ? `Altro: ${altroText}` : 'Altro');
    else onSelect(val);
  };
  const handleAltroText = (v) => {
    setAltroText(v);
    onSelect(v ? `Altro: ${v}` : 'Altro');
  };
  return (
    <div className="mt-screen mt-screen-q">
      <QHeader screen={screen} />
      <div className="mt-options">
        {screen.options.map((opt, i) => {
          const val = optValue(opt);
          const label = optLabel(opt);
          const selected = val === 'Altro'
            ? (answer === 'Altro' || (answer && answer.startsWith('Altro:')))
            : answer === val;
          return (
            <React.Fragment key={val}>
              <button className={`mt-option ${selected ? 'is-selected' : ''}`} onClick={() => handleSelect(val)}>
                <span className="mt-option-key">{i + 1}</span>
                <span className="mt-option-label">{label}</span>
                <span className="mt-option-check">
                  <svg width="14" height="14" viewBox="0 0 14 14" fill="none">
                    <path d="M3 7.5l3 3 5-6" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" />
                  </svg>
                </span>
              </button>
              {val === 'Altro' && selected && (
                <input className="mt-altro-input" type="text" placeholder="Specifica…" value={altroText}
                  onChange={(e) => handleAltroText(e.target.value)} autoFocus />
              )}
            </React.Fragment>
          );
        })}
      </div>
    </div>
  );
}

// ── MULTI ──
function MultiScreen({ screen, answer, onToggle, onSetAnswer }) {
  const sel = Array.isArray(answer) ? answer : [];
  const [altroText, setAltroText] = useState('');
  const isAltroOn = sel.some((s) => s === 'Altro' || s.startsWith('Altro:'));
  const EXCLUSIVE = ['Nessuno', 'Mai'];
  const isExclusive = (o) => EXCLUSIVE.includes(o);
  const withoutExclusive = (arr) => arr.filter((s) => !EXCLUSIVE.includes(s));
  const handleToggle = (opt) => {
    if (isExclusive(opt)) { onSetAnswer(sel.includes(opt) ? [] : [opt]); return; }
    const clean = withoutExclusive(sel);
    const isOn = clean.includes(opt);
    onSetAnswer(isOn ? clean.filter((s) => s !== opt) : [...clean, opt]);
  };
  const handleAltroToggle = () => {
    if (isAltroOn) { onSetAnswer(sel.filter((s) => s !== 'Altro' && !s.startsWith('Altro:'))); setAltroText(''); }
    else { const clean = withoutExclusive(sel); onSetAnswer([...clean, altroText ? `Altro: ${altroText}` : 'Altro']); }
  };
  const handleAltroText = (v) => {
    setAltroText(v);
    const clean = sel.filter((s) => s !== 'Altro' && !s.startsWith('Altro:') && !isExclusive(s));
    onSetAnswer([...clean, v ? `Altro: ${v}` : 'Altro']);
  };
  return (
    <div className="mt-screen mt-screen-q">
      <QHeader screen={screen} />
      <div className="mt-options">
        {screen.options.map((opt, i) => {
          const val = optValue(opt);
          const label = optLabel(opt);
          const isOn = val === 'Altro' ? isAltroOn : sel.includes(val);
          return (
            <React.Fragment key={val}>
              <button className={`mt-option ${isOn ? 'is-selected' : ''}`}
                onClick={() => val === 'Altro' ? handleAltroToggle() : handleToggle(val)}>
                <span className="mt-option-key">{String.fromCharCode(65 + i)}</span>
                <span className="mt-option-label">{label}</span>
                <span className="mt-option-check mt-option-check-multi">
                  <svg width="14" height="14" viewBox="0 0 14 14" fill="none">
                    <path d="M3 7.5l3 3 5-6" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" />
                  </svg>
                </span>
              </button>
              {val === 'Altro' && isAltroOn && (
                <input className="mt-altro-input" type="text" placeholder="Specifica cosa…" value={altroText}
                  onChange={(e) => handleAltroText(e.target.value)} autoFocus />
              )}
            </React.Fragment>
          );
        })}
      </div>
    </div>
  );
}

// ── TEXT (textarea, or single-line input when screen.input is set) ──
function TextScreen({ screen, answer, onText }) {
  const ref = useRef(null);
  useEffect(() => {
    const t = setTimeout(() => ref.current && ref.current.focus(), 350);
    return () => clearTimeout(t);
  }, [screen.id]);
  const err = fieldError(screen, answer);
  const showErr = err && (answer || '').trim().length > 0;
  const inputMode = screen.input === 'tel' ? 'tel' : screen.input === 'email' ? 'email' : screen.input === 'url' ? 'url' : 'text';
  return (
    <div className="mt-screen mt-screen-q">
      <QHeader screen={screen} />
      {screen.input ? (
        <input
          ref={ref}
          className={`mt-input ${showErr ? 'is-invalid' : ''}`}
          type={screen.input}
          inputMode={inputMode}
          autoComplete={screen.input === 'email' ? 'email' : screen.input === 'tel' ? 'tel' : 'off'}
          placeholder={screen.placeholder || 'Scrivi qui…'}
          value={answer || ''}
          onChange={(e) => onText(e.target.value)}
        />
      ) : (
        <textarea ref={ref} className="mt-textarea" rows={3} placeholder={screen.placeholder || 'Scrivi qui…'}
          value={answer || ''} onChange={(e) => onText(e.target.value)} />
      )}
      {showErr && <div className="mt-input-err">{err}</div>}
    </div>
  );
}

// ── FILE (portfolio upload; stored as { name, type, size, dataBase64 }) ──
function FileScreen({ screen, answer, onSetAnswer }) {
  const inputRef = useRef(null);
  const [err, setErr] = useState('');
  const MAX = 5 * 1024 * 1024;
  const onPick = (e) => {
    const f = e.target.files && e.target.files[0];
    if (!f) return;
    if (f.size > MAX) {
      setErr('File troppo grande (max 5 MB). Per i video usa un link nelle domande sopra.');
      if (inputRef.current) inputRef.current.value = '';
      return;
    }
    setErr('');
    const reader = new FileReader();
    reader.onload = () => {
      const base64 = String(reader.result).split(',')[1] || '';
      onSetAnswer({ name: f.name, type: f.type || 'application/octet-stream', size: f.size, dataBase64: base64 });
    };
    reader.readAsDataURL(f);
  };
  const clear = () => {
    onSetAnswer(null);
    if (inputRef.current) inputRef.current.value = '';
    setErr('');
  };
  return (
    <div className="mt-screen mt-screen-q">
      <QHeader screen={screen} />
      <div className="mt-file">
        <label className="mt-file-btn">
          <input ref={inputRef} type="file" hidden onChange={onPick}
            accept=".pdf,.png,.jpg,.jpeg,.gif,.webp,.doc,.docx,.ppt,.pptx,.key,.zip" />
          <svg width="18" height="18" viewBox="0 0 18 18" fill="none" aria-hidden="true">
            <path d="M9 12V3M5 7l4-4 4 4M3 13v1a1 1 0 001 1h10a1 1 0 001-1v-1" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round" />
          </svg>
          <span>{answer ? 'Cambia file' : 'Scegli un file'}</span>
        </label>
        {answer && (
          <div className="mt-file-chip">
            <span className="mt-file-name">{answer.name}</span>
            <span className="mt-file-size">{(answer.size / 1024 / 1024).toFixed(1)} MB</span>
            <button className="mt-file-x" onClick={clear} type="button" aria-label="Rimuovi">✕</button>
          </div>
        )}
        {err && <div className="mt-input-err">{err}</div>}
      </div>
    </div>
  );
}

// ── THANKS ──
function ThanksScreen({ screen, onSubmit, submitState, answers }) {
  const sentRef = useRef(false);
  useEffect(() => {
    if (!sentRef.current) { sentRef.current = true; onSubmit(); }
  }, []);
  return (
    <div className="mt-screen mt-screen-thanks">
      <div className="mt-thanks-mark">
        <svg width="64" height="64" viewBox="0 0 64 64" fill="none" aria-hidden="true">
          <circle cx="32" cy="32" r="30" stroke="var(--accent)" strokeWidth="1.5" />
          <path d="M20 33l8 8 16-18" stroke="var(--accent)" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round" className="mt-thanks-tick" />
        </svg>
      </div>
      <h1 className="mt-title mt-thanks-title">{(screen && screen.title) || 'Grazie.'}</h1>
      <p className="mt-body mt-thanks-body">{(screen && screen.body) || 'Abbiamo ricevuto la tua candidatura.'}</p>
      <div className="mt-thanks-status">
        {submitState === 'sending' && <span>Sto inviando la candidatura…</span>}
        {submitState === 'sent' && <span className="mt-thanks-sent">Candidatura inviata ✓</span>}
        {submitState === 'error' && <span className="mt-thanks-err">Errore, riprova o scrivici</span>}
      </div>
    </div>
  );
}

// ── QUESTION HEADER ──
function QHeader({ screen }) {
  return (
    <div className="mt-q-head">
      <div className="mt-q-num">
        <span className="mt-q-num-n">{screen.qNum}</span>
        <svg width="10" height="10" viewBox="0 0 10 10" fill="none">
          <path d="M2 5h6M5 2l3 3-3 3" stroke="currentColor" strokeWidth="1.2" strokeLinecap="round" strokeLinejoin="round" />
        </svg>
      </div>
      <h2 className="mt-q-title">
        {screen.title}
        {screen.optional && <span className="mt-q-optional"> · opzionale</span>}
      </h2>
      {screen.hint && <div className="mt-q-hint">{screen.hint}</div>}
    </div>
  );
}

window.CareersForm = CareersForm;
