function Settings({ part }) {
  const { L, lang, setLang, D, target, setTarget, openImport, toast, prefs, setPrefs, setup, setSetup, openSetup, startTour } = useMizo();
  const base = { name: D.restaurant.name, address: D.restaurant.address, phone: D.restaurant.phone, seats: D.restaurant.seats, email: 'eleni@souvlakivillage.ca', ...(setup.r || {}) };
  const [f, setF] = React.useState(base);
  const [saved, setSaved] = React.useState(base);
  const [errs, setErrs] = React.useState({});
  const [prep, setPrep] = React.useState(null);
  const dirty = JSON.stringify(f) !== JSON.stringify(saved);
  const save = () => { const e = { name: vReq(f.name, L), address: vReq(f.address, L), phone: vPhone(f.phone, L), email: vEmail(f.email, L), seats: f.seats && Number(f.seats) > 0 ? null : L('Enter a number above 0.', 'Entrez un nombre supérieur à 0.') }; setErrs(e); if (Object.values(e).some(Boolean)) { toast(L('Please fix the highlighted fields', 'Veuillez corriger les champs signalés')); return; } setSaved(f); setSetup({ ...setup, r: f, done: { ...setup.done, restaurant: true } }); toast(L('Restaurant details saved', 'Détails enregistrés')); };
  const groups = [
    [L('Point of sale', 'Point de vente'), [['lightspeed', 'Lightspeed Restaurant', 'cash-register', L('Sales, items and payments', 'Ventes, articles et paiements')], ['square', 'Square', 'cash-register', L('Sales and payments', 'Ventes et paiements')], ['clover', 'Clover', 'cash-register', L('Sales and payments', 'Ventes et paiements')]]],
    [L('Accounting', 'Comptabilité'), [['qbo', 'QuickBooks Online', 'book-open-text', L('Send invoices and expenses to your accountant', 'Envoyer factures et dépenses à votre comptable')], ['sage', 'Sage 50', 'book-open-text', L('Accounting', 'Comptabilité')]]],
    [L('Delivery apps', 'Livraison'), [['uber', 'Uber Eats', 'moped', L('Orders, payouts and commissions', 'Commandes, versements et commissions')], ['dd', 'DoorDash', 'moped', L('Orders, payouts and commissions', 'Commandes, versements et commissions')]]],
    [L('Payroll & bank', 'Paie et banque'), [['nethris', 'Nethris', 'users-three', L('Send approved pay runs', 'Envoyer les paies approuvées')], ['desj', 'Desjardins', 'bank', L('Bank balance and deposits', 'Solde et dépôts')]]],
  ];
  const posSel = setup.pos;
  const textOpts = [['normal', L('Normal', 'Normal')], ['large', L('Large', 'Grand')], ['xl', L('Extra large', 'Très grand')]];
  return (
    <div className="page">
      <PageHead title={L('Settings', 'Paramètres')} sub={part === 'integrations' ? L('Bring your data in from Excel today. Live connections to your POS, accounting and delivery apps come in the next release — you can prepare them now.', 'Importez vos données Excel dès aujourd’hui. Les connexions directes arrivent dans la prochaine version — préparez-les maintenant.') : L('Your restaurant, how MIZO looks, and help.', 'Votre restaurant, l’affichage de MIZO et l’aide.')} />
      {part !== 'integrations' ? <div className="settings">
        <section className="panel">
          <h3>{L('Restaurant', 'Restaurant')}</h3>
          <div className="form-grid">
            <Field span label={L('Restaurant name', 'Nom du restaurant')} id="st-n" error={errs.name}><input id="st-n" className="input" value={f.name} onChange={(e) => setF({ ...f, name: e.target.value })} /></Field>
            <Field span label={L('Street address', 'Adresse')} id="st-a" error={errs.address}><input id="st-a" className="input" value={f.address} onChange={(e) => setF({ ...f, address: e.target.value })} /></Field>
            <Field label={L('Phone', 'Téléphone')} id="st-p" error={errs.phone} hint={L('10 digits', '10 chiffres')}><input id="st-p" className="input" inputMode="tel" value={f.phone} onChange={(e) => setF({ ...f, phone: e.target.value })} /></Field>
            <Field label={L('Seats', 'Places')} id="st-s" error={errs.seats}><input id="st-s" className="input" type="number" min="0" value={f.seats} onChange={(e) => setF({ ...f, seats: e.target.value })} /></Field>
            <Field span label={L('Email for orders and briefings', 'Courriel pour commandes et résumés')} id="st-e" error={errs.email}><input id="st-e" className="input" type="email" value={f.email} onChange={(e) => setF({ ...f, email: e.target.value })} /></Field>
          </div>
          {dirty ? <div className="save-bar"><Icon n="pencil-simple" /><span>{L('You have unsaved changes', 'Modifications non enregistrées')}</span><button className="btn btn-ghost" onClick={() => { setF(saved); setErrs({}); }}>{L('Discard', 'Annuler')}</button><button className="btn btn-primary" onClick={save}><Icon n="floppy-disk" />{L('Save changes', 'Enregistrer')}</button></div> : <div className="muted sm"><Icon n="check-circle" /> {L('All changes saved', 'Tout est enregistré')}</div>}
        </section>
        <section className="panel">
          <h3>{L('Money & targets', 'Argent et cibles')}</h3>
          <div className="set-row"><div><div>{L('Currency', 'Devise')}</div><div className="muted sm">{L('Used for every amount in MIZO', 'Utilisée pour tous les montants')}</div></div><select className="input" style={{ maxWidth: 140 }} value={setup.cur} onChange={(e) => setSetup({ ...setup, cur: e.target.value })} aria-label={L('Currency', 'Devise')}><option value="CAD">CAD $</option><option value="USD">USD $</option><option value="EUR">EUR €</option></select></div>
          <div className="set-row"><div><div>{L('Sales taxes', 'Taxes de vente')}</div><div className="muted sm">{L('Québec', 'Québec')}</div></div><span className="tnum">{L('GST 5% · QST 9.975%', 'TPS 5 % · TVQ 9,975 %')}</span></div>
          <div className="set-row col">
            <div className="dr-row"><div><div>{L('Food cost target', 'Cible de coût alimentaire')}</div><div className="muted sm">{L('Dishes above this are flagged. Most restaurants use 28–32%.', 'Les plats au-dessus sont signalés. La plupart utilisent 28–32 %.')}</div></div><b className="big tnum">{target}%</b></div>
            <input type="range" className="range" min="22" max="38" step="1" value={target} onChange={(e) => setTarget(Number(e.target.value))} aria-label={L('Food cost target', 'Cible de coût alimentaire')} />
          </div>
        </section>
        <section className="panel">
          <h3>{L('Display & reading', 'Affichage et lecture')}</h3>
          <div className="set-row"><div><div>{L('Language', 'Langue')}</div><div className="muted sm">{L('Also at the top of every screen', 'Aussi en haut de chaque écran')}</div></div><Seg size="sm" value={lang} onChange={setLang} options={[['en', 'English'], ['fr', 'Français']]} /></div>
          <div className="set-row"><div><div>{L('Text size', 'Taille du texte')}</div><div className="muted sm">{L('Makes everything bigger, including buttons', 'Agrandit tout, boutons compris')}</div></div><Seg size="sm" value={prefs.text} onChange={(v) => setPrefs({ text: v })} options={textOpts} /></div>
          <div className="set-row"><div><div>{L('Stronger contrast', 'Contraste renforcé')}</div><div className="muted sm">{L('Brighter secondary text and clearer lines', 'Texte secondaire plus clair et lignes plus nettes')}</div></div><Toggle on={prefs.contrast === 'high'} label={L('Stronger contrast', 'Contraste renforcé')} onChange={(v) => setPrefs({ contrast: v ? 'high' : 'normal' })} /></div>
          <div className="set-row"><div><div>{L('Reduce motion', 'Réduire les animations')}</div><div className="muted sm">{L('Turns off sliding and fading effects', 'Désactive glissements et fondus')}</div></div><Toggle on={prefs.motion === 'reduce'} label={L('Reduce motion', 'Réduire les animations')} onChange={(v) => setPrefs({ motion: v ? 'reduce' : 'full' })} /></div>
        </section>
        <section className="panel">
          <h3>{L('Help & setup', 'Aide et configuration')}</h3>
          <div className="set-row"><div><div>{L('Setup guide', 'Guide de configuration')}</div><div className="muted sm">{L(`${SETUP_STEPS.filter(([k]) => setup.done[k]).length} of ${SETUP_STEPS.length} steps done`, `${SETUP_STEPS.filter(([k]) => setup.done[k]).length} étapes sur ${SETUP_STEPS.length}`)}</div></div><button className="btn btn-secondary" onClick={() => { setSetup({ ...setup, hide: false }); openSetup(); }}>{L('Open', 'Ouvrir')}</button></div>
          <div className="set-row"><div><div>{L('Product tour', 'Visite guidée')}</div><div className="muted sm">{L('2 minutes, 8 stops', '2 minutes, 8 étapes')}</div></div><button className="btn btn-secondary" onClick={startTour}>{L('Start', 'Commencer')}</button></div>
          <div className="set-row"><div><div>{L('Keyboard shortcuts', 'Raccourcis clavier')}</div><div className="muted sm"><kbd>Ctrl</kbd> <kbd>K</kbd> {L('search', 'recherche')} · <kbd>?</kbd> {L('help', 'aide')} · <kbd>Esc</kbd> {L('close', 'fermer')}</div></div></div>
          <div className="set-row"><div><div>{L('Talk to a person', 'Parler à quelqu’un')}</div><div className="muted sm">1-855-555-0199 · {L('Mon–Sat, 8 am–8 pm', 'lun.–sam., 8 h–20 h')}</div></div></div>
        </section>
      </div> : <>
        <section className="panel">
          <div className="panel-head"><div><h3>{L('Excel and CSV files', 'Fichiers Excel et CSV')}</h3><p className="muted">{L('Available now. MIZO matches your columns and shows you everything before saving.', 'Disponible. MIZO associe vos colonnes et vous montre tout avant d’enregistrer.')}</p></div><Pill tone="pos">{L('Ready', 'Prêt')}</Pill></div>
          <div className="kind-grid">{[['inventory', 'package', L('Inventory', 'Inventaire')], ['recipes', 'cooking-pot', L('Recipes', 'Recettes')], ['suppliers', 'truck', L('Suppliers', 'Fournisseurs')], ['invoices', 'receipt', L('Invoices', 'Factures')]].map(([k, ic, t]) => <button key={k} className="kind" onClick={() => openImport(k)}><Icon n={ic} s="1.5rem" /><div><div>{L('Import', 'Importer')} {t.toLowerCase()}</div><div className="muted sm">.xlsx · .xls · .csv</div></div></button>)}</div>
        </section>
        {groups.map(([g, items]) => <section key={g} className="panel">
          <h3>{g}</h3>
          <div className="integ">{items.map(([k, n, ic, d]) => { const ready = posSel === k || (setup.prep || {})[k]; return (
            <div key={k} className="integ-item">
              <span className="integ-ic"><Icon n={ic} s="1.4rem" /></span>
              <div className="integ-text"><div>{n}</div><div className="muted sm">{d}</div></div>
              {ready ? <Pill tone="warn">{L('Prepared · connects next release', 'Préparé · prochaine version')}</Pill> : <button className="btn btn-secondary" onClick={() => setPrep([k, n])}>{L('Prepare', 'Préparer')}</button>}
            </div>
          ); })}</div>
        </section>)}
      </>}
      <Modal open={!!prep} onClose={() => setPrep(null)} title={prep ? L(`Get ready to connect ${prep[1]}`, `Préparer la connexion ${prep[1]}`) : ''} actions={<><button className="btn btn-secondary" onClick={() => setPrep(null)}>{L('Cancel', 'Annuler')}</button><button className="btn btn-primary" onClick={() => { setSetup({ ...setup, prep: { ...(setup.prep || {}), [prep[0]]: true }, pos: groups[0][1].some(([k]) => k === prep[0]) ? prep[0] : setup.pos, done: groups[0][1].some(([k]) => k === prep[0]) ? { ...setup.done, pos: true } : setup.done }); toast(L('Saved — we’ll email you when the connection is ready', 'Enregistré — nous vous écrirons quand la connexion sera prête')); setPrep(null); }}><Icon n="check" />{L('Mark as prepared', 'Marquer comme prêt')}</button></>}>
        <p className="muted" style={{ marginTop: 0 }}>{L('The live connection is not available in this version. When it is, it takes about 15 minutes. Have these ready:', 'La connexion n’est pas encore disponible. Elle prendra environ 15 minutes. Préparez :')}</p>
        <ul className="ob-check">{[L('The owner or admin login for this account', 'L’accès administrateur de ce compte'), L('Permission to share sales or payout data with MIZO', 'L’autorisation de partager ventes ou versements avec MIZO'), L('A few minutes to match items (MIZO suggests every match)', 'Quelques minutes pour associer les articles (MIZO propose tout)')].map((t, j) => <li key={j}><Icon n="check-circle" />{t}</li>)}</ul>
      </Modal>
    </div>
  );
}

const IMP_FIELDS = [['name', ['Item name', 'Nom de l’article'], /item|name|produit|article|nom|description|ingr/i], ['cat', ['Category', 'Catégorie'], /cat|group|famille|type/i], ['qty', ['On hand', 'En stock'], /qt|quant|qty|on.?hand|stock|count|compte/i], ['unit', ['Unit', 'Unité'], /unit|unité|uom|mesure/i], ['cost', ['Unit cost', 'Coût unitaire'], /cost|coût|cout|price|prix/i], ['sup', ['Supplier', 'Fournisseur'], /sup|fourn|vendor|vend/i]];
function parseCsv(text) {
  const rows = []; let row = [], cell = '', q = false; const sep = (text.split('\n')[0].match(/;/g) || []).length > (text.split('\n')[0].match(/,/g) || []).length ? ';' : ',';
  for (let i = 0; i < text.length; i++) { const ch = text[i]; if (q) { if (ch === '"' && text[i + 1] === '"') { cell += '"'; i++; } else if (ch === '"') q = false; else cell += ch; } else if (ch === '"') q = true; else if (ch === sep) { row.push(cell.trim()); cell = ''; } else if (ch === '\n' || ch === '\r') { if (ch === '\r' && text[i + 1] === '\n') i++; row.push(cell.trim()); if (row.some((c) => c !== '')) rows.push(row); row = []; cell = ''; } else cell += ch; }
  row.push(cell.trim()); if (row.some((c) => c !== '')) rows.push(row); return rows;
}
function ImportWizard({ open, onClose, kind: initialKind }) {
  const { L, lang, fmt, toast } = useMizo();
  const [step, setStep] = React.useState(0);
  const [kind, setKind] = React.useState(initialKind || 'inventory');
  const [file, setFile] = React.useState(null);
  const [drag, setDrag] = React.useState(false);
  const [busy, setBusy] = React.useState(false);
  const [map, setMap] = React.useState({});
  const [done, setDone] = React.useState(null);
  React.useEffect(() => { if (open) { setStep(0); setFile(null); setKind(initialKind || 'inventory'); setMap({}); setDone(null); } }, [open]);
  const kinds = [
    ['inventory', 'package', L('Inventory', 'Inventaire'), L('Ingredients, quantities, costs', 'Ingrédients, quantités, coûts')],
    ['recipes', 'cooking-pot', L('Recipes', 'Recettes'), L('Dishes and their ingredients', 'Plats et ingrédients')],
    ['suppliers', 'truck', L('Suppliers', 'Fournisseurs'), L('Names, contacts, items', 'Noms, contacts, articles')],
    ['invoices', 'receipt', L('Invoices', 'Factures'), L('Purchases and amounts', 'Achats et montants')],
  ];
  const sample = { head: ['Produit', 'Catégorie', 'Qté', 'Unité', 'Prix unitaire', 'Fournisseur'], rows: [['Halloumi', 'Laitiers', '6', 'kg', '16,80 $', 'Aegean Imports'], ['Pain pita', 'Boulangerie', '180', 'unité', '0,42 $', 'Boulangerie Pita'], ['Feta AOP', 'Laitiers', '18', 'kg', '14,50 $', 'Aegean Imports'], ['Tomates', 'Légumes', '26', 'kg', '4,20 $', 'Marché Central'], ['Origan', 'Épices', '', 'kg', '28,00 $', 'Aegean Imports']], total: 5 };
  const autoMap = (head) => { const m = {}; const used = new Set(); head.forEach((h, i) => { const f = IMP_FIELDS.find(([k, , re]) => !used.has(k) && re.test(h)); if (f) { m[i] = f[0]; used.add(f[0]); } else m[i] = ''; }); return m; };
  const pick = (f) => {
    if (f && /\.csv$/i.test(f.name)) { const r = new FileReader(); r.onload = () => { const rows = parseCsv(String(r.result)); if (!rows.length) { setFile({ name: f.name, size: Math.max(1, Math.round(f.size / 1024)) + ' KB', err: L('This file looks empty.', 'Ce fichier semble vide.') }); return; } const head = rows[0], body = rows.slice(1); setFile({ name: f.name, size: Math.max(1, Math.round(f.size / 1024)) + ' KB', real: true, head, rows: body, total: body.length }); setMap(autoMap(head)); }; r.readAsText(f); return; }
    setFile({ name: f ? f.name : (kind === 'invoices' ? 'facture_aegean_oct.xlsx' : 'inventaire_octobre.xlsx'), size: f ? Math.max(1, Math.round(f.size / 1024)) + ' KB' : '48 KB', real: false, ...sample }); setMap(autoMap(sample.head));
  };
  const D2 = file || sample, head = D2.head || [], rows = D2.rows || [];
  const mapped = Object.entries(map).filter(([, v]) => v);
  const qtyCol = Object.keys(map).find((k) => map[k] === 'qty'), nameCol = Object.keys(map).find((k) => map[k] === 'name');
  const missing = qtyCol != null ? rows.filter((r) => !String(r[qtyCol] || '').trim()).length : 0;
  const ready = rows.length - missing;
  const steps = [L('What', 'Quoi'), L('Upload', 'Fichier'), L('Match columns', 'Colonnes'), L('Review', 'Vérifier')];
  const next = () => { if (step === 1) { setBusy(true); setTimeout(() => { setBusy(false); setStep(2); }, 700); return; } if (step < 3) setStep(step + 1); else setDone({ n: rows.length, missing }); };
  const srcTag = file && file.real ? <span className="tag tag-accent"><Icon n="check-circle" />{L('Read from your file', 'Lu dans votre fichier')}</span> : <span className="sim-tag"><Icon n="flask" />{L('Sample preview — Excel files are read in Phase 2', 'Aperçu d’exemple — les fichiers Excel seront lus en phase 2')}</span>;
  return (
    <Modal open={open} onClose={onClose} wide title={<span className="wiz-title"><Icon n="microsoft-excel-logo" />{L('Import from Excel or CSV', 'Importer depuis Excel ou CSV')}</span>}
      actions={done ? <button className="btn btn-primary" onClick={onClose}>{L('Done', 'Terminé')}</button> : <>{step > 0 ? <button className="btn btn-secondary" onClick={() => setStep(step - 1)}>{L('Back', 'Retour')}</button> : <button className="btn btn-secondary" onClick={onClose}>{L('Cancel', 'Annuler')}</button>}<button className="btn btn-primary" disabled={(step === 1 && (!file || file.err)) || busy || (step === 2 && !nameCol)} onClick={next}>{step === 3 ? L(`Check ${rows.length} rows`, `Vérifier ${rows.length} lignes`) : L('Continue', 'Continuer')}<Icon n={step === 3 ? 'check' : 'arrow-right'} /></button></>}>
      {done ? <div className="px-done"><span className="empty-ic"><Icon n="flask" /></span><b>{L(`${done.n} rows checked — nothing was added to your inventory`, `${done.n} lignes vérifiées — rien n’a été ajouté à l’inventaire`)}</b><p className="muted">{L(`${done.n - done.missing} rows are ready${done.missing ? ` and ${done.missing} need a quantity` : ''}. In Phase 2 this step saves the rows to your account. Today it only checks the file.`, `${done.n - done.missing} lignes sont prêtes${done.missing ? ` et ${done.missing} sans quantité` : ''}. En phase 2, cette étape enregistre les lignes. Aujourd’hui, elle vérifie seulement le fichier.`)}</p></div> : <>
      <ol className="wiz-steps">{steps.map((s, i) => <li key={i} className={i === step ? 'on' : i < step ? 'done' : ''}><span>{i < step ? <Icon n="check" /> : i + 1}</span>{s}</li>)}</ol>
      {step === 0 ? (
        <div className="kind-grid">
          {kinds.map(([k, ic, t, d]) => (
            <button key={k} className={'kind' + (kind === k ? ' on' : '')} onClick={() => setKind(k)}><Icon n={ic} s="1.5rem" /><div><div>{t}</div><div className="muted sm">{d}</div></div></button>
          ))}
        </div>
      ) : null}
      {step === 1 && busy ? <div className="imp-busy"><Skeleton rows={4} /><div><b>{L('Reading your file…', 'Lecture du fichier…')}</b><div className="muted sm">{L('Finding the header row and the columns', 'Recherche des en-têtes et des colonnes')}</div></div></div> : null}
      {step === 1 && !busy ? (
        <div className={'drop' + (drag ? ' drag' : '') + (file ? ' has' : '')} onDragOver={(e) => { e.preventDefault(); setDrag(true); }} onDragLeave={() => setDrag(false)} onDrop={(e) => { e.preventDefault(); setDrag(false); const f = e.dataTransfer.files[0]; if (f) pick(f); }}>
          {file ? (
            <><Icon n={file.real ? 'file-csv' : 'file-xls'} s="2.4rem" /><div><div>{file.name}</div><div className="muted sm">{file.err ? <span className="txt-neg">{file.err}</span> : <>{file.size} · {L(`${D2.total} rows, ${head.length} columns found`, `${D2.total} lignes, ${head.length} colonnes trouvées`)}</>}</div><div style={{ marginTop: '.4rem' }}>{srcTag}</div></div><button className="btn btn-ghost" onClick={() => setFile(null)}>{L('Replace', 'Remplacer')}</button></>
          ) : (
            <><Icon n="upload-simple" s="2.4rem" /><div className="drop-t">{L('Drag your spreadsheet here', 'Glissez votre fichier ici')}</div><div className="muted sm">{L('.csv files are read now · .xlsx and .xls are previewed with sample data until Phase 2', 'Les .csv sont lus · .xlsx et .xls utilisent un exemple jusqu’à la phase 2')}</div>
              <div className="drop-actions"><label className="btn btn-secondary">{L('Choose file', 'Choisir un fichier')}<input type="file" accept=".xlsx,.xls,.csv" hidden onChange={(e) => e.target.files[0] && pick(e.target.files[0])} /></label><button className="btn btn-ghost" onClick={() => pick()}>{L('Use a sample file', 'Utiliser un exemple')}</button></div></>
          )}
        </div>
      ) : null}
      {step === 2 ? (
        <div>
          <div className="dr-row" style={{ marginBottom: '.6rem' }}><p className="muted" style={{ margin: 0 }}>{L('MIZO matched your columns by their names. Change any that look wrong, or skip columns you don’t need.', 'MIZO a associé vos colonnes selon leur nom. Corrigez au besoin ou ignorez les colonnes inutiles.')}</p>{srcTag}</div>
          <div className="map-row map-head muted sm"><span>{L('Column in your file', 'Colonne de votre fichier')}</span><span></span><span>{L('Goes into MIZO as', 'Devient dans MIZO')}</span><span>{L('Example', 'Exemple')}</span></div>
          <div className="map">
            {head.map((h, i) => (
              <div key={i} className="map-row"><span className="map-src">{h || L('(no header)', '(sans en-tête)')}</span><Icon n="arrow-right" className="muted" /><select className="input" value={map[i] || ''} onChange={(e) => setMap({ ...map, [i]: e.target.value })} aria-label={h}><option value="">{L('Skip this column', 'Ignorer')}</option>{IMP_FIELDS.map(([k, n]) => <option key={k} value={k}>{L(...n)}</option>)}</select><span className="map-conf muted">{(rows[0] || [])[i] || '—'}</span></div>
            ))}
          </div>
          {!nameCol ? <div className="field-err" style={{ marginTop: '.6rem' }}><Icon n="warning-circle" />{L('Choose which column holds the item name to continue.', 'Choisissez la colonne du nom de l’article pour continuer.')}</div> : null}
        </div>
      ) : null}
      {step === 3 ? (
        <div>
          <div className="review-sum"><span className="txt-pos"><Icon n="check-circle" /> {L(`${ready} rows ready`, `${ready} lignes prêtes`)}</span>{missing ? <span className="txt-warn"><Icon n="warning" /> {L(`${missing} row${missing > 1 ? 's' : ''} missing a quantity — will be imported as 0`, `${missing} ligne(s) sans quantité — importée(s) à 0`)}</span> : null}{srcTag}</div>
          <div className="table-scroll"><table className="table mtable">
            <thead><tr>{mapped.map(([i, k]) => <th key={i}>{L(...IMP_FIELDS.find((f) => f[0] === k)[1])}</th>)}</tr></thead>
            <tbody>{rows.slice(0, 8).map((r, j) => <tr key={j}>{mapped.map(([i, k]) => <td key={i} className={!String(r[i] || '').trim() ? 'cell-warn' : ''}>{String(r[i] || '').trim() || '—'}</td>)}</tr>)}</tbody>
          </table></div>
          {rows.length > 8 ? <p className="muted sm">{L(`Showing 8 of ${rows.length} rows`, `8 lignes sur ${rows.length}`)}</p> : null}
        </div>
      ) : null}
      </>}
    </Modal>
  );
}
Object.assign(window, { Settings, ImportWizard, parseCsv, IMP_FIELDS });
