/* ------------------------------------------------------------------ *
 *  Mobile wizard — formulaire step-by-step (< 768 px)
 * ------------------------------------------------------------------ */

function useIsMobile() {
  const [is, setIs] = useState(() => window.innerWidth < 768);
  useEffect(() => {
    function h() { setIs(window.innerWidth < 768); }
    window.addEventListener('resize', h);
    return () => window.removeEventListener('resize', h);
  }, []);
  return is;
}

/* ---- small shared UI ---- */

function CheckIcon({ size = 10 }) {
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor"
         strokeWidth="3" strokeLinecap="round" strokeLinejoin="round">
      <path d="M4 12l5 5L20 6"/>
    </svg>
  );
}

function ChevronIcon({ down }) {
  return (
    <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor"
         strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"
         className={`transition-transform duration-200 ${down ? 'rotate-180' : ''}`}>
      <path d="M6 9l6 6 6-6"/>
    </svg>
  );
}

function RadioCard({ active, onClick, children }) {
  return (
    <button onClick={onClick}
            className={`w-full text-left p-4 rounded-2xl border transition-all
                        ${active
                          ? 'border-brand-500 bg-white shadow-pop ring-1 ring-brand-500/20'
                          : 'border-ink-200 bg-white shadow-card active:border-ink-300'}`}>
      <div className="flex items-start gap-3">
        <div className={`w-5 h-5 rounded-full border-2 mt-0.5 shrink-0 grid place-items-center
                        ${active ? 'border-brand-500 bg-brand-500 text-white' : 'border-ink-300 bg-white'}`}>
          {active && <CheckIcon />}
        </div>
        <div className="flex-1 min-w-0">{children}</div>
      </div>
    </button>
  );
}

/* ================================================================== *
 *  Step components
 * ================================================================== */

function StepMachine({ machine, changeMachine, prixEcosysteme, setPrixEcosysteme, prixCustomise, setPrixCustomise, MACHINES, t, currencySymbol }) {
  const { NumberInput } = window;
  return (
    <div className="px-4 py-5 space-y-3">
      <div>
        <h2 className="text-[17px] font-semibold text-ink-900">{t('sel1.title')}</h2>
        <p className="text-[13px] text-ink-500 mt-0.5">{t('sel1.sub')}</p>
      </div>
      <div className="space-y-2.5">
        {MACHINES.map(m => (
          <RadioCard key={m.id} active={machine === m.id} onClick={() => changeMachine(m.id)}>
            <div className="font-semibold text-ink-900 text-[15px]">{m.label}</div>
            <div className="text-[12.5px] text-ink-500 mt-0.5">{t('machines.' + m.id + '.sub')}</div>
            <div className="text-[11.5px] text-ink-400 mt-1">{t('machines.' + m.id + '.blurb')}</div>
          </RadioCard>
        ))}
      </div>
      <div className="bg-white rounded-xl border border-ink-200 p-4">
        <div className="text-[12.5px] font-medium text-ink-700 mb-2">{t('sel1.prix.label')}</div>
        <div className="flex items-center gap-3">
          <NumberInput value={prixEcosysteme}
                       onChange={v => { setPrixEcosysteme(v); setPrixCustomise(true); }}
                       suffix={currencySymbol}/>
          {prixCustomise && (
            <button onClick={() => { setPrixCustomise(false); setPrixEcosysteme(MACHINES.find(m => m.id === machine).prixDefaut); }}
                    className="text-[11px] text-brand-600 underline shrink-0">
              {t('sel1.prix.restore')}
            </button>
          )}
        </div>
        <p className="text-[11px] text-ink-400 italic mt-1">{t('sel1.prix.note')}</p>
      </div>
    </div>
  );
}

function StepMaterial({ midasMat, setMidasMat, midasMatCouts, setMidasMatCouts, MIDAS_MATERIAUX, t, currencySymbol }) {
  const { NumberInput } = window;
  return (
    <div className="px-4 py-5 space-y-3">
      <div>
        <h2 className="text-[17px] font-semibold text-ink-900">{t('sel2.title')}</h2>
        <p className="text-[13px] text-ink-500 mt-0.5">{t('sel2.sub')}</p>
      </div>
      <div className="space-y-2.5">
        {MIDAS_MATERIAUX.map(m => (
          <RadioCard key={m.id} active={midasMat === m.id} onClick={() => setMidasMat(m.id)}>
            <div className="font-semibold text-ink-900 text-[15px]">{m.label}</div>
            <div className="text-[12.5px] text-ink-500 mt-0.5">{t('mat.' + m.id + '.sub')}</div>
            <div className="text-[11.5px] text-ink-400 mt-1">{t('mat.' + m.id + '.blurb')}</div>
            <div className="mt-3 pt-3 border-t border-ink-100 flex items-center justify-between"
                 onClick={e => e.stopPropagation()}>
              <span className="text-[11px] uppercase tracking-wider text-ink-400">{t('sel2.cout')}</span>
              <NumberInput value={midasMatCouts[m.id]}
                           onChange={v => setMidasMatCouts(c => ({ ...c, [m.id]: v }))}
                           suffix={currencySymbol} step={0.01}
                           ariaLabel={t('sel2.cout') + ' ' + m.label}/>
            </div>
          </RadioCard>
        ))}
      </div>
      <p className="text-[11.5px] text-ink-400 italic">{t('sel2.note')}</p>
    </div>
  );
}

function StepDesign({ designMode, setDesignMode, fraisDesignCustom, setFraisDesignCustom, MODES_DESIGN, t, currencySymbol }) {
  const { NumberInput } = window;
  return (
    <div className="px-4 py-5 space-y-3">
      <div>
        <h2 className="text-[17px] font-semibold text-ink-900">{t('sel3.title')}</h2>
        <p className="text-[13px] text-ink-500 mt-0.5">{t('sel3.sub')}</p>
      </div>
      <div className="space-y-2.5">
        {MODES_DESIGN.map(m => {
          const active = designMode === m.id;
          return (
            <RadioCard key={m.id} active={active} onClick={() => setDesignMode(m.id)}>
              <div className="font-semibold text-ink-900 text-[15px]">{t('design.' + m.id + '.label')}</div>
              <div className="text-[12.5px] text-ink-500 mt-0.5">{t('design.' + m.id + '.sub')}</div>
              <div className="text-[11.5px] text-ink-400 mt-1">{t('design.' + m.id + '.hint')}</div>
              <div className="mt-3 pt-3 border-t border-ink-100 flex items-center justify-between"
                   onClick={e => e.stopPropagation()}>
                <span className="text-[11px] uppercase tracking-wider text-ink-400">{t('sel3.frais')}</span>
                {m.fixe ? (
                  <span className="text-[13px] font-semibold tnum text-ink-300">0 {currencySymbol}</span>
                ) : (
                  <NumberInput value={fraisDesignCustom[m.id]}
                               onChange={v => setFraisDesignCustom(f => ({ ...f, [m.id]: v }))}
                               suffix={currencySymbol}
                               ariaLabel={t('sel3.frais')}/>
                )}
              </div>
            </RadioCard>
          );
        })}
      </div>
    </div>
  );
}

function VolumeCard({ r, fraisDesign, onSetVal, onToggle, t, fmt, currencySymbol }) {
  const { NumberInput, calculerLigne } = window;
  const [expanded, setExpanded] = useState(false);
  const c = calculerLigne(r, fraisDesign);
  const label = t('cat.' + r.id + '.label');

  return (
    <div className={`bg-white rounded-xl border transition-all ${r.actif ? 'border-ink-200' : 'border-ink-100 opacity-55'}`}>
      {/* Header row */}
      <div className="flex items-center gap-2.5 px-3.5 pt-3 pb-2">
        <button onClick={() => onToggle(r.id)}
                className={`w-5 h-5 rounded border-2 shrink-0 grid place-items-center transition
                            ${r.actif ? 'bg-brand-500 border-brand-500 text-white' : 'bg-white border-ink-300'}`}>
          {r.actif && <CheckIcon />}
        </button>
        <div className="flex-1 min-w-0">
          <div className="text-[13px] font-medium text-ink-900 truncate">{label}</div>
          <div className="text-[10.5px] text-ink-400 truncate">{t('cat.' + r.id + '.sub')}</div>
        </div>
        <div className="text-right shrink-0 mr-1">
          <div className={`text-[13px] font-semibold tnum leading-tight
                           ${c.economieMois > 0 ? 'text-emerald-700' : c.economieMois < 0 ? 'text-rose-700' : 'text-ink-400'}`}>
            {c.economieMois === 0 ? '—' : fmt.EUR(c.economieMois)}
          </div>
          <div className="text-[10px] text-ink-400">{t('mob.saving')}</div>
        </div>
        <button onClick={() => setExpanded(e => !e)}
                className="w-7 h-7 rounded-lg bg-ink-50 grid place-items-center shrink-0 text-ink-400">
          <ChevronIcon down={expanded} />
        </button>
      </div>

      {/* Volume slider — always visible when active */}
      {r.actif && (
        <div className="flex items-center gap-2.5 px-3.5 pb-3">
          <input type="range" min={0}
                 max={r.id === 'pro2-modeles' ? 80 : r.id === 'pro2-retainer' ? 40 : 30}
                 step={1}
                 value={r.values.volume}
                 onChange={e => onSetVal(r.id, 'volume', parseInt(e.target.value, 10))}
                 className="flex-1"/>
          <NumberInput value={r.values.volume}
                       onChange={v => onSetVal(r.id, 'volume', v)}
                       ariaLabel={t('table.col.volume')}/>
        </div>
      )}

      {/* Expanded details */}
      {expanded && r.actif && (
        <div className="border-t border-ink-100 px-3.5 py-3 space-y-3">
          <div className="grid grid-cols-2 gap-3">
            <div>
              <div className="text-[10.5px] text-ink-400 mb-1">{t('table.col.coutLabo')}</div>
              <NumberInput value={r.values.coutLabo}
                           onChange={v => onSetVal(r.id, 'coutLabo', v)}
                           suffix={currencySymbol} ariaLabel={t('table.col.coutLabo')}/>
            </div>
            <div>
              <div className="text-[10.5px] text-ink-400 mb-1">{t('table.col.materiau')}</div>
              <NumberInput value={r.values.coutMateriau}
                           onChange={v => onSetVal(r.id, 'coutMateriau', v)}
                           suffix={currencySymbol} step={0.01} ariaLabel={t('table.col.materiau')}/>
            </div>
          </div>
          {r.machine === 'pro2' && (() => {
            const dm = r.values.designMode || 'sprintray';
            return (
              <div>
                <div className="text-[10.5px] text-ink-400 mb-1.5">{t('table.col.design')}</div>
                <div className="flex items-center gap-2 flex-wrap">
                  <button onClick={() => onSetVal(r.id, 'designMode', 'sprintray')}
                          className={`px-3 py-1 text-[12px] rounded-full border transition whitespace-nowrap
                            ${dm === 'sprintray' ? 'bg-brand-500 border-brand-500 text-white' : 'border-ink-200 text-ink-500'}`}>
                    SR{r.srCost > 0 ? ` ${fmt.EUR2(r.srCost)}` : ` ${t('table.design.free')}`}
                  </button>
                  <button onClick={() => onSetVal(r.id, 'designMode', 'other')}
                          className={`px-3 py-1 text-[12px] rounded-full border transition whitespace-nowrap
                            ${dm !== 'sprintray' ? 'bg-brand-500 border-brand-500 text-white' : 'border-ink-200 text-ink-500'}`}>
                    {t('table.design.other')}
                  </button>
                  {dm !== 'sprintray' && (
                    <NumberInput value={r.values.laboCost || undefined}
                                 onChange={v => onSetVal(r.id, 'laboCost', v)}
                                 suffix={currencySymbol}
                                 ariaLabel={t('table.design.other')}/>
                  )}
                </div>
              </div>
            );
          })()}
          {r.machine === 'midas' && (() => {
            const dm = r.values.designMode || 'ia';
            const currentVal = dm === 'sprintray' ? (r.values.srCost || undefined) : (r.values.laboCost || undefined);
            const currentKey = dm === 'sprintray' ? 'srCost' : 'laboCost';
            return (
              <div>
                <div className="text-[10.5px] text-ink-400 mb-1.5">{t('table.col.design')}</div>
                <div className="flex items-center gap-2 flex-wrap">
                  <button onClick={() => onSetVal(r.id, 'designMode', 'ia')}
                          className={`px-3 py-1 text-[12px] rounded-full border transition whitespace-nowrap
                            ${dm === 'ia' ? 'bg-brand-500 border-brand-500 text-white' : 'border-ink-200 text-ink-500'}`}>
                    {t('table.design.ia')}
                  </button>
                  <button onClick={() => onSetVal(r.id, 'designMode', 'sprintray')}
                          className={`px-3 py-1 text-[12px] rounded-full border transition whitespace-nowrap
                            ${dm === 'sprintray' ? 'bg-brand-500 border-brand-500 text-white' : 'border-ink-200 text-ink-500'}`}>
                    SR
                  </button>
                  <button onClick={() => onSetVal(r.id, 'designMode', 'labo')}
                          className={`px-3 py-1 text-[12px] rounded-full border transition whitespace-nowrap
                            ${dm === 'labo' ? 'bg-brand-500 border-brand-500 text-white' : 'border-ink-200 text-ink-500'}`}>
                    {t('table.design.labo')}
                  </button>
                  {dm !== 'ia' && (
                    <NumberInput value={currentVal}
                                 onChange={v => onSetVal(r.id, currentKey, v)}
                                 suffix={currencySymbol}
                                 ariaLabel={t('table.col.design')}/>
                  )}
                </div>
              </div>
            );
          })()}
        </div>
      )}
    </div>
  );
}

function StepVolumes({ visibleRows, setVisibleRows, fraisDesign, t, fmt, currencySymbol }) {
  function onSetVal(id, key, v) {
    setVisibleRows(rs => rs.map(r =>
      r.id === id ? { ...r, values: { ...r.values, [key]: v } } : r
    ));
  }
  function onToggle(id) {
    setVisibleRows(rs => rs.map(r => r.id === id ? { ...r, actif: !r.actif } : r));
  }

  const groups = [];
  let lastMachine = null;
  visibleRows.forEach(r => {
    if (r.machine !== lastMachine) {
      groups.push({ machine: r.machine, rows: [] });
      lastMachine = r.machine;
    }
    groups[groups.length - 1].rows.push(r);
  });

  return (
    <div className="px-4 py-5 space-y-5">
      <div>
        <h2 className="text-[17px] font-semibold text-ink-900">{t('table.title')}</h2>
        <p className="text-[13px] text-ink-500 mt-0.5">{t('table.sub')}</p>
      </div>
      {groups.map(g => (
        <div key={g.machine} className="space-y-2">
          <div className="text-[11px] font-semibold uppercase tracking-wider text-brand-700 px-1">
            SprintRay {g.machine === 'midas' ? 'Midas' : 'Pro 2'}
          </div>
          {g.rows.map(r => (
            <VolumeCard key={r.id} r={r} fraisDesign={fraisDesign}
                        onSetVal={onSetVal} onToggle={onToggle} t={t} fmt={fmt} currencySymbol={currencySymbol}/>
          ))}
        </div>
      ))}
    </div>
  );
}

function MobileBarComparison({ totaux, t, fmt }) {
  const laboAn   = totaux.coutLaboAn   || 0;
  const interneAn = totaux.coutInterneAn || 0;
  const ratio = laboAn > 0 ? Math.min(interneAn / laboAn, 1) : 0;

  return (
    <div className="bg-white rounded-2xl border border-ink-200 p-4">
      <h3 className="text-[13px] font-semibold text-ink-900 leading-tight">{t('dash.bar.title')}</h3>
      <p className="text-[11.5px] text-ink-500 mt-0.5 mb-4">{t('dash.bar.sub')}</p>
      <div className="space-y-3.5">
        <div>
          <div className="flex items-baseline justify-between mb-1.5">
            <span className="text-[12px] text-ink-500">{t('dash.bar.laboShort')}</span>
            <span className="text-[13px] font-semibold tnum text-ink-600">{fmt.EUR(laboAn)}</span>
          </div>
          <div className="h-3 bg-ink-100 rounded-full">
            <div className="h-full bg-ink-300 rounded-full" style={{ width: '100%' }}/>
          </div>
        </div>
        <div>
          <div className="flex items-baseline justify-between mb-1.5">
            <span className="text-[12px] text-brand-700">{t('dash.bar.interneShort')}</span>
            <span className="text-[13px] font-semibold tnum text-brand-700">{fmt.EUR(interneAn)}</span>
          </div>
          <div className="h-3 bg-ink-100 rounded-full overflow-hidden">
            <div className="h-full bg-brand-500 rounded-full transition-all duration-500"
                 style={{ width: `${Math.round(ratio * 100)}%` }}/>
          </div>
        </div>
      </div>
      {laboAn > interneAn && (
        <div className="mt-3.5 pt-3 border-t border-ink-100 flex items-center gap-2">
          <span className="w-2 h-2 rounded-full bg-brand-500 shrink-0"/>
          <span className="text-[11.5px] text-ink-600">{t('dash.eco.helper', fmt.EUR(totaux.economieMois))}</span>
        </div>
      )}
    </div>
  );
}

function MobileAmortChart({ totaux, prixEcosysteme, t, fmt }) {
  const Re = window.Recharts;
  const { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, ReferenceDot } = Re;

  const economieMois  = totaux.economieMois;
  const rentable      = economieMois > 0;
  const moisROI       = rentable ? Math.ceil(prixEcosysteme / economieMois) : null;
  const moisROIborne  = moisROI != null && moisROI <= 36 ? moisROI : null;

  const data = [];
  for (let m = 0; m <= 36; m++) {
    data.push({ mois: m, cumul: Math.round(m * economieMois), seuil: prixEcosysteme });
  }

  return (
    <div className="bg-white rounded-2xl border border-ink-200 p-4">
      <h3 className="text-[13px] font-semibold text-ink-900 leading-tight">{t('dash.amort.title')}</h3>
      <p className="text-[11.5px] text-ink-500 mt-0.5 mb-3">{t('dash.amort.sub')}</p>
      <div className="h-44">
        <ResponsiveContainer width="100%" height="100%">
          <LineChart data={data} margin={{ top: 8, right: 10, left: 0, bottom: 0 }}>
            <CartesianGrid strokeDasharray="3 3" stroke="#EEEFF5" vertical={false}/>
            <XAxis dataKey="mois"
                   tick={{ fontSize: 10, fill: '#7E81A0' }}
                   axisLine={false} tickLine={false}
                   tickFormatter={v => v + t('dash.amort.msuffix')}
                   ticks={[0, 12, 24, 36]}/>
            <YAxis tick={{ fontSize: 10, fill: '#7E81A0' }} axisLine={false} tickLine={false}
                   tickFormatter={v => v >= 1000 ? (v / 1000).toFixed(0) + 'k' : v}
                   width={32}/>
            <Tooltip formatter={v => fmt.EUR(v)} labelFormatter={l => t('dash.amort.mois', l)}/>
            <Line type="monotone" dataKey="seuil" stroke="#B9BBCE" strokeDasharray="4 4"
                  strokeWidth={1.5} dot={false} name={t('dash.amort.seuil')}/>
            <Line type="monotone" dataKey="cumul" stroke="#5B3DF5"
                  strokeWidth={2.5} dot={false} name={t('dash.amort.cumul')}/>
            {moisROIborne != null && (
              <ReferenceDot x={moisROIborne} y={prixEcosysteme} r={5}
                            fill="#5B3DF5" stroke="#fff" strokeWidth={2}
                            label={{ value: t('dash.amort.roi', moisROIborne), position: 'top',
                                     fill: '#3B22B0', fontSize: 10, fontWeight: 600 }}/>
            )}
          </LineChart>
        </ResponsiveContainer>
      </div>
      <div className="mt-2 text-[11.5px] text-ink-500 flex items-center gap-2">
        {rentable
          ? <><span className="w-2 h-2 rounded-full bg-brand-500 shrink-0"/>{t('dash.amort.ok', moisROI)}</>
          : <><span className="w-2 h-2 rounded-full bg-amber-500 shrink-0"/>{t('dash.amort.nok')}</>}
      </div>
    </div>
  );
}

function StepResults({ totaux, prixEcosysteme, machineLabel, setStep, t, fmt,
                       machine, visibleRows,
                       tempsOn, setTempsOn, tempsParams, setTempsParams,
                       finOn, setFinOn, finParams, setFinParams,
                       cameraOn, setCameraOn, cameraParams, setCameraParams }) {
  const { ModuleTempsFauteuil, ModuleFinancement, ModuleCamera } = window;
  const [copied, setCopied] = useState(false);

  const economieMois = totaux.economieMois;
  const economieAn   = totaux.economieAn;
  const beneficeAn1  = economieAn - prixEcosysteme;
  const rentable     = economieMois > 0;
  const moisROI      = rentable ? Math.ceil(prixEcosysteme / economieMois) : null;

  const shareLines = [
    t('mob.share.intro'),
    '',
    `${t('dash.eco.label')} : ${fmt.EUR(economieAn)}`,
    `${t('dash.ben.label')} : ${fmt.EURc(beneficeAn1)}`,
    `${t('dash.roi.label')} : ${rentable ? t('synth.gen.roiOk', moisROI) : t('dash.roi.nd')}`,
  ];

  if (finOn) {
    const r = (finParams.tauxAnnuel || 0) > 0 ? finParams.tauxAnnuel / 100 / 12 : 0;
    const n = finParams.dureeMois;
    const loyerCalc = n > 0 ? (r > 0 ? prixEcosysteme * r / (1 - Math.pow(1 + r, -n)) : prixEcosysteme / n) : 0;
    const loyer = finParams.loyerManuel > 0 ? finParams.loyerManuel : loyerCalc;
    const net = economieMois - loyer;
    shareLines.push('');
    shareLines.push(`${t('mod.fin.title')} : ${fmt.EUR(loyer)}/mois · net ${fmt.EURc(net)}/mois`);
  }

  if (tempsOn && machine !== 'pro2') {
    const creneaux = visibleRows.reduce((s, r) => (!r.actif || r.machine !== 'midas') ? s : s + (r.values.volume || 0), 0);
    const potentielMois = creneaux * (tempsParams.tauxRemplissage / 100) * tempsParams.tarifActe;
    shareLines.push('');
    shareLines.push(`${t('mod.temps.title')} : ${creneaux} ${t('mod.temps.creneaux')} → ${fmt.EUR(potentielMois)}/mois`);
  }

  if (cameraOn) {
    const camMens  = cameraParams.mensualiteManuelle || 0;
    const ecoNette = economieMois - camMens;
    const roiAvec  = ecoNette > 0 ? Math.ceil(prixEcosysteme / ecoNette) : null;
    shareLines.push('');
    if (roiAvec && moisROI) {
      shareLines.push(t('mob.share.cam', fmt.EUR(camMens), roiAvec, moisROI));
    } else {
      shareLines.push(`${t('mod.cam.title')} : ${fmt.EUR(camMens)}/mois`);
    }
  }

  shareLines.push('');
  shareLines.push('https://simuprint.lamouqueterie.com');

  const shareText = shareLines.join('\n');

  async function share() {
    if (navigator.share) {
      try {
        await navigator.share({ title: t('mob.share.title'), text: shareText });
      } catch (_) {}
    } else {
      try {
        await navigator.clipboard.writeText(shareText);
      } catch (_) {
        const ta = document.createElement('textarea');
        ta.value = shareText;
        Object.assign(ta.style, { position: 'fixed', opacity: '0' });
        document.body.appendChild(ta);
        ta.select();
        document.execCommand('copy');
        document.body.removeChild(ta);
      }
      setCopied(true);
      setTimeout(() => setCopied(false), 2500);
    }
  }

  return (
    <div className="px-4 py-5 space-y-4 pb-10">
      {/* Hero savings */}
      <div className="bg-gradient-to-br from-brand-600 to-brand-800 rounded-2xl p-5 text-white">
        <div className="text-[11.5px] font-medium uppercase tracking-wider opacity-75 mb-1">
          {t('dash.eco.label')}
        </div>
        <div className="text-[42px] font-semibold tnum leading-none">
          {fmt.EUR(economieAn)}
        </div>
        <div className="text-[13px] opacity-75 mt-1.5">
          {t('dash.eco.helper', fmt.EUR(economieMois))}
        </div>
      </div>

      {/* KPI cards */}
      <div className="grid grid-cols-2 gap-3">
        <div className={`rounded-2xl border p-4 ${beneficeAn1 >= 0 ? 'bg-emerald-50 border-emerald-200' : 'bg-amber-50 border-amber-200'}`}>
          <div className="text-[10.5px] uppercase tracking-wider text-ink-500 mb-1.5">{t('dash.ben.label')}</div>
          <div className={`text-[22px] font-semibold tnum leading-tight ${beneficeAn1 >= 0 ? 'text-emerald-700' : 'text-amber-700'}`}>
            {fmt.EUR(beneficeAn1)}
          </div>
          <div className="text-[10.5px] text-ink-400 mt-1">{t('dash.ben.sub', fmt.EUR(prixEcosysteme))}</div>
        </div>
        <div className={`rounded-2xl border p-4 ${rentable ? 'bg-brand-50 border-brand-200' : 'bg-amber-50 border-amber-200'}`}>
          <div className="text-[10.5px] uppercase tracking-wider text-ink-500 mb-1.5">{t('dash.roi.label')}</div>
          <div className={`text-[22px] font-semibold tnum leading-tight ${rentable ? 'text-brand-700' : 'text-amber-700'}`}>
            {rentable ? t('synth.gen.roiOk', moisROI) : t('dash.roi.nd')}
          </div>
          <div className="text-[10.5px] text-ink-400 mt-1">
            {rentable
              ? (moisROI <= 12 ? t('dash.roi.sub12') : t('dash.roi.sub12+', fmt.dec1(moisROI / 12)))
              : t('dash.roi.subNone')}
          </div>
        </div>
      </div>

      {/* Equipment */}
      <div className="bg-white rounded-xl border border-ink-200 px-4 py-3 text-[12.5px]">
        <span className="font-medium text-ink-900">{machineLabel}</span>
        <span className="text-ink-400 mx-1.5">·</span>
        <span className="text-ink-500">{t('sel1.prix.label').split(' (')[0]}</span>
        <span className="font-semibold tnum text-ink-900 ml-1">{fmt.EUR(prixEcosysteme)}</span>
      </div>

      {/* Charts */}
      <MobileBarComparison totaux={totaux} t={t} fmt={fmt}/>
      <MobileAmortChart totaux={totaux} prixEcosysteme={prixEcosysteme} t={t} fmt={fmt}/>

      {/* Optional modules */}
      {machine !== 'pro2' && (
        <ModuleTempsFauteuil
          enabled={tempsOn} onToggle={setTempsOn}
          params={tempsParams} setParams={setTempsParams}
          rows={visibleRows}
        />
      )}
      <ModuleFinancement
        enabled={finOn} onToggle={setFinOn}
        params={finParams} setParams={setFinParams}
        economieMois={totaux.economieMois}
        prixEcosysteme={prixEcosysteme}
      />
      <ModuleCamera
        enabled={cameraOn} onToggle={setCameraOn}
        params={cameraParams} setParams={setCameraParams}
        economieMois={totaux.economieMois}
        prixEcosysteme={prixEcosysteme}
      />

      {/* Actions */}
      <div className="space-y-2.5">
        <button onClick={share}
                className={`w-full py-4 rounded-xl font-semibold text-[15px] flex items-center justify-center gap-2.5 transition shadow-pop
                            ${copied ? 'bg-emerald-500 text-white' : 'bg-brand-500 text-white active:bg-brand-600'}`}>
          {copied ? (
            <>
              <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
                <path d="M4 12l5 5L20 6"/>
              </svg>
              {t('mob.copied')}
            </>
          ) : (
            <>
              <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
                <circle cx="18" cy="5" r="3"/><circle cx="6" cy="12" r="3"/><circle cx="18" cy="19" r="3"/>
                <line x1="8.59" y1="13.51" x2="15.42" y2="17.49"/>
                <line x1="15.41" y1="6.51" x2="8.59" y2="10.49"/>
              </svg>
              {t('mob.share')}
            </>
          )}
        </button>

        <button onClick={() => setStep(0)}
                className="w-full py-3.5 rounded-xl border border-ink-200 bg-white text-ink-700 font-medium text-[14px] transition active:bg-ink-50">
          {t('mob.edit')}
        </button>
      </div>

      <p className="text-[10.5px] text-ink-400 text-center leading-relaxed px-2">
        {t('synth.gen.disclaimer')}
      </p>
    </div>
  );
}

/* ================================================================== *
 *  Main MobileWizard component
 * ================================================================== */

function MobileWizard() {
  const { t, fmt, currencySymbol } = useLang();
  const {
    CATALOGUE, MACHINES, MIDAS_MATERIAUX, MODES_DESIGN,
    calculerTotaux, Wordmark, LangPicker, DarkModeToggle, CurrencyPicker,
  } = window;

  /* --- shared state (mirrors App) --- */
  const [machine, setMachine]               = useState('both');
  const [midasMat, setMidasMat]             = useState('ceramic-crown');
  const [midasMatCouts, setMidasMatCouts]   = useState({ 'ceramic-crown': 25, 'crown-ht': 25, 'onx': 29 });
  const [prixEcosysteme, setPrixEcosysteme] = useState(MACHINES.find(m => m.id === 'both').prixDefaut);
  const [prixCustomise, setPrixCustomise]   = useState(false);
  const [allRows, setAllRows]               = useState(() =>
    CATALOGUE.map(c => ({
      ...c,
      def: { ...c.defauts, coutMateriau: c.defauts.coutMateriau ?? null },
      values: {
        coutLabo:     c.defauts.coutLabo,
        volume:       c.defauts.volume,
        coutMateriau: c.defauts.coutMateriau ?? 0,
        ...(c.machine !== 'midas' ? {
          designMode: 'sprintray',
          laboCost: 0,
        } : {
          designMode: 'ia',
          srCost: 12,
          laboCost: 0,
        }),
      },
      actif: true,
    }))
  );
  const [step, setStep] = useState(0);

  const fraisDesign = 0;
  const showMidasMat = machine === 'midas' || machine === 'both';

  const STEP_IDS = useMemo(() => {
    const s = ['machine'];
    if (showMidasMat) s.push('material');
    s.push('volumes', 'results');
    return s;
  }, [showMidasMat, machine]);

  const safeStep      = Math.min(step, STEP_IDS.length - 1);
  const currentStepId = STEP_IDS[safeStep];

  function changeMachine(id) {
    setMachine(id);
    if (!prixCustomise) setPrixEcosysteme(MACHINES.find(m => m.id === id).prixDefaut);
  }

  const visibleRows = useMemo(() => {
    return allRows
      .filter(r => machine === 'both' ? true : r.machine === machine)
      .map(r => {
        if (r.machine === 'midas' && r.midasUtiliseMateriau) {
          return {
            ...r,
            _midasMaterialLabel: MIDAS_MATERIAUX.find(m => m.id === midasMat).label,
            values: { ...r.values, coutMateriau: midasMatCouts[midasMat] || 0 },
          };
        }
        return r;
      });
  }, [allRows, machine, midasMat, midasMatCouts]);

  function setVisibleRows(updater) {
    setAllRows(rs => {
      const nextVisible = typeof updater === 'function' ? updater(visibleRows) : updater;
      const byId = new Map(nextVisible.map(r => [r.id, r]));

      const midasRow = nextVisible.find(r => r.machine === 'midas' && r.midasUtiliseMateriau);
      if (midasRow) {
        const newMat = midasRow.values.coutMateriau;
        if (newMat !== midasMatCouts[midasMat]) {
          setMidasMatCouts(m => ({ ...m, [midasMat]: newMat }));
        }
      }

      return rs.map(r => {
        const upd = byId.get(r.id);
        if (!upd) return r;
        if (r.machine === 'midas' && r.midasUtiliseMateriau) {
          const { coutMateriau, ...rest } = upd.values;
          return { ...r, ...upd, values: { ...r.values, ...rest } };
        }
        return { ...r, ...upd, values: { ...r.values, ...upd.values } };
      });
    });
  }

  const totaux = useMemo(
    () => calculerTotaux(visibleRows, fraisDesign),
    [visibleRows, fraisDesign]
  );

  const [tempsOn, setTempsOn]         = useState(false);
  const [tempsParams, setTempsParams] = useState({
    tarifActe: 150, tauxRemplissage: 80,
    casProvisoiresMois: 8, economieProvisoireParCas: 25,
  });

  const [finOn, setFinOn]             = useState(false);
  const [finParams, setFinParams]     = useState({
    dureeMois: 60, tauxAnnuel: 0, loyerManuel: 0,
  });

  const [cameraOn, setCameraOn]       = useState(false);
  const [cameraParams, setCameraParams] = useState({
    prix: 0, dureeMois: 60, tauxAnnuel: 0, mensualiteManuelle: 0,
  });

  function goNext() { setStep(s => Math.min(s + 1, STEP_IDS.length - 1)); }
  function goBack() { setStep(s => Math.max(s - 1, 0)); }

  const stepLabels = STEP_IDS.map(id => t('mob.step.' + id));
  const pct = Math.round(((safeStep + 1) / STEP_IDS.length) * 100);

  const commonProps = { t, fmt, currencySymbol, MACHINES, MIDAS_MATERIAUX, MODES_DESIGN };

  return (
    <div className="min-h-screen flex flex-col bg-ink-50">

      {/* Header */}
      <header className="bg-white border-b border-ink-100 sticky top-0 z-30">
        <div className="px-4 py-3 flex items-center justify-between gap-3">
          <Wordmark/>
          <div className="flex items-center gap-2">
            <DarkModeToggle/>
            <CurrencyPicker/>
            <LangPicker/>
          </div>
        </div>
      </header>

      {/* Progress */}
      <div className="bg-white border-b border-ink-100 px-4 pt-3 pb-2.5">
        <div className="flex items-center justify-between mb-1.5">
          <span className="text-[13.5px] font-semibold text-ink-900">{stepLabels[safeStep]}</span>
          <span className="text-[11.5px] text-ink-400 tabular-nums">
            {t('mob.step.of', safeStep + 1, STEP_IDS.length)}
          </span>
        </div>
        <div className="h-1.5 bg-ink-100 rounded-full overflow-hidden">
          <div className="h-full bg-brand-500 rounded-full transition-all duration-300"
               style={{ width: pct + '%' }}/>
        </div>
        <div className="flex gap-1.5 mt-2">
          {STEP_IDS.map((id, i) => (
            <div key={id}
                 className={`flex-1 h-0.5 rounded-full transition-colors duration-300 ${i <= safeStep ? 'bg-brand-400' : 'bg-ink-200'}`}/>
          ))}
        </div>
      </div>

      {/* Step content */}
      <div className="flex-1 overflow-y-auto">
        {currentStepId === 'machine'  && (
          <StepMachine {...commonProps}
            machine={machine} changeMachine={changeMachine}
            prixEcosysteme={prixEcosysteme} setPrixEcosysteme={setPrixEcosysteme}
            prixCustomise={prixCustomise} setPrixCustomise={setPrixCustomise}/>
        )}
        {currentStepId === 'material' && (
          <StepMaterial {...commonProps}
            midasMat={midasMat} setMidasMat={setMidasMat}
            midasMatCouts={midasMatCouts} setMidasMatCouts={setMidasMatCouts}/>
        )}
        {currentStepId === 'volumes'  && (
          <StepVolumes {...commonProps}
            visibleRows={visibleRows} setVisibleRows={setVisibleRows}
            fraisDesign={fraisDesign}/>
        )}
        {currentStepId === 'results'  && (
          <StepResults {...commonProps}
            totaux={totaux} prixEcosysteme={prixEcosysteme}
            machineLabel={MACHINES.find(m => m.id === machine).label}
            setStep={setStep}
            machine={machine} visibleRows={visibleRows}
            tempsOn={tempsOn} setTempsOn={setTempsOn}
            tempsParams={tempsParams} setTempsParams={setTempsParams}
            finOn={finOn} setFinOn={setFinOn}
            finParams={finParams} setFinParams={setFinParams}
            cameraOn={cameraOn} setCameraOn={setCameraOn}
            cameraParams={cameraParams} setCameraParams={setCameraParams}/>
        )}
      </div>

      {/* Bottom navigation */}
      {currentStepId !== 'results' && (
        <div className="sticky bottom-0 bg-white border-t border-ink-100 px-4 py-3">
          <div className="flex gap-3">
            {safeStep > 0 && (
              <button onClick={goBack}
                      className="flex-[2] py-3.5 rounded-xl border border-ink-200 text-ink-700 font-medium text-[14px] transition active:bg-ink-50">
                {t('mob.back')}
              </button>
            )}
            <button onClick={goNext}
                    className="flex-[3] py-3.5 rounded-xl bg-brand-500 text-white font-semibold text-[15px] transition active:bg-brand-600 shadow-pop">
              {currentStepId === 'volumes' ? t('mob.see.results') : t('mob.next')}
            </button>
          </div>
        </div>
      )}
    </div>
  );
}

Object.assign(window, { useIsMobile, MobileWizard });
