// Modules: Materials, Customers, Vendors, Crusher, Sales Orders — Full ERP form replication
const { useContext: mCtx, useState: mSt, useEffect: mEf, useMemo: mMemo, useRef: mRef } = React;
const AppCtx = window.AppCtx;

const STATUS_OPTIONS = ['Pending', 'Delivered', 'Cancelled', 'Completed'];
// CRUSHER_MATERIALS removed — now read live from Store.all('materials'). See CrusherModal.
const _UNUSED_CRUSHER_MATERIALS = ['(Black) Soil', '10 20 Mix', '10MM', '12MM', '20MM', '40MM', '6MM', 'BOULDER', 'DUST', 'Debriz', 'GSB', 'IRON BAR 10mm (Ton)', 'MSAND', 'NANU SAND', 'River Stone', 'Slag Sand Dry (Ton)', 'W Sand', 'WATER', 'WMM'];
const GST_OPTIONS = ['0', '5', '12', '18', '28'];
function _gst(val, fallback) { return (val != null && val !== '') ? String(val) : fallback; }
const MATERIAL_CATEGORIES = ['Aggregate', 'Sand', 'Debris', 'RMC', 'Other'];

// ── Section Heading ───────────────────────────────────────
const SH = ({ title, action }) =>
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 10, paddingBottom: 7, borderBottom: '2px solid #FEF3E8' }}>
    <span style={{ color: 'var(--or)', fontWeight: 700, fontSize: 13 }}>{title}</span>
    {action}
  </div>;


const Sec = ({ children, style }) => <div style={{ marginBottom: 20, ...style }}>{children}</div>;

// ── Materials ─────────────────────────────────────────────
function MaterialsPage() {
  window.useStoreSync();
  const { companyId, session } = mCtx(AppCtx);
  const [items, setItems] = mSt([]);
  const [search, setSearch] = mSt('');
  const [modal, setModal] = mSt(false);
  const [editItem, setEdit] = mSt(null);
  const [delId, setDelId] = mSt(null);
  const [form, setForm] = mSt({});
  mEf(() => {load();return Store.on(load);}, [companyId]);
  function load() {setItems(window.filterAssigned(Store.all('materials'), companyId));}
  const filtered = mMemo(() => {if (!search) return items;const q = search.toLowerCase();return items.filter((m) => m.name.toLowerCase().includes(q) || (m.unit || '').toLowerCase().includes(q));}, [items, search]);
  function openAdd() {setForm({ status: 'Active' });setEdit(null);setModal(true);}
  function openEdit(m) {setForm({ ...m });setEdit(m);setModal(true);}
  function handleSave(e) {
    e.preventDefault();
    // Resolve custom UOM: if 'Others' selected, use unitCustom as the actual unit
    const resolvedForm = { ...form };
    if (form.unit === 'Others' && form.unitCustom) {
      resolvedForm.unit = form.unitCustom.trim();
      delete resolvedForm.unitCustom;
    }
    // Resolve category: if 'Other', store the custom-typed value as the category
    if (resolvedForm.category === 'Other' && resolvedForm.categoryCustom) {
      resolvedForm.category = resolvedForm.categoryCustom.trim();
    }
    delete resolvedForm.categoryCustom;
    if (editItem) {Store.update('materials', editItem.id, resolvedForm);Store.addLog('UPDATE', 'Material', `Updated: ${resolvedForm.name}`);} else
    {Store.add('materials', resolvedForm);Store.addLog('CREATE', 'Material', `Created: ${resolvedForm.name}`);}
    window.toast && window.toast(editItem ? 'Material updated' : 'Material created', 'ok');
    setModal(false);load();
  }
  function handleDelete() {Store.del('materials', delId);Store.addLog('DELETE', 'Material', 'Deleted');setDelId(null);load();window.toast && window.toast('Deleted', 'ok');}
  return (
    <div>
      <div className="ph"><div><h1>Materials</h1><p>Aggregate, road material and sand products</p></div><div className="ph-act"><button className="btn btn-or" onClick={openAdd}><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round"><line x1="12" y1="5" x2="12" y2="19" /><line x1="5" y1="12" x2="19" y2="12" /></svg> Add Material</button></div></div>
      <div className="frow"><div className="fs"><svg className="fs-ic" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5"><circle cx="11" cy="11" r="8" /><path d="M21 21l-4.35-4.35" /></svg><input value={search} onChange={(e) => setSearch(e.target.value)} placeholder="Search materials…" /></div><span className="f-cnt">{filtered.length} materials</span></div>
      <div className="card"><div className="tbl-w"><table className="tbl"><thead><tr><th style={{ width: 70, textAlign: 'center' }}>SR. NO.</th><th>MATERIAL NAME</th><th>CATEGORY</th><th>UOM</th><th>CONV. FACTOR</th><th>QTY ADJUSTMENT</th><th>ACTIONS</th></tr></thead><tbody>
        {filtered.length === 0 ?
              <tr className="empty"><td colSpan="7" style={{ textAlign: 'center', padding: 36, color: 'var(--txt2)' }}>No materials found</td></tr> :
              filtered.map((m, idx) =>
              <tr key={m.id}>
              <td style={{ color: 'var(--txt2)', fontWeight: 500, textAlign: 'center' }}>{idx + 1}</td>
              <td><strong>{m.name}</strong></td>
              <td>{m.category ? <span className={`bdg ${m.category === 'Debris' ? 'bg-rd' : m.category === 'Aggregate' ? 'bg-bl' : m.category === 'Sand' ? 'bg-yw' : m.category === 'RMC' ? 'bg-pu' : 'bg-gy'}`} style={{ fontSize: 10.5 }}>{m.category}</span> : <span style={{ color: 'var(--txt3)', fontSize: 11 }}>—</span>}</td>
              <td><span className="bdg bg-or" style={{ fontSize: 10.5 }}>{m.unit || 'Ton'}</span></td>
              <td style={{ fontSize: 11, fontFamily: 'var(--font)', color: m.conversionFactor ? 'var(--or)' : 'var(--txt3)' }}>{m.conversionFactor ? `1 ${m.baseUnit || 'MT'}=${m.conversionFactor} ${m.secondaryUnit || 'm³'}` : '—'}</td>
              <td>{m.qtyAdjEnabled && m.qtyAdjStatus !== 'Inactive' ? (<span className="bdg bg-yw" style={{ fontSize: 10.5 }}>{(m.qtyAdjType === 'Other' ? (m.qtyAdjCustomType || 'Other') : m.qtyAdjType) || 'Adj'} {m.qtyAdjPct || 0}%</span>) : (<span style={{ color: 'var(--txt3)', fontSize: 11 }}>—</span>)}</td>
              <td><div className="ra"><button className="btn btn-wh btn-sm" onClick={() => openEdit(m)}>Edit</button><button className="btn btn-rd btn-sm" onClick={() => setDelId(m.id)}>Delete</button></div></td>
            </tr>
              )}
      </tbody></table></div></div>
      <window.ConversionFactorsSection companyId={companyId} session={session} />
      {modal &&
      <div className="mbg">
          <div className="mod mod-lg">
            <div className="mod-hd"><h2>{editItem ? 'Edit' : 'Add'} Material</h2><button className="mod-x" onClick={() => setModal(false)}>×</button></div>
            <form onSubmit={handleSave}>
              <div className="mod-bd">
                <div className="fg">
                  <div className="fld"><label>Material Name <span className="req">*</span></label><input className="inp" value={form.name || ''} onChange={(e) => setForm((p) => ({ ...p, name: e.target.value }))} required placeholder="Enter material name" /></div>
                  <div className="fld"><label>Material Category</label><window.FormSelect placeholder="— Select Category —" value={form.category || ''} onChange={(v) => setForm((p) => ({ ...p, category: v, categoryCustom: '' }))} options={MATERIAL_CATEGORIES.map((c) => ({value:c,label:c}))}/>{form.category === 'Other' && <input className="inp" style={{ marginTop: 6 }} value={form.categoryCustom || ''} onChange={(e) => setForm((p) => ({ ...p, categoryCustom: e.target.value }))} placeholder="Enter custom category…" />}<span style={{ fontSize: 10.5, color: 'var(--txt2)', marginTop: 3, display: 'block', lineHeight: 1.4 }}>Set to <strong>Debris</strong> to appear in Debris Movement module.</span></div>
                  <div className="fld"><label>Unit of Measure <span className="req">*</span></label><window.FormSelect value={form.unit === 'Bags' || form.unit === 'Pieces' || form.unit === 'Nos' || form.unit === 'Loads' || form.unit === 'Trips' || !['Ton', 'Cubic Meter', 'Kilogram'].includes(form.unit) && form.unit ? 'Others' : form.unit || 'Ton'} onChange={(v) => {if (v === 'Others') {setForm((p) => ({ ...p, unit: 'Others', unitCustom: p.unitCustom || '' }));} else {setForm((p) => ({ ...p, unit: v, unitCustom: '' }));}}} options={[{value:'Ton',label:'Ton'},{value:'Cubic Meter',label:'Cubic Meter'},{value:'Kilogram',label:'Kilogram'},{value:'Others',label:'Others'}]}/>
                  {(form.unit === 'Others' || !['Ton', 'Cubic Meter', 'Kilogram'].includes(form.unit) && form.unit && form.unit !== 'Liters') && <input className="inp" style={{ marginTop: 6 }} value={form.unitCustom || (!['Ton', 'Cubic Meter', 'Kilogram', 'Others'].includes(form.unit) ? form.unit : '')} onChange={(e) => setForm((p) => ({ ...p, unitCustom: e.target.value, unit: 'Others' }))} required placeholder="Enter custom unit (e.g. Bags, Pieces, Nos)" />}
                  </div>
                  <div className="fld"><label>Density Factor <span style={{ fontSize: 11, color: 'var(--txt2)' }}>(Ton/m³)</span></label><input className="inp" type="number" value={form.density || ''} onChange={(e) => setForm((p) => ({ ...p, density: parseFloat(e.target.value) || 1.50 }))} step="0.01" min="0.1" max="5" placeholder="1.50" /><span style={{ fontSize: 11, color: 'var(--txt2)', marginTop: 3, display: 'block' }}>Used to convert Cubic Meter ↔ Ton. Default: 1.50</span></div>
                </div>
                <hr className="f-div" style={{ margin: '12px 0 10px' }} />
                <div style={{ fontSize: 12, fontWeight: 700, color: 'var(--or)', marginBottom: 8 }}>Unit Conversion</div>
                <div className="fg3">
                  <div className="fld">
                    <label>Base Unit</label>
                    <window.FormSelect value={form.baseUnit || 'MT'} onChange={(v) => setForm((p) => ({ ...p, baseUnit: v }))} options={[{value:'MT',label:'MT — Metric Ton'},{value:'m³',label:'m³ — Cubic Meter'},{value:'Kg',label:'Kg — Kilogram'}]}/>
                  </div>
                  <div className="fld">
                    <label>Secondary Unit</label>
                    <window.FormSelect value={form.secondaryUnit || 'm³'} onChange={(v) => setForm((p) => ({ ...p, secondaryUnit: v }))} options={[{value:'m³',label:'m³ — Cubic Meter'},{value:'MT',label:'MT — Metric Ton'},{value:'Kg',label:'Kg — Kilogram'}]}/>
                  </div>
                  <div className="fld">
                    <label>Conversion Factor</label>
                    <input className="inp" type="number" value={form.conversionFactor || ''} onChange={(e) => setForm((p) => ({ ...p, conversionFactor: e.target.value }))} placeholder="e.g. 0.67" step="0.001" min="0" />
                    {form.conversionFactor && <span style={{ fontSize: 10.5, color: 'var(--txt2)', marginTop: 2, display: 'block', lineHeight: 1.4 }}>1 {form.baseUnit || 'MT'} = {form.conversionFactor} {form.secondaryUnit || 'm³'}</span>}
                  </div>
                </div>
                <div style={{ marginTop: 10 }}>
                  <label style={{ display: 'flex', alignItems: 'center', gap: 7, cursor: 'pointer', fontSize: 12 }}>
                    <input type="checkbox" checked={!!form.allowOverride} onChange={(e) => setForm((p) => ({ ...p, allowOverride: e.target.checked }))} style={{ accentColor: 'var(--or)' }} />
                    Allow Manual Override per Transaction
                  </label>
                </div>
                <hr className="f-div" style={{ margin: '14px 0 10px' }} />
                <div style={{ fontSize: 12, fontWeight: 700, color: 'var(--or)', marginBottom: 8 }}>Quantity Adjustment Settings</div>
                <div style={{ marginBottom: 10 }}>
                  <label style={{ display: 'flex', alignItems: 'center', gap: 7, cursor: 'pointer', fontSize: 12 }}>
                    <input type="checkbox" checked={!!form.qtyAdjEnabled} onChange={(e) => setForm((p) => ({ ...p, qtyAdjEnabled: e.target.checked }))} style={{ accentColor: 'var(--or)' }} />
                    Enable Quantity Adjustment for Stockyard Inventory
                  </label>
                  <div style={{ fontSize: 10.5, color: 'var(--txt2)', marginTop: 3, marginLeft: 24, lineHeight: 1.5 }}>When enabled, Gross Qty (inventory deduction) = Net Qty × (1 + Adj%). Sales and billing always continue using Net Quantity — no other modules are affected.</div>
                </div>
                {!!form.qtyAdjEnabled && (<>
                  <div className="fg">
                    <div className="fld">
                      <label>Adjustment Type</label>
                      <window.FormSelect placeholder="— Select Type —" value={form.qtyAdjType || ''} onChange={(v) => setForm((p) => ({ ...p, qtyAdjType: v, qtyAdjCustomType: v !== 'Other' ? '' : p.qtyAdjCustomType }))} options={[{value:'Moisture',label:'Moisture'},{value:'Shrinkage',label:'Shrinkage'},{value:'Dust Loss',label:'Dust Loss'},{value:'Other',label:'Other'}]}/>
                      {form.qtyAdjType === 'Other' && (
                        <div style={{ marginTop: 8 }}>
                          <label style={{ fontSize: 11, fontWeight: 600, color: 'var(--txt2)', display: 'block', marginBottom: 4 }}>Adjustment Name <span className="req">*</span></label>
                          <input
                            className="inp"
                            value={form.qtyAdjCustomType || ''}
                            onChange={(e) => setForm((p) => ({ ...p, qtyAdjCustomType: e.target.value }))}
                            placeholder="e.g. Moisture Recovery, Compaction, Drying Loss…"
                            required
                          />
                          <span style={{ fontSize: 10.5, color: 'var(--or)', marginTop: 3, display: 'block' }}>This name replaces "Other" everywhere in the OM GROUP ERP</span>
                        </div>
                      )}
                      {form.qtyAdjType !== 'Other' && <span style={{ fontSize: 10.5, color: 'var(--txt2)', marginTop: 3, display: 'block' }}>Select "Other" to define a custom adjustment name</span>}
                    </div>
                    <div className="fld">
                      <label>Default Adjustment %</label>
                      <input className="inp" type="number" value={form.qtyAdjPct || ''} onChange={(e) => setForm((p) => ({ ...p, qtyAdjPct: parseFloat(e.target.value) || 0 }))} min="0" max="100" step="0.01" placeholder="e.g. 2" />
                      {form.qtyAdjPct > 0 && (<span style={{ fontSize: 10.5, color: 'var(--ok)', marginTop: 3, display: 'block' }}>Example: 25.000 MT net → {(25 * (1 + (form.qtyAdjPct || 0) / 100)).toFixed(3)} MT gross (inventory deduction)</span>)}
                    </div>
                  </div>
                  <div className="fg">
                    <div className="fld">
                      <label style={{ display: 'flex', alignItems: 'center', gap: 7, cursor: 'pointer', fontSize: 12 }}>
                        <input type="checkbox" checked={!!form.qtyAdjAllowOverride} onChange={(e) => setForm((p) => ({ ...p, qtyAdjAllowOverride: e.target.checked }))} style={{ accentColor: 'var(--or)' }} />
                        Allow Override During Transaction
                      </label>
                      <span style={{ fontSize: 10.5, color: 'var(--txt2)', marginTop: 3, display: 'block' }}>If enabled, operators can edit the adjustment % when recording a stock movement. Otherwise it is locked to this default.</span>
                    </div>
                    <div className="fld">
                      <label>Configuration Status</label>
                      <window.FormSelect value={form.qtyAdjStatus || 'Active'} onChange={(v) => setForm((p) => ({ ...p, qtyAdjStatus: v }))} options={[{value:'Active',label:'Active'},{value:'Inactive',label:'Inactive'}]}/>
                    </div>
                  </div>
                  <div style={{ background: '#F0FDF4', border: '1px solid #86EFAC', borderRadius: 6, padding: '8px 12px', fontSize: 11, color: '#166534', lineHeight: 1.6, marginTop: 2 }}>
                    <strong>Scope — Inventory only:</strong> Affects Inventory Deduction in Stock Register. Sales Quantity, Customer Billing, Revenue, and Transport Settlement always use Net Quantity unchanged.
                  </div>
                </>)}
                <window.CompanyAssignmentSection form={form} setForm={setForm} />
              </div>
              <div className="mod-ft"><button type="button" className="btn btn-wh" onClick={() => setModal(false)}>Cancel</button><button type="submit" className="btn btn-or">{editItem ? 'Update Material' : 'Create Material'}</button></div>
            </form>
          </div>
        </div>
      }
      {delId && <window.Confirm onOk={handleDelete} onCancel={() => setDelId(null)} />}
    </div>);

}

// ── Customer Page ─────────────────────────────────────────
function CustomersPage() {
  window.useStoreSync();
  const { companyId } = mCtx(AppCtx);
  const [items, setItems] = mSt([]);
  const [search, setSearch] = mSt('');
  const [page, setPage] = mSt(1);
  const [modal, setModal] = mSt(false);
  const [editItem, setEdit] = mSt(null);
  const [delId, setDelId] = mSt(null);
  const PER = 50;
  mEf(() => {setItems(window.filterAssigned(Store.all('customers'), companyId));}, [companyId]);
  function load() {setItems(window.filterAssigned(Store.all('customers'), companyId));}
  const filtered = mMemo(() => items.filter((it) => {if (!search) return true;const q = search.toLowerCase();return ['name', 'contactPerson', 'mobile', 'email', 'gst'].some((k) => String(it[k] || '').toLowerCase().includes(q));}), [items, search]);
  const paged = filtered.slice((page - 1) * PER, page * PER);
  const totalPgs = Math.ceil(filtered.length / PER);
  function getActivePO(cid) {return Store.all('salesOrders', companyId).filter((o) => o.customerId === cid && o.status === 'Pending').length;}
  function exportCSV() {const hdr = 'Name,GST,Contact,Mobile,Email,Address,Status';const rows = filtered.map((c) => `"${c.name}","${c.gst || ''}","${c.contactPerson || ''}","${c.mobile || ''}","${c.email || ''}","${c.address || ''}","${c.status || ''}"`).join('\n');const blob = new Blob([hdr + '\n' + rows], { type: 'text/csv' });const a = document.createElement('a');a.href = URL.createObjectURL(blob);a.download = 'customers.csv';a.click();}
  function openAdd() {setEdit(null);setModal(true);}
  function openEdit(it) {setEdit(it);setModal(true);}
  function handleSaved() {load();setModal(false);}
  function handleDelete() {Store.del('customers', delId);Store.addLog('DELETE', 'Customer', 'Deleted');setDelId(null);load();window.toast && window.toast('Deleted', 'ok');}
  return (
    <div>
      <div className="ph">
        <div><h1>Customers</h1><p>Client accounts and delivery contacts</p></div>
        <div className="ph-act">
          <button className="btn btn-wh btn-sm" onClick={exportCSV}><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4" /><polyline points="7 10 12 15 17 10" /><line x1="12" y1="15" x2="12" y2="3" /></svg> Export CSV</button>
          <button className="btn btn-or" onClick={openAdd}><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round"><line x1="12" y1="5" x2="12" y2="19" /><line x1="5" y1="12" x2="19" y2="12" /></svg> Add Customer</button>
        </div>
      </div>
      <div className="frow">
        <div className="fs"><svg className="fs-ic" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5"><circle cx="11" cy="11" r="8" /><path d="M21 21l-4.35-4.35" /></svg><input value={search} onChange={(e) => {setSearch(e.target.value);setPage(1);}} placeholder="Search name, contact, GST…" /></div>
        <span className="f-cnt">{filtered.length} customers</span>
      </div>
      <div className="card">
        <div className="tbl-w">
          <table className="tbl">
            <thead><tr><th>NAME</th><th>GST NUMBER</th><th>CONTACT</th><th>ADDRESS</th><th>ACTIVE PO</th><th>ACTIONS</th></tr></thead>
            <tbody>
              {paged.length === 0 ? <tr className="empty"><td colSpan="6" style={{ textAlign: 'center', padding: 36, color: 'var(--txt2)' }}>No customers found</td></tr> :
              paged.map((c) =>
              <tr key={c.id}>
                  <td><strong style={{ fontSize: 12 }}>{c.name}</strong></td>
                  <td><span style={{ fontFamily: 'var(--font)', fontSize: 11 }}>{c.gst || '—'}</span></td>
                  <td>{c.contactPerson || '—'}</td>
                  <td className="wrap" style={{ fontSize: 11.5 }}>{c.address || '—'}</td>
                  <td>{getActivePO(c.id) > 0 ? <span className="bdg bg-or">{getActivePO(c.id)} Active</span> : <span className="bdg bg-gy">0</span>}</td>
                  <td><div className="ra"><button className="btn btn-wh btn-sm" onClick={() => openEdit(c)}>Edit</button><button className="btn btn-rd btn-sm" onClick={() => setDelId(c.id)}>Delete</button></div></td>
                </tr>
              )}
            </tbody>
          </table>
        </div>
      </div>
      {totalPgs > 1 && <div className="pag"><button className="pg-b" onClick={() => setPage(1)} disabled={page === 1}>«</button><button className="pg-b" onClick={() => setPage((p) => p - 1)} disabled={page === 1}>‹</button><span className="pg-inf">Page {page} of {totalPgs}</span><button className="pg-b" onClick={() => setPage((p) => p + 1)} disabled={page === totalPgs}>›</button><button className="pg-b" onClick={() => setPage(totalPgs)} disabled={page === totalPgs}>»</button></div>}
      {modal && <CustomerModal item={editItem} companyId={companyId} onSaved={handleSaved} onClose={() => setModal(false)} />}
      {delId && <window.Confirm onOk={handleDelete} onCancel={() => setDelId(null)} />}
    </div>);

}

function CustomerModal({ item, companyId, onSaved, onClose }) {
  const [form, setForm] = mSt(item ? { ...item, street: item.street || item.address || '' } : { status: 'Active', state: 'Goa' });
  const setF = (k, v) => setForm((p) => ({ ...p, [k]: v }));
  const [_initFrmC] = mSt(() => JSON.stringify(form));
  const [_discardC, _setDiscardC] = mSt(false);
  function _guardCloseC() {if (JSON.stringify(form) !== _initFrmC) _setDiscardC(true);else onClose();}
  function handleSave(e) {
    e.preventDefault();
    const address = [form.street, form.city, form.state, form.pincode].filter(Boolean).join(', ');
    const data = { ...form, address };
    if (item) {Store.update('customers', item.id, data);Store.addLog('UPDATE', 'Customer', `Updated: ${form.name}`);} else
    {Store.add('customers', data);Store.addLog('CREATE', 'Customer', `Created: ${form.name}`);}
    window.toast && window.toast(item ? 'Customer updated' : 'Customer created', 'ok');
    onSaved();
  }
  return (
    <>
    <div className="mbg">
      <div className="mod mod-xl" style={{ maxHeight: '92vh' }}>
        <div className="mod-hd"><h2>{item ? 'Edit' : 'Add'} Customer</h2><button className="mod-x" onClick={_guardCloseC}>×</button></div>
        <form onSubmit={handleSave}>
          <div className="mod-bd">
            <Sec>
              <SH title="Customer Information" />
              <div className="fg">
                <div className="fld"><label>Customer Name <span className="req">*</span></label><input className="inp" value={form.name || ''} onChange={(e) => setF('name', e.target.value)} required placeholder="Full company or person name" /></div>
                <div className="fld">
                  <label>GST Number</label>
                  <input className="inp" value={form.gst || ''} onChange={(e) => setF('gst', e.target.value)} placeholder="30AABCX1234A1Z5" />
                  <span style={{ fontSize: 10.5, color: 'var(--txt2)', marginTop: 2, lineHeight: 1.4, display: 'block' }}>GST format: 2 digit state + 5 char PAN + 4 digit + 1 entity + Z + check digit</span>
                </div>
                <div className="fld"><label>Contact Person</label><input className="inp" value={form.contactPerson || ''} onChange={(e) => setF('contactPerson', e.target.value)} placeholder="Primary contact name" /></div>
                <div className="fld"><label>Mobile Number</label><input className="inp" type="tel" value={form.mobile || ''} onChange={(e) => setF('mobile', e.target.value)} placeholder="9876543210" /></div>
                <div className="fld full"><label>Email Address</label><input className="inp" type="email" value={form.email || ''} onChange={(e) => setF('email', e.target.value)} placeholder="contact@company.com" /></div>
              </div>
            </Sec>
            <Sec>
              <SH title="Address Details" />
              <div className="fg">
                <div className="fld full"><label>Street / Location <span className="req">*</span></label><input className="inp" value={form.street || ''} onChange={(e) => setF('street', e.target.value)} placeholder="Street address or project site location" required /></div>
                <div className="fld"><label>City <span className="req">*</span></label><input className="inp" value={form.city || ''} onChange={(e) => setF('city', e.target.value)} placeholder="e.g. Panaji" required /></div>
                <div className="fld"><label>State <span className="req">*</span></label><input className="inp" value={form.state || ''} onChange={(e) => setF('state', e.target.value)} placeholder="e.g. Goa" /></div>
                <div className="fld"><label>Pincode</label><input className="inp" value={form.pincode || ''} onChange={(e) => setF('pincode', e.target.value)} placeholder="403001" maxLength={6} /></div>
                <div className="fld"><label>Google Maps Link <span style={{ color: 'var(--txt2)', fontWeight: 400, fontSize: 11 }}>(Optional)</span></label><input className="inp" value={form.mapsLink || ''} onChange={(e) => setF('mapsLink', e.target.value)} placeholder="https://maps.google.com/…" /></div>
              </div>
            </Sec>
            <window.CompanyAssignmentSection form={form} setForm={setForm} />
          </div>
          <div className="mod-ft">
            <button type="button" className="btn btn-wh" onClick={_guardCloseC}>Cancel</button>
            <button type="submit" className="btn btn-or">{item ? 'Update Customer' : 'Create Customer'}</button>
          </div>
        </form>
      </div>
    </div>
    {_discardC && <window.DiscardChangesModal onContinue={() => _setDiscardC(false)} onDiscard={onClose} />}
    </>);

}

// ── Vendor Page ───────────────────────────────────────────
function VendorsPage() {
  window.useStoreSync();
  const { companyId } = mCtx(AppCtx);
  const [items, setItems] = mSt([]);const [search, setSearch] = mSt('');const [page, setPage] = mSt(1);const [modal, setModal] = mSt(false);const [editItem, setEdit] = mSt(null);const [delId, setDelId] = mSt(null);
  const PER = 50;
  mEf(() => {setItems(window.filterAssigned(Store.all('vendors'), companyId));}, [companyId]);
  function load() {setItems(window.filterAssigned(Store.all('vendors'), companyId));}
  const filtered = mMemo(() => items.filter((it) => {if (!search) return true;const q = search.toLowerCase();return ['name', 'mobile', 'email', 'gst'].some((k) => String(it[k] || '').toLowerCase().includes(q));}), [items, search]);
  const paged = filtered.slice((page - 1) * PER, page * PER);const totalPgs = Math.ceil(filtered.length / PER);
  function getActivePO(vid) {return Store.all('purchases', companyId).filter((p) => p.vendorId === vid && p.status === 'Pending').length;}
  function exportCSV() {const hdr = 'Name,GST,Contact,Mobile,Address';const rows = filtered.map((v) => `"${v.name}","${v.gst || ''}","${v.contactPerson || ''}","${v.mobile || ''}","${v.address || ''}"`).join('\n');const blob = new Blob([hdr + '\n' + rows], { type: 'text/csv' });const a = document.createElement('a');a.href = URL.createObjectURL(blob);a.download = 'vendors.csv';a.click();}
  function handleDelete() {Store.del('vendors', delId);Store.addLog('DELETE', 'Vendor', 'Deleted');setDelId(null);load();window.toast && window.toast('Deleted', 'ok');}
  return (
    <div>
      <div className="ph"><div><h1>Vendors</h1><p>Supplier accounts and contacts</p></div><div className="ph-act"><button className="btn btn-wh btn-sm" onClick={exportCSV}><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4" /><polyline points="7 10 12 15 17 10" /><line x1="12" y1="15" x2="12" y2="3" /></svg> Export CSV</button><button className="btn btn-or" onClick={() => {setEdit(null);setModal(true);}}><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round"><line x1="12" y1="5" x2="12" y2="19" /><line x1="5" y1="12" x2="19" y2="12" /></svg> Add Vendor</button></div></div>
      <div className="frow">
        <div className="fs"><svg className="fs-ic" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5"><circle cx="11" cy="11" r="8" /><path d="M21 21l-4.35-4.35" /></svg><input value={search} onChange={(e) => {setSearch(e.target.value);setPage(1);}} placeholder="Search vendor, GST…" /></div>
        <span className="f-cnt">{filtered.length} vendors</span>
      </div>
      <div className="card"><div className="tbl-w"><table className="tbl"><thead><tr><th>NAME</th><th>GST NUMBER</th><th>CONTACT</th><th>ADDRESS</th><th>ACTIVE PO</th><th>ACTIONS</th></tr></thead><tbody>
        {paged.length === 0 ? <tr className="empty"><td colSpan="6" style={{ textAlign: 'center', padding: 36, color: 'var(--txt2)' }}>No vendors found</td></tr> : paged.map((v) =>
              <tr key={v.id}><td><strong style={{ fontSize: 12 }}>{v.name}</strong></td><td><span style={{ fontFamily: 'var(--font)', fontSize: 11 }}>{v.gst || '—'}</span></td><td>{v.contactPerson || '—'}</td><td className="wrap" style={{ fontSize: 11.5 }}>{v.address || '—'}</td><td>{getActivePO(v.id) > 0 ? <span className="bdg bg-or">{getActivePO(v.id)} Active</span> : <span className="bdg bg-gy">0</span>}</td><td><div className="ra"><button className="btn btn-wh btn-sm" onClick={() => {setEdit(v);setModal(true);}}>Edit</button><button className="btn btn-rd btn-sm" onClick={() => setDelId(v.id)}>Delete</button></div></td></tr>
              )}
      </tbody></table></div></div>
      {totalPgs > 1 && <div className="pag"><button className="pg-b" onClick={() => setPage(1)} disabled={page === 1}>«</button><button className="pg-b" onClick={() => setPage((p) => p - 1)} disabled={page === 1}>‹</button><span className="pg-inf">Page {page} of {totalPgs}</span><button className="pg-b" onClick={() => setPage((p) => p + 1)} disabled={page === totalPgs}>›</button><button className="pg-b" onClick={() => setPage(totalPgs)} disabled={page === totalPgs}>»</button></div>}
      {modal && <VendorModal item={editItem} companyId={companyId} onSaved={() => {load();setModal(false);}} onClose={() => setModal(false)} />}
      {delId && <window.Confirm onOk={handleDelete} onCancel={() => setDelId(null)} />}
    </div>);

}

function VendorModal({ item, companyId, onSaved, onClose }) {
  const [form, setForm] = mSt(item ? { ...item, street: item.street || item.address || '' } : { status: 'Active', state: 'Goa' });
  const setF = (k, v) => setForm((p) => ({ ...p, [k]: v }));
  const [_initFrmV] = mSt(() => JSON.stringify(form));
  const [_discardV, _setDiscardV] = mSt(false);
  function _guardCloseV() {if (JSON.stringify(form) !== _initFrmV) _setDiscardV(true);else onClose();}
  function handleSave(e) {e.preventDefault();const address = [form.street, form.city, form.state, form.pincode].filter(Boolean).join(', ');const data = { ...form, address };if (item) {Store.update('vendors', item.id, data);Store.addLog('UPDATE', 'Vendor', `Updated: ${form.name}`);} else {Store.add('vendors', data);Store.addLog('CREATE', 'Vendor', `Created: ${form.name}`);}window.toast && window.toast(item ? 'Vendor updated' : 'Vendor created', 'ok');onSaved();}
  return (
    <>
    <div className="mbg">
      <div className="mod mod-xl" style={{ maxHeight: '92vh' }}>
        <div className="mod-hd"><h2>{item ? 'Edit' : 'Add'} Vendor</h2><button className="mod-x" onClick={_guardCloseV}>×</button></div>
        <form onSubmit={handleSave}>
          <div className="mod-bd">
            <Sec><SH title="Vendor Details" />
              <div className="fg">
                <div className="fld"><label>Vendor Name <span className="req">*</span></label><input className="inp" value={form.name || ''} onChange={(e) => setF('name', e.target.value)} required placeholder="Full vendor company name" /></div>
                <div className="fld"><label>GST Number</label><input className="inp" value={form.gst || ''} onChange={(e) => setF('gst', e.target.value)} placeholder="30AABCX1234A1Z5" /><span style={{ fontSize: 10.5, color: 'var(--txt2)', marginTop: 2, display: 'block' }}>2 digit state + 5 char PAN + 4 digit + 1 entity + Z + check</span></div>
                <div className="fld"><label>Contact Person</label><input className="inp" value={form.contactPerson || ''} onChange={(e) => setF('contactPerson', e.target.value)} /></div>
                <div className="fld"><label>Mobile Number</label><input className="inp" type="tel" value={form.mobile || ''} onChange={(e) => setF('mobile', e.target.value)} placeholder="9876543210" /></div>
                <div className="fld full"><label>Email Address</label><input className="inp" type="email" value={form.email || ''} onChange={(e) => setF('email', e.target.value)} /></div>
              </div>
            </Sec>
            <Sec><SH title="Address Details" />
              <div className="fg">
                <div className="fld full"><label>Street / Location <span className="req">*</span></label><input className="inp" value={form.street || ''} onChange={(e) => setF('street', e.target.value)} required placeholder="Quarry or site address" /></div>
                <div className="fld"><label>City</label><input className="inp" value={form.city || ''} onChange={(e) => setF('city', e.target.value)} placeholder="e.g. Bicholim" /></div>
                <div className="fld"><label>State</label><input className="inp" value={form.state || ''} onChange={(e) => setF('state', e.target.value)} placeholder="e.g. Goa" /></div>
                <div className="fld"><label>Pincode</label><input className="inp" value={form.pincode || ''} onChange={(e) => setF('pincode', e.target.value)} placeholder="403504" /></div>
                <div className="fld"><label>Google Maps Link <span style={{ color: 'var(--txt2)', fontWeight: 400, fontSize: 11 }}>(Optional)</span></label><input className="inp" value={form.mapsLink || ''} onChange={(e) => setF('mapsLink', e.target.value)} /></div>
              </div>
            </Sec>
            <window.CompanyAssignmentSection form={form} setForm={setForm} />
          </div>
          <div className="mod-ft"><button type="button" className="btn btn-wh" onClick={_guardCloseV}>Cancel</button><button type="submit" className="btn btn-or">{item ? 'Update Vendor' : 'Create Vendor'}</button></div>
        </form>
      </div>
    </div>
    {_discardV && <window.DiscardChangesModal onContinue={() => _setDiscardV(false)} onDiscard={onClose} />}
    </>);

}

// ── Crusher Page ──────────────────────────────────────────
function CrusherPage() {
  window.useStoreSync();
  const { companyId } = mCtx(AppCtx);
  const [items, setItems] = mSt([]);const [search, setSearch] = mSt('');const [page, setPage] = mSt(1);const [modal, setModal] = mSt(false);const [editItem, setEdit] = mSt(null);const [delId, setDelId] = mSt(null);
  const PER = 50;
  mEf(() => {setItems(window.filterAssigned(Store.all('crushers'), companyId));}, [companyId]);
  function load() {setItems(window.filterAssigned(Store.all('crushers'), companyId));}
  const filtered = mMemo(() => items.filter((it) => {if (!search) return true;const q = search.toLowerCase();return ['name', 'location', 'owner'].some((k) => String(it[k] || '').toLowerCase().includes(q));}), [items, search]);
  const paged = filtered.slice((page - 1) * PER, page * PER);const totalPgs = Math.ceil(filtered.length / PER);
  function handleDelete() {Store.del('crushers', delId);Store.addLog('DELETE', 'Crusher', 'Deleted');setDelId(null);load();window.toast && window.toast('Deleted', 'ok');}
  return (
    <div>
      <div className="ph"><div><h1>Crusher</h1><p>Crusher sites and pickup points</p></div><div className="ph-act"><button className="btn btn-or" onClick={() => {setEdit(null);setModal(true);}}><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round"><line x1="12" y1="5" x2="12" y2="19" /><line x1="5" y1="12" x2="19" y2="12" /></svg> Add Crusher</button></div></div>
      <div className="frow"><div className="fs"><svg className="fs-ic" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5"><circle cx="11" cy="11" r="8" /><path d="M21 21l-4.35-4.35" /></svg><input value={search} onChange={(e) => {setSearch(e.target.value);setPage(1);}} placeholder="Search crusher, location…" /></div><span className="f-cnt">{filtered.length} records</span></div>
      <div className="card"><div className="tbl-w"><table className="tbl"><thead><tr><th>NAME</th><th>OWNER</th><th>LOCATION</th><th>MATERIALS</th><th>STATUS</th><th>ACTIONS</th></tr></thead><tbody>
        {paged.length === 0 ? <tr className="empty"><td colSpan="6" style={{ textAlign: 'center', padding: 36, color: 'var(--txt2)' }}>No crushers found</td></tr> : paged.map((c) =>
              <tr key={c.id}>
            <td><strong>{c.name}</strong></td><td>{c.owner}</td><td>{c.location}</td>
            <td>{c.materials ? <span style={{ display: 'flex', flexWrap: 'wrap', gap: 3 }}>{String(c.materials).split(',').map((m) => m.trim()).filter(Boolean).map((m) => <span key={m} className="bdg bg-or" style={{ fontSize: 10, padding: '1px 4px' }}>{m}</span>)}</span> : '—'}</td>
            <td><window.Badge v={c.status} /></td>
            <td><div className="ra"><button className="btn btn-wh btn-sm" onClick={() => {setEdit(c);setModal(true);}}>Edit</button><button className="btn btn-rd btn-sm" onClick={() => setDelId(c.id)}>Delete</button></div></td>
          </tr>
              )}
      </tbody></table></div></div>
      {totalPgs > 1 && <div className="pag"><button className="pg-b" onClick={() => setPage(1)} disabled={page === 1}>«</button><button className="pg-b" onClick={() => setPage((p) => p - 1)} disabled={page === 1}>‹</button><span className="pg-inf">Page {page} of {totalPgs}</span><button className="pg-b" onClick={() => setPage((p) => p + 1)} disabled={page === totalPgs}>›</button><button className="pg-b" onClick={() => setPage(totalPgs)} disabled={page === totalPgs}>»</button></div>}
      {modal && <CrusherModal item={editItem} companyId={companyId} onSaved={() => {load();setModal(false);}} onClose={() => setModal(false)} />}
      {delId && <window.Confirm onOk={handleDelete} onCancel={() => setDelId(null)} />}
    </div>);

}

function CrusherModal({ item, companyId, onSaved, onClose }) {
  const existingLocs = ['Sattari, North Goa', 'Bicholim, North Goa', 'Sanguem, South Goa', 'Canacona, South Goa', 'Pernem, North Goa', 'Ponda, South Goa', 'Various Locations'];
  const [form, setForm] = mSt(item || { status: 'Active' });
  const [locType, setLocType] = mSt(item?.location && existingLocs.includes(item.location) ? 'existing' : 'custom');
  // ── Live materials from Store — fully dynamic, reflects Add/Edit/Delete instantly ──
  const [liveMats, setLiveMats] = mSt(() => Store.all('materials').filter((m) => m.status !== 'Inactive').map((m) => m.name).sort());
  mEf(() => {
    function refresh() {setLiveMats(Store.all('materials').filter((m) => m.status !== 'Inactive').map((m) => m.name).sort());}
    const unsub = Store.on(refresh);
    return unsub;
  }, []);
  const [selMats, setSelMats] = mSt(() => {if (!item?.materials) return new Set();return new Set(String(item.materials).split(',').map((m) => m.trim()).filter(Boolean));});
  const setF = (k, v) => setForm((p) => ({ ...p, [k]: v }));
  function toggleMat(m) {setSelMats((p) => {const n = new Set(p);n.has(m) ? n.delete(m) : n.add(m);return n;});}
  function handleSave(e) {
    e.preventDefault();
    const loc = locType === 'existing' ? form.locationExisting : form.locationCustom;
    const data = { ...form, location: loc || '', materials: [...selMats].join(', ') };
    if (item) {Store.update('crushers', item.id, data);Store.addLog('UPDATE', 'Crusher', `Updated: ${form.name}`);} else
    {Store.add('crushers', data);Store.addLog('CREATE', 'Crusher', `Added: ${form.name}`);}
    window.toast && window.toast(item ? 'Crusher updated' : 'Crusher added', 'ok');onSaved();
  }
  return (
    <div className="mbg">
      <div className="mod mod-lg" style={{ maxHeight: '90vh' }}>
        <div className="mod-hd"><h2>Add New Crusher Site</h2><button className="mod-x" onClick={onClose}>×</button></div>
        <form onSubmit={handleSave}>
          <div className="mod-bd">
            <Sec><SH title="Site Details" />
              <div className="fg">
                <div className="fld"><label>Site Name <span className="req">*</span></label><input className="inp" value={form.name || ''} onChange={(e) => setF('name', e.target.value)} required placeholder="e.g. AP Fernandes" /></div>
                <div className="fld"><label>Owner Name <span className="req">*</span></label><input className="inp" value={form.owner || ''} onChange={(e) => setF('owner', e.target.value)} required placeholder="Owner company or person" /></div>
                <div className="fld"><label>Status</label><window.FormSelect value={form.status || 'Active'} onChange={(v) => setF('status', v)} options={[{value:'Active',label:'Active'},{value:'Inactive',label:'Inactive'}]}/></div>
              </div>
            </Sec>
            <Sec><SH title="Location" />
              <div style={{ display: 'flex', gap: 20, marginBottom: 12 }}>
                <label style={{ display: 'flex', alignItems: 'center', gap: 6, cursor: 'pointer', fontSize: 12.5, fontWeight: 500 }}>
                  <input type="radio" name="locType" value="existing" checked={locType === 'existing'} onChange={() => setLocType('existing')} style={{ accentColor: 'var(--or)' }} />Select Existing Location
                </label>
                <label style={{ display: 'flex', alignItems: 'center', gap: 6, cursor: 'pointer', fontSize: 12.5, fontWeight: 500 }}>
                  <input type="radio" name="locType" value="custom" checked={locType === 'custom'} onChange={() => setLocType('custom')} style={{ accentColor: 'var(--or)' }} />Enter Custom Location
                </label>
              </div>
              {locType === 'existing' ?
              <div className="fld"><label>Select Location <span className="req">*</span></label><window.FormSelect placeholder="Select location…" value={form.locationExisting || ''} onChange={(v) => setF('locationExisting', v)} options={existingLocs.map((l) => ({value:l,label:l}))}/></div> :

              <div className="fld"><label>Custom Location <span className="req">*</span></label><input className="inp" value={form.locationCustom || ''} onChange={(e) => setF('locationCustom', e.target.value)} placeholder="Enter full location name" /></div>
              }
            </Sec>
            <Sec style={{ marginBottom: 0 }}><SH title="Materials" />
              <div style={{ marginBottom: 8, fontSize: 11.5, color: 'var(--txt2)' }}>{selMats.size} material{selMats.size !== 1 ? 's' : ''} selected</div>
              <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4,1fr)', gap: 5 }}>
                {liveMats.length === 0 && <div style={{ gridColumn: '1/-1', fontSize: 12, color: 'var(--txt3)', padding: '8px 0' }}>No materials found. Add materials in the Materials module first.</div>}
                {liveMats.map((m) =>
                <label key={m} style={{ display: 'flex', alignItems: 'center', gap: 5, cursor: 'pointer', fontSize: 12, padding: '4px 6px', borderRadius: 3, background: selMats.has(m) ? 'var(--or-lt)' : 'transparent', border: '1px solid', borderColor: selMats.has(m) ? 'var(--or-bdr)' : 'transparent', transition: 'all .1s' }}>
                    <input type="checkbox" checked={selMats.has(m)} onChange={() => toggleMat(m)} style={{ accentColor: 'var(--or)', flexShrink: 0 }} />{m}
                  </label>
                )}
              </div>
            </Sec>
            <window.CompanyAssignmentSection form={form} setForm={setForm} />
          </div>
          <div className="mod-ft"><button type="button" className="btn btn-wh" onClick={onClose}>Cancel</button><button type="submit" className="btn btn-or">{item ? 'Update Crusher' : 'Create Crusher'}</button></div>
        </form>
      </div>
    </div>);

}

// ── Sales Orders ──────────────────────────────────────────
function SalesPage() {
  window.useStoreSync();
  const { companyId, session } = mCtx(AppCtx);
  const isGroup = companyId === 'group';
  const [items, setItems] = mSt([]);const [search, setSearch] = mSt('');const [showFP, setShowFP] = mSt(false);
  const [fv, setFv] = mSt({ dateFrom: '', dateTo: '', status: '', customerId: '', materialId: '', crusherId: '' });
  const [applied, setApplied] = mSt({ dateFrom: '', dateTo: '', status: '', customerId: '', materialId: '', crusherId: '' });
  const [page, setPage] = mSt(1);const [modal, setModal] = mSt(false);const [editItem, setEdit] = mSt(null);const [delId, setDelId] = mSt(null);
  const [soItems, setSoItems] = mSt([{ id: window.uid(), materialId: '', uom: 'MT', quantity: '', ratePerTon: '', gst: '5', amount: 0 }]);
  const [soForm, setSoForm] = mSt({});
  const [soOverride, setSoOverride] = mSt(false);
  const [soActivePO, setSoActivePO] = mSt(null);
  const [soExpand, setSoExpand] = mSt(null);
  const [soStatement, setSoStatement] = mSt(null);
  const soIsInitialEditLoad = mRef(false);
  const PER = 50;
  const customers = window.filterAssigned(Store.all('customers'), companyId);const materials = window.filterAssigned(Store.all('materials'), companyId);const crushers = window.filterAssigned(Store.all('crushers'), companyId);
  // ── Transporter Master — live sync so TM additions/changes reflect instantly ──────
  const [soTmAll, setSoTmAll] = mSt(() => Store.all('transporterMaster', 'group'));
  const [soAllVeh, setSoAllVeh] = mSt(() => Store.all('vehicleMaster', 'group') || []);
  mEf(() => {
    const unsub = Store.on(() => {setSoTmAll(Store.all('transporterMaster', 'group'));setSoAllVeh(Store.all('vehicleMaster', 'group') || []);});
    return unsub;
  }, []);
  const soTmActive = soTmAll.filter((t) => t.status === 'Active' || !t.status);
  const soTmVehicles = mMemo(() => soForm.transporterMasterId ?
  soAllVeh.filter((v) => v.transporterId === soForm.transporterMasterId && (v.status === 'Active' || !v.status)) :
  [], [soAllVeh, soForm.transporterMasterId]);
  mEf(() => {load();return Store.on(load);}, [companyId]);
  function load() {setItems(Store.all('salesOrders', companyId));}
  // ── Auto-fill Delivery Address from Customer Master ───────────────────────────────
  mEf(() => {
    if (!modal || !soForm.customerId) return;
    if (soIsInitialEditLoad.current) { soIsInitialEditLoad.current = false; return; }
    const _cust = Store.byId('customers', soForm.customerId);
    if (_cust && _cust.address) { setSoForm(p => ({ ...p, deliveryAddress: _cust.address })); }
  }, [soForm.customerId, modal]);

  // ── Auto-fill: watch customer + company, fetch active sales PO, populate rates ──
  mEf(() => {
    if (!modal) {setSoActivePO(null);return;}
    const coId = isGroup ? soForm.companyId || '' : companyId;
    if (!coId || !soForm.customerId || !window.RateEngine) {setSoActivePO(null);return;}
    const po = window.RateEngine.getActivePO(coId, 'customer', soForm.customerId);
    setSoActivePO(po ? { poNumber: po.poNumber } : null);
    if (!soOverride && po) {
      setSoItems((prev) => prev.map((row) => {
        if (!row.materialId) return row;
        const rr = (po.rates || []).find((r) => r.materialId === row.materialId);
        if (!rr) return { ...row, _autoFilled: false };
        const qty = parseFloat(row.quantity) || 0,rate = parseFloat(rr.rate) || 0;
        return { ...row, ratePerTon: rate, gst: _gst(rr.gst, _gst(po.defaultGst, '5')), amount: qty * rate, _autoFilled: true, _autoRate: rate, _autoPO: po.poNumber };
      }));
    }
  }, [soForm.customerId, soForm.companyId, modal, soOverride, companyId, isGroup]);
  function applyFP() {setApplied({ ...fv });setPage(1);setShowFP(false);}
  function clearFP() {const e = { dateFrom: '', dateTo: '', status: '', customerId: '', materialId: '', crusherId: '' };setFv(e);setApplied(e);setSearch('');setPage(1);}
  const filtered = mMemo(() => items.filter((it) => {
    if (search) {const q = search.toLowerCase();if (![it.challanNumber, it.vehicleFull].some((v) => String(v || '').toLowerCase().includes(q)) && !Store.name('customers', it.customerId).toLowerCase().includes(q)) return false;}
    if (applied.dateFrom && it.date < applied.dateFrom) return false;if (applied.dateTo && it.date > applied.dateTo) return false;
    if (applied.status && it.status !== applied.status) return false;if (applied.customerId && it.customerId !== applied.customerId) return false;
    if (applied.materialId && it.materialId !== applied.materialId) return false;if (applied.crusherId && it.crusherSite !== applied.crusherId) return false;
    return true;
  }), [items, search, applied]);
  const activeFilters = Object.values(applied).filter(Boolean).length;
  // GST/total figures are recalculated fresh per row (never trusted from
  // stored fields) so historical per-line rounding can never leak into this
  // report total — see window.GstEngine.recalcRecord.
  const soRecalc = mMemo(() => window.GstEngine.sumRecalc(filtered), [filtered]);
  const soTotals = mMemo(() => ({ qty: filtered.reduce((s, o) => s + (parseFloat(o.quantity) || 0), 0), amt: soRecalc.subtotal, amtGst: soRecalc.total }), [filtered]);
  const totalPgs = Math.ceil(filtered.length / PER);const paged = filtered.slice((page - 1) * PER, page * PER);

  function openAdd() {
    soIsInitialEditLoad.current = false;
    setSoForm({ date: new Date().toISOString().slice(0, 10), status: 'Delivered', transportRequired: 'Yes', transporterMasterId: '', transporterName: '', vehicleFull: '', companyId: isGroup ? '' : companyId });
    setSoItems([{ id: window.uid(), materialId: '', uom: 'MT', quantity: '', ratePerTon: '', gst: '5', amount: 0 }]);
    setEdit(null);setModal(true);
    setSoOverride(false);setSoActivePO(null);
  }
  function openEdit(it) {
    setSoForm({ ...it });
    // HIGH-03: populate item lines from flat-format legacy records to prevent data loss on edit
    setSoItems(it.items?.length ? it.items.map((i) => ({ ...i })) : [{
      id: window.uid(),
      materialId: it.materialId || '',
      uom: it.uom || 'MT',
      quantity: it.quantity || '',
      ratePerTon: it.rate || 0,
      gst: _gst(it.gst, '5'),
      amount: it.subtotal || 0
    }]);
    soIsInitialEditLoad.current = true;
    setEdit(it);setModal(true);
    setSoOverride(false);setSoActivePO(null);
  }
  const setSF = (k, v) => setSoForm((p) => ({ ...p, [k]: v }));
  function updItem(idx, k, v) {
    const coId = isGroup ? soForm.companyId || '' : companyId;
    const _po = coId && soForm.customerId && window.RateEngine ? window.RateEngine.getActivePO(coId, 'customer', soForm.customerId) : null;
    setSoItems((p) => p.map((r, i) => {
      if (i !== idx) return r;
      const u = { ...r, [k]: v };
      // Auto-fill rate when material selected
      if (k === 'materialId' && v && !soOverride && _po) {
        const rr = (_po.rates || []).find((x) => x.materialId === v);
        if (rr) {const qty = parseFloat(u.quantity) || 0,rate = parseFloat(rr.rate) || 0;u.ratePerTon = rate;u.gst = _gst(rr.gst, _gst(_po.defaultGst, '5'));u.amount = qty * rate;u._autoFilled = true;u._autoRate = rate;u._autoPO = _po.poNumber;} else
        {u._autoFilled = false;}
      }
      if (k === 'quantity' || k === 'ratePerTon' && (soOverride || !u._autoFilled)) {
        const qty = parseFloat(k === 'quantity' ? v : u.quantity) || 0;const rate = parseFloat(k === 'ratePerTon' ? v : u.ratePerTon) || 0;u.amount = qty * rate;
      }
      return u;
    }));
  }
  function addItem() {setSoItems((p) => [...p, { id: window.uid(), materialId: '', uom: 'MT', quantity: '', ratePerTon: '', gst: '5', amount: 0 }]);}
  function remItem(idx) {setSoItems((p) => p.filter((_, i) => i !== idx));}
  const totals = mMemo(() => {const subtotal = soItems.reduce((s, r) => s + (parseFloat(r.amount) || 0), 0);const gstAmount = soItems.reduce((s, r) => s + ((parseFloat(r.amount) || 0) * (parseFloat(r.gst) || 0) / 100), 0);return { subtotal, gstAmount, total: subtotal + gstAmount };}, [soItems]);

  function handleSave(e) {
    e.preventDefault();
    const coErr = window.requireGroupCompany(isGroup, soForm.companyId);
    if (coErr) {window.toast && window.toast(coErr, 'er');return;}
    if (soForm.transportRequired !== 'No') {
      if (!soForm.transporterMasterId) {window.toast && window.toast('Please select a Transporter.', 'er');return;}
      if (!soForm.vehicleFull) {window.toast && window.toast('Please select a Vehicle.', 'er');return;}
    }
    // Record rate overrides to audit log
    if (soOverride && window.RateEngine) {
      const coId = isGroup ? soForm.companyId || companyId : companyId;
      soItems.forEach((row) => {
        if (row._autoFilled && row._autoRate != null && parseFloat(row.ratePerTon) !== parseFloat(row._autoRate)) {
          window.RateEngine.recordOverride({ companyId: coId, partyType: 'customer', partyId: soForm.customerId, materialId: row.materialId, materialName: Store.name('materials', row.materialId), poNumber: row._autoPO || '', autoRate: row._autoRate, overrideRate: parseFloat(row.ratePerTon), userName: Store.data.session?.userName });
        }
      });
    }
    const firstMat = soItems[0]?.materialId;const totalQty = soItems.reduce((s, r) => s + (parseFloat(r.quantity) || 0), 0);
    // Persist top-level UOM from first item so reports can always find it
    const firstUom = soItems[0]?.uom || 'MT';
    const data = { ...soForm, materialId: firstMat, quantity: totalQty, uom: firstUom, items: soItems, ...totals };
    if (editItem) {Store.update('salesOrders', editItem.id, data);Store.addLog('UPDATE', 'Sales Order', `Updated ${soForm.challanNumber}`);} else
    {Store.add('salesOrders', data);Store.addLog('CREATE', 'Sales Order', `Created ${soForm.challanNumber}`);}
    setModal(false);load();window.toast && window.toast(editItem ? 'Updated' : 'Sales order created', 'ok');
  }
  function handleDelete() {Store.del('salesOrders', delId);Store.addLog('DELETE', 'Sales Order', 'Deleted');setDelId(null);load();window.toast && window.toast('Deleted', 'ok');}
  // Standard Export — the default, visible to every employee. Never includes
  // Rate or any figure derived from it (Subtotal / GST / Total are all
  // rate-derived, so they're excluded here too).
  function exportStandard() {
    // Canonical source-company attribution (erp/company-attribution.js).
    // REPORT SCOPE ≠ TRANSACTION COMPANY: the column is resolved per record,
    // never from the active company selector.
    const _q  = v => '"' + String(v==null?'':v).replace(/"/g,'""') + '"';
    const _co = r => window.ERPCompanyAttribution
      ? window.ERPCompanyAttribution.resolveTransactionCompany(r).companyName
      : (Store.name('companies', r && r.companyId) || 'Unassigned');
    const _coHdr = isGroup ? 'OM Group Company,' : '';
    const _coCell = r => isGroup ? _q(_co(r)) + ',' : '';
    const hdr = _coHdr + 'Date,Customer,Material,Vehicle,Crusher,Qty,UOM,Challan,Subtotal (Pre-GST),GST Amount,Total+GST,Status';
    // Subtotal/GST/Total are read via the same GstEngine.recalcRecord used by
    // Confidential Export and the on-screen table — each row's own record (o),
    // never recalculated differently or borrowed from another transaction.
    // Rate itself is deliberately omitted — this is the one thing that stays hidden.
    const rows = filtered.map((o) => {const c = window.GstEngine.recalcRecord(o);return _coCell(o) + [o.date, Store.name('customers', o.customerId), Store.name('materials', o.materialId), o.vehicleFull || '', Store.name('crushers', o.crusherSite) || '', o.quantity, o.uom || 'MT', o.challanNumber || '', c.subtotal, c.gstAmount, c.total, o.status].map(_q).join(',');}).join('\r\n');
    const blob = new Blob(['\uFEFF' + hdr + '\r\n' + rows], { type: 'text/csv;charset=utf-8' });const a = document.createElement('a');a.href = URL.createObjectURL(blob);a.download = 'sales_orders.csv';a.click();
    Store.addLog('EXPORT', 'Sales Order', `Standard export: ${filtered.length} records`);
    window.toast && window.toast('CSV exported', 'ok');
  }
  // Confidential Export — same content as the export this module has always
  // produced (Rate-derived pricing included), gated behind the Confidential
  // Export permission. Every row is built straight from its own transaction
  // record (`o`), so rates can never shift, mix, or inherit across rows.
  function exportConfidential() {
    const rows = filtered.map((o) => {
      const c = window.GstEngine.recalcRecord(o);
      return { id: o.id, subtotal: c.subtotal, gstAmount: c.gstAmount, total: c.total, _o: o, _c: c };
    });
    const check = window.ExportPermission ? window.ExportPermission.validateExportIntegrity(rows, { rateKeys: ['subtotal', 'total'] }) : { ok: true };
    if (!check.ok) { window.toast && window.toast(check.reason || 'Export blocked — data integrity check failed', 'er'); return; }
    // Canonical source-company attribution (erp/company-attribution.js).
    // REPORT SCOPE ≠ TRANSACTION COMPANY: the column is resolved per record,
    // never from the active company selector.
    const _q  = v => '"' + String(v==null?'':v).replace(/"/g,'""') + '"';
    const _co = r => window.ERPCompanyAttribution
      ? window.ERPCompanyAttribution.resolveTransactionCompany(r).companyName
      : (Store.name('companies', r && r.companyId) || 'Unassigned');
    const _coHdr = isGroup ? 'OM Group Company,' : '';
    const _coCell = r => isGroup ? _q(_co(r)) + ',' : '';
    const hdr = _coHdr + 'Date,Customer,Material,Vehicle,Crusher,Qty,UOM,Challan,Rate,Subtotal (Pre-GST),GST Amount,Total+GST,Status';
    // Rate is read directly off the original order record — same value the
    // order was created/saved with (o.rate, falling back to the first line
    // item's stored rate for multi-item orders). Never recalculated, never
    // pulled from current material pricing.
    const csvRows = rows.map(({ _o: o, _c: c }) => {
      const rate = (o.rate != null && o.rate !== '') ? o.rate : (o.items?.[0]?.ratePerTon ?? '');
      return _coCell(o) + [o.date, Store.name('customers', o.customerId), Store.name('materials', o.materialId), o.vehicleFull || '', Store.name('crushers', o.crusherSite) || '', o.quantity, o.uom || 'MT', o.challanNumber || '', rate, c.subtotal, c.gstAmount, c.total, o.status].map(_q).join(',');
    }).join('\r\n');
    const blob = new Blob(['\uFEFF' + hdr + '\r\n' + csvRows], { type: 'text/csv;charset=utf-8' });const a = document.createElement('a');a.href = URL.createObjectURL(blob);a.download = 'sales_orders_confidential.csv';a.click();
    Store.addLog('EXPORT', 'Sales Order', `Confidential export: ${filtered.length} records`);
    window.toast && window.toast('Confidential CSV exported', 'ok');
  }
  const exportCSV = exportStandard;
  const canExportConfidential = !!(window.ExportPermission && window.ExportPermission.canExportConfidential(session));

  const fpFields = [
  { key: 'dateFrom', label: 'Start Date', type: 'date' }, { key: 'dateTo', label: 'End Date', type: 'date' },
  { key: 'status', label: 'Status', width: 120, options: STATUS_OPTIONS.map((s) => ({ value: s, label: s })) },
  { key: 'crusherId', label: 'Crusher', width: 140, options: crushers.map((c) => ({ value: c.id, label: c.name })) },
  { key: 'customerId', label: 'Customer', width: 160, options: customers.map((c) => ({ value: c.id, label: c.name })) },
  { key: 'materialId', label: 'Material', width: 130, options: materials.map((m) => ({ value: m.id, label: m.name })) }];


  return (
    <div>
      <div className="ph"><div><h1>Sales Orders</h1><p>Customer material sales — {filtered.length} records</p></div><div className="ph-act"><button className={`btn btn-sm ${showFP ? 'btn-or' : 'btn-wh'}`} onClick={() => setShowFP((p) => !p)}><svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><polygon points="22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3" /></svg> Filters{activeFilters > 0 && <span style={{ background: '#fff', color: 'var(--or)', borderRadius: 10, padding: '0 4px', fontSize: 10, fontWeight: 700, marginLeft: 2 }}>{activeFilters}</span>}</button><window.ExportMenu onStandard={exportStandard} onConfidential={exportConfidential} canConfidential={canExportConfidential} label="Export CSV" /><button className="btn btn-or" onClick={openAdd}><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round"><line x1="12" y1="5" x2="12" y2="19" /><line x1="5" y1="12" x2="19" y2="12" /></svg> Add Sales Order</button></div></div>
      <window.FilterPanel show={showFP} fields={fpFields} values={fv} onChange={(k, v) => setFv((p) => ({ ...p, [k]: v }))} onApply={applyFP} onRefresh={load} onExport={exportCSV} onClear={clearFP} />
      <div className="frow"><div className="fs"><svg className="fs-ic" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5"><circle cx="11" cy="11" r="8" /><path d="M21 21l-4.35-4.35" /></svg><input value={search} onChange={(e) => {setSearch(e.target.value);setPage(1);}} placeholder="Search challan, vehicle, customer…" /></div>{(search || activeFilters > 0) && <button className="btn btn-gh btn-sm" onClick={clearFP}>Clear All</button>}<span className="f-cnt">{filtered.length} records</span></div>
      <div className="card"><div className="tbl-w"><table className="tbl"><thead><tr><th style={{ width: 26, padding: '7px 4px' }}></th><th>DATE</th>{isGroup && <th>OM GROUP COMPANY</th>}<th>CUSTOMER</th><th>MATERIAL</th><th>VEHICLE</th><th>CRUSHER</th><th>QUANTITY</th><th>UOM</th><th>CHALLAN NO.</th><th>AMOUNT</th><th>AMOUNT WITH GST</th><th>STATUS</th><th>TRANSPORT</th><th>ACTIONS</th></tr></thead><tbody>
        {paged.length === 0 ? <tr className="empty"><td colSpan={14 + (isGroup ? 1 : 0)} style={{ textAlign: 'center', padding: 40, color: 'var(--txt2)' }}>No sales orders found</td></tr> : paged.map((o) => {
                const isOpen = soExpand === o.id;
                const items = o.items?.length ? o.items : [{ materialId: o.materialId, uom: o.uom || 'MT', quantity: o.quantity, ratePerTon: o.rate || 0, gst: o.gst || 5, amount: o.subtotal || 0 }];
                return (
                  <React.Fragment key={o.id}>
              <tr>
                <td style={{ textAlign: 'center', padding: '5px 4px', cursor: 'pointer', width: 26 }} onClick={() => setSoExpand(isOpen ? null : o.id)}>
                  <span style={{ color: 'var(--or)', fontSize: 9, display: 'inline-block', transition: 'transform .15s', transform: isOpen ? 'rotate(90deg)' : 'none' }}>&#9658;</span>
                </td>
                <td>{window.fmtDate(o.date)}</td>
                {isGroup && <td><span className="bdg bg-or" style={{ fontSize: 10, padding: '1px 5px' }}>{Store.name('companies', o.companyId)}</span></td>}
                <td style={{ fontWeight: 500 }}>{Store.name('customers', o.customerId)}</td>
                <td>{Store.name('materials', o.materialId)}</td>
                <td><span style={{ fontFamily: 'var(--font)', fontSize: 11, background: '#F9FAFB', padding: '1px 5px', borderRadius: 3 }}>{o.vehicleFull || '—'}</span></td>
                <td style={{ fontSize: 11.5, color: 'var(--txt2)' }}>{Store.name('crushers', o.crusherSite) || '—'}</td>
                <td style={{ fontWeight: 600 }}>{window.formatQuantity(o.quantity)}</td>
                <td style={{ color: 'var(--txt2)' }}>{o.uom || 'MT'}</td>
                <td style={{ fontFamily: 'var(--font)', fontSize: 11.5 }}>{o.challanNumber || '—'}</td>
                <td>{window.fmtCur(window.gSub(o))}</td>
                <td style={{ fontWeight: 600, color: 'var(--or)' }}>{window.fmtCur(window.gAmt(o))}</td>
                <td><window.Badge v={o.status} /></td>
                <td>{(o.transportRequired||'Yes')==='No'?<span style={{fontSize:10,fontWeight:700,padding:'2px 7px',borderRadius:3,background:'#F3F4F6',color:'#57534E',whiteSpace:'nowrap'}}>No Transport</span>:<span style={{fontSize:10,fontWeight:700,padding:'2px 7px',borderRadius:3,background:'#DCFCE7',color:'#15803D',whiteSpace:'nowrap'}}>Transport</span>}</td>
                <td><div className="ra"><button className="btn btn-wh btn-sm" onClick={() => openEdit(o)}>Edit</button><button className="btn btn-wh btn-sm" onClick={() => setSoStatement(o)}>Statement</button><button className="btn btn-rd btn-sm" onClick={() => setDelId(o.id)}>Delete</button></div></td>
              </tr>
              {isOpen &&
                    <tr>
                  <td colSpan={14 + (isGroup ? 1 : 0)} style={{ padding: 0 }}>
                    <window.SalesDrillDown o={o} isGroup={isGroup} />
                  </td>
                </tr>
                    }
            </React.Fragment>);

              })}
      </tbody></table></div></div>
      {filtered.length > 0 && <div style={{ background: '#FFF9F5', border: '1px solid var(--or-bdr)', borderRadius: 'var(--r)', padding: '8px 14px', marginTop: 6, display: 'flex', gap: 24, alignItems: 'center', flexWrap: 'wrap' }}><span style={{ fontWeight: 700, fontSize: 12, color: 'var(--txt2)' }}>Totals ({filtered.length} Records)</span><span style={{ fontSize: 12 }}><span style={{ color: 'var(--txt2)' }}>Total Qty: </span><strong>{soTotals.qty.toFixed(3)} Ton</strong></span><span style={{ fontSize: 12 }}><span style={{ color: 'var(--txt2)' }}>Total Amount: </span><strong>{window.fmtCur(soTotals.amt)}</strong></span><span style={{ fontSize: 12 }}><span style={{ color: 'var(--txt2)' }}>Amount With GST: </span><strong style={{ color: 'var(--or)' }}>{window.fmtCur(soTotals.amtGst)}</strong></span></div>}
      {totalPgs > 1 && <div className="pag"><button className="pg-b" onClick={() => setPage(1)} disabled={page === 1}>«</button><button className="pg-b" onClick={() => setPage((p) => p - 1)} disabled={page === 1}>‹</button><span className="pg-inf">Page {page} of {totalPgs}</span><button className="pg-b" onClick={() => setPage((p) => p + 1)} disabled={page === totalPgs}>›</button><button className="pg-b" onClick={() => setPage(totalPgs)} disabled={page === totalPgs}>»</button></div>}

      {modal &&
      <div className="mbg">
          <div className="mod mod-xl" style={{ maxHeight: '92vh' }}>
            <div className="mod-hd"><h2>{editItem ? 'Edit' : 'Add'} Sales Order</h2><button className="mod-x" onClick={() => setModal(false)}>×</button></div>
            <form onSubmit={handleSave}>
              <div className="mod-bd">
                {isGroup && <window.GroupCompanyField value={soForm.companyId} onChange={(v) => setSF('companyId', v)} />}
                {/* Row 1: Customer, Date, Status */}
                <Sec><SH title="Order Details" />
                  <div className="fg3">
                    <div className="fld"><label>Customer Name <span className="req">*</span></label><window.FormSelect placeholder="Select Customer" value={soForm.customerId || ''} onChange={(v) => setSF('customerId', v)} options={customers.map((c) => ({value:c.id,label:c.name}))}/></div>
                    <div className="fld"><label>Order Date <span className="req">*</span></label><input className="inp" type="date" value={soForm.date || ''} onChange={(e) => setSF('date', e.target.value)} required /></div>
                    <div className="fld"><label>Status <span className="req">*</span></label><window.FormSelect value={soForm.status || 'Pending'} onChange={(v) => setSF('status', v)} options={STATUS_OPTIONS.map((s) => ({value:s,label:s}))}/></div>
                  </div>
                  {/* Transport Required */}
                  <div className="fg3" style={{marginTop:10}}>
                    <div className="fld">
                      <label>Transport Required <span className="req">*</span></label>
                      <window.FormSelect value={soForm.transportRequired||'Yes'} onChange={(v)=>setSF('transportRequired',v)} options={[{value:'Yes',label:'Yes — OM Group arranges transport'},{value:'No',label:'No — Customer pickup / direct delivery'}]}/>
                      {soForm.transportRequired==='No'&&<div style={{fontSize:10.5,color:'var(--txt2)',marginTop:3,fontStyle:'italic'}}>No transport record will be generated for this order.</div>}
                    </div>
                  </div>
                  {/* Row 2: Crusher always shown · Transporter+Vehicle when transport=Yes · free-text Vehicle when transport=No */}
                  <div className="fg3" style={{ marginTop: 10 }}>
                    {(soForm.transportRequired||'Yes')!=='No' ? (
                      <>
                        <div className="fld">
                          <label>Transporter Name <span className="req">*</span></label>
                          <window.SearchableSelect
                          options={soTmActive.map((t) => ({ value: t.id, label: t.name }))}
                          value={soForm.transporterMasterId || ''}
                          onChange={(v, label) => setSoForm((p) => ({ ...p, transporterMasterId: v, transporterName: label || '', vehicleFull: '' }))}
                          placeholder="Search transporter…"
                          noOptionsMsg={soTmActive.length === 0 ? 'No active transporters — add in Transporter Master first' : 'No transporter matches'} />
                          {soTmActive.length === 0 && <div style={{ fontSize: 10.5, color: 'var(--warn)', marginTop: 3 }}><svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" style={{ display: 'inline', verticalAlign: '-1px', flexShrink: 0, marginRight: 4 }}><path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3z" /><path d="M12 9v4" /><path d="M12 17h.01" /></svg>No active transporters found.</div>}
                        </div>
                        <div className="fld">
                          <label>Vehicle Number <span className="req">*</span>{soTmVehicles.length > 0 && <span style={{ fontSize: 10, color: 'var(--txt2)', fontWeight: 400, marginLeft: 4 }}>({soTmVehicles.length} vehicles)</span>}</label>
                          <window.SearchableSelect
                          options={soTmVehicles.map((v) => ({ value: v.vehicleNumber, label: v.vehicleNumber + (v.vehicleType ? ' (' + v.vehicleType + ')' : '') }))}
                          value={soForm.vehicleFull || ''}
                          onChange={(v) => setSF('vehicleFull', v)}
                          placeholder={!soForm.transporterMasterId ? 'Select a transporter first…' : soTmVehicles.length === 0 ? 'No active vehicles for this transporter' : 'Search vehicle number…'}
                          noOptionsMsg={!soForm.transporterMasterId ? 'Select a transporter first' : 'No vehicles match'}
                          inputStyle={{ fontFamily: 'var(--font)', fontWeight: 600 }} />
                        </div>
                      </>
                    ) : (
                      <div className="fld">
                        <label>Vehicle Number</label>
                        <input className="inp" value={soForm.vehicleFull||''} onChange={(e)=>setSF('vehicleFull',e.target.value)} placeholder="Enter Vehicle Number e.g. GA03A1234" style={{fontFamily:'var(--font)',fontWeight:600}}/>
                        <div style={{fontSize:10.5,color:'var(--txt2)',marginTop:3}}>Vehicle recorded for traceability — OM Group is not arranging transport.</div>
                      </div>
                    )}
                    <div className="fld"><label>Crusher</label><window.FormSelect placeholder="Select Crusher" value={soForm.crusherSite || ''} onChange={(v) => setSF('crusherSite', v)} options={crushers.map((c) => ({value:c.id,label:c.name}))}/></div>
                  </div>
                  {/* Row 3: Royalty Pass, Challan, Delivery Address */}
                  <div className="fg3" style={{ marginTop: 10, display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 14 }}>
                    <div className="fld"><label>Royalty Pass</label><input className="inp" value={soForm.royaltyPass || ''} onChange={(e) => setSF('royaltyPass', e.target.value)} placeholder="RP-10001" /></div>
                    <div className="fld"><label>Challan Number</label><input className="inp" value={soForm.challanNumber || ''} onChange={(e) => setSF('challanNumber', e.target.value)} placeholder="SC-0001" /></div>
                    <div className="fld"><label>Delivery Address</label><input className="inp" value={soForm.deliveryAddress || ''} onChange={(e) => setSF('deliveryAddress', e.target.value)} placeholder="Project site address" />{soForm.customerId && (() => { const _ca = customers.find(c => c.id === soForm.customerId); return (!_ca || !_ca.address) ? <span style={{fontSize:10.5,color:'var(--txt3)',marginTop:3,display:'block',fontStyle:'italic'}}>No address found for this customer.</span> : null; })()}</div>
                  </div>
                </Sec>

                {/* Item Details */}
                <Sec style={{ marginBottom: 0 }}>
                  <SH title="Item Details" action={<button type="button" className="btn btn-or btn-sm" onClick={addItem}><svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round"><line x1="12" y1="5" x2="12" y2="19" /><line x1="5" y1="12" x2="19" y2="12" /></svg> Add Item</button>} />
                  {/* Auto-fill rate banner */}
                  {soActivePO &&
                <div style={{ background: '#F0FDF4', border: '1px solid #BBF7D0', borderRadius: 4, padding: '8px 12px', marginBottom: 10, display: 'flex', alignItems: 'center', justifyContent: 'space-between', flexWrap: 'wrap', gap: 8 }}>
                      <span style={{ fontSize: 11.5, fontWeight: 600, color: '#166534' }}><svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" style={{ display: 'inline', verticalAlign: '-1px', marginRight: 4 }}><path d="M5 13l4 4L19 7" /></svg>AUTO-FILL ACTIVE — Rates from <span style={{ fontFamily: 'var(--font)' }}>{soActivePO.poNumber}</span></span>
                      <label style={{ display: 'flex', alignItems: 'center', gap: 6, cursor: 'pointer', fontSize: 12 }}>
                        <input type="checkbox" checked={soOverride} onChange={(e) => setSoOverride(e.target.checked)} style={{ accentColor: 'var(--warn)' }} />
                        <span style={{ color: 'var(--txt2)', fontWeight: 500 }}>Override Auto-Filled Rate</span>
                      </label>
                    </div>
                }
                  {!soActivePO && soForm.customerId &&
                <div style={{ background: '#FFFBF5', border: '1px solid var(--or-bdr)', borderRadius: 4, padding: '7px 12px', marginBottom: 10, fontSize: 11.5, color: 'var(--txt2)' }}>
                      <svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" style={{ display: 'inline', verticalAlign: '-1px', flexShrink: 0, marginRight: 4 }}><path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3z" /><path d="M12 9v4" /><path d="M12 17h.01" /></svg>No active Price Order found for this customer. Enter rates manually or create a Price Order first.
                    </div>
                }
                  <div className="ig">
                    {/* table-layout:fixed via .ig table CSS.
                     colgroup locks every column — no name or value can push neighbours. */}
                    <table>
                      <colgroup>
                        <col style={{ width: '21%' }} />{/* Material     */}
                        <col style={{ width: '10%' }} />{/* UOM          */}
                        <col style={{ width: '9%' }} />{/* Quantity     */}
                        <col style={{ width: '10%' }} />{/* Conversion   */}
                        <col style={{ width: '16%' }} />{/* Rate Per Ton */}
                        <col style={{ width: '9%' }} />{/* GST %        */}
                        <col style={{ width: '16%' }} />{/* Amount       */}
                        <col style={{ width: '9%' }} />{/* ×            */}
                      </colgroup>
                      <thead><tr><th>Material</th><th>UOM</th><th>Quantity</th><th>Conversion</th><th>Rate Per Ton ₹</th><th>GST %</th><th>Amount ₹</th><th></th></tr></thead>
                      <tbody>
                        {soItems.map((row, idx) =>
                      <tr key={row.id}>
                            <td style={{ minWidth: 110 }}><select value={row.materialId} onChange={(e) => updItem(idx, 'materialId', e.target.value)} style={{ width: '100%' }}><option value="">Select</option>{materials.map((m) => <option key={m.id} value={m.id}>{m.name}</option>)}</select></td>
                            <td><select value={row.uom || 'MT'} onChange={(e) => updItem(idx, 'uom', e.target.value)} style={{ width: '100%', minWidth: 56, fontSize: "12px" }}><option value="MT">MT</option><option value="Ton">Ton</option><option value="CUM">CUM</option><option value="CFT">CFT</option><option value="Kg">Kg</option></select></td>
                            <td>
                              <input type="number" value={row.quantity} onChange={(e) => updItem(idx, 'quantity', e.target.value)} style={{ width: '100%' }} min="0" step="0.001" />
                            </td>
                            {/* Conversion — dedicated fixed column with twoLine badge */}
                            <td style={{ verticalAlign: 'middle', padding: '4px 6px' }}>
                              {!!window.ConversionBadge ?
                          <window.ConversionBadge materialId={row.materialId} qty={row.quantity} rate={row.ratePerTon} unit={row.uom} twoLine /> :
                          null}
                            </td>
                            <td>
                              <input type="number" value={row.ratePerTon}
                          onChange={(e) => (soOverride || !row._autoFilled) && updItem(idx, 'ratePerTon', e.target.value)}
                          readOnly={!!(row._autoFilled && !soOverride)}
                          style={{ width: '100%', background: row._autoFilled && !soOverride ? '#F0FDF4' : '#fff', cursor: row._autoFilled && !soOverride ? 'not-allowed' : 'text' }}
                          min="0" step="0.01" />
                              {/* Fixed-height AUTO label slot — matches purchase grid */}
                              <div style={{ height: 14, overflow: 'hidden', fontSize: 9, fontWeight: 700, lineHeight: '14px', marginTop: 1, whiteSpace: 'nowrap' }}>
                                {row._autoFilled && !soOverride && <span style={{ color: '#166534', display: 'inline-flex', alignItems: 'center', gap: 2 }}>AUTO <svg width="9" height="9" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"><path d="M5 13l4 4L19 7" /></svg></span>}
                                {row._autoFilled && soOverride && <span style={{ color: '#92400E' }}>OVERRIDE</span>}
                              </div>
                            </td>
                            <td><select value={row.gst} onChange={(e) => updItem(idx, 'gst', e.target.value)} style={{ width: '100%' }}><option value="0">0% Exempt</option><option value="5">5%</option><option value="12">12%</option><option value="18">18%</option><option value="28">28%</option></select></td>
                            <td><span className="ro">{window.fmtCur(row.amount || 0)}</span></td>
                            <td style={{ textAlign: 'center' }}>{soItems.length > 1 && <button type="button" onClick={() => remItem(idx)} style={{ background: 'none', border: 'none', color: 'var(--err)', cursor: 'pointer', fontSize: 18 }}>×</button>}</td>
                          </tr>
                      )}
                      </tbody>
                      <tfoot>
                        <tr><td colSpan="6" style={{ textAlign: 'right', fontWeight: 600, color: 'var(--txt2)' }}>Subtotal:</td><td colSpan="2" style={{ fontWeight: 700 }}>{window.fmtCur(totals.subtotal)}</td></tr>
                        <tr><td colSpan="6" style={{ textAlign: 'right', fontWeight: 600, color: 'var(--txt2)' }}>GST:</td><td colSpan="2" style={{ fontWeight: 700 }}>{window.fmtCur(totals.gstAmount)}</td></tr>
                        <tr><td colSpan="6" style={{ textAlign: 'right', fontWeight: 700, color: 'var(--or)' }}>Total:</td><td colSpan="2" style={{ fontWeight: 700, fontSize: 14, color: 'var(--or)' }}>{window.fmtCur(totals.total)}</td></tr>
                      </tfoot>
                    </table>
                  </div>
                </Sec>
              </div>
              <div className="mod-ft"><button type="button" className="btn btn-wh" onClick={() => setModal(false)}>Cancel</button><button type="submit" className="btn btn-or">{editItem ? 'Update Order' : 'Create Sales Order'}</button></div>
            </form>
          </div>
        </div>
      }
      {delId && <window.Confirm onOk={handleDelete} onCancel={() => setDelId(null)} />}
      {soStatement && <window.SalesOrderStatement order={soStatement} onClose={() => setSoStatement(null)} session={null} />}
    </div>);

}

window.FilterPanel = window.FilterPanel;
window.MaterialsPage = MaterialsPage;
window.CustomersPage = CustomersPage;
window.VendorsPage = VendorsPage;
window.CrusherPage = CrusherPage;
window.SalesPage = SalesPage;
window.STATUS_OPTIONS = STATUS_OPTIONS;