/* SeaVin — Checkout flow (multi-step, with status simulation) */

/* ── TEST MODE ──────────────────────────────────────────────────────────────
   STRIPE_OFF = true  → Stripe disabilitato: niente PaymentIntent, niente Payment
   Element, niente pulsante "Paga". Lo step pagamento mostra solo il pulsante che
   avvia /api/simulate-payment (genera il report senza addebito).
   Per RIATTIVARE Stripe quando i test sono finiti: rimetti STRIPE_OFF = false.
   ──────────────────────────────────────────────────────────────────────────── */
const STRIPE_OFF = true;
/* ── LISTINO REALE ───────────────────────────────────────────────────────────
   natante €99 · imbarcazione €250 · pacchetto imbarcazione+estratto ATCN €329
   (estratto da solo, DOPO la consegna: €150). Il TOTALE segue sempre la classe
   RILEVATA (correzione automatica sul mismatch), ma il pagamento resta SIMULATO
   (STRIPE_OFF): nessun addebito reale. Il server è già allineato: l'importo in
   /api/create-payment-intent viene calcolato da boat-class.js lato server
   (mai dal client; abbassare a natante è accettato solo su classe presunta).
   Al go-live basta STRIPE_OFF = false + chiavi Stripe. */
const API = (window.SEAVIN_API != null) ? window.SEAVIN_API : "http://localhost:3001";

function Checkout() {
  const [cfg, setCfg] = useConfig({
    palette: "cream", theme: "light", typeset: "editorial",
    heroLayout: "split", tone: "reassuring", lang: "it",
  });
  const t = window.SEAVIN_I18N[cfg.lang];
  const it = cfg.lang === "it";
  /* Ripristina dati form solo se entro 90 secondi (uscita accidentale) */
  const RESTORE_TTL = 90_000;
  const existing = (() => {
    const saved = loadRequest();
    if (!saved || !saved.startedAt) return null;
    if (Date.now() - saved.startedAt > RESTORE_TTL) { clearRequest(); return null; }
    return saved;
  })();

  /* Step sempre a 0 — si ricomincia sempre dall'inizio */
  const [step, setStep] = useState(0);
  /* Servizio scelto al passo 0: "natante" (€39 lancio) | "imbarcazione" (€99 lancio) |
     "pacchetto" (imbarcazione + estratto ATCN, €329). Preselezionabile dalla
     pagina prezzi via ?service=. La classe RILEVATA resta l'autorità sul
     prezzo: se contraddice la scelta, il servizio si corregge da solo. */
  const [servizio, setServizioRaw] = useState(existing?.servizio || null);
  const [avvisoClasse, setAvvisoClasse] = useState(null);
  const setServizio = (s) => { setServizioRaw(s); setAtcn(s === "pacchetto"); };
  const [hin, setHin] = useState(existing?.hin || "");
  const [plate, setPlate] = useState(existing?.plate || "");
  const [mode, setMode] = useState(existing?.mode || "hin");
  const [boatName, setBoatName] = useState(existing?.boatName || "");
  const [builder, setBuilder] = useState(existing?.builder || "");
  /* Paese del cantiere: valorizzato SOLO selezionando dalla tendina (fonte
     certa); digitando a mano si azzera. Aiuta l'AI sugli omonimi. */
  const [builderCountry, setBuilderCountry] = useState(existing?.builderCountry || "");
  const [model, setModel] = useState(existing?.model || "");
  const [year, setYear] = useState(existing?.year || "");
  const [porto, setPorto] = useState(existing?.porto || "");
  const [portoAttuale, setPortoAttuale] = useState(existing?.portoAttuale || "");
  const [email, setEmail] = useState("");
  const [acctEmail, setAcctEmail] = useState(null);
  const [agree, setAgree] = useState(false);

  /* Se l'utente è loggato, il report usa l'email del suo account: così ogni
     report generato finisce nella sua sezione "Richieste report". */
  useEffect(() => {
    const apply = () => {
      const u = window.SeaVAuth && window.SeaVAuth.currentUser && window.SeaVAuth.currentUser();
      if (u && u.email) { setAcctEmail(u.email); setEmail(e => e || u.email); }
    };
    const r = window.SeaVAuth && window.SeaVAuth.ready;
    if (r && r.then) r.then(apply); else apply();
  }, []);

  /* Preselezione del servizio dalla pagina prezzi (?service=natante|imbarcazione|pacchetto) */
  useEffect(() => {
    const s = new URLSearchParams(window.location.search).get("service");
    if (s === "natante" || s === "imbarcazione" || s === "pacchetto") setServizio(s);
    // eslint-disable-next-line
  }, []);

  /* ── Dichiarazioni venditore ── */
  const [sellerPrice,           setSellerPrice]           = useState("");
  const [sellerConsumption,     setSellerConsumption]     = useState("");
  const [sellerIncidents,       setSellerIncidents]       = useState(null);   // null | "si" | "no"
  const [sellerIncidentsDetail, setSellerIncidentsDetail] = useState("");
  const [sellerMgmtCost,        setSellerMgmtCost]        = useState("");

  /* ── Stripe state ── */
  const [clientSecret,    setClientSecret]    = useState(null);
  const [paymentIntentId, setPaymentIntentId] = useState(null);
  const [stripeReady,     setStripeReady]     = useState(false);
  const [paymentLoading,  setPaymentLoading]  = useState(false);
  const [paymentError,    setPaymentError]    = useState(null);
  const [jobId,           setJobId]           = useState(null);
  const stripeRef   = useRef(null);
  const elementsRef = useRef(null);

  /* ── Fase 2 — classe/prezzo rilevati automaticamente ──
     Ripristinati dal salvataggio (90s) come gli altri campi, così una correzione
     manuale o l'ATCN scelto non si perdono ricaricando la pagina. */
  const [boatClass, setBoatClass] = useState(existing?.boatClass || null); // {tipo,lengthM,prezzoEUR,atcnAddonEUR,confidence,fonte}
  const [detecting, setDetecting] = useState(false);
  const [atcn, setAtcn]           = useState(existing?.atcn || false); // estratto ATCN (+€79 nel pacchetto), solo imbarcazioni
  const detectedKey = useRef(existing?.boatDetectedKey || "");

  const fieldsKey = (b, m, y) => `${b}|${m}|${y}`.toLowerCase();

  /* Chiede al server la classe (natante/imbarcazione) → prezzo. Idempotente per
     coppia cantiere|modello|anno; non scavalca l'override manuale finché cantiere
     o modello non cambiano; ignora le risposte obsolete (fetch fuori ordine);
     dopo un errore si può ritentare (la chiave viene liberata). */
  const detectClass = async (b0, m0, y0) => {
    const b = String(b0 != null ? b0 : builder).trim();
    const m = String(m0 != null ? m0 : model).trim();
    const y = String(y0 != null ? y0 : year).trim();
    if (!b || !m) return;
    const key = fieldsKey(b, m, y);
    if (key === detectedKey.current) return; // già rilevato (o rilevazione in corso)
    detectedKey.current = key;
    setAvvisoClasse(null);
    setDetecting(true);
    try {
      const res = await fetch(`${API}/api/boat-class?builder=${encodeURIComponent(b)}&model=${encodeURIComponent(m)}&year=${encodeURIComponent(y)}&country=${encodeURIComponent(builderCountry || "")}`);
      const data = await res.json();
      if (detectedKey.current !== key) return; // risposta obsoleta: nel frattempo è partita un'altra rilevazione
      if (data && data.fonte === "errore") detectedKey.current = ""; // errore lato server → il prossimo blur/Continua ritenta
      setBoatClass(data);
      /* CORREZIONE AUTOMATICA: la classe rilevata è l'autorità sul prezzo.
         Se contraddice il servizio scelto, il servizio si allinea da solo
         (con avviso). Un natante perde anche l'estratto ATCN (non iscritto). */
      if (data && data.tipo) {
        setServizioRaw(s => {
          if (data.tipo === "natante" && s !== "natante") {
            setAtcn(false);
            if (s) setAvvisoClasse(it ? "La barca risulta un natante (≤10 m): servizio e prezzo aggiornati. L'estratto ATCN non si applica ai natanti." : "This boat is a small craft (≤10 m): service and price updated. ATCN extract doesn't apply.");
            return "natante";
          }
          if (data.tipo === "imbarcazione" && s === "natante") {
            setAvvisoClasse(it ? "La barca risulta un'imbarcazione (>10 m): servizio e prezzo aggiornati a €" + data.prezzoEUR + "." : "This boat is over 10 m: service and price updated to €" + data.prezzoEUR + ".");
            return "imbarcazione";
          }
          return s;
        });
      }
      if (!data || data.tipo !== "imbarcazione") setAtcn(false);
      setDetecting(false);
    } catch (e) {
      if (detectedKey.current !== key) return;
      detectedKey.current = ""; // errore di rete → il prossimo blur/Continua ritenta
      // Anche offline nessuna scelta libera del prezzo: presunzione imbarcazione.
      setBoatClass({ tipo: "imbarcazione", lengthM: null, prezzoEUR: 99, atcnAddonEUR: 79, atcnSingoloEUR: 150, confidence: null, fonte: "presunto" });
      setDetecting(false);
    }
  };

  /* Niente correzione manuale: la classe la decide la rilevazione (che sul
     server esegue SEMPRE una ricerca web, mai a memoria). Il prezzo autorevole
     resta comunque calcolato dal server al momento del pagamento. */

  /* Rileva al montaggio se i dati barca sono stati ripristinati. */
  useEffect(() => { if (builder.trim() && model.trim()) detectClass(); /* eslint-disable-next-line */ }, []);

  /* Listino = prezzo rilevato + eventuale add-on ATCN (solo imbarcazioni).
     Vale solo con cantiere+modello compilati: svuotando i campi il totale torna
     "—" insieme al pannello classe (mai un prezzo orfano dei suoi dati). */
  const prezzoScelto = { natante: 39, imbarcazione: 99, pacchetto: 178 }[servizio] || null; // offerta di lancio
  const atcnExtraEUR = servizio === "pacchetto"
    ? ((boatClass && boatClass.atcnAddonEUR) || 79)    // scelto dal listino: prezzo pacchetto
    : ((boatClass && boatClass.atcnSingoloEUR) || 150); // aggiunto al pagamento: prezzo pieno
  const listinoEUR = (builder.trim() && model.trim() && boatClass && boatClass.prezzoEUR != null)
    ? boatClass.prezzoEUR + (atcn && boatClass.tipo === "imbarcazione" ? atcnExtraEUR : 0)
    : prezzoScelto; // prima della rilevazione vale il servizio scelto dal listino

  const steps = it
    ? ["Servizio", "Identificativi", "Venditore", "Revisione", "Pagamento", "Tracking"]
    : ["Service", "Identifiers", "Seller", "Review", "Payment", "Tracking"];

  /* scelto: passato esplicitamente quando si sceglie e si avanza nello stesso
     click (lo stato React non è ancora aggiornato dentro l'handler) */
  const next = (scelto) => {
    if (step === 0 && !(scelto || servizio)) return; // prima si sceglie il servizio
    if (step === 1) detectClass(); // rileva classe/prezzo lasciando gli identificativi
    setStep(Math.min(step + 1, steps.length - 1));
  };
  const back = () => setStep(Math.max(step - 1, 0));

  /* ── Salvataggio LIVE del modulo (ripristino entro 90s per uscita accidentale).
     Sincronizzato con quello che l'utente scrive davvero: se un campo viene
     cancellato, anche la copia salvata si svuota — niente testi "fantasma"
     che ricompaiono al reload. Debounce per non scrivere a ogni tasto. ── */
  useEffect(() => {
    if (step >= 5) return; // dal tracking in poi il modulo non si tocca più
    const t = setTimeout(() => {
      saveRequest({
        hin, plate, mode, boatName, builder, builderCountry, model, year, porto, portoAttuale,
        servizio, step, email,
        sellerPrice, sellerConsumption, sellerIncidents, sellerIncidentsDetail, sellerMgmtCost,
        boatClass, atcn, boatDetectedKey: detectedKey.current,
        startedAt: Date.now(),
      });
    }, 250);
    return () => clearTimeout(t);
  }, [hin, plate, mode, boatName, builder, builderCountry, model, year, porto, portoAttuale,
      email,
      sellerPrice, sellerConsumption, sellerIncidents, sellerIncidentsDetail, sellerMgmtCost,
      boatClass, atcn, servizio, step]);

  /* ── Resume: deep-link a un job esistente via ?job=<id> → va dritto al tracking.
     Usato dal profilo ("Richieste report") per riaprire un report già generato.
     Con ?servizio=natante|imbarcazione|pacchetto (le card prezzi in home) il
     servizio arriva preselezionato e si parte dagli identificativi. ── */
  useEffect(() => {
    const qs = new URLSearchParams(window.location.search);
    const jid = qs.get("job");
    if (jid) { setJobId(jid); setStep(5); return; }
    const sv = qs.get("servizio");
    if (["natante", "imbarcazione", "pacchetto"].includes(sv)) { setServizio(sv); setStep(1); }
  }, []);

  /* ── Step 4: crea PaymentIntent quando si arriva al pagamento ── */
  useEffect(() => {
    if (STRIPE_OFF || step !== 4 || clientSecret) return;
    setPaymentError(null);
    fetch(`${API}/api/create-payment-intent`, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        email, hin, plate, mode, boatName, builder, model, year, porto, portoAttuale,
        sellerPrice, sellerConsumption, sellerIncidents, sellerIncidentsDetail, sellerMgmtCost,
        boatTipo: (boatClass && boatClass.tipo) || null,
        boatLengthM: boatClass && boatClass.lengthM != null ? boatClass.lengthM : null,
        atcn: !!atcn,
      }),
    })
      .then(r => r.json())
      .then(data => {
        if (data.error) throw new Error(data.error);
        setClientSecret(data.clientSecret);
        setPaymentIntentId(data.paymentIntentId);
      })
      .catch(err => setPaymentError("Errore connessione server: " + err.message));
  }, [step]);

  /* ── Monta Stripe Payment Element quando clientSecret è disponibile ── */
  useEffect(() => {
    if (STRIPE_OFF || !clientSecret || step !== 4 || !window.Stripe) return;
    const timer = setTimeout(() => {
      const mountEl = document.getElementById("stripe-payment-element");
      if (!mountEl) return;
      const stripe   = window.Stripe(window.STRIPE_PK);
      const elements = stripe.elements({
        clientSecret,
        appearance: {
          theme: "flat",
          variables: {
            colorPrimary:       "#1f4a5c",
            colorBackground:    "#faf6ec",
            colorText:          "#15130e",
            colorDanger:        "#9e2a1e",
            fontFamily:         '"Inter Tight", sans-serif',
            borderRadius:       "0px",
            spacingUnit:        "4px",
          },
          rules: {
            ".Input": { border: "1px solid #cdc3ad", padding: "12px 14px", fontSize: "14px" },
            ".Input:focus": { border: "1px solid #1f4a5c", boxShadow: "none" },
            ".Label": { fontFamily: '"JetBrains Mono", monospace', fontSize: "10.5px", letterSpacing: "0.04em", textTransform: "uppercase", color: "#6b6456" },
          },
        },
      });
      stripeRef.current   = stripe;
      elementsRef.current = elements;
      const payEl = elements.create("payment", { layout: "tabs" });
      payEl.mount(mountEl);
      payEl.on("ready", () => setStripeReady(true));
    }, 150);
    return () => clearTimeout(timer);
  }, [clientSecret, step]);

  /* ── Dev: simula pagamento senza addebitare nulla ── */
  const isDev = window.location.hostname === "localhost" || window.location.hostname === "127.0.0.1";

  const simulatePayment = async () => {
    if (!email || !/^\S+@\S+\.\S+$/.test(email)) {
      setPaymentError(it
        ? "Inserisci un'email valida sopra — il report verrà inviato lì."
        : "Enter a valid email above — the report will be sent there.");
      return;
    }
    setPaymentLoading(true);
    setPaymentError(null);
    try {
      const res = await fetch(`${API}/api/simulate-payment`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          email, hin, plate, mode, boatName, builder, model, year, porto, portoAttuale, servizio, atcn,
          sellerPrice, sellerConsumption, sellerIncidents, sellerIncidentsDetail, sellerMgmtCost,
          // Fase 2: classe/ATCN registrati sull'ordine (il prezzo autorevole resta lato server)
          boatTipo: (boatClass && boatClass.tipo) || null,
          boatLengthM: boatClass && boatClass.lengthM != null ? boatClass.lengthM : null,
          atcn: !!atcn,
        }),
      });
      const data = await res.json();
      if (data.error) throw new Error(data.error);
      setJobId(data.jobId);
      next();
    } catch (err) {
      setPaymentError((it ? "Errore simulazione: " : "Simulation error: ") + err.message);
      setPaymentLoading(false);
    }
  };

  /* ── Avvia la pipeline AI dopo pagamento Stripe ── */
  const startPipeline = async (pid) => {
    try {
      const res = await fetch(`${API}/api/start-pipeline`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          paymentId: pid,
          boatData: {
            email, hin, plate, mode, boatName, builder, model, year, porto, portoAttuale,
            sellerPrice, sellerConsumption, sellerIncidents, sellerIncidentsDetail, sellerMgmtCost,
            boatTipo: (boatClass && boatClass.tipo) || null,
            boatLengthM: boatClass && boatClass.lengthM != null ? boatClass.lengthM : null,
            atcn: !!atcn,
          },
        }),
      });
      const data = await res.json();
      if (data.jobId) setJobId(data.jobId);
    } catch (err) {
      console.warn("Pipeline start failed:", err.message);
    }
  };

  /* ── Conferma pagamento Stripe ── */
  const confirmPayment = async () => {
    if (!stripeRef.current || !elementsRef.current) return;
    setPaymentLoading(true);
    setPaymentError(null);
    const { error, paymentIntent } = await stripeRef.current.confirmPayment({
      elements: elementsRef.current,
      confirmParams: {
        return_url:     `${window.location.origin}/checkout.html?step=4`,
        receipt_email:  email,
      },
      redirect: "if_required",
    });
    if (error) {
      setPaymentError(error.message);
      setPaymentLoading(false);
    } else if (paymentIntent?.status === "succeeded") {
      await startPipeline(paymentIntent.id || paymentIntentId);
      next();
    }
  };

  return (
    <Page active="" minimal={true} cfg={cfg} setCfg={setCfg} t={t}>
      <section className="cloud checkout-soft" style={{ paddingTop: "var(--s-7)", paddingBottom: "var(--s-9)" }}>
        <div className="shell" style={{ maxWidth: 1080 }}>
          {/* Stepper — compare solo dopo la scelta del servizio */}
          {step > 0 && <div style={{
            display: "grid",
            gridTemplateColumns: `repeat(${steps.length}, 1fr)`,
            gap: 2,
            marginBottom: "var(--s-7)",
            border: "1px solid color-mix(in srgb, var(--rule) 75%, transparent)", borderRadius: 14, overflow: "hidden", boxShadow: "var(--cl-shadow)"
          }}>
            {steps.map((s, i) => (
              <div key={i} style={{
                padding: "14px 18px",
                background: i <= step ? "var(--ink)" : "var(--bg-card)",
                color: i <= step ? "var(--bg)" : "var(--ink-mute)",
                borderRight: i < steps.length - 1 ? "1px solid var(--rule)" : 0,
              }}>
                <div className="mono" style={{ fontSize: 10.5, letterSpacing: "0.04em", opacity: 0.7, marginBottom: 2 }}>STEP {String(i+1).padStart(2, "0")}</div>
                <div className="mono" style={{ fontSize: 13, letterSpacing: "0.04em", textTransform: "uppercase" }}>{s}</div>
              </div>
            ))}
          </div>}

          <div style={{ display: "grid", gridTemplateColumns: step === 0 ? "1fr" : "1.5fr 1fr", gap: "var(--s-7)" }}>
            {/* Main panel */}
            <div>
              {/* ── Listino di lancio: schermata centrata, senza stepper né riepilogo.
                  Prezzi in OFFERTA con il pieno barrato; l'estratto ATCN si sceglie
                  o col pacchetto (79) o al pagamento (+150), mai a metà. ── */}
              {step === 0 && (
                <div style={{ maxWidth: 920, margin: "0 auto" }}>
                  <div style={{ textAlign: "center", maxWidth: 620, margin: "0 auto var(--s-6)" }}>
                    <span style={{ display: "inline-flex", alignItems: "center", gap: 7, fontSize: 12, fontWeight: 600, background: "color-mix(in srgb, var(--accent-deep) 10%, transparent)", color: "var(--accent-deep)", padding: "5px 14px", borderRadius: 999 }}>
                      {it ? "Offerta di lancio · per poco" : "Launch offer · limited"}
                    </span>
                    <h1 style={{ fontSize: "var(--step-4)", letterSpacing: "-0.03em", lineHeight: 1.05, marginTop: 16 }}>
                      {it ? "Scegli il report " : "Choose the report "}
                      <em style={{ fontStyle: "italic", color: "var(--accent-deep)" }}>{it ? "che ti serve." : "you need."}</em>
                    </h1>
                    <p style={{ marginTop: 14, fontSize: 15.5, color: "var(--ink-soft)", lineHeight: 1.55 }}>
                      {it ? "Prezzi di lancio, una tantum: paghi una volta e il report è tuo per sempre. Consegna immediata." : "Launch pricing, one-off: pay once, the report is yours forever. Instant delivery."}
                    </p>
                  </div>

                  <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fit, minmax(240px, 1fr))", gap: 16, alignItems: "stretch" }}>
                    {[
                      { k: "natante", n: it ? "Natante" : "Small craft", d: it ? "Barche fino a 10 metri: gommoni, open, moto d'acqua." : "Boats up to 10 m: RIBs, open boats, PWC.", p: 39, orig: 99,
                        f: it ? ["14 sezioni di analisi", "Scheda tecnica e mercato", "Consegna immediata", "Archivio nel tuo account"] : ["14 analysis sections", "Specs & market", "Instant delivery", "Stored in your account"] },
                      { k: "imbarcazione", n: it ? "Imbarcazione" : "Vessel", d: it ? "Oltre 10 metri: il report completo con tutte le analisi." : "Over 10 m: the full report, all analyses.", p: 99, orig: 250, pop: true,
                        f: it ? ["Tutto del report natante", "Analisi estesa per grandi scafi", "Criticità note del modello", "Voto e verdetto finale"] : ["Everything in small craft", "Extended hull analysis", "Known model issues", "Grade & final verdict"] },
                      { k: "pacchetto", n: it ? "Imbarcazione + ATCN" : "Vessel + ATCN", d: it ? "Il report completo più l'estratto ufficiale del registro." : "Full report plus the official registry extract.", p: 178, orig: 329, stella: true, nota: it ? "99 + 79 invece di 99 + 150" : "99 + 79 instead of 99 + 150",
                        f: it ? ["Tutto del report imbarcazione", "Estratto ufficiale del registro", "Titolarità e gravami certificati", "Estratto in 1–3 giorni"] : ["Everything in vessel report", "Official registry extract", "Certified title & liens", "Extract in 1–3 days"] },
                    ].map(c => (
                      <div key={c.k}
                        style={{
                          textAlign: "left", padding: "24px 22px",
                          border: c.pop ? "2px solid var(--ink)" : "1px solid color-mix(in srgb, var(--rule) 75%, transparent)",
                          borderRadius: 16,
                          boxShadow: c.pop ? "var(--cl-shadow-su)" : "var(--cl-shadow)",
                          background: "var(--bg-card)",
                          display: "flex", flexDirection: "column", position: "relative",
                        }}>
                        {c.pop && (
                          <span style={{ position: "absolute", top: -11, left: 22, fontSize: 11, fontWeight: 600, background: "var(--accent-deep)", color: "#fff", padding: "3px 12px", borderRadius: 999 }}>
                            {it ? "più scelto" : "most chosen"}
                          </span>
                        )}
                        {c.stella && (
                          <span aria-hidden="true" style={{ position: "absolute", top: -34, right: -14, width: 96, height: 96, transform: "rotate(10deg)", pointerEvents: "none" }}>
                            <svg viewBox="0 0 120 120" width="96" height="96">
                              <g fill="var(--accent-deep)">
                                <rect x="24" y="24" width="72" height="72" rx="14"/>
                                <rect x="24" y="24" width="72" height="72" rx="14" transform="rotate(45 60 60)"/>
                              </g>
                              <text x="60" y="55" textAnchor="middle" fill="#fff" fontSize="21" fontWeight="700" fontFamily="inherit">€79</text>
                              <text x="60" y="72" textAnchor="middle" fill="#fff" fontSize="11" fontWeight="600" fontFamily="inherit">{it ? "estratto" : "extract"}</text>
                              <text x="60" y="85" textAnchor="middle" fill="#fff" fontSize="11" fontWeight="600" fontFamily="inherit">ATCN!</text>
                            </svg>
                          </span>
                        )}
                        <div style={{ fontFamily: "var(--font-display)", fontSize: 22, letterSpacing: "-0.02em" }}>{c.n}</div>
                        <div style={{ display: "flex", alignItems: "baseline", gap: 10, marginTop: 10, flexWrap: "wrap" }}>
                          <span style={{ fontFamily: "var(--font-display)", fontSize: 42, letterSpacing: "-0.03em", color: "var(--accent-deep)" }}>€ {c.p}</span>
                          <span style={{ fontSize: 18, color: "var(--ink-faint)", textDecoration: "line-through", textDecorationThickness: 2 }}>€ {c.orig}</span>
                          <span style={{ fontSize: 12.5, color: "var(--ink-mute)" }}>{it ? "una tantum" : "one-off"}</span>
                        </div>
                        <div style={{ fontSize: 12, color: "var(--accent-deep)", fontWeight: 600, marginTop: 4 }}>
                          {c.nota || (it ? `Risparmi € ${c.orig - c.p} col prezzo di lancio` : `Save € ${c.orig - c.p} at launch price`)}
                        </div>
                        <p style={{ fontSize: 13.5, color: "var(--ink-soft)", lineHeight: 1.5, marginTop: 12 }}>{c.d}</p>
                        <div style={{ marginTop: 14, marginBottom: 20 }}>
                          {c.f.map((x, j) => (
                            <div key={j} style={{ display: "flex", gap: 9, alignItems: "flex-start", fontSize: 13.5, padding: "5px 0" }}>
                              <span style={{ color: "var(--accent-deep)", flex: "none" }}>✓</span>{x}
                            </div>
                          ))}
                        </div>
                        <button type="button" className="btn btn--accent" style={{ marginTop: "auto", width: "100%", justifyContent: "center" }}
                          onClick={() => { setServizio(c.k); setAvvisoClasse(null); next(c.k); }}>
                          {it ? "Scegli" : "Choose"} →
                        </button>
                      </div>
                    ))}
                  </div>
                </div>
              )}

              {step === 1 && (
                <StepBlock num="02" k={it ? "Identificativi imbarcazione" : "Boat identifiers"}
                  t={it ? "Cosa stiamo tracciando?" : "What are we tracing?"}>
                  {/* Identità barca — i dati che la ricerca SeaVin usa */}
                  <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 16, marginBottom: 16 }}>
                    <Field label={it ? "Cantiere" : "Builder"}>
                      <SuggestInput value={builder}
                        onChange={(v) => { setBuilder(v); setBuilderCountry(""); }}
                        onPick={(nome, cc) => setBuilderCountry(cc || "")}
                        onBlur={() => detectClass()}
                        placeholder={it ? "Lagoon" : "Lagoon"}
                        list={window.SEAVIN_CANTIERI || []}
                        inputStyle={{ border: "1px solid color-mix(in srgb, var(--rule) 75%, transparent)", borderRadius: 12, width: "100%", background: "var(--bg-card)" }}/>
                    </Field>
                    <Field label={it ? "Modello" : "Model"}>
                      <input className="vin-form__input"
                        style={{ border: "1px solid color-mix(in srgb, var(--rule) 75%, transparent)", borderRadius: 12, width: "100%", background: "var(--bg-card)" }}
                        value={model} onChange={e => setModel(e.target.value)}
                        onBlur={() => detectClass()}
                        placeholder={it ? "42" : "42"}/>
                    </Field>
                  </div>
                  <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 16, marginBottom: 16 }}>
                    <Field label={it ? "Nome imbarcazione" : "Boat name"} hint={it ? "per uso charter" : "for charter check"}>
                      <input className="vin-form__input"
                        style={{ border: "1px solid color-mix(in srgb, var(--rule) 75%, transparent)", borderRadius: 12, width: "100%", background: "var(--bg-card)" }}
                        value={boatName} onChange={e => setBoatName(e.target.value)}
                        placeholder={it ? "Orion III" : "Orion III"}/>
                    </Field>
                    <Field label={it ? "Anno" : "Year"}>
                      <input className="vin-form__input"
                        style={{ border: "1px solid color-mix(in srgb, var(--rule) 75%, transparent)", borderRadius: 12, width: "100%", background: "var(--bg-card)" }}
                        value={year} onChange={e => setYear(e.target.value.replace(/[^0-9]/g, "").slice(0, 4))}
                        placeholder="2020" inputMode="numeric"/>
                    </Field>
                  </div>
                  <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 16, marginBottom: 24 }}>
                    <Field label={it ? "Porto attuale / di ormeggio" : "Current / berthing port"} hint={it ? "dov'è ora — per il meteo" : "where it is now — for weather"}>
                      <input className="vin-form__input"
                        style={{ border: "1px solid color-mix(in srgb, var(--rule) 75%, transparent)", borderRadius: 12, width: "100%", background: "var(--bg-card)" }}
                        value={portoAttuale} onChange={e => setPortoAttuale(e.target.value)}
                        placeholder={it ? "es. Cervia" : "e.g. Cervia"}/>
                    </Field>
                    <Field label={it ? "Porto destinazione (opz.)" : "Destination port (opt.)"} hint={it ? "dove vuoi tenerla — per i costi" : "where you'll keep it — for costs"}>
                      <input className="vin-form__input"
                        style={{ border: "1px solid color-mix(in srgb, var(--rule) 90%, transparent)", borderRadius: 12, width: "100%", background: "var(--bg-card)" }}
                        value={porto} onChange={e => setPorto(e.target.value)}
                        placeholder={it ? "es. Alimos Marina" : "e.g. Alimos Marina"}/>
                    </Field>
                  </div>

                  {/* HIN/targa: servono solo per l'estratto ATCN (pacchetto).
                      Per i report senza estratto la sezione non compare. */}
                  {atcn && (
                    <>
                      <div style={{ display: "flex", gap: 2, marginBottom: 24, justifyContent: "center" }}>
                        {[{ k: "hin", l: "HIN (14 char.)" }, { k: "plate", l: it ? "Targa" : "Plate" }].map(o => (
                          <button key={o.k} onClick={() => setMode(o.k)} style={{
                            padding: "12px 18px",
                            border: "1px solid color-mix(in srgb, var(--rule) 75%, transparent)", borderRadius: 12,
                            background: mode === o.k ? "var(--ink)" : "transparent",
                            color: mode === o.k ? "var(--bg)" : "var(--ink)",
                            fontFamily: "var(--font-mono)", fontSize: 12, letterSpacing: "0.08em", textTransform: "uppercase"
                          }}>{o.l}</button>
                        ))}
                      </div>

                      {mode === "hin" && (
                        <Field label="HIN" hint={it ? "14 caratteri · trovabile sullo specchio di poppa" : "14 chars · found on transom"}>
                          <input className="vin-form__input" style={{ border: "1px solid color-mix(in srgb, var(--rule) 75%, transparent)", borderRadius: 12, width: "100%", background: "var(--bg-card)" }}
                            value={hin} onChange={(e) => setHin(e.target.value.toUpperCase())}
                            placeholder="XFA68114F516" />
                        </Field>
                      )}
                      {mode === "plate" && (
                        <>
                          <Field label={it ? "Numero immatricolazione" : "Registration number"}>
                            <input className="vin-form__input" style={{ border: "1px solid color-mix(in srgb, var(--rule) 75%, transparent)", borderRadius: 12, width: "100%", background: "var(--bg-card)" }}
                              value={plate} onChange={(e) => setPlate(e.target.value.toUpperCase())}
                              placeholder="GE 8472" />
                          </Field>
                          <Field label={it ? "Capitaneria" : "Port authority"}>
                            <select style={{ padding: "14px 22px", fontFamily: "var(--font-mono)", fontSize: 15, border: "1px solid color-mix(in srgb, var(--rule) 90%, transparent)", borderRadius: 12, width: "100%", background: "var(--bg-card)" }}>
                              <option>Genova</option><option>La Spezia</option><option>Napoli</option><option>Venezia</option><option>Cagliari</option>
                            </select>
                          </Field>
                        </>
                      )}
                      <div style={{ marginTop: 24, padding: 16, background: "var(--bg-elev)", border: "1px solid color-mix(in srgb, var(--rule) 90%, transparent)", borderRadius: 12 }}>
                        <div style={{ fontSize: 15, fontWeight: 600, color: "var(--ink)", letterSpacing: "0.01em", marginBottom: 10 }}>
                          {it ? "Perché serve l'HIN?" : "Why do we need the HIN?"}
                        </div>
                        <p style={{ fontSize: 14, color: "var(--ink-soft)", lineHeight: 1.6 }}>
                          {it ? "L'estratto ATCN richiede un identificatore univoco dell'unità: l'Hull Identification Number o la targa di immatricolazione permettono la verifica documentale ufficiale sul registro." : "The ATCN extract requires a unique identifier: the Hull Identification Number or the registration plate enable the official registry verification."}
                        </p>
                      </div>
                    </>
                  )}
                </StepBlock>
              )}

              {step === 2 && (
                <StepBlock num="03" k={it ? "Dichiarazioni venditore" : "Seller declarations"}
                  t={it ? "Cosa ti ha detto il venditore?" : "What has the seller told you?"}>
                  <p style={{ fontSize: 15, color: "var(--ink-soft)", marginBottom: 28, lineHeight: 1.65 }}>
                    {it
                      ? "Queste informazioni ci permettono di confrontare quanto dichiarato dal venditore con i dati reali. Vengono incluse nel report come sezione di verifica."
                      : "This information lets us compare what the seller declared against real data. It's included in the report as a verification section."}
                  </p>

                  {/* Prezzo richiesto */}
                  <Field label={it ? "Prezzo richiesto dal venditore" : "Asking price"}>
                    <input className="vin-form__input"
                      style={{ border: "1px solid color-mix(in srgb, var(--rule) 75%, transparent)", borderRadius: 12, width: "100%", background: "var(--bg-card)" }}
                      value={sellerPrice} onChange={e => setSellerPrice(e.target.value)}
                      placeholder={it ? "€ 95.000" : "€ 95,000"}/>
                  </Field>

                  {/* Consumo dichiarato */}
                  <Field label={it ? "Consumo dichiarato dal venditore" : "Declared fuel consumption"}>
                    <input className="vin-form__input"
                      style={{ border: "1px solid color-mix(in srgb, var(--rule) 75%, transparent)", borderRadius: 12, width: "100%", background: "var(--bg-card)" }}
                      value={sellerConsumption} onChange={e => setSellerConsumption(e.target.value)}
                      placeholder={it ? "es. 80 L/h a 25 nodi" : "e.g. 80 L/h at 25 knots"}/>
                  </Field>

                  {/* Sinistri dichiarati */}
                  <div style={{ marginBottom: 16 }}>
                    <div style={{ fontSize: 15, fontWeight: 600, color: "var(--ink)", letterSpacing: "0.01em", marginBottom: 12 }}>
                      {it ? "Ha dichiarato sinistri o danni?" : "Has the seller declared any incidents or damage?"}
                    </div>
                    <div style={{ display: "flex", gap: 8, marginBottom: sellerIncidents === "si" ? 12 : 0, justifyContent: "center" }}>
                      {[{ v: "no", l: it ? "No, nessuno" : "No, none" }, { v: "si", l: it ? "Sì, ha dichiarato" : "Yes, declared" }].map(o => (
                        <button key={o.v} onClick={() => setSellerIncidents(o.v)} style={{
                          padding: "12px 22px", borderRadius: 999, border: "1px solid " + (sellerIncidents === o.v ? "var(--ink)" : "color-mix(in srgb, var(--rule) 90%, transparent)"),
                          background: sellerIncidents === o.v ? "var(--ink)" : "transparent",
                          color: sellerIncidents === o.v ? "var(--bg)" : "var(--ink-mute)",
                          fontSize: 14, fontWeight: 600, transition: "background .18s ease, color .18s ease"
                        }}>{o.l}</button>
                      ))}
                    </div>
                    {sellerIncidents === "si" && (
                      <textarea
                        style={{ width: "100%", padding: "12px 14px", border: "1px solid color-mix(in srgb, var(--rule) 75%, transparent)", borderRadius: 12, background: "var(--bg-card)", fontFamily: "var(--font-mono)", fontSize: 13, resize: "vertical", minHeight: 80, marginTop: 8 }}
                        value={sellerIncidentsDetail} onChange={e => setSellerIncidentsDetail(e.target.value)}
                        placeholder={it ? "Descrivi brevemente: tipo di sinistro, anno, riparazioni..." : "Briefly describe: type of incident, year, repairs..."}/>
                    )}
                  </div>

                  {/* Costo gestione annuo */}
                  <Field label={it ? "Costo di gestione annuo dichiarato" : "Declared annual running cost"}>
                    <input className="vin-form__input"
                      style={{ border: "1px solid color-mix(in srgb, var(--rule) 75%, transparent)", borderRadius: 12, width: "100%", background: "var(--bg-card)" }}
                      value={sellerMgmtCost} onChange={e => setSellerMgmtCost(e.target.value)}
                      placeholder={it ? "es. € 12.000/anno" : "e.g. € 12,000/year"}/>
                  </Field>

                  <div style={{ padding: "12px 16px", borderRadius: 12, background: "var(--secondary-tint)", border: "1px solid color-mix(in oklab, var(--secondary), transparent 60%)" }}>
                    <span style={{ fontSize: 12, letterSpacing: "0.01em", color: "var(--secondary-deep)" }}>
                      {it ? "ⓘ Tutti i campi sono facoltativi ma migliorano la qualità del report." : "ⓘ All fields are optional but improve report quality."}
                    </span>
                  </div>
                </StepBlock>
              )}

              {/* Il passo "Documenti" (caricamento identità/mandato) è stato tolto:
                  la legittimazione servirà solo a chi chiederà l'estratto ATCN e
                  verrà gestita in quella pratica, non nel checkout di tutti. */}

              {step === 3 && (
                <StepBlock num="04" k={it ? "Revisione" : "Review"}
                  t={it ? "Conferma la richiesta" : "Confirm your request"}>
                  <div style={{ border: "1px solid color-mix(in srgb, var(--rule) 75%, transparent)", borderRadius: 12, padding: 24, background: "var(--bg-card)", marginBottom: 24 }}>
                    <div style={{ fontSize: 15, fontWeight: 600, color: "var(--ink)", letterSpacing: "0.01em", marginBottom: 18 }}>
                      {it ? "Dichiarazione" : "Declaration"}
                    </div>
                    <div style={{ fontFamily: "var(--font-display)", fontSize: 22, lineHeight: 1.35, letterSpacing: "-0.015em", marginBottom: 18 }}>
                      {it
                        ? "Dichiaro di essere interessato all'acquisto dell'imbarcazione identificata. Autorizzo SeaVin e i soggetti convenzionati per la verifica documentale a richiedere per mio conto i dati ufficiali presso l'autorità competente."
                        : "I declare that I am interested in purchasing the identified boat. I authorise SeaVin and its affiliated document verification partners to request the official data from the competent authority on my behalf."}
                    </div>
                    <div style={{ marginTop: 16, paddingTop: 16, borderTop: "1px solid var(--rule)" }}>
                      {(builder || model) && <div className="spec"><span className="spec__k">{it ? "Barca" : "Boat"}</span><span className="spec__v">{[builder, model, year].filter(Boolean).join(" ") || "—"}</span></div>}
                      {boatName && <div className="spec"><span className="spec__k">{it ? "Nome" : "Name"}</span><span className="spec__v">{boatName}</span></div>}
                      {(portoAttuale || porto) && <div className="spec"><span className="spec__k">{it ? "Porto" : "Port"}</span><span className="spec__v">{[portoAttuale, porto].filter(Boolean).join(" → ")}</span></div>}
                      <div className="spec"><span className="spec__k">Soggetto</span><span className="spec__v">{hin || plate || "—"}</span></div>
                      <div className="spec" style={{ borderBottom: 0 }}><span className="spec__k">Modalità</span><span className="spec__v">{mode.toUpperCase()}</span></div>
                    </div>

                    {/* Seller declarations summary */}
                    {(sellerPrice || sellerConsumption || sellerIncidents || sellerMgmtCost) && (
                      <div style={{ marginTop: 16, paddingTop: 16, borderTop: "1px solid var(--rule)" }}>
                        <div style={{ fontSize: 15, fontWeight: 600, color: "var(--ink)", letterSpacing: "0.01em", marginBottom: 12 }}>
                          {it ? "Dichiarazioni venditore" : "Seller declarations"}
                        </div>
                        {sellerPrice && <div className="spec"><span className="spec__k">{it ? "Prezzo richiesto" : "Asking price"}</span><span className="spec__v">{sellerPrice}</span></div>}
                        {sellerConsumption && <div className="spec"><span className="spec__k">{it ? "Consumo dichiarato" : "Declared consumption"}</span><span className="spec__v">{sellerConsumption}</span></div>}
                        {sellerIncidents && <div className="spec"><span className="spec__k">{it ? "Sinistri dichiarati" : "Declared incidents"}</span><span className="spec__v">{sellerIncidents === "si" ? (it ? "Sì" : "Yes") : (it ? "Nessuno" : "None")}</span></div>}
                        {sellerMgmtCost && <div className="spec" style={{ borderBottom: 0 }}><span className="spec__k">{it ? "Gestione annua" : "Annual running cost"}</span><span className="spec__v">{sellerMgmtCost}</span></div>}
                      </div>
                    )}

                  </div>
                  <label style={{ display: "flex", gap: 12, cursor: "pointer", padding: 16, border: "1px solid color-mix(in srgb, var(--rule) 90%, transparent)", borderRadius: 12 }}>
                    <input type="checkbox" checked={agree} onChange={(e) => setAgree(e.target.checked)} style={{ marginTop: 4 }}/>
                    <span style={{ fontSize: 14.5, color: "var(--ink-soft)", lineHeight: 1.6 }}>
                      {it ? "Accetto i Termini di Servizio e confermo che i dati forniti sono veritieri. Comprendo che l'uso improprio è perseguibile ex art. 483 c.p." : "I accept the Terms of Service and confirm the data provided is truthful. I understand that misuse is prosecutable under art. 483 CC."}
                    </span>
                  </label>
                </StepBlock>
              )}

              {step === 4 && (
                <StepBlock num="05" k={STRIPE_OFF ? (it ? "Modalità test" : "Test mode") : (it ? "Pagamento sicuro" : "Secure payment")}
                  t={STRIPE_OFF ? (it ? "Nessun addebito · report di test" : "No charge · test report") : (it ? "€ 1 · Addebito immediato" : "€ 1 · Immediate charge")}>

                  {/* Email */}
                  <Field label="Email" hint={it ? "Ricevi la ricevuta qui" : "Receipt sent here"}>
                    <input className="vin-form__input"
                      style={{ border: "1px solid color-mix(in srgb, var(--rule) 75%, transparent)", borderRadius: 12, width: "100%", background: "var(--bg-card)" }}
                      type="email" value={email}
                      onChange={(e) => setEmail(e.target.value)}
                      placeholder="tu@email.it"/>
                    {acctEmail && email === acctEmail && (
                      <div style={{ fontSize: 11.5, color: "var(--accent-deep)", marginTop: 6, letterSpacing: "0.01em" }}>
                        ✓ {it ? "Collegato al tuo account — lo ritrovi in “Richieste report”" : "Linked to your account — find it in “My reports”"}
                      </div>
                    )}
                  </Field>

                  {/* Estratto ATCN proposto SOLO qui per chi ha scelto l'imbarcazione:
                      prezzo pieno +€150 (il prezzo scontato da 79 è solo del pacchetto
                      scelto dal listino). HIN/targa raccolti al volo se mancano. */}
                  {servizio === "imbarcazione" && boatClass && boatClass.tipo === "imbarcazione" && !atcn && (
                    <div style={{ margin: "4px 0 16px", padding: "16px 20px", border: "1px dashed var(--accent-deep)", borderRadius: 14, background: "var(--bg-card)", textAlign: "left" }}>
                      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", gap: 14, flexWrap: "wrap" }}>
                        <div style={{ minWidth: 220, flex: 1 }}>
                          <div style={{ fontSize: 14.5, fontWeight: 600 }}>{it ? "Vuoi anche l'estratto ATCN ufficiale?" : "Want the official ATCN extract too?"}</div>
                          <div style={{ fontSize: 12.5, color: "var(--ink-soft)", marginTop: 4, lineHeight: 1.5 }}>
                            {it ? "Titolarità e gravami certificati dal registro, consegnato in 1–3 giorni insieme al report." : "Certified title and liens from the registry, delivered in 1–3 days alongside the report."}
                          </div>
                        </div>
                        <button type="button" className="btn btn--accent" style={{ flex: "none" }} onClick={() => setAtcn(true)}>
                          {it ? "Aggiungi · +€150" : "Add · +€150"}
                        </button>
                      </div>
                    </div>
                  )}
                  {servizio === "imbarcazione" && atcn && (
                    <div style={{ margin: "4px 0 16px", padding: "14px 20px", border: "1px solid color-mix(in srgb, var(--rule) 90%, transparent)", borderRadius: 14, background: "var(--bg-elev)", textAlign: "left" }}>
                      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", gap: 12, flexWrap: "wrap" }}>
                        <span style={{ fontSize: 13, fontWeight: 600 }}>✓ {it ? "Estratto ATCN aggiunto · +€150" : "ATCN extract added · +€150"}</span>
                        <button type="button" onClick={() => setAtcn(false)}
                          style={{ background: "none", border: "none", color: "var(--accent)", cursor: "pointer", font: "inherit", fontSize: 12.5, padding: 0 }}>
                          {it ? "rimuovi" : "remove"}
                        </button>
                      </div>
                      <div style={{ marginTop: 12 }}>
                        <div style={{ fontSize: 12.5, color: "var(--ink-soft)", marginBottom: 8 }}>
                          {it ? "Per l'estratto serve l'HIN oppure la targa:" : "The extract needs the HIN or the plate:"}
                        </div>
                        <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 10 }}>
                          <input className="vin-form__input" style={{ border: "1px solid color-mix(in srgb, var(--rule) 75%, transparent)", borderRadius: 12, width: "100%", background: "var(--bg-card)" }}
                            value={hin} onChange={(e) => setHin(e.target.value.toUpperCase())} placeholder="HIN · IT-ABC12345D404"/>
                          <input className="vin-form__input" style={{ border: "1px solid color-mix(in srgb, var(--rule) 75%, transparent)", borderRadius: 12, width: "100%", background: "var(--bg-card)" }}
                            value={plate} onChange={(e) => setPlate(e.target.value.toUpperCase())} placeholder={it ? "oppure targa · 1AB2345" : "or plate · 1AB2345"}/>
                        </div>
                        {!(hin.trim() || plate.trim()) && (
                          <div style={{ fontSize: 12, color: "#a6501f", marginTop: 8 }}>
                            {it ? "Compila almeno uno dei due per procedere al pagamento." : "Fill at least one to proceed to payment."}
                          </div>
                        )}
                      </div>
                    </div>
                  )}

                  {/* Errore (sempre visibile, anche in modalità test) */}
                  {paymentError && (
                    <div style={{ padding: 16, background: "color-mix(in oklab, var(--danger), transparent 92%)", border: "1px solid var(--danger)", marginBottom: 12 }}>
                      <span className="mono" style={{ fontSize: 12, color: "var(--danger)", letterSpacing: "0.06em" }}>
                        ⚠ {paymentError}
                      </span>
                    </div>
                  )}

                  {/* Stripe Payment Element — nascosto in TEST MODE */}
                  {!STRIPE_OFF && (
                    <>
                      <div style={{ marginBottom: 18 }}>
                        <div style={{ fontSize: 15, fontWeight: 600, color: "var(--ink)", letterSpacing: "0.01em", marginBottom: 12 }}>
                          {it ? "Dati di pagamento" : "Payment details"}
                        </div>
                        {!clientSecret && (
                          <div style={{ padding: 28, background: "var(--bg-elev)", border: "1px solid color-mix(in srgb, var(--rule) 90%, transparent)", borderRadius: 12, textAlign: "center" }}>
                            <span className="mono" style={{ fontSize: 11, letterSpacing: "0.04em", color: "var(--ink-mute)" }}>
                              {it ? "Connessione a Stripe..." : "Connecting to Stripe..."}
                            </span>
                          </div>
                        )}
                        <div id="stripe-payment-element" style={{ display: clientSecret ? "block" : "none" }}></div>
                      </div>

                      <div style={{ display: "flex", gap: 20, padding: "12px 0", borderTop: "1px solid var(--rule)", marginTop: 8 }}>
                        <span style={{ fontSize: 11, color: "var(--ink-mute)", letterSpacing: "0.03em" }}>🔒 {it ? "Pagamento crittografato SSL" : "SSL encrypted payment"}</span>
                        <span style={{ fontSize: 11, color: "var(--ink-mute)", letterSpacing: "0.03em" }}>✓ {it ? "Gestito da Stripe" : "Powered by Stripe"}</span>
                      </div>
                    </>
                  )}

                  {/* ── Avvio test (DEV / Stripe disattivato): bypassa Stripe ─────────────────── */}
                  {(isDev || STRIPE_OFF) && (
                    <div style={{ marginTop: 24, padding: 16, border: "1px dashed #f59e0b", borderRadius: 12, background: "color-mix(in oklab, #f59e0b, transparent 92%)" }}>
                      <div className="mono" style={{ fontSize: 9.5, letterSpacing: "0.04em", color: "#92400e", marginBottom: 10, textTransform: "uppercase" }}>
                        ⚡ Developer mode · localhost only
                      </div>
                      <p style={{ fontSize: 12, color: "#78350f", marginBottom: 14, lineHeight: 1.5 }}>
                        {it
                          ? <>Bypassa Stripe e avvia direttamente la pipeline AI. Nessun addebito. L'email di report arriva all'indirizzo inserito sopra{email ? <> (<strong>{email}</strong>)</> : ""}.</>
                          : <>Bypasses Stripe and triggers the AI pipeline directly. No charge. Report email goes to the address entered above{email ? <> (<strong>{email}</strong>)</> : ""}.</>}
                      </p>
                      <button
                        onClick={simulatePayment}
                        disabled={paymentLoading || (atcn && !hin.trim() && !plate.trim())}
                        style={{
                          padding: "10px 20px",
                          border: "1px solid #92400e",
                          background: paymentLoading ? "transparent" : "#92400e",
                          color: paymentLoading ? "#92400e" : "#fef3c7",
                          fontFamily: "var(--font-mono)", fontSize: 11,
                          letterSpacing: "0.1em", textTransform: "uppercase",
                          cursor: paymentLoading ? "not-allowed" : "pointer",
                        }}
                      >
                        {paymentLoading
                          ? (it ? "Pipeline AI in esecuzione..." : "AI pipeline running...")
                          : (it ? "⚡ Simula pagamento" : "⚡ Simulate payment")}
                      </button>
                    </div>
                  )}
                </StepBlock>
              )}

              {step === 5 && <ProcessView it={it} jobId={jobId} boatData={{
                hin, plate, mode, boatName, builder, model, year, porto, portoAttuale, email, servizio, atcn,
                sellerPrice, sellerConsumption, sellerIncidents, sellerIncidentsDetail, sellerMgmtCost,
              }}/>}
            </div>

            {/* Sidebar summary — non nella schermata del listino */}
            {step > 0 && <aside style={{ alignSelf: "start", position: "sticky", top: 100 }}>
              <div style={{ border: "1px solid color-mix(in srgb, var(--rule) 75%, transparent)", borderRadius: 16, boxShadow: "var(--cl-shadow)", padding: 24, background: "var(--bg-card)" }}>
                <div style={{ fontSize: 16, fontWeight: 600, color: "var(--ink)", letterSpacing: "0.01em", marginBottom: 20 }}>
                  {it ? "Riepilogo ordine" : "Order summary"}
                </div>
                <div style={{ fontFamily: "var(--font-display)", fontSize: 26, letterSpacing: "-0.02em", lineHeight: 1.15, marginBottom: 20 }}>
                  {servizio === "natante" ? (it ? "Report Natante" : "Small Craft Report")
                    : servizio === "pacchetto" ? (it ? "Report + Estratto ATCN" : "Report + ATCN Extract")
                    : servizio === "imbarcazione" ? (it ? "Report Imbarcazione" : "Vessel Report")
                    : (it ? "Report SeaVin" : "SeaVin Report")}
                </div>
                {atcn && <div className="spec"><span className="spec__k">{it ? "Estratto ATCN ufficiale" : "Official ATCN extract"}</span><span className="spec__v">✓</span></div>}
                <div className="spec"><span className="spec__k">{it ? "14 sezioni analisi" : "14 analyses"}</span><span className="spec__v">✓</span></div>
                <div className="spec"><span className="spec__k">{it ? "Consegna report" : "Report delivery"}</span><span className="spec__v">{it ? "immediata" : "instant"}</span></div>
                {atcn && <div className="spec"><span className="spec__k">{it ? "Consegna estratto" : "Extract delivery"}</span><span className="spec__v">{it ? "1–3 giorni" : "1–3 days"}</span></div>}
                <div className="spec"><span className="spec__k">{it ? "Archivio" : "Vault"}</span><span className="spec__v">10 {it ? "anni" : "years"}</span></div>

                {/* ── Fase 2: classe rilevata automaticamente → prezzo ── */}
                <div style={{ marginTop: 16, paddingTop: 16, borderTop: "1px solid var(--rule)" }}>
                  <div style={{ fontSize: 15, fontWeight: 600, color: "var(--ink)", letterSpacing: "0.01em", marginBottom: 12 }}>
                    {it ? "Classe imbarcazione" : "Boat class"}
                  </div>

                  {detecting && (
                    <div style={{ fontSize: 12.5, color: "var(--ink-mute)" }}>{it ? "Rilevamento automatico…" : "Auto-detecting…"}</div>
                  )}

                  {!detecting && (!boatClass || !builder.trim() || !model.trim()) && (
                    <div style={{ fontSize: 12, color: "var(--ink-mute)", lineHeight: 1.5 }}>
                      {it ? "Inserisci cantiere e modello per calcolare il prezzo." : "Enter builder and model to compute the price."}
                    </div>
                  )}

                  {!detecting && boatClass && builder.trim() && model.trim() && (
                    boatClass.tipo ? (
                      <div>
                        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline", gap: 8 }}>
                          <span style={{ fontSize: 13.5, fontWeight: 500 }}>
                            {boatClass.tipo === "natante" ? (it ? "Natante" : "Small craft") : (it ? "Imbarcazione" : "Boat")}
                            {boatClass.lengthM != null && <span style={{ color: "var(--ink-mute)", fontWeight: 400 }}> · ≈ {boatClass.lengthM} m</span>}
                          </span>
                          <span style={{ fontFamily: "var(--font-display)", fontSize: 20 }}>€ {boatClass.prezzoEUR}</span>
                        </div>
                        <div className="mono" style={{ fontSize: 11, letterSpacing: "0.02em", color: "var(--ink-mute)", marginTop: 5 }}>
                          {boatClass.fonte === "presunto" ? (it ? "classe presunta" : "assumed class")
                            : boatClass.lengthM != null ? (it ? "verificata con ricerca web" : "verified via web search")
                            : (it ? "rilevata" : "detected")}
                        </div>
                        {avvisoClasse && (
                          <div style={{ marginTop: 12, padding: "10px 12px", background: "var(--secondary-tint)", border: "1px solid color-mix(in oklab, var(--secondary), transparent 60%)", fontSize: 12, lineHeight: 1.5, color: "var(--ink)" }}>
                            ⚠ {avvisoClasse}
                          </div>
                        )}
                      </div>
                    ) : (
                      <div style={{ fontSize: 12, color: "var(--ink-mute)", lineHeight: 1.5 }}>
                        {it ? "Rilevazione in corso al prossimo passaggio." : "Detection will run at the next step."}
                      </div>
                    )
                  )}
                </div>

                <div style={{ marginTop: 20, paddingTop: 20, borderTop: "1px solid color-mix(in srgb, var(--rule) 60%, transparent)", display: "flex", justifyContent: "space-between", alignItems: "baseline" }}>
                  <span style={{ fontSize: 15, fontWeight: 600, color: "var(--ink)" }}>{it ? "Totale" : "Total"}</span>
                  <span style={{ fontFamily: "var(--font-display)", fontSize: 44, letterSpacing: "-0.03em" }}>
                    {listinoEUR != null ? `€ ${listinoEUR}` : "€ —"}
                  </span>
                </div>
                <div style={{ fontSize: 11, color: "var(--ink-faint)", letterSpacing: "0.02em", textAlign: "right", marginTop: 4 }}>
                  {it ? "IVA inclusa" : "VAT included"}
                </div>
              </div>

              {step > 0 && step < 5 && (
                <div style={{ marginTop: 16, display: "flex", gap: 8 }}>
                  {step > 0 && (
                    <button className="btn btn--ghost" style={{ flex: "0 0 auto" }} onClick={back}>←</button>
                  )}
                  {step === 4 ? (STRIPE_OFF ? null : (
                    <button
                      className="btn btn--accent"
                      style={{ flex: 1, opacity: (!stripeReady || paymentLoading) ? 0.6 : 1 }}
                      onClick={confirmPayment}
                      disabled={!stripeReady || paymentLoading || !email || (atcn && !hin.trim() && !plate.trim())}
                    >
                      {paymentLoading
                        ? (it ? "Elaborazione..." : "Processing...")
                        : (it ? `Paga € ${listinoEUR != null ? listinoEUR : "—"} →` : `Pay € ${listinoEUR != null ? listinoEUR : "—"} →`)}
                    </button>
                  )) : (
                    <button
                      className="btn btn--accent"
                      style={{ flex: 1 }}
                      onClick={next}
                      disabled={(step === 0 && !servizio) || (step === 3 && !agree)}
                    >
                      {it ? "Continua" : "Continue"} →
                    </button>
                  )}
                </div>
              )}

              <div style={{ marginTop: 24, padding: 18, border: "1px dashed color-mix(in srgb, var(--rule) 80%, transparent)", borderRadius: 12 }}>
                <Stamp>SeaVin · Verified 0042-IT</Stamp>
                <p style={{ fontSize: 12, color: "var(--ink-mute)", marginTop: 12, lineHeight: 1.5 }}>
                  {it ? "Verifica documentale ufficiale. Firma digitale eIDAS." : "Official document verification. eIDAS digital signing."}
                </p>
              </div>
            </aside>}
          </div>
        </div>
      </section>
    </Page>
  );
}

function StepBlock({ num, k, t, children }) {
  return (
    <div style={{ textAlign: "center" }}>
      <div style={{ marginBottom: 26 }}>
        <div style={{ display: "inline-flex", alignItems: "center", gap: 8, marginBottom: 12 }}>
          <span style={{ display: "inline-flex", alignItems: "center", fontSize: 11, fontWeight: 600, letterSpacing: "0.02em", background: "color-mix(in srgb, var(--ink) 7%, transparent)", color: "var(--ink-soft)", padding: "4px 12px", borderRadius: 999 }}>
            {num}
          </span>
          <span style={{ fontSize: 12.5, color: "var(--ink-mute)" }}>{k}</span>
        </div>
        <h2 style={{ fontSize: "var(--step-3)", letterSpacing: "-0.03em", lineHeight: 1 }}>{t}</h2>
      </div>
      {children}
    </div>
  );
}

/* Campo con autocompletamento (stile boat24): digitando compaiono i
   suggerimenti con la BANDIERA di provenienza, cliccabili o navigabili
   con le frecce. La ricerca ignora trattini, spazi e punteggiatura
   ("sead", "sea d" e "sea-d" trovano tutti Sea-Doo).
   Le voci sono coppie [nome, paeseISO]; paese "" = provenienza incerta,
   quindi NIENTE bandiera (mai bandiere sbagliate). Sprite: assets/flags.svg,
   iniettato una volta nel DOM (l'<use> esterno non è affidabile ovunque). */
function caricaBandiere() {
  if (document.getElementById("seavin-flags")) return;
  const div = document.createElement("div");
  div.id = "seavin-flags";
  div.style.display = "none";
  document.body.appendChild(div);
  fetch("assets/flags.svg").then(r => r.text()).then(svg => { div.innerHTML = svg; }).catch(() => {});
}

function SuggestInput({ value, onChange, onPick, onBlur, placeholder, list, inputStyle }) {
  const [open, setOpen] = useState(false);
  const [hi, setHi] = useState(-1);
  useEffect(() => { caricaBandiere(); }, []);
  // chiave permissiva: minuscole, senza accenti, SOLO lettere e numeri
  const chiave = (s) => String(s || "").toLowerCase().normalize("NFD")
    .replace(/[̀-ͯ]/g, "").replace(/[^a-z0-9]+/g, "");
  const q = chiave(value);
  const matches = useMemo(() => {
    if (q.length < 2) return [];
    const inizia = [], contiene = [];
    for (const voce of (list || [])) {
      const nome = Array.isArray(voce) ? voce[0] : voce;
      const cc = (Array.isArray(voce) && voce[1]) ? voce[1] : "";
      const n = chiave(nome);
      if (n === q) continue;          // già scritto per esteso: niente tendina
      if (n.startsWith(q)) { if (inizia.length < 40) inizia.push([nome, cc]); }
      else if (contiene.length < 12 && n.includes(q)) contiene.push([nome, cc]);
      if (inizia.length >= 40) break;
    }
    return inizia.concat(contiene).slice(0, 40);
  }, [q, list]);

  const visibile = open && matches.length > 0;
  const pick = (nome, cc) => {
    onChange(nome);
    if (onPick) onPick(nome, cc || "");  // dalla tendina il paese è certo
    setOpen(false); setHi(-1);
  };
  const onKey = (e) => {
    if (!visibile) return;
    if (e.key === "ArrowDown") { e.preventDefault(); setHi(h => (h + 1) % matches.length); }
    else if (e.key === "ArrowUp") { e.preventDefault(); setHi(h => (h - 1 + matches.length) % matches.length); }
    else if (e.key === "Enter") { if (hi >= 0) { e.preventDefault(); pick(matches[hi][0], matches[hi][1]); } }
    else if (e.key === "Escape") { setOpen(false); setHi(-1); }
  };

  /* Come boat24: la parte già digitata resta leggera, il RESTO in grassetto.
     La ricerca ignora trattini/spazi, quindi mappo ogni carattere della
     chiave sul carattere corrispondente del nome originale ("sea d" evidenzia
     correttamente dentro "Sea-Doo"). */
  const evidenzia = (nome) => {
    const mappa = []; let k = "";
    for (let i = 0; i < nome.length; i++) {
      const c = nome[i].toLowerCase().normalize("NFD").replace(/[̀-ͯ]/g, "").replace(/[^a-z0-9]/g, "");
      for (const ch of c) { mappa.push(i); k += ch; }
    }
    const pos = k.indexOf(q);
    if (q.length < 2 || pos < 0) return <span>{nome}</span>;
    const inizio = mappa[pos];
    const fine = mappa[pos + q.length - 1] + 1;
    return (
      <span>
        {inizio > 0 && <b style={{ fontWeight: 700 }}>{nome.slice(0, inizio)}</b>}
        <span style={{ fontWeight: 400, opacity: 0.6 }}>{nome.slice(inizio, fine)}</span>
        <b style={{ fontWeight: 700 }}>{nome.slice(fine)}</b>
      </span>
    );
  };

  return (
    <div style={{ position: "relative" }}>
      <input className="vin-form__input" style={inputStyle} value={value}
        placeholder={placeholder} autoComplete="off" spellCheck={false}
        onChange={e => { onChange(e.target.value); setOpen(true); setHi(-1); }}
        onFocus={() => setOpen(true)}
        onBlur={(e) => { if (onBlur) onBlur(e); setTimeout(() => { setOpen(false); setHi(-1); }, 150); }}
        onKeyDown={onKey}/>
      {visibile && (
        <div style={{ position: "absolute", top: "100%", left: 0, right: 0, zIndex: 30,
          background: "var(--bg-card)", border: "1px solid color-mix(in srgb, var(--rule) 75%, transparent)", borderRadius: 12, borderTop: "none",
          maxHeight: 300, overflowY: "auto", boxShadow: "0 12px 28px rgba(11,37,64,.14)" }}>
          {matches.map(([nome, cc], i) => (
            <div key={nome + cc}
              onMouseDown={e => { e.preventDefault(); pick(nome, cc); }}
              onMouseEnter={() => setHi(i)}
              style={{ padding: "8px 12px", cursor: "pointer", fontSize: 14, textAlign: "left",
                display: "flex", alignItems: "center", gap: 10,
                background: i === hi ? "var(--ink)" : "transparent",
                color: i === hi ? "var(--bg)" : "var(--ink)" }}>
              {/* nome a filo sinistro (si scorrono i prefissi), bandiera a destra */}
              <span style={{ flex: 1, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{evidenzia(nome)}</span>
              <span style={{ width: 21, height: 15, flex: "none", display: "inline-block" }}>
                {cc && (
                  <svg width="20" height="15" viewBox="0 0 640 480" style={{ display: "block", outline: "1px solid rgba(11,37,64,.15)" }}>
                    <use href={"#fl-" + cc.toLowerCase()}/>
                  </svg>
                )}
              </span>
            </div>
          ))}
        </div>
      )}
    </div>
  );
}

function Field({ label, hint, children }) {
  return (
    <div style={{ marginBottom: 20 }}>
      <div style={{ textAlign: "center", marginBottom: 10 }}>
        <div style={{ fontSize: 15, fontWeight: 600, color: "var(--ink)", letterSpacing: "0.01em" }}>{label}</div>
      </div>
      {children}
      {hint && <div style={{ fontSize: 13, color: "var(--ink-faint)", textAlign: "center", marginTop: 7 }}>{hint}</div>}
    </div>
  );
}

/* ============================================================
   ProcessView — pannello trasparente che mostra:
   • Dati raccolti dal checkout
   • Log live della pipeline AI (ricerche + risultati)
   • Report finale con tutti gli step
   ============================================================ */
function ProcessView({ it, jobId, boatData }) {
  const [job, setJob] = useState(null);
  const [pollError, setPollError] = useState(null);

  useEffect(() => {
    if (!jobId) return;
    let cancelled = false;
    let timer = null;

    const poll = async () => {
      try {
        const res = await fetch(`${API}/api/job/${jobId}`);
        if (!res.ok) throw new Error(`HTTP ${res.status}`);
        const data = await res.json();
        if (cancelled) return;
        setJob(data);
        setPollError(null);
        if (data.status !== "complete" && data.status !== "error") {
          timer = setTimeout(poll, 1500);
        }
      } catch (err) {
        if (!cancelled) {
          setPollError(err.message);
          timer = setTimeout(poll, 3000);
        }
      }
    };
    poll();
    return () => { cancelled = true; if (timer) clearTimeout(timer); };
  }, [jobId]);

  const statusLabel = {
    pending:       it ? "In coda"               : "Queued",
    running:       it ? "Analisi in corso..."   : "Running...",
    report_ready:  it ? "✓ Report pronto — invio email…" : "✓ Report ready — sending email…",
    email_sending: it ? "✓ Report pronto — invio email…" : "✓ Report ready — sending email…",
    complete:      it ? "✓ Completato"          : "✓ Complete",
    error:         it ? "✗ Errore"              : "✗ Error",
  };
  const statusColor = {
    pending: "#8a7f70", running: "#2e6e82", report_ready: "#1b7a3e", email_sending: "#1b7a3e",
    complete: "#1b7a3e", error: "#9e2a1e",
  };

  const status = job?.status || "pending";
  /* Il report è fruibile appena esiste: PDF ed email proseguono in background. */
  const reportVisible = status === "complete" || status === "report_ready" || status === "email_sending";
  const subject = boatData.hin || boatData.plate || boatData.boatName || "—";

  return (
    <StepBlock num="06" k={it ? "Pipeline trasparente" : "Transparent pipeline"}
      t={it ? "Tutto quello che sta succedendo" : "Everything that's happening"}>

      {!jobId && (
        <div style={{ padding: 24, border: "1px solid color-mix(in srgb, var(--rule) 90%, transparent)", borderRadius: 12, background: "var(--bg-card)" }}>
          <span className="mono" style={{ fontSize: 12, color: "var(--ink-mute)" }}>
            {it ? "Nessun job attivo." : "No active job."}
          </span>
        </div>
      )}

      {jobId && (
        <>
          {/* Status bar — con l'ondina del logo che galleggia finché si lavora */}
          <div style={{ padding: "16px 20px", background: "var(--ink)", color: "var(--bg)", marginBottom: 20, display: "flex", justifyContent: "space-between", alignItems: "center", flexWrap: "wrap", gap: 10 }}>
            <div>
              <div className="mono" style={{ fontSize: 10, letterSpacing: "0.04em", opacity: 0.6, marginBottom: 4 }}>JOB ID</div>
              <div className="mono" style={{ fontSize: 13 }}>{jobId}</div>
            </div>
            {status !== "complete" && status !== "error" && (
              <OndaMark className="onda-loader" style={{ display: "block", width: 64, height: "auto", opacity: 0.9 }}/>
            )}
            <div style={{ textAlign: "right" }}>
              <div className="mono" style={{ fontSize: 10, letterSpacing: "0.04em", opacity: 0.6, marginBottom: 4 }}>STATO</div>
              <div className="mono" style={{ fontSize: 13, color: reportVisible ? "#6ee7a0" : status === "error" ? "#f87171" : "#7fb0be" }}>
                {statusLabel[status] || status}
              </div>
            </div>
          </div>

          {pollError && (
            <div style={{ padding: 12, background: "#fef2f2", border: "1px solid #9e2a1e", marginBottom: 16 }}>
              <span className="mono" style={{ fontSize: 11, color: "#9e2a1e" }}>⚠ Polling error: {pollError}</span>
            </div>
          )}

          {/* ── Sezione 1: Dati raccolti ── */}
          <Section title={it ? "1 · Dati raccolti dal checkout" : "1 · Data collected from checkout"}>
            <div style={{ background: "var(--bg-card)", border: "1px solid color-mix(in srgb, var(--rule) 90%, transparent)", borderRadius: 12, padding: 16 }}>
              <DataRow k={it ? "Barca" : "Boat"} v={[boatData.builder, boatData.model, boatData.year].filter(Boolean).join(" ")}/>
              <DataRow k={it ? "Nome imbarcazione" : "Boat name"} v={boatData.boatName}/>
              <DataRow k={it ? "Porto attuale" : "Current port"} v={boatData.portoAttuale}/>
              <DataRow k={it ? "Porto destinazione" : "Destination port"} v={boatData.porto}/>
              <DataRow k={it ? "Identificatore"    : "Identifier"} v={subject + " (" + (boatData.mode || "hin").toUpperCase() + ")"}/>
              <DataRow k="Email" v={boatData.email}/>
              <DataRow k={it ? "Prezzo venditore"   : "Asking price"} v={boatData.sellerPrice}/>
              <DataRow k={it ? "Consumo dichiarato" : "Declared consumption"} v={boatData.sellerConsumption}/>
              <DataRow k={it ? "Sinistri" : "Incidents"} v={boatData.sellerIncidents === "si" ? `Sì — ${boatData.sellerIncidentsDetail || "—"}` : boatData.sellerIncidents === "no" ? (it ? "Nessuno" : "None") : null}/>
              <DataRow k={it ? "Gestione annua" : "Annual cost"} v={boatData.sellerMgmtCost} last/>
            </div>
          </Section>

          {/* ── Sezione 2: Log pipeline live ── */}
          <Section title={it ? "2 · Log pipeline AI (live)" : "2 · AI pipeline log (live)"}>
            <div style={{ background: "#0f1419", color: "#c9d1d9", fontFamily: "var(--font-mono)", fontSize: 12, padding: 16, maxHeight: 380, overflowY: "auto", border: "1px solid color-mix(in srgb, var(--rule) 75%, transparent)", borderRadius: 12, lineHeight: 1.6 }}>
              {(!job || !job.events || job.events.length === 0) && (
                <div style={{ opacity: 0.5 }}>{it ? "In attesa..." : "Waiting..."}</div>
              )}
              {(job?.events || []).map((ev, i) => <LogLine key={i} ev={ev} it={it}/>)}
              {(status === "running" || status === "report_ready" || status === "email_sending") && (
                <div style={{ opacity: 0.7, marginTop: 6 }}>▌<span style={{ animation: "blink 1s infinite" }}></span></div>
              )}
            </div>
            {job?.usage && typeof job.usage === "object" && (
              <div style={{ marginTop: 8, display: "flex", gap: 14, flexWrap: "wrap" }}>
                {typeof job.usage.input_tokens === "number" && (
                  <span className="mono" style={{ fontSize: 10.5, color: "var(--ink-mute)" }}>
                    TOKEN IN: {job.usage.input_tokens.toLocaleString()} · OUT: {Number(job.usage.output_tokens || 0).toLocaleString()}
                  </span>
                )}
                {job.usage.marketAnnunci?.puliti != null && (
                  <span className="mono" style={{ fontSize: 10.5, color: "var(--ink-mute)" }}>ANNUNCI: {job.usage.marketAnnunci.puliti}</span>
                )}
                {job.usage.photos != null && (
                  <span className="mono" style={{ fontSize: 10.5, color: "var(--ink-mute)" }}>FOTO: {job.usage.photos}</span>
                )}
                {job.usage.concorrentiCount != null && (
                  <span className="mono" style={{ fontSize: 10.5, color: "var(--ink-mute)" }}>CONCORRENTI: {job.usage.concorrentiCount}</span>
                )}
                {job.usage.raccVoto != null && (
                  <span className="mono" style={{ fontSize: 10.5, color: "var(--ink-mute)" }}>VOTO: {job.usage.raccVoto}</span>
                )}
              </div>
            )}
          </Section>

          {/* ── Sezione 3: Ricerche web dettagliate ── */}
          {job?.searches?.length > 0 && (
            <Section title={it ? `3 · Ricerche web eseguite (${job.searches.length})` : `3 · Web searches (${job.searches.length})`}>
              {job.searches.map((s, i) => (
                <div key={i} style={{ border: "1px solid color-mix(in srgb, var(--rule) 90%, transparent)", borderRadius: 12, background: "var(--bg-card)", marginBottom: 10, padding: 14 }}>
                  <div className="mono" style={{ fontSize: 11, color: "#2e6e82", marginBottom: 8, letterSpacing: "0.04em" }}>
                    🔍 "{s.query}"
                  </div>
                  {s.error && (
                    <div style={{ fontSize: 12, color: "#9e2a1e", fontStyle: "italic" }}>Errore: {s.error}</div>
                  )}
                  {s.results?.length > 0 && (
                    <div style={{ fontSize: 12, lineHeight: 1.5 }}>
                      {s.results.map((r, j) => (
                        <div key={j} style={{ marginBottom: 6, paddingLeft: 16, borderLeft: "2px solid var(--rule)" }}>
                          <a href={r.url} target="_blank" rel="noopener" style={{ color: "var(--ink)", fontWeight: 500, textDecoration: "underline" }}>{r.title || r.url}</a>
                          <div className="mono" style={{ fontSize: 10, color: "var(--ink-mute)", marginTop: 2, wordBreak: "break-all" }}>{r.url}{r.page_age && " · " + r.page_age}</div>
                        </div>
                      ))}
                    </div>
                  )}
                </div>
              ))}
            </Section>
          )}

          {/* ── Sezione 4: Report finale (foglio.html incorporato) ── */}
          {reportVisible && (
            <Section title={it ? "4 · Il tuo report" : "4 · Your report"}>
              <iframe
                src={`${API}/report/${jobId}`}
                style={{ width: "100%", height: 1000, border: "1px solid color-mix(in srgb, var(--rule) 75%, transparent)", borderRadius: 12, background: "#fff", display: "block" }}
                title="Report SeaVin"
              />
              <div style={{ marginTop: 10, display: "flex", gap: 16, flexWrap: "wrap", justifyContent: "center" }}>
                <a className="mono" href={`${API}/report/${jobId}`} target="_blank" rel="noopener"
                  style={{ fontSize: 11, letterSpacing: "0.08em", color: "var(--ink)", textDecoration: "underline" }}>
                  {it ? "Apri il report in una nuova scheda ↗" : "Open report in new tab ↗"}
                </a>
                {job?.emailSent && (
                  <span className="mono" style={{ fontSize: 11, color: "#1b7a3e" }}>
                    ✓ {it ? `Link inviato a ${boatData.email}` : "Link emailed"}
                  </span>
                )}
                {!job?.emailSent && status !== "complete" && (
                  <span className="mono" style={{ fontSize: 11, color: "var(--ink-mute)" }}>
                    {it ? "Invio email in corso…" : "Sending email…"}
                  </span>
                )}
              </div>
            </Section>
          )}

          {/* ── Errore globale ── */}
          {status === "error" && job?.error && (
            <div style={{ padding: 16, background: "#fef2f2", border: "1px solid #9e2a1e", marginTop: 20 }}>
              <div className="mono" style={{ fontSize: 11, color: "#9e2a1e", letterSpacing: "0.1em", marginBottom: 6 }}>PIPELINE ERROR</div>
              <div style={{ fontSize: 13, color: "#7f1d1d", wordBreak: "break-word" }}>{job.error}</div>
            </div>
          )}
        </>
      )}
    </StepBlock>
  );
}

function Section({ title, children }) {
  return (
    <div style={{ marginBottom: 24 }}>
      <div style={{ fontSize: 15, fontWeight: 600, color: "var(--ink)", letterSpacing: "0.01em", marginBottom: 12 }}>
        {title}
      </div>
      {children}
    </div>
  );
}

function DataRow({ k, v, last }) {
  return (
    <div style={{
      display: "flex", justifyContent: "space-between", gap: 16,
      padding: "8px 0", borderBottom: last ? 0 : "1px solid var(--rule)",
      fontSize: 13,
    }}>
      <span style={{ fontSize: 12, letterSpacing: "0.01em", color: "var(--ink-mute)" }}>{k}</span>
      <span style={{ textAlign: "right", color: v ? "var(--ink)" : "var(--ink-faint)" }}>{v || "—"}</span>
    </div>
  );
}

function LogLine({ ev, it }) {
  const time = new Date(ev.ts).toLocaleTimeString("it-IT", { hour12: false });
  const base = { display: "flex", gap: 10 };
  const timeStyle = { color: "#6e7681", flexShrink: 0 };

  if (ev.type === "search_query") {
    return <div style={base}><span style={timeStyle}>{time}</span><span>🔍 <span style={{ color: "#79c0ff" }}>web_search</span> query: <span style={{ color: "#a5d6ff" }}>"{ev.query}"</span></span></div>;
  }
  if (ev.type === "search_results") {
    return <div style={base}><span style={timeStyle}>{time}</span><span style={{ color: "#7ee787" }}>   → {ev.count} {it ? "risultati" : "results"}</span></div>;
  }
  if (ev.type === "search_error") {
    return <div style={base}><span style={timeStyle}>{time}</span><span style={{ color: "#f87171" }}>   ✗ {ev.error}</span></div>;
  }
  if (ev.type === "text_block") {
    return <div style={base}><span style={timeStyle}>{time}</span><span style={{ color: "#d2a8ff" }}>✎ text ({ev.text.length} char)</span></div>;
  }
  if (ev.type === "prompt_sent") {
    return <div style={base}><span style={timeStyle}>{time}</span><span style={{ color: "#ffa657" }}>→ prompt inviato (system: {ev.systemPromptLen}ch, user: {ev.userPromptLen}ch)</span></div>;
  }
  if (ev.type === "complete") {
    return <div style={base}><span style={timeStyle}>{time}</span><span style={{ color: "#7ee787" }}>✓ analisi completata — {ev.searches} ricerche · {ev.textLen} char</span></div>;
  }
  if (ev.type === "error") {
    return <div style={base}><span style={timeStyle}>{time}</span><span style={{ color: "#f87171" }}>✗ {ev.text}</span></div>;
  }
  const prefix = ev.level === "warn" ? "⚠" : ev.level === "error" ? "✗" : "•";
  const color  = ev.level === "warn" ? "#ffa657" : ev.level === "error" ? "#f87171" : "#8b949e";
  return <div style={base}><span style={timeStyle}>{time}</span><span style={{ color }}>{prefix} {ev.text}</span></div>;
}

/* ── Error Boundary: una pagina bianca non deve MAI piu accadere.
   Se un render lancia, mostra un fallback leggibile invece dello schermo vuoto. ── */
class AppErrorBoundary extends React.Component {
  constructor(props) { super(props); this.state = { err: null }; }
  static getDerivedStateFromError(err) { return { err }; }
  componentDidCatch(err, info) { console.error("[SeaVin] errore di rendering:", err, info); }
  render() {
    if (this.state.err) {
      const jid = new URLSearchParams(window.location.search).get("job");
      return (
        <div style={{ maxWidth: 640, margin: "80px auto", padding: 32, fontFamily: "var(--font-mono, monospace)", color: "#15130e" }}>
          <div style={{ fontSize: 12, letterSpacing: "0.04em", color: "#9e2a1e", marginBottom: 12 }}>ERRORE DI VISUALIZZAZIONE</div>
          <h2 style={{ fontFamily: "var(--font-display, serif)", fontSize: 26, margin: "0 0 12px" }}>Qualcosa è andato storto nel mostrare la pagina</h2>
          <p style={{ fontSize: 14, lineHeight: 1.6, color: "#4a463d" }}>
            Il report è comunque al sicuro. {jid
              ? <>Puoi aprirlo direttamente qui: <a href={`${API}/report/${jid}`} target="_blank" rel="noopener" style={{ color: "#1f4a5c" }}>apri il report ↗</a>.</>
              : <>Ricarica la pagina; se persiste, riprova dal tuo profilo.</>}
          </p>
          <div style={{ marginTop: 16, display: "flex", gap: 12 }}>
            <button onClick={() => location.reload()} style={{ padding: "10px 18px", border: "1px solid #15130e", background: "transparent", cursor: "pointer", fontFamily: "inherit", fontSize: 12, letterSpacing: "0.08em" }}>RICARICA</button>
            <a href="dashboard.html#requests" style={{ padding: "10px 18px", border: "1px solid #15130e", textDecoration: "none", color: "#15130e", fontSize: 12, letterSpacing: "0.08em" }}>I MIEI REPORT</a>
          </div>
          <pre style={{ marginTop: 20, fontSize: 11, color: "#9aa0a6", whiteSpace: "pre-wrap" }}>{String(this.state.err && this.state.err.message || this.state.err)}</pre>
        </div>
      );
    }
    return this.props.children;
  }
}

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