// Admin — Companies, Users, Audit Logs, 4 Operational Reports
const { useState: aSt, useEffect: aEf, useContext: aCtx, useMemo: aMemo } = React;
const AppCtx = window.AppCtx;

// ── Companies ─────────────────────────────────────────────
function CompaniesPage() {
  const { setCompany, companyId: currentCompanyId } = aCtx(AppCtx);
  const [items,    setItems]   = aSt([]);
  const [search,   setSearch]  = aSt('');
  const [page,     setPage]    = aSt(1);
  const [modal,    setModal]   = aSt(false);
  const [editId,   setEditId]  = aSt(null);
  const [delData,  setDelData] = aSt(null);   // { company, counts }
  const [deleting, setDeleting]= aSt(false);
  const [form,     setForm]    = aSt({});
  const PER = 50;

  aEf(()=>{ load(); return Store.on(load); },[]);
  function load() { setItems(Store.all('companies')); }

  const filtered = aMemo(()=>{
    if (!search) return items;
    const q = search.toLowerCase();
    return items.filter(it=>['name','address'].some(k=>String(it[k]||'').toLowerCase().includes(q)));
  },[items, search]);

  const totalPgs = Math.max(1, Math.ceil(filtered.length/PER));
  const paged    = filtered.slice((page-1)*PER, page*PER);

  function openAdd()   { setForm({}); setEditId(null); setModal(true); }
  function openEdit(c) { setForm({...c}); setEditId(c.id); setModal(true); }
  function setF(k,v)   { setForm(p=>({...p,[k]:v})); }

  function handleSave(e) {
    e.preventDefault();
    if (editId) {
      Store.update('companies', editId, form);
      Store.addLog('UPDATE','Company',`Updated: ${form.name}`);
    } else {
      Store.add('companies', form);
      Store.addLog('CREATE','Company',`Created: ${form.name}`);
    }
    setModal(false); load();
    window.toast&&window.toast(editId?'Company updated':'Company created','ok');
  }

  function openDelete(c) {
    const counts = Store.getCompanyDeletePreview(c.id);
    setDelData({ company:c, counts });
  }

  function handleDelete() {
    if (!delData||deleting) return;
    setDeleting(true);
    const result = Store.deleteCompany(delData.company.id);
    if (result?.error) {
      window.toast&&window.toast(result.message,'er');
      setDeleting(false);
      return;
    }
    setDelData(null); setDeleting(false);
    load();
    if (result?.switched) setCompany(result.newCompanyId);
    window.toast&&window.toast(`"${result?.company?.name}" permanently deleted`,'ok');
  }

  const counts   = delData?.counts || {};
  const totalRecs= Object.values(counts).reduce((s,v)=>s+(v||0), 0);
  const isCurrent= delData?.company?.id === currentCompanyId;

  const DEL_ROWS = [
    { label:'Purchase Orders',    key:'purchases'         },
    { label:'Sales Orders',       key:'salesOrders'       },
    { label:'Internal Transfers', key:'internalTransfers' },
    { label:'Transport Entries',  key:'transportEntries'  },
    { label:'Diesel Records',     key:'dieselRecords'     },
    { label:'Stockyards',         key:'stockyards'        },
    { label:'Stock Movements',    key:'stockMovements'    },
    { label:'Debris Movements',   key:'debrisMovements'   },
    { label:'RMC Plants',         key:'rmcPlants'         },
    { label:'Transporters',       key:'transporters'      },
    { label:'Audit Log Entries',  key:'auditLogs'         },
    { label:'Settlement Records', key:'settlementRecords' },
  ];

  return (
    <div>
      {/* ── Page Header ── */}
      <div className="ph">
        <div>
          <h1>Companies</h1>
          <p>Group companies and subsidiaries — deletion is permanent and cascades all associated data</p>
        </div>
        <div className="ph-act">
          <button className="btn btn-or" onClick={openAdd}>
            <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5"><path d="M12 5v14M5 12h14"/></svg>
            Add Company
          </button>
        </div>
      </div>

      {/* ── Search Bar ── */}
      <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 companies…" />
        </div>
        {search&&<button className="btn btn-gh btn-sm" onClick={()=>{setSearch('');setPage(1);}}>Clear</button>}
        <span className="f-cnt">{filtered.length} companies</span>
      </div>

      {/* ── Table ── */}
      <div className="card">
        <div className="tbl-w">
          <table className="tbl">
            <thead>
              <tr><th>SR</th><th>COMPANY NAME</th><th>ADDRESS</th><th>CREATED</th><th>ACTIONS</th></tr>
            </thead>
            <tbody>
              {paged.length===0
                ? <tr className="empty"><td colSpan="5" style={{textAlign:'center',padding:36,color:'var(--txt2)'}}>No companies found</td></tr>
                : paged.map((c,i)=>(
                  <tr key={c.id}>
                    <td style={{color:'var(--txt2)',fontSize:11}}>{(page-1)*PER+i+1}</td>
                    <td>
                      <strong>{c.name}</strong>
                      {c.id===currentCompanyId&&<span style={{marginLeft:7,fontSize:10,background:'var(--or-lt)',color:'var(--or)',border:'1px solid var(--or-bdr)',borderRadius:3,padding:'1px 5px',fontWeight:600,verticalAlign:'middle'}}>ACTIVE</span>}
                    </td>
                    <td style={{fontSize:11.5,color:'var(--txt2)'}}>{c.address||'—'}</td>
                    <td style={{fontSize:11,color:'var(--txt2)'}}>{c.createdAt||'—'}</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={()=>openDelete(c)}>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>
      )}

      {/* ── Add / Edit Modal ── */}
      {modal&&(
        <div className="mbg">
          <div className="mod">
            <div className="mod-hd">
              <h2>{editId?'Edit':'Add'} Company</h2>
              <button className="mod-x" onClick={()=>setModal(false)}>×</button>
            </div>
            <form onSubmit={handleSave}>
              <div className="mod-bd">
                <div className="fg">
                  <window.CompanyLogoField value={form.logo} onChange={v=>setF('logo',v)} onRemove={()=>setF('logo',null)} />
                  <div className="fld" style={{gridColumn:'1/-1'}}>
                    <label>Company Name <span className="req">*</span></label>
                    <input className="inp" value={form.name||''} onChange={e=>setF('name',e.target.value)} required placeholder="e.g. OM Transport" />
                  </div>
                  <div className="fld" style={{gridColumn:'1/-1'}}>
                    <label>Address</label>
                    <textarea className="inp" value={form.address||''} onChange={e=>setF('address',e.target.value)} rows={3} placeholder="Full address…" style={{resize:'vertical'}}></textarea>
                  </div>
                  <div className="fld">
                    <label>GST Number</label>
                    <input className="inp" value={form.gst||''} onChange={e=>setF('gst',e.target.value)} placeholder="e.g. 27AABCU9603R1ZX" />
                  </div>
                  <div className="fld">
                    <label>Phone</label>
                    <input className="inp" value={form.phone||''} onChange={e=>setF('phone',e.target.value)} placeholder="e.g. +91 98765 43210" />
                  </div>
                  <div className="fld">
                    <label>Email</label>
                    <input className="inp" type="email" value={form.email||''} onChange={e=>setF('email',e.target.value)} placeholder="e.g. accounts@omgroup.in" />
                  </div>
                  <div className="fld">
                    <label>Website</label>
                    <input className="inp" value={form.website||''} onChange={e=>setF('website',e.target.value)} placeholder="e.g. www.omgroup.in" />
                  </div>
                </div>
              </div>
              <div className="mod-ft">
                <button type="button" className="btn btn-wh" onClick={()=>setModal(false)}>Cancel</button>
                <button type="submit" className="btn btn-or">{editId?'Update Company':'Create Company'}</button>
              </div>
            </form>
          </div>
        </div>
      )}

      {/* ── Cascading Delete Warning Modal ── */}
      {delData&&(
        <div className="mbg">
          <div className="mod" style={{maxWidth:520,width:'92vw'}}>

            {/* Modal header — red danger theme */}
            <div className="mod-hd" style={{background:'#FEF2F2',borderBottom:'2px solid #FECACA'}}>
              <div style={{display:'flex',alignItems:'center',gap:8}}>
                <svg width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="#DC2626" strokeWidth="2.5"><path d="M10.29 3.86L1.82 18a2 2 0 001.71 3h16.94a2 2 0 001.71-3L13.71 3.86a2 2 0 00-3.42 0z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg>
                <h2 style={{color:'#991B1B',fontSize:14}}>Delete Company</h2>
              </div>
              <button className="mod-x" style={{color:'#991B1B'}} onClick={()=>!deleting&&setDelData(null)}>×</button>
            </div>

            <div className="mod-bd" style={{display:'flex',flexDirection:'column',gap:12,padding:'14px 16px'}}>

              {/* Warning paragraph */}
              <div style={{background:'#FFF1F1',border:'1px solid #FECACA',borderRadius:4,padding:'11px 13px'}}>
                <p style={{fontSize:12.5,color:'#7F1D1D',lineHeight:1.75,margin:0}}>
                  You are about to permanently delete{' '}
                  <strong style={{color:'#DC2626'}}>"{delData.company.name}"</strong>{' '}
                  and all associated transactions, reports, stock records, diesel records,
                  transporter records, internal transfers, and historical data.
                </p>
                <p style={{fontSize:12,color:'#991B1B',fontWeight:700,margin:'9px 0 0'}}>
                  <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" style={{display:'inline',verticalAlign:'-1px',flexShrink:0,marginRight:6}}><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>This action cannot be undone.
                </p>
              </div>

              {/* Active-company warning */}
              {isCurrent&&(
                <div style={{background:'#FEF9C3',border:'1px solid #FDE047',borderRadius:4,padding:'9px 12px',fontSize:12,color:'#713F12',display:'flex',gap:7,alignItems:'flex-start'}}>
                  <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#CA8A04" strokeWidth="2.5" style={{flexShrink:0,marginTop:1}}><circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/></svg>
                  <span>This is your <strong>currently active company</strong>. After deletion you will be automatically switched to another company.</span>
                </div>
              )}

              {/* Record counts table */}
              <div>
                <div style={{fontSize:11.5,fontWeight:600,color:'var(--txt)',marginBottom:6}}>
                  {totalRecs>0
                    ? `${totalRecs.toLocaleString('en-IN')} records will be permanently erased:`
                    : 'No transactional records found for this company.'}
                </div>
                {totalRecs>0&&(
                  <div style={{border:'1px solid #FECACA',borderRadius:4,overflow:'hidden',fontSize:12}}>
                    {DEL_ROWS.filter(r=>(counts[r.key]||0)>0).map((r,i,arr)=>(
                      <div key={r.key} style={{
                        display:'flex',justifyContent:'space-between',
                        padding:'5px 11px',
                        background:i%2===0?'#fff':'#FFF5F5',
                        borderBottom:i<arr.length-1?'1px solid #FECACA':'none',
                      }}>
                        <span style={{color:'var(--txt)'}}>{r.label}</span>
                        <span style={{fontWeight:600,color:'#DC2626'}}>{(counts[r.key]||0).toLocaleString('en-IN')}</span>
                      </div>
                    ))}
                    <div style={{display:'flex',justifyContent:'space-between',padding:'7px 11px',background:'#FEE2E2',fontWeight:700,borderTop:'2px solid #FECACA'}}>
                      <span style={{color:'#7F1D1D'}}>Total Records Deleted</span>
                      <span style={{color:'#DC2626'}}>{totalRecs.toLocaleString('en-IN')}</span>
                    </div>
                  </div>
                )}
              </div>

              {/* Post-deletion behaviour note */}
              <div style={{fontSize:11,color:'var(--txt2)',background:'#F9FAFB',border:'1px solid var(--bdr)',borderRadius:4,padding:'8px 11px',lineHeight:1.65}}>
                <strong style={{color:'var(--txt)'}}>After deletion:</strong> The OM Group Dashboard, all KPIs,
                charts, and analytics will instantly recalculate. All form dropdowns and report
                filters will exclude this company. No orphaned records will remain.
              </div>
            </div>

            {/* Footer */}
            <div className="mod-ft" style={{background:'#FEF2F2',borderTop:'1px solid #FECACA'}}>
              <button className="btn btn-wh" onClick={()=>setDelData(null)} disabled={deleting}>
                Cancel
              </button>
              <button
                className="btn"
                style={{background:'#DC2626',color:'#fff',border:'1px solid #B91C1C',fontWeight:600,gap:5,display:'flex',alignItems:'center'}}
                onClick={handleDelete}
                disabled={deleting}
              >
                {deleting
                  ? <><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" style={{animation:'spin 1s linear infinite'}}><path d="M21 12a9 9 0 11-18 0 9 9 0 0118 0"/></svg> Deleting…</>
                  : <><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5"><polyline points="3 6 5 6 21 6"/><path d="M19 6l-1 14H6L5 6"/><path d="M10 11v6M14 11v6"/><path d="M9 6V4a1 1 0 011-1h4a1 1 0 011 1v2"/></svg> Permanently Delete</>
                }
              </button>
            </div>
          </div>
        </div>
      )}
    </div>
  );
}

// ── Users ─────────────────────────────────────────────────
function UsersPage() {
  window.useStoreSync();
  const [items, setItems]   = aSt([]);
  const [search, setSearch] = aSt('');
  const [fRole,  setFRole]  = aSt('');
  const [page,   setPage]   = aSt(1);
  const [modal,  setModal]  = aSt(false);
  const [editId, setEditId] = aSt(null);
  const [delId,  setDelId]  = aSt(null);
  const [form,   setForm]   = aSt({});
  const PER = 50;

  const companies = Store.all('companies');
  const ROLES = ['SUPER_ADMIN','ADMIN','MANAGER','ACCOUNTANT','OPERATOR','VIEWER'];
  const PERMS = ['Create','Edit','Delete','View','Export'];
  const ROLE_PERMS = {
    SUPER_ADMIN:['Create','Edit','Delete','View','Export'],
    ADMIN:      ['Create','Edit','Delete','View','Export'],
    MANAGER:    ['Create','Edit','View','Export'],
    ACCOUNTANT: ['Create','View','Export'],
    OPERATOR:   ['Create','View'],
    VIEWER:     ['View'],
  };

  aEf(()=>{ setItems(Store.all('users')); return Store.on(()=>setItems(Store.all('users'))); },[]);
  function load() { setItems(Store.all('users')); }

  const filtered = aMemo(()=> items.filter(it=>{
    if (search) { const q=search.toLowerCase(); if (!['name','email'].some(k=>String(it[k]||'').toLowerCase().includes(q))) return false; }
    if (fRole && it.role!==fRole) return false;
    return true;
  }),[items,search,fRole]);

  const totalPgs = Math.ceil(filtered.length/PER);
  const paged    = filtered.slice((page-1)*PER, page*PER);

  function openAdd() { setForm({ status:'Active', companies:[], role:'VIEWER' }); setEditId(null); setModal(true); }
  function openEdit(u) { setForm({...u, companies:[...(u.companies||[])]}); setEditId(u.id); setModal(true); }
  function setF(k,v) { setForm(p=>({...p,[k]:v})); }
  function toggleCo(id) { setForm(p=>({ ...p, companies: p.companies?.includes(id) ? p.companies.filter(c=>c!==id) : [...(p.companies||[]),id] })); }
  function handleSave(e) { e.preventDefault(); if (editId) { Store.update('users',editId,form); Store.addLog('UPDATE','User',`Updated: ${form.name}`); } else { Store.add('users',form); Store.addLog('CREATE','User',`Created: ${form.name}`); } setModal(false); load(); window.toast&&window.toast(editId?'Updated':'User created','ok'); }
  function handleDelete() { Store.del('users',delId); Store.addLog('DELETE','User','Deleted user'); setDelId(null); load(); window.toast&&window.toast('Deleted','ok'); }

  const perms = ROLE_PERMS[form.role]||[];

  return (
    <div>
      <div className="ph">
        <div><h1>User Management</h1><p>Manage accounts, roles and company access</p></div>
        <div className="ph-act">
          <button className="btn btn-or" onClick={openAdd}><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5"><path d="M12 5v14M5 12h14"/></svg> Add User</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, email…" /></div>
        <window.FiltSelect placeholder="All Roles" value={fRole} onChange={v=>{setFRole(v);setPage(1);}} options={ROLES.map(r=>({value:r,label:r.replace(/_/g,' ')}))}/>
        {(search||fRole)&&<button className="btn btn-gh btn-sm" onClick={()=>{setSearch('');setFRole('');setPage(1);}}>Clear</button>}
        <span className="f-cnt">{filtered.length} users</span>
      </div>
      <div className="card">
        <div className="tbl-w">
          <table className="tbl">
            <thead><tr><th>ID</th><th>NAME</th><th>EMAIL</th><th>ROLE</th><th>LAST LOGIN</th><th>CREATED</th><th>ACTIONS</th></tr></thead>
            <tbody>
              {paged.length===0
                ? <tr className="empty"><td colSpan="7" style={{textAlign:'center',padding:36,color:'var(--txt2)'}}>No users found</td></tr>
                : paged.map((u,i)=>(
                  <tr key={u.id}>
                    <td style={{color:'var(--txt2)',fontSize:11}}>{(page-1)*PER+i+1}</td>
                    <td><strong>{u.name}</strong></td>
                    <td style={{fontSize:11.5,color:'var(--txt2)'}}>{u.email}</td>
                    <td><window.Badge v={u.role}/></td>
                    <td style={{fontSize:11,color:'var(--txt2)'}}>{u.lastLogin||'—'}</td>
                    <td style={{fontSize:11,color:'var(--txt2)'}}>{u.createdAt||'—'}</td>
                    <td><div className="ra"><button className="btn btn-wh btn-sm" onClick={()=>openEdit(u)}>Edit</button><button className="btn btn-rd btn-sm" onClick={()=>setDelId(u.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&&(
        <div className="mbg">
          <div className="mod mod-lg">
            <div className="mod-hd"><h2>{editId?'Edit':'Add'} User</h2><button className="mod-x" onClick={()=>setModal(false)}>×</button></div>
            <UserModalBody editId={editId} form={form} setF={setF} companies={companies} toggleCo={toggleCo} handleSave={handleSave} onClose={()=>setModal(false)} ROLES={ROLES} PERMS={PERMS} ROLE_PERMS={ROLE_PERMS}/>
          </div>
        </div>
      )}
      {delId&&<window.Confirm onOk={handleDelete} onCancel={()=>setDelId(null)} />}
    </div>
  );
}

function UserModalBody({editId,form,setF,companies,toggleCo,handleSave,onClose,ROLES,PERMS,ROLE_PERMS}) {
  const [coSearch, setCoSearch] = aSt('');
  const perms = ROLE_PERMS[form.role]||[];
  const filteredCos = coSearch ? companies.filter(c=>c.name.toLowerCase().includes(coSearch.toLowerCase())) : companies;
  const selCount = (form.companies||[]).length;
  const allSelected = companies.every(c=>(form.companies||[]).includes(c.id));
  function toggleAll() {
    if (allSelected) setF('companies',[]);
    else setF('companies', companies.map(c=>c.id));
  }
  return (
    <form onSubmit={handleSave}>
      <div className="mod-bd">
        {/* User Details */}
        <div style={{marginBottom:18}}>
          <div style={{color:'var(--or)',fontWeight:700,fontSize:13,marginBottom:10,paddingBottom:7,borderBottom:'2px solid #FEF3E8'}}>User Details</div>
          <div className="fg">
            <div className="fld"><label>Email <span className="req">*</span></label><input className="inp" type="email" value={form.email||''} onChange={e=>setF('email',e.target.value)} required placeholder="user@omgroup.com"/></div>
            <div className="fld"><label>Name <span className="req">*</span></label><input className="inp" value={form.name||''} onChange={e=>setF('name',e.target.value)} required placeholder="Full name"/></div>
            <div className="fld">
              <label>Role <span className="req">*</span></label>
              <window.FormSelect placeholder="Select Role" value={form.role||''} onChange={v=>setF('role',v)} options={[{value:'VIEWER',label:'Staff'},{value:'OPERATOR',label:'Operator'},{value:'ACCOUNTANT',label:'Accountant'},{value:'MANAGER',label:'Manager'},{value:'ADMIN',label:'Admin'},{value:'SUPER_ADMIN',label:'Super Admin'}]}/>
            </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>
          {/* Confidential pricing export override — role default shown, per-user override optional */}
          <div style={{marginTop:12,padding:'10px 12px',border:'1px solid var(--bdr)',borderRadius:6,background:'#FAFAFA'}}>
            <label style={{display:'flex',alignItems:'center',gap:8,cursor:'pointer',fontSize:12.5,fontWeight:600}}>
              <input type="checkbox"
                checked={form.canExportConfidential!=null ? !!form.canExportConfidential : (window.ExportPermission ? window.ExportPermission.DEFAULT_ROLES.includes(form.role) : false)}
                onChange={e=>setF('canExportConfidential', e.target.checked)}
                style={{accentColor:'var(--or)'}}/>
              Can Export Confidential Pricing
            </label>
            <div style={{marginTop:4,marginLeft:22,fontSize:11,color:'var(--txt3)',lineHeight:1.5}}>
              Controls access to "Confidential Export" (includes Rate) on Sales &amp; Purchase. Everyone else only ever sees Standard Export.
              {form.canExportConfidential==null && window.ExportPermission && (window.ExportPermission.DEFAULT_ROLES.includes(form.role) ? ' Currently ON by role default.' : ' Currently OFF by role default.')}
            </div>
          </div>
        </div>
        {/* Assign Companies */}
        <div style={{marginBottom:16}}>
          <div style={{color:'var(--or)',fontWeight:700,fontSize:13,marginBottom:10,paddingBottom:7,borderBottom:'2px solid #FEF3E8'}}>Assign Companies</div>
          {/* Search + select all */}
          <div style={{display:'flex',gap:8,alignItems:'center',marginBottom:8}}>
            <div className="fs" style={{flex:1}}>
              <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={coSearch} onChange={e=>setCoSearch(e.target.value)} placeholder="Search companies…" />
            </div>
            <label style={{display:'flex',alignItems:'center',gap:5,cursor:'pointer',fontSize:12,whiteSpace:'nowrap',fontWeight:500}}>
              <input type="checkbox" checked={allSelected} onChange={toggleAll} style={{accentColor:'var(--or)'}}/>
              Select All
            </label>
          </div>
          {/* Company list */}
          <div style={{border:'1px solid var(--bdr)',borderRadius:4,maxHeight:200,overflowY:'auto'}}>
            {filteredCos.map((c,i)=>(
              <label key={c.id} style={{display:'flex',alignItems:'center',gap:8,padding:'8px 12px',cursor:'pointer',borderBottom:i<filteredCos.length-1?'1px solid #F3F4F6':'none',background:(form.companies||[]).includes(c.id)?'#FFF7ED':'#fff',transition:'background .1s'}}>
                <input type="checkbox" checked={(form.companies||[]).includes(c.id)} onChange={()=>toggleCo(c.id)} style={{accentColor:'var(--or)',flexShrink:0}}/>
                <span style={{fontSize:12,fontWeight:500}}>{c.name}</span>
              </label>
            ))}
            {filteredCos.length===0&&<div style={{padding:'12px',fontSize:12,color:'var(--txt2)',textAlign:'center'}}>No companies match search</div>}
          </div>
          {/* Count + helper */}
          <div style={{marginTop:7,fontSize:11.5,color:'var(--txt2)'}}>
            <strong style={{color:'var(--txt)'}}>{selCount} of {companies.length}</strong> selected
          </div>
          <div style={{marginTop:4,fontSize:11,color:'var(--txt3)',lineHeight:1.5}}>
            {selCount===0 ? 'If no companies are selected, user will be assigned to all companies and have access to all company data.' : `User will have access to ${selCount} selected ${selCount===1?'company':'companies'}.`}
          </div>
        </div>
        {/* Permissions Preview */}
        {form.role&&(
          <div>
            <div style={{color:'var(--or)',fontWeight:700,fontSize:13,marginBottom:10,paddingBottom:7,borderBottom:'2px solid #FEF3E8'}}>Permissions — {form.role.replace(/_/g,' ')}</div>
            <div style={{border:'1px solid var(--bdr)',borderRadius:4,fontSize:12}}>
              <div style={{display:'grid',gridTemplateColumns:'1fr repeat(5,70px)',background:'#F9FAFB',borderBottom:'1px solid var(--bdr)'}}>
                <div style={{padding:'6px 10px',fontWeight:600,fontSize:11,color:'var(--txt2)',textTransform:'uppercase'}}>Module</div>
                {PERMS.map(p=><div key={p} style={{padding:'6px 4px',fontWeight:600,fontSize:11,color:'var(--txt2)',textTransform:'uppercase',textAlign:'center'}}>{p}</div>)}
              </div>
              {['Purchases','Sales','Transport','Diesel','Materials','Reports'].map(mod=>(
                <div key={mod} style={{display:'grid',gridTemplateColumns:'1fr repeat(5,70px)',borderBottom:'1px solid #F3F4F6'}}>
                  <div style={{padding:'6px 10px',fontWeight:500}}>{mod}</div>
                  {PERMS.map(p=><div key={p} style={{padding:'6px 4px',textAlign:'center',fontSize:13}}>{perms.includes(p)?<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="var(--ok)" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"><path d="M5 13l4 4L19 7"/></svg>:<span style={{color:'#E5E7EB'}}>—</span>}</div>)}
                </div>
              ))}
            </div>
          </div>
        )}
      </div>
      <div className="mod-ft"><button type="button" className="btn btn-wh" onClick={onClose}>Cancel</button><button type="submit" className="btn btn-or">{editId?'Update':'Create User'}</button></div>
    </form>
  );
}

// ── Data Integrity Panel ──────────────────────────────────
// Live audit from window.VerificationEngine — proves every KPI is reading
// the same centralized calculation engine (GstEngine / ProfitEngine) rather
// than a page-local formula that could drift out of sync.
function DataIntegrityPanel() {
  window.useStoreSync();
  const [open, setOpen] = aSt(false);
  const report = window.VerificationEngine ? window.VerificationEngine.lastReport() : null;
  if (!report) return null;
  const fails = report.checks.filter(c => !c.ok);
  const ok = report.allOk;
  return (
    <div className="card" style={{padding:'12px 14px', marginBottom:14, border:`1px solid ${ok?'#BBF7D0':'#FECACA'}`}}>
      <div style={{display:'flex',alignItems:'center',justifyContent:'space-between',cursor:'pointer'}} onClick={()=>setOpen(o=>!o)}>
        <div style={{display:'flex',alignItems:'center',gap:8}}>
          <span style={{width:9,height:9,borderRadius:'50%',background:ok?'#16A34A':'#DC2626',display:'inline-block',flexShrink:0}}></span>
          <strong style={{fontSize:12.5}}>Data Integrity — Universal Synchronization Audit</strong>
          <span style={{fontSize:11,color:'var(--txt2)'}}>{report.checks.length} checks · {ok ? 'all consistent' : `${fails.length} mismatch${fails.length===1?'':'es'}`}</span>
        </div>
        <span style={{fontSize:11,color:'var(--txt2)'}}>{open?'Hide':'Details'} ▾</span>
      </div>
      {open && (
        <div style={{marginTop:10,maxHeight:260,overflowY:'auto'}}>
          <table className="tbl" style={{fontSize:11}}>
            <thead><tr><th>Check</th><th>Scope</th><th>Engine Value</th><th>Cross-Checked Value</th><th>Status</th></tr></thead>
            <tbody>
              {report.checks.map((c,i)=>(
                <tr key={i}>
                  <td>{c.label}</td>
                  <td>{c.scope}</td>
                  <td style={{fontFamily:'var(--font)'}}>{window.fmtCur(c.a)}</td>
                  <td style={{fontFamily:'var(--font)'}}>{window.fmtCur(c.b)}</td>
                  <td><span className={`bdg bg-${c.ok?'gn':'rd'}`}>{c.ok?'MATCH':'MISMATCH'}</span></td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      )}
    </div>
  );
}

// ── Audit Logs ────────────────────────────────────────────
function AuditPage() {
  window.useStoreSync();
  const { companyId } = aCtx(AppCtx);
  const [search, setSearch]   = aSt('');
  const [fAction, setFAction] = aSt('');
  const [fEntity, setFEntity] = aSt('');
  const [page, setPage]       = aSt(1);
  const PER = 50;

  const logs     = Store.all('auditLogs', companyId);
  const entities = [...new Set(logs.map(l=>l.entity))].sort();
  const ACTIONS  = ['LOGIN','LOGOUT','CREATE','UPDATE','DELETE','EXPORT'];

  const filtered = aMemo(()=> logs.filter(l=>{
    if (search) { const q=search.toLowerCase(); if (!['user','details','entity'].some(k=>String(l[k]||'').toLowerCase().includes(q))) return false; }
    if (fAction && l.action!==fAction) return false;
    if (fEntity && l.entity!==fEntity) return false;
    return true;
  }),[logs,search,fAction,fEntity]);

  const totalPgs = Math.ceil(filtered.length/PER);
  const paged    = filtered.slice((page-1)*PER, page*PER);
  const aClr = { LOGIN:'bl',LOGOUT:'gy',CREATE:'gn',UPDATE:'yw',DELETE:'rd',EXPORT:'pu' };

  return (
    <div>
      <div className="ph">
        <div><h1>Audit Logs</h1><p>Complete activity trail — every action recorded</p></div>
        <div className="ph-act">
          <button className="btn btn-wh btn-sm" onClick={()=>{
            const hdr=['Timestamp','User','Action','Entity','Details','Company'];
            const rows=filtered.map(l=>[
              l.timestamp||'',l.user||'',l.action||'',l.entity||'',l.details||'',
              Store.name('companies',l.companyId)||'',
            ].map(v=>'"'+String(v).replace(/"/g,'""')+'"'));
            const csv='\uFEFF'+[hdr.map(h=>'"'+h+'"').join(','),...rows.map(r=>r.join(','))].join('\r\n');
            const blob=new Blob([csv],{type:'text/csv;charset=utf-8'});const a=document.createElement('a');a.href=URL.createObjectURL(blob);a.download='audit_logs.csv';document.body.appendChild(a);a.click();setTimeout(()=>{URL.revokeObjectURL(a.href);a.remove();},1500);
            window.toast&&window.toast('Exported '+filtered.length+' audit log entries','ok');
          }}><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>
        </div>
      </div>
      <DataIntegrityPanel/>
      <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 user, details…" /></div>
        <window.FiltSelect placeholder="All Actions" value={fAction} onChange={v=>{setFAction(v);setPage(1);}} options={ACTIONS.map(a=>({value:a,label:a}))}/>
        <window.FiltSelect placeholder="All Entities" value={fEntity} onChange={v=>{setFEntity(v);setPage(1);}} options={entities.map(e=>({value:e,label:e}))}/>
        {(search||fAction||fEntity)&&<button className="btn btn-gh btn-sm" onClick={()=>{setSearch('');setFAction('');setFEntity('');setPage(1);}}>Clear</button>}
        <span className="f-cnt">{filtered.length} logs</span>
      </div>
      <div className="card">
        <div className="tbl-w">
          <table className="tbl">
            <thead><tr><th>TIME</th><th>USER</th><th>ACTION</th><th>ENTITY</th><th>DETAILS</th></tr></thead>
            <tbody>
              {paged.length===0
                ? <tr className="empty"><td colSpan="5" style={{textAlign:'center',padding:36,color:'var(--txt2)'}}>No logs</td></tr>
                : paged.map(l=>(
                  <tr key={l.id}>
                    <td style={{fontFamily:'var(--font)',fontSize:11,whiteSpace:'nowrap',color:'var(--txt2)'}}>{l.timestamp}</td>
                    <td><strong style={{fontSize:12}}>{l.user}</strong></td>
                    <td><span className={`bdg bg-${aClr[l.action]||'gy'}`}>{l.action}</span></td>
                    <td style={{fontSize:11.5,color:'var(--txt2)'}}>{l.entity}</td>
                    <td style={{fontSize:11.5,color:'var(--txt2)',whiteSpace:'nowrap'}}>{l.details}</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>}
    </div>
  );
}

// ── TransactionIntelPanel ──────────────────────────────────
// Expandable intelligence panel for each Report 1 row.
// DISPLAY ONLY — no calculations changed.
function TransactionIntelPanel({ row, pConv, sConv, txType, txMeta }) {
  const anyConv = pConv || sConv;
  const pUom = row.pOrigUom || 'MT';
  const sUom = row.sOrigUom || 'MT';
  const pFormula = pConv ? `${Number(row.pOrigQty).toFixed(3)} ${pUom} × ${row.pDensity} = ${Number(row.purchaseQty).toFixed(3)} Ton` : null;
  const sFormula = sConv ? `${Number(row.sOrigQty).toFixed(3)} ${sUom} × ${row.pDensity} = ${Number(row.saleQty).toFixed(3)} Ton` : null;
  const isPerfect = Math.abs(row.diff) < 0.01 && row.purchaseQty > 0 && row.saleQty > 0;

  // Live GST — always read from source records so edited values are always current
  const _liveP  = Store.byId('purchases',   row.id)     || {};
  const _liveS  = Store.byId('salesOrders', row.saleId) || {};
  const _pItem  = (_liveP.items||[]).find(function(it){return it.materialId===(row.pMaterialId||row.materialId);}) || {};
  const _sItem  = (_liveS.items||[]).find(function(it){return it.materialId===(row.sMaterialId||_liveS.materialId);}) || (_liveS.items||[])[0] || {};
  // Material is read independently from each source record. Never inherited,
  // never defaulted to the other side — missing stays missing.
  const _RC       = window.OMRecon;
  const pMatDisp  = _RC.displayMaterial(row.pMaterial);
  const sMatDisp  = row.saleId ? _RC.displayMaterial(row.sMaterial) : '—';
  const matStatus = row.materialStatus || 'NOT_AVAILABLE';
  const pGstPct   = parseFloat(_pItem.gstPercent||_pItem.gst||0);
  const pSubtotal = parseFloat(_pItem.subtotal)  || row.pAmount || 0;
  const pGstAmt   = pSubtotal*pGstPct/100; // always fresh — never trust legacy-rounded stored gstAmount
  const pAmtGst   = pSubtotal + pGstAmt;
  const sGstPct   = parseFloat(_sItem.gst||_sItem.gstPercent||0);
  const sSubtotal = parseFloat(_sItem.amount)    || row.sAmount || 0;
  const sGstAmt   = sSubtotal*sGstPct/100; // exact — no rounding
  const sAmtGst   = sSubtotal + sGstAmt;

  const IR = ({lbl,val,mono,hi}) => (
    <div style={{display:'flex',gap:6,padding:'2.5px 0',borderBottom:'1px solid #F3F4F6',fontSize:11.5,minHeight:22}}>
      <span style={{color:'var(--txt2)',flex:'0 0 116px',fontSize:11,lineHeight:'22px'}}>{lbl}</span>
      <span style={{fontWeight:600,color:hi||'var(--txt)',fontFamily:'var(--font)',wordBreak:'break-all',lineHeight:'22px'}}>{val||'—'}</span>
    </div>
  );

  return (
    <div style={{padding:'12px 14px 14px',background:'#F8FAFF',borderBottom:'2px solid #BFDBFE'}}>
      <div className="rg-intel">

        {/* Purchase Side */}
        <div>
          <div style={{fontSize:10,fontWeight:700,textTransform:'uppercase',letterSpacing:'.05em',color:'#166534',marginBottom:7,display:'flex',alignItems:'center',gap:5}}>
            <span style={{width:6,height:6,borderRadius:'50%',background:'#166534',display:'inline-block',flexShrink:0}}></span>Purchase Side
          </div>
          <IR lbl="Company" val={Store.name('companies',row.companyId)||'—'}/>
          <IR lbl="Vendor" val={row.purchasedFrom}/>
          <IR lbl="Material" val={pMatDisp} hi={matStatus==='DIFFERENT'?'#B45309':null}/>
          <IR lbl="Original Qty" val={`${Number(row.pOrigQty||0).toFixed(3)} ${pUom}`}/>
          {pConv&&<IR lbl="Density Used" val={String(row.pDensity)}/>}
          {pConv&&<IR lbl="Converted Qty" val={`${Number(row.purchaseQty).toFixed(3)} Ton`} hi="var(--or)"/>}
          {row.pRate>0&&<IR lbl="Rate" val={window.fmtCur(row.pRate)}/>}
          {pSubtotal>0&&<IR lbl="Amount" val={window.fmtCur(pSubtotal)}/>}
          {pGstPct>0&&<IR lbl="GST %" val={`${pGstPct}%`}/>}
          {pGstPct>0&&<IR lbl="GST Amount" val={window.fmtCur(pGstAmt)}/>}
          {pAmtGst>0&&<IR lbl="Amt With GST" val={window.fmtCur(pAmtGst)} hi="var(--or)"/>}
          <IR lbl="Challan No." val={row.challanNo} mono/>
        </div>

        {/* Sale Side */}
        <div>
          <div style={{fontSize:10,fontWeight:700,textTransform:'uppercase',letterSpacing:'.05em',color:'#991B1B',marginBottom:7,display:'flex',alignItems:'center',gap:5}}>
            <span style={{width:6,height:6,borderRadius:'50%',background:'#991B1B',display:'inline-block',flexShrink:0}}></span>Sale Side
          </div>
          <IR lbl="Company" val={row.saleCompanyId?Store.name('companies',row.saleCompanyId)||'—':'—'}/>
          <IR lbl="Customer" val={row.soldTo}/>
          <IR lbl="Material" val={sMatDisp} hi={matStatus==='DIFFERENT'?'#B45309':null}/>
          <IR lbl="Original Qty" val={`${Number(row.sOrigQty||0).toFixed(3)} ${sUom}`}/>
          {sConv&&<IR lbl="Density Used" val={String(row.pDensity)}/>}
          {sConv&&<IR lbl="Converted Qty" val={`${Number(row.saleQty).toFixed(3)} Ton`} hi="var(--or)"/>}
          {row.sRate>0&&<IR lbl="Rate" val={window.fmtCur(row.sRate)}/>}
          {sSubtotal>0&&<IR lbl="Amount" val={window.fmtCur(sSubtotal)}/>}
          {sGstPct>0&&<IR lbl="GST %" val={`${sGstPct}%`}/>}
          {sGstPct>0&&<IR lbl="GST Amount" val={window.fmtCur(sGstAmt)}/>}
          {sAmtGst>0&&<IR lbl="Amt With GST" val={window.fmtCur(sAmtGst)} hi="var(--or)"/>}
          <IR lbl="Challan No." val={row.saleChallanNo||row.challanNo} mono/>
        </div>

        {/* Intelligence Column */}
        <div style={{display:'flex',flexDirection:'column',gap:8}}>

          {/* Material Classification — business condition, not an error */}
          <div style={{background:'#fff',border:'1px solid var(--bdr)',borderRadius:4,padding:'9px 11px'}}>
            <div style={{fontSize:9.5,fontWeight:700,textTransform:'uppercase',letterSpacing:'.05em',color:'var(--txt3)',marginBottom:6}}>Material Classification</div>
            <div style={{display:'flex',alignItems:'center',gap:5,marginBottom:4}}>
              <span style={{width:6,height:6,borderRadius:'50%',flexShrink:0,display:'inline-block',background:matStatus==='MATCHED'?'var(--ok)':matStatus==='DIFFERENT'?'#B45309':'var(--txt3)'}}></span>
              <span style={{fontSize:11.5,fontWeight:600,color:matStatus==='MATCHED'?'var(--ok)':matStatus==='DIFFERENT'?'#B45309':'var(--txt3)'}}>{matStatus==='MATCHED'?'Same':matStatus==='DIFFERENT'?'Different':'Not available'}</span>
            </div>
            <div style={{fontSize:11,color:'var(--txt2)'}}>Purchase: <strong style={{color:'var(--txt)'}}>{pMatDisp}</strong></div>
            <div style={{fontSize:11,color:'var(--txt2)'}}>Sale: <strong style={{color:'var(--txt)'}}>{sMatDisp}</strong></div>
            {matStatus==='DIFFERENT'&&<div style={{fontSize:10.5,color:'var(--txt3)',marginTop:4,lineHeight:1.35}}>{row.materialMismatchReason||'Material classification differs between purchase and sale.'}</div>}
            {row.matchAmbiguous&&<div style={{fontSize:10.5,color:'#B45309',marginTop:4,fontWeight:600}}>Ambiguous match — multiple candidate records share this challan.</div>}
          </div>

          {/* Conversion Analysis */}
          <div style={{background:'#fff',border:'1px solid var(--bdr)',borderRadius:4,padding:'9px 11px'}}>
            <div style={{fontSize:9.5,fontWeight:700,textTransform:'uppercase',letterSpacing:'.05em',color:'var(--txt3)',marginBottom:6}}>Conversion Analysis</div>
            {anyConv ? (
              <div>
                {pConv&&<div style={{fontSize:10.5,marginBottom:3,fontFamily:'var(--font)',color:'#7C3AED',background:'#F5F3FF',padding:'3px 6px',borderRadius:3}}>{pFormula}</div>}
                {sConv&&<div style={{fontSize:10.5,marginBottom:3,fontFamily:'var(--font)',color:'#7C3AED',background:'#F5F3FF',padding:'3px 6px',borderRadius:3}}>{sFormula}</div>}
                <div style={{display:'flex',alignItems:'center',gap:5,marginTop:5}}>
                  <span style={{width:6,height:6,borderRadius:'50%',background:isPerfect?'var(--ok)':'var(--err)',display:'inline-block',flexShrink:0}}></span>
                  <span style={{fontSize:11.5,fontWeight:600,color:isPerfect?'var(--ok)':'var(--err)'}}>{isPerfect?'Perfect Match':'Mismatch Detected'}</span>
                </div>
              </div>
            ) : (
              <div style={{fontSize:11,color:'var(--txt3)',fontStyle:'italic'}}>No Conversion Applied<br/><span style={{fontSize:10.5}}>Purchase UOM = Sale UOM</span></div>
            )}
          </div>

          {/* Transfer Analysis */}
          <div style={{background:'#fff',border:'1px solid var(--bdr)',borderRadius:4,padding:'9px 11px'}}>
            <div style={{fontSize:9.5,fontWeight:700,textTransform:'uppercase',letterSpacing:'.05em',color:'var(--txt3)',marginBottom:6}}>Transfer Analysis</div>
            <div style={{fontSize:11.5,marginBottom:3}}><span style={{color:'var(--txt2)'}}>Detected: </span><strong style={{color:row.isInternalTransfer?'var(--ok)':'var(--txt3)'}}>{row.isInternalTransfer?'YES':'NO'}</strong></div>
            {row.isInternalTransfer&&(
              <React.Fragment>
                <div style={{fontSize:11,marginBottom:2}}><span style={{color:'var(--txt2)'}}>From: </span><strong>{Store.name('companies',row.companyId)||'—'}</strong></div>
                <div style={{fontSize:11,marginBottom:4}}><span style={{color:'var(--txt2)'}}>To: </span><strong>{Store.name('companies',row.saleCompanyId)||'—'}</strong></div>
              </React.Fragment>
            )}
            <div style={{marginTop:4,paddingTop:5,borderTop:'1px solid #F3F4F6'}}>
              <div style={{display:'flex',alignItems:'center',justifyContent:'space-between',marginBottom:5}}>
                <span style={{fontSize:10,color:'var(--txt2)',fontWeight:600,textTransform:'uppercase',letterSpacing:'.04em'}}>Match Confidence</span>
                <span className="kpi-val" style={{fontSize:14,fontWeight:700,display:'inline-block',color:(row.matchConfidence||0)>=70?'var(--ok)':(row.matchConfidence||0)>=40?'var(--warn)':'var(--err)'}}>{row.matchConfidence||0}%</span>
              </div>
              {(row.matchBasis||[]).filter(b=>b.k!=='Transfer Engine').map(b=>(
                <div key={b.k} style={{display:'flex',alignItems:'center',gap:5,fontSize:11,marginBottom:3}}>
                  <span style={{width:15,height:15,borderRadius:2,background:b.v?'#DCFCE7':'#FEE2E2',color:b.v?'#166534':'#991B1B',display:'inline-flex',alignItems:'center',justifyContent:'center',fontSize:9,fontWeight:700,flexShrink:0}}>{b.v?<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>:<svg width="9" height="9" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"><path d="M18 6L6 18M6 6l12 12"/></svg>}</span>
                  <span style={{color:b.v?'var(--txt)':'var(--txt3)'}}>{b.k}</span>
                </div>
              ))}
            </div>
          </div>

          {/* Type badge */}
          <div style={{textAlign:'center',padding:'7px',background:txMeta.bg,borderRadius:4,border:`1px solid ${txMeta.color}33`}}>
            <div style={{fontSize:9,color:txMeta.color,fontWeight:700,textTransform:'uppercase',letterSpacing:'.06em'}}>Transaction Type</div>
            <div style={{fontSize:12,color:txMeta.color,fontWeight:700,marginTop:2}}>{txMeta.label}</div>
          </div>
        </div>
      </div>
    </div>
  );
}
window.TransactionIntelPanel = TransactionIntelPanel;

// ── DrillDownTxTable ──────────────────────────────────────
// Reusable transaction table for drill-down panels
function DrillDownTxTable({ rows, type }) {
  if (!rows || !rows.length) return (
    <div style={{padding:'10px 12px',fontSize:11.5,color:'var(--txt3)',fontStyle:'italic',border:'1px solid var(--bdr)',borderRadius:'var(--r)',marginTop:4}}>
      No {type==='purchase'?'purchase':'sale'} transactions found in this selection
    </div>
  );
  const hasCrusher = type === 'purchase';
  const partyHdr   = type === 'purchase' ? 'VENDOR' : 'CUSTOMER';
  const preQtyCols = hasCrusher ? 7 : 6;
  return (
    <div style={{overflowX:'auto',border:'1px solid var(--bdr)',borderRadius:'var(--r)'}}>
      <table style={{width:'100%',borderCollapse:'collapse',fontSize:11.5,minWidth:hasCrusher?740:640}}>
        <thead>
          <tr style={{background:'#F9FAFB'}}>
            {['DATE','COMPANY','CHALLAN NO.','VEHICLE NO.','MATERIAL',partyHdr,hasCrusher?'CRUSHER':null,'QTY','UOM','AMOUNT','STATUS'].filter(Boolean).map(h=>(
              <th key={h} style={{padding:'5px 8px',textAlign:['QTY','AMOUNT'].includes(h)?'right':'left',fontSize:10,fontWeight:700,color:'var(--txt2)',borderBottom:'1px solid var(--bdr)',whiteSpace:'nowrap',letterSpacing:'.03em'}}>{h}</th>
            ))}
          </tr>
        </thead>
        <tbody>
          {rows.map((tx,i)=>(
            <tr key={tx.id||i} style={{borderBottom:'1px solid #F3F4F6',background:i%2===0?'#fff':'#FAFAFA'}}>
              <td style={{padding:'4px 8px',whiteSpace:'nowrap',fontSize:11}}>{window.fmtDate(tx.date)}</td>
              <td style={{padding:'4px 8px',fontSize:10.5,color:'var(--txt2)',whiteSpace:'nowrap'}}>{tx.company||'—'}</td>
              <td style={{padding:'4px 8px',fontFamily:'var(--font)',fontSize:10.5,fontWeight:500}}>{tx.challan||'—'}</td>
              <td style={{padding:'4px 8px',fontFamily:'var(--font)',fontSize:10.5}}>{tx.vehicle||'—'}</td>
              <td style={{padding:'4px 8px',fontWeight:500}}>{tx.material||'—'}</td>
              <td style={{padding:'4px 8px',fontSize:11}}>{type==='purchase'?tx.vendor||'—':tx.customer||'—'}</td>
              {hasCrusher&&<td style={{padding:'4px 8px',fontSize:10.5,color:'var(--txt2)'}}>{tx.crusher||'—'}</td>}
              <td style={{padding:'4px 8px',textAlign:'right',fontWeight:600}}>{Number(tx.qty||0).toFixed(3)}</td>
              <td style={{padding:'4px 8px',color:'var(--txt2)'}}>{tx.uom||'MT'}</td>
              <td style={{padding:'4px 8px',textAlign:'right'}}>{window.fmtCur(tx.amount||0)}</td>
              <td style={{padding:'4px 8px'}}><window.Badge v={tx.status}/></td>
            </tr>
          ))}
        </tbody>
        <tfoot>
          <tr style={{background:'#F9FAFB',borderTop:'2px solid var(--bdr)'}}>
            <td colSpan={preQtyCols} style={{padding:'4px 8px',fontWeight:700,fontSize:11,color:'var(--txt2)'}}>TOTAL — {rows.length} record{rows.length!==1?'s':''}</td>
            <td style={{padding:'4px 8px',textAlign:'right',fontWeight:700,color:'var(--or)'}}>{rows.reduce((s,r)=>s+(parseFloat(r.qty)||0),0).toFixed(3)}</td>
            <td colSpan={3}></td>
          </tr>
        </tfoot>
      </table>
    </div>
  );
}
window.DrillDownTxTable = DrillDownTxTable;

// ── DrillDownPanel ─────────────────────────────────────────
// Inline expandable panel — shows loss breakdown + full transaction lists
function DrillDownPanel({ pTxList, sTxList, txList, showLossBreakdown, pQty, sQty, diff, lossP, label }) {
  const pList   = pTxList || [];
  const sList   = sTxList || [];
  const allList = txList  || [];
  const lossBreakItems = [
    {l:'Pickup Qty',   v:Number(pQty||0).toFixed(3), sub:'Tons',      c:'var(--txt)'},
    'arrow',
    {l:'Delivery Qty', v:Number(sQty||0).toFixed(3), sub:'Tons',      c:'var(--txt)'},
    'arrow',
    {l:'Difference',   v:Number(diff||0).toFixed(3), sub:'Tons',      c:(diff||0)>=0?'var(--ok)':'var(--err)'},
    'arrow',
    {l:'Loss %',       v:(lossP||'0.00')+'%',         sub:'of Pickup', c:parseFloat(lossP||0)>2?'var(--err)':parseFloat(lossP||0)>0?'var(--warn)':'var(--ok)'},
  ];
  return (
    <div style={{padding:'12px 16px 16px',background:'#FAFBFF',borderTop:'2px solid var(--or-bdr)'}}>
      {label&&<div style={{fontWeight:700,fontSize:12,color:'var(--or)',marginBottom:10,display:'flex',alignItems:'center',gap:6}}>
        <svg 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>
        {label}
      </div>}

      {showLossBreakdown&&(
        <div style={{display:'flex',alignItems:'center',marginBottom:14,padding:'10px 16px',background:'#fff',border:'1px solid var(--bdr)',borderRadius:'var(--r)',flexWrap:'wrap',gap:4}}>
          {lossBreakItems.map((item,idx)=>item==='arrow'
            ?<div key={idx} style={{fontSize:20,color:'var(--txt3)',padding:'0 6px',alignSelf:'center',lineHeight:1}}>→</div>
            :<div key={idx} style={{display:'flex',flexDirection:'column',alignItems:'center',padding:'4px 16px',minWidth:90}}>
               <div style={{fontSize:10,color:'var(--txt3)',fontWeight:600,textTransform:'uppercase',letterSpacing:'.04em',marginBottom:4}}>{item.l}</div>
               <div style={{fontSize:18,fontWeight:700,color:item.c,lineHeight:1}}>{item.v}</div>
               <div style={{fontSize:10,color:'var(--txt3)',marginTop:2}}>{item.sub}</div>
             </div>
          )}
        </div>
      )}

      {Array.isArray(txList) ? (
        <div>
          <div style={{fontWeight:700,fontSize:11,color:'#1E40AF',marginBottom:6,display:'flex',alignItems:'center',gap:5,textTransform:'uppercase',letterSpacing:'.04em'}}>
            <span style={{width:5,height:5,borderRadius:'50%',background:'#1E40AF',display:'inline-block',flexShrink:0}}></span>
            All Transactions — {allList.length} record{allList.length!==1?'s':''}
          </div>
          <DrillDownTxTable rows={allList} type="sale"/>
        </div>
      ) : (
        <div className="rg-2">
          <div>
            <div style={{fontWeight:700,fontSize:11,color:'#166534',marginBottom:6,display:'flex',alignItems:'center',gap:5,textTransform:'uppercase',letterSpacing:'.04em'}}>
              <span style={{width:5,height:5,borderRadius:'50%',background:'#166534',display:'inline-block',flexShrink:0}}></span>
              Purchase Transactions — {pList.length} record{pList.length!==1?'s':''}
            </div>
            <DrillDownTxTable rows={pList} type="purchase"/>
          </div>
          <div>
            <div style={{fontWeight:700,fontSize:11,color:'#991B1B',marginBottom:6,display:'flex',alignItems:'center',gap:5,textTransform:'uppercase',letterSpacing:'.04em'}}>
              <span style={{width:5,height:5,borderRadius:'50%',background:'#991B1B',display:'inline-block',flexShrink:0}}></span>
              Sale Transactions — {sList.length} record{sList.length!==1?'s':''}
            </div>
            <DrillDownTxTable rows={sList} type="sale"/>
          </div>
        </div>
      )}
    </div>
  );
}
window.DrillDownPanel = DrillDownPanel;

// ── Reports ───────────────────────────────────────────────
function ReportsPage() {
  window.useStoreSync();
  const { companyId } = aCtx(AppCtx);
  const isGroupMode = companyId === 'group';
  const [rType,    setRType]    = aSt('transport');
  const [fGroupCo, setFGroupCo] = aSt('');
  const [dateFrom, setFrom]    = aSt('');
  const [dateTo,   setTo]      = aSt('');
  const [fMat,     setFMat]    = aSt('');
  const [fCust,    setFCust]   = aSt('');
  const [fVend,    setFVend]   = aSt('');
  const [fVehicle, setFVehicle]= aSt('');
  const [search,   setSearch]  = aSt('');
  const [page,     setPage]    = aSt(1);
  const [rExpand,  setRExpand]  = aSt(null);
  const [fTxType,  setFTxType]  = aSt('');
  const PER = 50;

  const _allPurch   = isGroupMode ? Store.all('purchases')    : Store.all('purchases',   companyId);
  const _allSales   = isGroupMode ? Store.all('salesOrders')  : Store.all('salesOrders', companyId);
  const purchases   = fGroupCo ? _allPurch.filter(p=>p.companyId===fGroupCo) : _allPurch;
  const salesOrds   = fGroupCo ? _allSales.filter(s=>s.companyId===fGroupCo) : _allSales;
  const customers   = window.filterAssigned(Store.all('customers'), companyId);
  const vendors     = window.filterAssigned(Store.all('vendors'),   companyId);
  const materials   = window.filterAssigned(Store.all('materials'), companyId);
  const allCompanies = isGroupMode ? Store.all('companies') : [];

  const allVehicles = [...new Set([
    ...purchases.map(p=>p.vehicleFull),
    ...salesOrds.map(s=>s.vehicleFull),
  ].filter(Boolean))].sort();

  function inRange(d) {
    if (!d) return false;
    if (dateFrom && d < dateFrom) return false;
    if (dateTo   && d > dateTo)   return false;
    return true;
  }

  // ── Report 1: Overall Transport Data ────────────────────
  const transportData = aMemo(() => {
    const pFiltered = purchases.filter(p =>
      inRange(p.date) &&
      (!fMat  || p.items?.some(i=>i.materialId===fMat)) &&
      (!fVend || p.vendorId===fVend) &&
      (!fVehicle || p.vehicleFull===fVehicle)
    );
    const sFiltered = salesOrds.filter(s =>
      inRange(s.date) &&
      (!fMat  || s.materialId===fMat) &&
      (!fCust || s.customerId===fCust) &&
      (!fVehicle || s.vehicleFull===fVehicle)
    );

    // Global cross-company lookup for challan-based transfer detection
    const allSalesGlobal = Store.all('salesOrders');
    const salesByChallan = {};
    allSalesGlobal.forEach(s => {
      const ch = String(s.challanNumber||'').trim().toUpperCase();
      if (ch) { if (!salesByChallan[ch]) salesByChallan[ch]=[]; salesByChallan[ch].push(s); }
    });
    // Internal Transfer Engine records — authoritative source of truth
    const engineTransfers = Store.all('internalTransfers');
    const itByChallanVeh = {};
    engineTransfers.forEach(t => {
      const ch  = String(t.challanNumber||'').trim().toUpperCase();
      const veh = String(t.vehicleFull||'').toUpperCase().replace(/[\s\-\.]/g,'');
      if (ch) { if (veh) itByChallanVeh[ch+'|'+veh]=t; if (!itByChallanVeh[ch+'|*']) itByChallanVeh[ch+'|*']=t; }
    });
    // Confidence scoring — challan(45)+vehicle(25)+date(15)+quantity(15).
    // MATERIAL IS DELIBERATELY NOT A JOIN OR SCORING KEY: a purchase may be
    // legitimately reclassified before sale, so requiring/rewarding material
    // equality would hide exactly the relationships we need. Material is
    // compared AFTER matching (see reconciliation fields on each row).
    const _desc = (r, qty) => ({ challan: r.challanNumber, vehicle: r.vehicleFull, date: r.date, qty });
    const _recQty = r => r.items?.length ? r.items.reduce((s,i)=>s+(parseFloat(i.quantity)||0),0) : (parseFloat(r.quantity)||0);
    // Material names are always read from the record that owns them — never
    // inherited from the other side. Missing stays missing.
    const _matName = id => { const n = id ? Store.name('materials', id) : ''; return window.OMRecon.hasValue(n) ? n : null; };
    const _pMatId  = r => r.items?.[0]?.materialId || r.materialId || null;
    const _sMatId  = r => r.materialId || r.items?.[0]?.materialId || null;
    function reconFields(pMatName, sMatName, pQty, sQty, pCoId, sCoId, hasSale) {
      const cmp = window.OMRecon.compareMaterials(pMatName, hasSale ? sMatName : null);
      return {
        materialStatus: hasSale ? cmp.status : 'NOT_AVAILABLE',
        materialMismatch: hasSale ? cmp.materialMismatch : false,
        materialMismatchReason: hasSale ? cmp.reason : '',
        quantityDifference: hasSale ? (Number(sQty)||0)-(Number(pQty)||0) : 0,
        companyRelationship: hasSale ? (pCoId===sCoId?'same_company':'cross_company') : 'n/a',
      };
    }

    // Build rows keyed by challan
    const rows = [];
    const used = new Set();

    pFiltered.forEach(p => {
      const matId = p.items?.[0]?.materialId || p.materialId;
      const pQty = p.items ? p.items.reduce((s,i)=>s+Store.toStdTons(i.quantity,i.uom||'Ton',i.materialId||matId),0) : Store.toStdTons(p.quantity,'Ton',matId);
      // Challan-first matching with confidence scoring
      const pCh  = String(p.challanNumber||'').trim().toUpperCase();
      const pVeh = String(p.vehicleFull||'').toUpperCase().replace(/[\s\-\.]/g,'');
      const engineHit = pCh ? (itByChallanVeh[pCh+'|'+pVeh]||itByChallanVeh[pCh+'|*']) : null;
      // Candidate pool: sFiltered + global challan matches
      const candidates = new Map();
      // Challan number is the MANDATORY primary match key.
      // Never group purchases with sales that have a different (or missing) challan.
      if (pCh && salesByChallan[pCh]) {
        salesByChallan[pCh].forEach(s => { if(!used.has(s.id)) candidates.set(s.id,s); });
      }
      // No challan on purchase OR no matching challan in sales → standalone pending, no candidates
      const _pDesc = _desc(p, _recQty(p));
      const _picked = window.OMRecon.pickBest(_pDesc, Array.from(candidates.values()).map(s=>({rec:s,key:_desc(s,_recQty(s))})));
      let bestSale=_picked.rec, bestPts=_picked.pts, bestBasis=_picked.basis;
      const _ambiguous = _picked.ambiguous;
      let matchConf = engineHit ? Math.max(bestPts,100) : bestPts;
      let matchBasis = engineHit ? [{k:'Transfer Engine',v:true},...bestBasis] : bestBasis;
      const matchSale = bestSale;
      if (matchSale) used.add(matchSale.id);
      // Use item-level UOM for sales (mirrors how purchases are handled)
      const sQty = matchSale ? (matchSale.items?.length ? matchSale.items.reduce((s,i)=>s+Store.toStdTons(i.quantity,i.uom||'Ton',i.materialId||matchSale.materialId),0) : Store.toStdTons(matchSale.quantity,matchSale.uom||'Ton',matchSale.materialId)) : 0;
      const pOrigQty = p.items ? p.items.reduce((s,i)=>s+(parseFloat(i.quantity)||0),0) : parseFloat(p.quantity)||0;
      const pOrigUom = p.items?.[0]?.uom||'MT';
      const sOrigQty = matchSale ? (matchSale.items?.length ? matchSale.items.reduce((s,i)=>s+(parseFloat(i.quantity)||0),0) : parseFloat(matchSale.quantity)||0) : 0;
      const sOrigUom = matchSale ? (matchSale.items?.[0]?.uom||matchSale.uom||'MT') : 'MT';
      const pMat = Store.byId('materials', matId);
      const pDensity = parseFloat(pMat?.density)||1.50;
      rows.push({
        id: p.id,
        companyId: p.companyId,
        saleId: matchSale?.id,
        saleCompanyId: matchSale?.companyId,
        challanNo: p.challanNumber,
        vehicleNo: p.vehicleFull,
        // Legacy summary field (search / back-compat only) — NEVER used to render
        // either side's material. Each side reads its own record below.
        material:  _matName(matId) || '',
        materialId: matId,
        pMaterial: _matName(matId),            // ← purchase record
        pMaterialId: matId,
        sMaterial: matchSale ? _matName(_sMatId(matchSale)) : null,  // ← sales record
        sMaterialId: matchSale ? _sMatId(matchSale) : null,
        purchasedFrom: Store.name('vendors', p.vendorId),
        vendorId: p.vendorId,
        soldTo: matchSale ? Store.name('customers', matchSale.customerId) : '—',
        customerId: matchSale?.customerId,
        saleChallanNo: matchSale?.challanNumber,
        date: p.date,
        purchaseQty: pQty,
        uom: 'Ton',
        pOrigQty, pOrigUom, pDensity,
        pRate: p.items?.[0]?.ratePerTon||0,
        pAmount: p.subtotal||p.total||0,
        saleQty: sQty,
        saleUom: 'Ton',
        sOrigQty, sOrigUom,
        sRate: matchSale?.items?.[0]?.ratePerTon||matchSale?.rate||0,
        sAmount: matchSale?.subtotal||0,
        diff: sQty - pQty,
        convertedQty: pQty,
        trips: 1,
        isInternalTransfer: !!(engineHit||(matchSale&&p.companyId!==matchSale.companyId&&matchConf>=70)),
        matchConfidence: matchConf,
        matchBasis,
        matchAmbiguous: !!(_ambiguous && !engineHit),
        ...reconFields(_matName(matId), matchSale?_matName(_sMatId(matchSale)):null, pQty, sQty, p.companyId, matchSale?.companyId, !!matchSale),
        txType: (()=>{
          const _iT=!!(engineHit||(matchSale&&p.companyId!==matchSale.companyId&&matchConf>=70));
          const _tl=v=>['Ton','ton','MT','mt','Tons','tons'].includes(v||'MT');
          const _pCv=!_tl(pOrigUom)&&Math.abs(pQty-pOrigQty)>0.001&&pQty>0;
          const _sCv=!_tl(sOrigUom)&&Math.abs(sQty-sOrigQty)>0.001&&sQty>0;
          const _anyCv=_pCv||_sCv;
          if(!matchSale)return 'pending';
          if(_iT&&_anyCv)return 'density_transfer';
          if(_iT)return 'transfer';
          if(_anyCv&&Math.abs(pQty-sQty)>0.5)return 'mismatch';
          if(_anyCv)return 'converted';
          if(Math.abs(pQty-sQty)>0.5)return 'partial';
          return 'normal';
        })(),
      });
    });

    // ── IT Secondary Pass ─────────────────────────────────────────────────────
    // When viewing from the SALE SIDE of a cross-company internal transfer,
    // the purchase (from another company) is not in pFiltered, so it would
    // normally be invisible and the sale would appear as an orphaned "Pending Match".
    // This pass reads the IT engine record (which has immutable sourceCompanyId /
    // destCompanyId set at creation from the actual stored records) and builds a
    // complete row with the correct companies — never from the active context.
    const _itActiveId = isGroupMode ? fGroupCo : (companyId !== 'group' ? companyId : null);
    if (_itActiveId) {
      engineTransfers
        .filter(t => t._autoGenerated && t.destCompanyId === _itActiveId && t._purchaseId && t._salesId && !used.has(t._salesId))
        .forEach(t => {
          const origP = Store.byId('purchases',   t._purchaseId);
          const origS = Store.byId('salesOrders', t._salesId);
          if (!origP || !origS) return;
          // Apply date filter (same as pFiltered)
          if (!inRange(origP.date)) return;
          const _itMatId   = origP.items?.[0]?.materialId || origP.materialId;
          const _itPQty    = origP.items ? origP.items.reduce((s,i)=>s+Store.toStdTons(i.quantity,i.uom||'Ton',i.materialId||_itMatId),0) : Store.toStdTons(origP.quantity,'Ton',_itMatId);
          const _itSQty    = origS.items?.length ? origS.items.reduce((s,i)=>s+Store.toStdTons(i.quantity,i.uom||'Ton',i.materialId||origS.materialId),0) : Store.toStdTons(origS.quantity,origS.uom||'Ton',origS.materialId);
          const _itPOrig   = origP.items ? origP.items.reduce((s,i)=>s+(parseFloat(i.quantity)||0),0) : parseFloat(origP.quantity)||0;
          const _itPUom    = origP.items?.[0]?.uom||'MT';
          const _itSOrig   = origS.items?.length ? origS.items.reduce((s,i)=>s+(parseFloat(i.quantity)||0),0) : parseFloat(origS.quantity)||0;
          const _itSUom    = origS.items?.[0]?.uom||origS.uom||'MT';
          const _itDensity = parseFloat(Store.byId('materials',_itMatId)?.density)||1.50;
          used.add(origS.id);
          rows.push({
            id:             origP.id,
            companyId:      origP.companyId,    // ← ACTUAL purchase company from stored record
            saleId:         origS.id,
            saleCompanyId:  origS.companyId,    // ← ACTUAL sale company from stored record
            challanNo:      origP.challanNumber,
            vehicleNo:      origP.vehicleFull,
            material:       _matName(_itMatId) || '',
            materialId:     _itMatId,
            pMaterial:      _matName(_itMatId),
            pMaterialId:    _itMatId,
            sMaterial:      _matName(_sMatId(origS)),
            sMaterialId:    _sMatId(origS),
            purchasedFrom:  Store.name('vendors', origP.vendorId),
            vendorId:       origP.vendorId,
            soldTo:         Store.name('customers', origS.customerId),
            customerId:     origS.customerId,
            saleChallanNo:  origS.challanNumber,
            date:           origP.date,
            purchaseQty:    _itPQty,
            uom:            'Ton',
            pOrigQty: _itPOrig, pOrigUom: _itPUom, pDensity: _itDensity,
            pRate:   origP.items?.[0]?.ratePerTon||0,
            pAmount: origP.subtotal||origP.total||0,
            saleQty:  _itSQty,
            saleUom:  'Ton',
            sOrigQty: _itSOrig, sOrigUom: _itSUom,
            sRate:   origS.items?.[0]?.ratePerTon||origS.rate||0,
            sAmount: origS.subtotal||0,
            diff:    _itSQty - _itPQty,
            convertedQty: _itPQty,
            trips:   1,
            isInternalTransfer: true,
            matchConfidence: 100,
            matchBasis: [{k:'Transfer Engine',v:true},{k:'Challan Number',v:true},{k:'Vehicle',v:true}],
            matchAmbiguous: false,
            ...reconFields(_matName(_itMatId), _matName(_sMatId(origS)), _itPQty, _itSQty, origP.companyId, origS.companyId, true),
            txType: 'transfer',
          });
        });
    }

    // Unmatched sales
    sFiltered.filter(s=>!used.has(s.id)).forEach(s=>{
      const sQty = s.items?.length ? s.items.reduce((sum,i)=>sum+Store.toStdTons(i.quantity,i.uom||'Ton',i.materialId||s.materialId),0) : Store.toStdTons(s.quantity,s.uom||'Ton',s.materialId);
      const sOrigQty2 = s.items?.length ? s.items.reduce((sum,i)=>sum+(parseFloat(i.quantity)||0),0) : parseFloat(s.quantity)||0;
      const sOrigUom2 = s.items?.[0]?.uom||s.uom||'MT';
      rows.push({
        id: s.id,
        companyId: s.companyId,
        saleId: s.id,
        saleCompanyId: s.companyId,
        challanNo: s.challanNumber,
        vehicleNo: s.vehicleFull,
        material:  _matName(_sMatId(s)) || '',
        materialId: _sMatId(s),
        pMaterial: null,                       // no purchase record — stays missing
        pMaterialId: null,
        sMaterial: _matName(_sMatId(s)),       // ← sales record
        sMaterialId: _sMatId(s),
        purchasedFrom: '—',
        vendorId: null,
        soldTo: Store.name('customers', s.customerId),
        customerId: s.customerId,
        saleChallanNo: s.challanNumber,
        date: s.date,
        purchaseQty: 0,
        uom: 'Ton',
        pOrigQty: 0, pOrigUom: 'Ton', pDensity: 1.50,
        pRate: 0, pAmount: 0,
        saleQty: sQty,
        saleUom: 'Ton',
        sOrigQty: sOrigQty2, sOrigUom: sOrigUom2,
        sRate: s.items?.[0]?.ratePerTon||s.rate||0,
        sAmount: s.subtotal||0,
        diff: sQty,
        convertedQty: sQty,
        trips: 1,
        isInternalTransfer: false,
        matchConfidence: 0,
        matchBasis: [],
        matchAmbiguous: false,
        ...reconFields(null, _matName(_sMatId(s)), 0, sQty, null, s.companyId, false),
        txType: 'pending',
      });
    });

    return rows.sort((a,b) => b.date.localeCompare(a.date));
  }, [purchases, salesOrds, dateFrom, dateTo, fMat, fCust, fVend, fVehicle]);

  const transportSummary = aMemo(() => {
    const pTrips = purchases.filter(p=>inRange(p.date)).length;
    const sTrips = salesOrds.filter(s=>inRange(s.date)).length;
    const totalP = purchases.filter(p=>inRange(p.date)).reduce((sum,p)=> sum+(p.items?p.items.reduce((s,i)=>s+Store.toStdTons(i.quantity,i.uom||'Ton',i.materialId),0):0), 0);
    const totalS = salesOrds.filter(s=>inRange(s.date)).reduce((acc,o)=>{const sq=o.items?.length?o.items.reduce((s,i)=>s+Store.toStdTons(i.quantity,i.uom||'Ton',i.materialId||o.materialId),0):Store.toStdTons(o.quantity,o.uom||'Ton',o.materialId);return acc+sq;},0);
    return { pTrips, sTrips, totalP, totalS, diff: totalS-totalP };
  }, [purchases, salesOrds, dateFrom, dateTo]);

  // ── Report 2: Trip Analysis (vehicle-wise) ───────────────
  const tripData = aMemo(() => {
    const byVehicle = {};
    purchases.filter(p=>inRange(p.date)&&(!fVehicle||p.vehicleFull===fVehicle)).forEach(p=>{
      const veh = p.vehicleFull||'Unknown';
      if (!byVehicle[veh]) byVehicle[veh]={ vehicle:veh, materials:{}, pTrips:0, sTrips:0, challans:[], dates:[], companyIds:new Set() };
      byVehicle[veh].companyIds.add(p.companyId);
      const matId = p.items?.[0]?.materialId||p.materialId;
      const pQty = p.items?p.items.reduce((s,i)=>s+Store.toStdTons(i.quantity,i.uom||'Ton',i.materialId||matId),0):0;
      const matName = Store.name('materials',matId);
      if (!byVehicle[veh].materials[matName]) byVehicle[veh].materials[matName]={mat:matName,matId,uom:'Ton',pQty:0,sQty:0,pOrigQty:0,pOrigUom:'MT',sOrigQty:0,sOrigUom:'MT',density:1.50,challans:[],dates:[],companyIds:new Set()};
      byVehicle[veh].materials[matName].companyIds.add(p.companyId);
      byVehicle[veh].materials[matName].pQty += pQty;
      const _tpo=p.items?p.items.reduce((s,i)=>s+(parseFloat(i.quantity)||0),0):(parseFloat(p.quantity)||0);
      byVehicle[veh].materials[matName].pOrigQty=(byVehicle[veh].materials[matName].pOrigQty||0)+_tpo;
      byVehicle[veh].materials[matName].pOrigUom=p.items?.[0]?.uom||'MT';
      byVehicle[veh].materials[matName].density=parseFloat(Store.byId('materials',matId)?.density)||1.50;
      byVehicle[veh].pTrips++;
      if (p.challanNumber) { byVehicle[veh].challans.push(p.challanNumber); byVehicle[veh].materials[matName].challans.push(p.challanNumber); }
      if (p.date) { const fd=window.fmtDate(p.date); byVehicle[veh].dates.push(fd); byVehicle[veh].materials[matName].dates.push(fd); }
      if(!byVehicle[veh].materials[matName].pTxList)byVehicle[veh].materials[matName].pTxList=[];
      byVehicle[veh].materials[matName].pTxList.push({type:'purchase',id:p.id,date:p.date,company:Store.name('companies',p.companyId),challan:p.challanNumber||'—',vehicle:p.vehicleFull||'—',material:matName,qty:p.items?p.items.reduce((acc,i)=>acc+(parseFloat(i.quantity)||0),0):parseFloat(p.quantity)||0,uom:p.items?.[0]?.uom||'MT',amount:p.total||0,status:p.status||'—',vendor:Store.name('vendors',p.vendorId),crusher:p.items?.[0]?.crusherSite?Store.name('crushers',p.items[0].crusherSite):'—'});
    });
    salesOrds.filter(s=>inRange(s.date)&&(!fVehicle||s.vehicleFull===fVehicle)).forEach(s=>{
      const veh = s.vehicleFull||'Unknown';
      if (!byVehicle[veh]) byVehicle[veh]={ vehicle:veh, materials:{}, pTrips:0, sTrips:0, challans:[], dates:[], companyIds:new Set() };
      const matName = Store.name('materials',s.materialId);
      if (!byVehicle[veh].materials[matName]) byVehicle[veh].materials[matName]={mat:matName,matId:s.materialId,uom:'Ton',pQty:0,sQty:0,pOrigQty:0,pOrigUom:'MT',sOrigQty:0,sOrigUom:'MT',density:1.50,challans:[],dates:[],companyIds:new Set()};
      byVehicle[veh].materials[matName].companyIds.add(s.companyId);
      const _tsq=s.items?.length?s.items.reduce((sum,i)=>sum+Store.toStdTons(i.quantity,i.uom||'Ton',i.materialId||s.materialId),0):Store.toStdTons(s.quantity,s.uom||'Ton',s.materialId);
      byVehicle[veh].materials[matName].sQty += _tsq;
      const _tso=s.items?.length?s.items.reduce((sum,i)=>sum+(parseFloat(i.quantity)||0),0):parseFloat(s.quantity)||0;
      byVehicle[veh].materials[matName].sOrigQty=(byVehicle[veh].materials[matName].sOrigQty||0)+_tso;
      byVehicle[veh].materials[matName].sOrigUom=s.items?.[0]?.uom||s.uom||'MT';
      byVehicle[veh].sTrips++;
      if (s.challanNumber) { byVehicle[veh].challans.push(s.challanNumber); byVehicle[veh].materials[matName].challans.push(s.challanNumber); }
      if (s.date) { const fd=window.fmtDate(s.date); byVehicle[veh].dates.push(fd); byVehicle[veh].materials[matName].dates.push(fd); }
      if(!byVehicle[veh].materials[matName].sTxList)byVehicle[veh].materials[matName].sTxList=[];
      byVehicle[veh].materials[matName].sTxList.push({type:'sale',id:s.id,date:s.date,company:Store.name('companies',s.companyId),challan:s.challanNumber||'—',vehicle:s.vehicleFull||'—',material:matName,qty:s.items?.length?s.items.reduce((acc,i)=>acc+(parseFloat(i.quantity)||0),0):parseFloat(s.quantity)||0,uom:s.items?.[0]?.uom||s.uom||'MT',amount:s.total||0,status:s.status||'—',customer:Store.name('customers',s.customerId)});
    });
    return Object.values(byVehicle).map(v=>({
      ...v,
      companyNames: [...v.companyIds].map(id=>Store.name('companies',id)).filter(Boolean),
      matRows: Object.values(v.materials).map(m=>({
        ...m,
        companyNames: [...m.companyIds].map(id=>Store.name('companies',id)).filter(Boolean),
        diff: m.sQty-m.pQty,
        lossP: m.pQty>0?((m.pQty-m.sQty)/m.pQty*100).toFixed(2):'0.00',
      })),
      totalTrips: v.pTrips+v.sTrips,
      matCount:   Object.keys(v.materials).length,
    }));
  }, [purchases, salesOrds, dateFrom, dateTo, fVehicle]);

  // ── Report 3: Material Loss Summary ─────────────────────
  const lossData = aMemo(() => {
    const byMat = {};
    materials.forEach(m=>{ byMat[m.id]={ matId:m.id, name:m.name, uom:m.unit||'MT', pQty:0, sQty:0, pOrigQty:0, pOrigUom:'MT', sOrigQty:0, sOrigUom:'MT', pTrips:0, sTrips:0, companyIds:new Set() }; });
    purchases.filter(p=>inRange(p.date)).forEach(p=>{
      if (p.items) p.items.forEach(it=>{
        if (!byMat[it.materialId]) byMat[it.materialId]={ matId:it.materialId, name:Store.name('materials',it.materialId), uom:'Ton (Std)', pQty:0, sQty:0, pOrigQty:0, pOrigUom:'MT', sOrigQty:0, sOrigUom:'MT', pTrips:0, sTrips:0, companyIds:new Set() };
        byMat[it.materialId].pQty += Store.toStdTons(it.quantity,it.uom||'Ton',it.materialId);
        byMat[it.materialId].pOrigQty=(byMat[it.materialId].pOrigQty||0)+(parseFloat(it.quantity)||0);
        byMat[it.materialId].pOrigUom=it.uom||'MT';
        byMat[it.materialId].pTrips++;
        if(!byMat[it.materialId].pTxList)byMat[it.materialId].pTxList=[];
        byMat[it.materialId].pTxList.push({type:'purchase',id:p.id,date:p.date,company:Store.name('companies',p.companyId),challan:p.challanNumber||'—',vehicle:p.vehicleFull||'—',material:Store.name('materials',it.materialId),qty:parseFloat(it.quantity)||0,uom:it.uom||'MT',amount:p.total||0,status:p.status||'—',vendor:Store.name('vendors',p.vendorId),crusher:it.crusherSite?Store.name('crushers',it.crusherSite):'—'});
        if(p.companyId) byMat[it.materialId].companyIds.add(p.companyId);
      });
    });
    salesOrds.filter(s=>inRange(s.date)).forEach(s=>{
      if (!byMat[s.materialId]) byMat[s.materialId]={ matId:s.materialId, name:Store.name('materials',s.materialId), uom:'Ton (Std)', pQty:0, sQty:0, pOrigQty:0, pOrigUom:'MT', sOrigQty:0, sOrigUom:'MT', pTrips:0, sTrips:0, companyIds:new Set() };
      const _lsq=s.items?.length?s.items.reduce((sum,i)=>sum+Store.toStdTons(i.quantity,i.uom||'Ton',i.materialId||s.materialId),0):Store.toStdTons(s.quantity,s.uom||'Ton',s.materialId);
      byMat[s.materialId].sQty += _lsq;
      const _lso=s.items?.length?s.items.reduce((sum,i)=>sum+(parseFloat(i.quantity)||0),0):parseFloat(s.quantity)||0;
      byMat[s.materialId].sOrigQty=(byMat[s.materialId].sOrigQty||0)+_lso;
      byMat[s.materialId].sOrigUom=s.items?.[0]?.uom||s.uom||'MT';
      byMat[s.materialId].sTrips++;
      if(!byMat[s.materialId].sTxList)byMat[s.materialId].sTxList=[];
      byMat[s.materialId].sTxList.push({type:'sale',id:s.id,date:s.date,company:Store.name('companies',s.companyId),challan:s.challanNumber||'—',vehicle:s.vehicleFull||'—',material:Store.name('materials',s.materialId),qty:s.items?.length?s.items.reduce((acc,i)=>acc+(parseFloat(i.quantity)||0),0):parseFloat(s.quantity)||0,uom:s.items?.[0]?.uom||s.uom||'MT',amount:s.total||0,status:s.status||'—',customer:Store.name('customers',s.customerId)});
      if(s.companyId) byMat[s.materialId].companyIds.add(s.companyId);
    });
    return Object.values(byMat)
      .filter(m=>m.pQty>0||m.sQty>0)
      .map(m=>({ ...m, companyNames:[...(m.companyIds||new Set())].map(id=>Store.name('companies',id)).filter(Boolean), diff:m.sQty-m.pQty, avgLoss:m.pQty>0?((m.pQty-m.sQty)/m.pQty*100).toFixed(2):'0.00', density:parseFloat(Store.byId('materials',m.matId)?.density)||1.50 }))
      .sort((a,b)=>b.pQty-a.pQty);
  }, [purchases, salesOrds, materials, dateFrom, dateTo]);

  // ── Report 4: Customer Summary ───────────────────────────
  const customerData = aMemo(() => {
    const byCust = {};
    salesOrds.filter(s=>inRange(s.date)&&(!fCust||s.customerId===fCust)).forEach(s=>{
      const key = `${s.customerId}|${s.materialId}`;
      if (!byCust[key]) byCust[key]={ custId:s.customerId, custName:Store.name('customers',s.customerId), matId:s.materialId, matName:Store.name('materials',s.materialId), qty:0, uom:s.items?.[0]?.uom||s.uom||'MT', convQty:0, vehicles:new Set(), txList:[], companyId:s.companyId };
      const _corig=s.items?.length?s.items.reduce((sum,i)=>sum+(parseFloat(i.quantity)||0),0):parseFloat(s.quantity)||0;
      byCust[key].qty += _corig;
      byCust[key].uom = s.items?.[0]?.uom||s.uom||'MT';
      const _cconv=s.items?.length?s.items.reduce((sum,i)=>sum+Store.toStdTons(i.quantity,i.uom||'Ton',i.materialId||s.materialId),0):Store.toStdTons(s.quantity,s.uom||'Ton',s.materialId);
      byCust[key].convQty += _cconv;
      if (s.vehicleFull) byCust[key].vehicles.add(s.vehicleFull);
      byCust[key].txList.push({type:'sale',id:s.id,date:s.date,company:Store.name('companies',s.companyId),challan:s.challanNumber||'—',vehicle:s.vehicleFull||'—',material:Store.name('materials',s.materialId),customer:Store.name('customers',s.customerId),qty:s.items?.length?s.items.reduce((acc,i)=>acc+(parseFloat(i.quantity)||0),0):parseFloat(s.quantity)||0,uom:s.items?.[0]?.uom||s.uom||'MT',amount:s.total||0,status:s.status||'—'});
    });
    return Object.values(byCust)
      .map(r=>({ ...r, vehicleCount:r.vehicles.size, density:parseFloat(Store.byId('materials',r.matId)?.density)||1.50 }))
      .sort((a,b)=>b.qty-a.qty);
  }, [salesOrds, dateFrom, dateTo, fCust]);

  // Transaction type classification — display only
  const [drillDown,      setDrillDown]      = aSt(null);
  const [tripMatExpand, setTripMatExpand] = aSt(null); // key: vehicle+'||'+matName
  const [lossExpand,    setLossExpand]    = aSt(null); // matId
  const [custExpand,    setCustExpand]    = aSt(null); // custId+'|'+matId
  const TX_META = {
    normal:           { label:'Normal Transaction',         bg:'#DBEAFE', color:'#1E40AF' },
    transfer:         { label:'Internal Transfer',          bg:'#DCFCE7', color:'#166534' },
    converted:        { label:'Density Converted',          bg:'#EDE9FE', color:'#6D28D9' },
    density_transfer: { label:'Density Converted Transfer', bg:'#D1FAE5', color:'#065F46' },
    pending:          { label:'Pending Match',              bg:'#FEF3C7', color:'#92400E' },
    mismatch:         { label:'Quantity Mismatch',          bg:'#FEE2E2', color:'#991B1B' },
    partial:          { label:'Partial Match',              bg:'#FEF9C3', color:'#854D0E' },
  };

  const REPORT_TYPES = [
    { id:'transport', label:'Overall Transport Data' },
    { id:'trip',      label:'Trip Analysis' },
    { id:'loss',      label:'Material Loss Summary' },
    { id:'customer',  label:'Customer Summary' },
  ];

  function clearFilters() { setFrom(''); setTo(''); setFMat(''); setFCust(''); setFVend(''); setFVehicle(''); setSearch(''); setFGroupCo(''); setFTxType(''); setPage(1); setTripMatExpand(null); setLossExpand(null); setCustExpand(null); }

  const transportFiltered = aMemo(()=>{
    let base = fTxType ? transportData.filter(r=>r.txType===fTxType) : transportData;
    if(!search) return base;
    const q=search.toLowerCase();
    return base.filter(r=>[r.challanNo,r.vehicleNo,r.material,r.pMaterial,r.sMaterial,r.purchasedFrom,r.soldTo].some(v=>String(v||'').toLowerCase().includes(q)));
  },[transportData,search,fTxType]);
  const tripFiltered = aMemo(()=>{ if(!search) return tripData; const q=search.toLowerCase(); return tripData.filter(v=>String(v.vehicle||'').toLowerCase().includes(q)||v.matRows?.some(r=>String(r.mat||'').toLowerCase().includes(q))||v.challans?.some(c=>String(c||'').toLowerCase().includes(q))); },[tripData,search]);
  const lossFiltered = aMemo(()=>{ if(!search) return lossData; const q=search.toLowerCase(); return lossData.filter(r=>String(r.name||'').toLowerCase().includes(q)); },[lossData,search]);
  const custFiltered = aMemo(()=>{ if(!search) return customerData; const q=search.toLowerCase(); return customerData.filter(r=>String(r.custName||'').toLowerCase().includes(q)||String(r.matName||'').toLowerCase().includes(q)); },[customerData,search]);

  // ── Company attribution (canonical resolver — erp/company-attribution.js) ──
  // REPORT SCOPE ≠ TRANSACTION COMPANY. `companyId` below is the *scope* the
  // user selected ('group' = consolidated); the owning company of every row is
  // always resolved from the stored record, never from this scope.
  const CA = window.ERPCompanyAttribution;
  const coName    = (rec, idFields) => CA
    ? CA.resolveTransactionCompany(rec, idFields?{idFields}:undefined).companyName
    : (Store.name('companies', rec&&rec.companyId) || 'Unassigned');
  const coNames   = ids => CA ? CA.companyNamesFor(ids) : [...(ids||[])].map(id=>Store.name('companies',id)).join(' | ');
  const scopeLabel = isGroupMode
    ? (fGroupCo ? Store.name('companies',fGroupCo)+' (within OM Group)' : 'OM Group (Consolidated)')
    : (Store.name('companies',companyId)||'—');

  // Data-quality audit of the *filtered* per-record datasets (§15/§16)
  const attrAudit = aMemo(()=>{
    if (!CA) return { transport:0, customer:0 };
    return {
      transport: CA.auditAttribution(transportFiltered).unassigned,
      customer:  CA.auditAttribution(custFiltered).unassigned,
    };
  },[transportFiltered,custFiltered]);
  const unattributed = rType==='transport' ? attrAudit.transport : rType==='customer' ? attrAudit.customer : 0;

  function exportCSV() {
    let cols=[], rows=[], fname='';
    if (rType==='transport') {
      rows = transportFiltered;                                  // exactly the on-screen filtered dataset
      const hasIT = rows.some(r=>r.isInternalTransfer);
      cols = [{ h:'OM Group Company', k:'companyId', f:(_,r)=>coName(r) }];
      if (hasIT) cols.push({ h:'Destination Company', k:'saleCompanyId',
        f:(_,r)=> r.isInternalTransfer ? coName(r,['saleCompanyId','destCompanyId','toCompanyId']) : '' });
      cols = cols.concat([
        { h:'Transaction Type', k:'txType', f:v=>(TX_META[v||'normal']||TX_META.normal).label },
        { h:'Challan No',       k:'challanNo' },
        { h:'Vehicle',          k:'vehicleNo' },
        { h:'Purchase Material', k:'pMaterial', f:v=>window.OMRecon.hasValue(v)?String(v):window.OMRecon.MISSING_LABEL },
        { h:'Sale Material',     k:'sMaterial', f:(v,r)=> r.saleId ? (window.OMRecon.hasValue(v)?String(v):window.OMRecon.MISSING_LABEL) : '' },
        { h:'Material Status',   k:'materialStatus', f:v=>v==='DIFFERENT'?'Different':v==='MATCHED'?'Matched':'Not available' },
        { h:'Purchased From',   k:'purchasedFrom' },
        { h:'Sold To',          k:'soldTo' },
        { h:'Date',             k:'date' },
        { h:'Purchase Qty',     k:'purchaseQty', f:v=>Number(v||0).toFixed(3) },
        { h:'Sale Qty',         k:'saleQty',     f:v=>Number(v||0).toFixed(3) },
        { h:'Difference',       k:'diff',        f:v=>Number(v||0).toFixed(3) },
      ]);
      fname='transport_report';
    } else if (rType==='trip') {
      tripFiltered.forEach(v=>(v.matRows||[]).forEach(m=>rows.push({ ...m, vehicle:v.vehicle, vPTrips:v.pTrips, vSTrips:v.sTrips })));
      cols = [
        { h:'OM Group Company', k:'companyIds', f:(_,r)=>coNames(r.companyIds) },
        { h:'Vehicle',          k:'vehicle' },
        { h:'Material',         k:'mat' },
        { h:'UOM',              k:'uom' },
        { h:'Pickup Qty',       k:'pQty', f:v=>Number(v||0).toFixed(3) },
        { h:'Delivery Qty',     k:'sQty', f:v=>Number(v||0).toFixed(3) },
        { h:'Difference',       k:'diff', f:v=>Number(v||0).toFixed(3) },
        { h:'Loss %',           k:'lossP' },
        { h:'Purchase Trips',   k:'vPTrips' },
        { h:'Sale Trips',       k:'vSTrips' },
      ];
      fname='trip_report';
    } else if (rType==='loss') {
      rows = lossFiltered;
      cols = [
        { h:'OM Group Company', k:'companyIds', f:(_,r)=>coNames(r.companyIds) },
        { h:'Material',         k:'name' },
        { h:'UOM',              k:'uom' },
        { h:'Purchase Qty',     k:'pQty', f:v=>Number(v||0).toFixed(3) },
        { h:'Sale Qty',         k:'sQty', f:v=>Number(v||0).toFixed(3) },
        { h:'Difference',       k:'diff', f:v=>Number(v||0).toFixed(3) },
        { h:'Purchase Trips',   k:'pTrips' },
        { h:'Sale Trips',       k:'sTrips' },
        { h:'Avg Loss %',       k:'avgLoss' },
      ];
      fname='loss_report';
    } else if (rType==='customer') {
      rows = custFiltered;
      cols = [
        { h:'OM Group Company', k:'companyId', f:(_,r)=>coName(r) },
        { h:'SR',               k:'_sr', f:(_,r)=>custFiltered.indexOf(r)+1 },
        { h:'Customer',         k:'custName' },
        { h:'Material',         k:'matName' },
        { h:'Quantity',         k:'qty', f:v=>Number(v||0).toFixed(3) },
        { h:'UOM',              k:'uom' },
        { h:'Converted Qty',    k:'convQty', f:v=>Number(v||0).toFixed(3) },
        { h:'Vehicle Count',    k:'vehicleCount' },
      ];
      fname='customer_report';
    }

    if (!rows.length) { window.toast&&window.toast('No data to export','er'); return; }

    // Canonical CSV serializer (RFC-4180 quoting, UTF-8 BOM, CRLF) — shared
    // with every other export in the app; no manual string concatenation.
    window.exportCSV(fname+'_'+scopeLabel, rows, cols);

    const missing = rows.filter(r=>String(cols[0].f(null,r))==='Unassigned').length;
    if (missing) window.toast&&window.toast(missing+' of '+rows.length+' exported rows have no source company assigned (Unassigned)','in');
    Store.addLog('EXPORT','Report',`Exported ${rType} report — scope: ${scopeLabel} — ${rows.length} rows`);
  }

  const fmt3=n=>Number(n||0).toFixed(3);

  return (
    <div>
      <div className="ph">
        <div><h1>Reports</h1><p>Operational logistics and transport analysis · Quantities normalized to Tons via material density</p></div>
        <div className="ph-act">
          <button className="btn btn-wh btn-sm" onClick={()=>window.print()}>
            <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><polyline points="6 9 6 2 18 2 18 9"/><path d="M6 18H4a2 2 0 01-2-2v-5a2 2 0 012-2h16a2 2 0 012 2v5a2 2 0 01-2 2h-2"/><rect x="6" y="14" width="12" height="8"/></svg>
            Print
          </button>
          <button className="btn btn-or" onClick={exportCSV}>
            <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4M7 10l5 5 5-5M12 15V3"/></svg>
            Export CSV
          </button>
        </div>
      </div>

      {/* Report Type Tabs */}
      <div className="rep-grid" style={{marginBottom:12}}>
        {REPORT_TYPES.map(rt=>(
          <div key={rt.id} className={`rep-tile${rType===rt.id?' sel':''}`} onClick={()=>{setRType(rt.id);setPage(1);}}>
            {rt.label}
          </div>
        ))}
      </div>

      {/* Search bar */}
      <div className="frow" style={{marginBottom:8}}>
        <div className="fs" style={{flex:1}}>
          <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 vehicle, challan, material, customer, vendor…" style={{width:'100%'}} />
        </div>
        {search&&<button className="btn btn-gh btn-sm" onClick={()=>setSearch('')}>Clear</button>}
        <span className="f-cnt">{rType==='transport'?`${transportFiltered.length} records`:rType==='trip'?`${tripFiltered.length} vehicles`:rType==='loss'?`${lossFiltered.length} materials`:`${custFiltered.length} rows`}</span>
      </div>

      {unattributed>0&&(
        <div className="card" style={{padding:'8px 12px',marginBottom:8,background:'#FFFBEB',border:'1px solid #FDE68A',display:'flex',alignItems:'center',gap:8}}>
          <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="#92400E" strokeWidth="2.2" strokeLinecap="round"><path d="M12 9v4M12 17h.01"/><path d="M10.29 3.86L1.82 18a2 2 0 001.71 3h16.94a2 2 0 001.71-3L13.71 3.86a2 2 0 00-3.42 0z"/></svg>
          <span style={{fontSize:11.5,color:'#92400E',fontWeight:600}}>{unattributed} record{unattributed!==1?'s':''} do not have a source company assigned — they export as “Unassigned”.</span>
        </div>
      )}

      {/* Filters */}
      <div className="card" style={{padding:'10px 12px',marginBottom:10}}>
        <div style={{display:'flex',gap:8,flexWrap:'wrap',alignItems:'flex-end'}}>
          <div style={{display:'flex',flexDirection:'column',gap:3}}>
            <label style={{fontSize:11,fontWeight:500,color:'var(--txt2)'}}>From Date</label>
            <input className="inp" type="date" value={dateFrom} onChange={e=>setFrom(e.target.value)} style={{width:140,height:28,fontSize:11.5,padding:'3px 7px'}} />
          </div>
          <div style={{display:'flex',flexDirection:'column',gap:3}}>
            <label style={{fontSize:11,fontWeight:500,color:'var(--txt2)'}}>To Date</label>
            <input className="inp" type="date" value={dateTo} onChange={e=>setTo(e.target.value)} style={{width:140,height:28,fontSize:11.5,padding:'3px 7px'}} />
          </div>
          {['transport','loss','trip'].includes(rType)&&(
            <div style={{display:'flex',flexDirection:'column',gap:3}}>
              <label style={{fontSize:11,fontWeight:500,color:'var(--txt2)'}}>Material</label>
              <window.FiltSelect placeholder="All Materials" value={fMat} onChange={v=>{setFMat(v);setPage(1);}} options={materials.map(m=>({value:m.id,label:m.name}))}/>
            </div>
          )}
          {['transport','trip'].includes(rType)&&(
            <div style={{display:'flex',flexDirection:'column',gap:3}}>
              <label style={{fontSize:11,fontWeight:500,color:'var(--txt2)'}}>Vehicle</label>
              <window.FiltSelect placeholder="All Vehicles" value={fVehicle} onChange={v=>{setFVehicle(v);setPage(1);}} options={allVehicles.map(v=>({value:v,label:v}))}/>
            </div>
          )}
          {['transport','customer'].includes(rType)&&(
            <div style={{display:'flex',flexDirection:'column',gap:3}}>
              <label style={{fontSize:11,fontWeight:500,color:'var(--txt2)'}}>Customer</label>
              <window.FiltSelect placeholder="All Customers" value={fCust} onChange={v=>{setFCust(v);setPage(1);}} options={customers.map(c=>({value:c.id,label:c.name}))}/>
            </div>
          )}
          {['transport'].includes(rType)&&(
            <div style={{display:'flex',flexDirection:'column',gap:3}}>
              <label style={{fontSize:11,fontWeight:500,color:'var(--txt2)'}}>Vendor</label>
              <window.FiltSelect placeholder="All Vendors" value={fVend} onChange={v=>{setFVend(v);setPage(1);}} options={vendors.map(v=>({value:v.id,label:v.name}))}/>
            </div>
          )}
          {['transport'].includes(rType)&&(
            <div style={{display:'flex',flexDirection:'column',gap:3}}>
              <label style={{fontSize:11,fontWeight:500,color:'var(--txt2)'}}>Transaction Type</label>
              <window.FiltSelect placeholder="All Transactions" value={fTxType} onChange={v=>{setFTxType(v);setPage(1);}} style={{minWidth:160}} options={[{value:'normal',label:'Normal Transaction'},{value:'transfer',label:'Internal Transfer'},{value:'converted',label:'Density Converted'},{value:'density_transfer',label:'Density Converted Transfer'},{value:'pending',label:'Pending Match'},{value:'partial',label:'Partial Match'},{value:'mismatch',label:'Quantity Mismatch'}]}/>
            </div>
          )}
          {isGroupMode&&(
            <div style={{display:'flex',flexDirection:'column',gap:3}}>
              <label style={{fontSize:11,fontWeight:500,color:'var(--txt2)'}}>OM Group Company</label>
              <window.FiltSelect placeholder="All Companies" value={fGroupCo} onChange={v=>{setFGroupCo(v);setPage(1);}} options={allCompanies.map(c=>({value:c.id,label:c.name}))}/>
            </div>
          )}
          <button className="btn btn-gh btn-sm" onClick={clearFilters}>Clear</button>
        </div>
      </div>

      {/* ── REPORT 1: Overall Transport Data ── */}
      {rType==='transport'&&(
        <>
          {/* Summary Cards */}
          <div className="rg-5" style={{marginBottom:10}}>
            {[
              { label:'Purchase Trips',  value:transportSummary.pTrips,               clr:'var(--txt)' },
              { label:'Sale Trips',      value:transportSummary.sTrips,               clr:'var(--txt)' },
              { label:'Total Purchase',  value:fmt3(transportSummary.totalP)+' Tons', clr:'var(--or)'  },
              { label:'Total Sale',      value:fmt3(transportSummary.totalS)+' Tons', clr:'var(--info)'},
              { label:'Net Difference',  value:fmt3(transportSummary.diff)+' Tons',   clr: transportSummary.diff>=0?'var(--ok)':'var(--err)' },
            ].map((c,i)=>(
              <div key={i} className="kpi">
                <div className="kpi-lbl">{c.label}</div>
                <div className="kpi-val" style={{fontSize:14,color:c.clr}}>{c.value}</div>
              </div>
            ))}
          </div>
          <div className="card">
            <div className="tbl-w">
              <table className="tbl">
                <thead>
                  <tr>
                    <th style={{width:26,padding:'7px 4px'}}></th>
                    <th>SR</th>{isGroupMode&&<th>OM GROUP COMPANY</th>}
                    <th>CHALLAN NO</th><th>VEHICLE NO</th><th>MATERIAL</th><th>PURCHASED FROM</th><th>SOLD TO</th><th>DATE</th>
                    <th>PURCHASE QTY</th><th>UOM</th><th>SALE QTY</th><th>UOM</th><th>DIFFERENCE</th>
                    <th>TRANSACTION TYPE</th><th>TRIPS</th>
                  </tr>
                </thead>
                <tbody>
                  {transportFiltered.length===0
                    ? <tr className="empty"><td colSpan={isGroupMode?17:16} style={{textAlign:'center',padding:36,color:'var(--txt2)'}}>No transport data for selected filters</td></tr>
                    : transportFiltered.slice((page-1)*PER, page*PER).map((r,i)=>{
                        const _tl=v=>['Ton','ton','MT','mt','Tons','tons'].includes(v||'MT');
                        const pConv=!_tl(r.pOrigUom)&&Math.abs(r.purchaseQty-r.pOrigQty)>0.001&&r.purchaseQty>0;
                        const sConv=!_tl(r.sOrigUom)&&Math.abs(r.saleQty-r.sOrigQty)>0.001&&r.saleQty>0;
                        const txMeta=TX_META[r.txType||'normal'];
                        const isExp=rExpand===r.id;
                        return (
                          <React.Fragment key={r.id}>
                            <tr style={{cursor:'pointer'}} onClick={()=>setRExpand(isExp?null:r.id)}>
                              <td style={{textAlign:'center',padding:'5px 4px',width:26}}>
                                <span style={{color:'var(--or)',fontSize:9,display:'inline-block',transition:'transform .15s',transform:isExp?'rotate(90deg)':'none'}}>&#9658;</span>
                              </td>
                              <td style={{color:'var(--txt2)'}}>{(page-1)*PER+i+1}</td>
                              {isGroupMode&&<td><span className="bdg bg-or" style={{fontSize:10,padding:'1px 5px',whiteSpace:'nowrap'}}>{Store.name('companies',r.companyId)||'—'}</span></td>}
                              <td style={{fontFamily:'var(--font)',fontSize:11.5}}>{r.challanNo||'—'}</td>
                              <td style={{fontFamily:'var(--font)',fontSize:11.5,fontWeight:600}}>{r.vehicleNo||'—'}</td>
                              <td>{r.materialStatus==='DIFFERENT'
                                ? <span style={{whiteSpace:'nowrap'}} title="Material classification differs between purchase and sale">{window.OMRecon.displayMaterial(r.pMaterial)}<span style={{color:'#B45309',margin:'0 4px'}}>&rarr;</span>{window.OMRecon.displayMaterial(r.sMaterial)}</span>
                                : (window.OMRecon.hasValue(r.pMaterial)?r.pMaterial:window.OMRecon.displayMaterial(r.sMaterial))}</td>
                              <td style={{whiteSpace:'nowrap',fontSize:11.5}}>{r.purchasedFrom}</td>
                              <td style={{whiteSpace:'nowrap',fontSize:11.5}}>{r.soldTo}</td>
                              <td style={{color:'var(--txt2)',whiteSpace:'nowrap'}}>{window.fmtDate(r.date)}</td>
                              <td><window.ConvQtyCell qty={r.purchaseQty} origQty={r.pOrigQty} origUom={r.pOrigUom} density={r.pDensity}/></td>
                              <td style={{color:'var(--txt2)'}}>Ton</td>
                              <td><window.ConvQtyCell qty={r.saleQty} origQty={r.sOrigQty} origUom={r.sOrigUom} density={r.pDensity}/></td>
                              <td style={{color:'var(--txt2)'}}>Ton</td>
                              <td style={{fontWeight:600,color:r.diff>=0?'var(--ok)':'var(--err)'}}>{fmt3(r.diff)}</td>
                              <td><span style={{display:'inline-flex',alignItems:'center',padding:'2px 7px',borderRadius:3,fontSize:10.5,fontWeight:600,background:txMeta.bg,color:txMeta.color,whiteSpace:'nowrap'}}>{txMeta.label}</span></td>
                              <td style={{color:'var(--txt2)'}}>{r.trips}</td>
                            </tr>
                            {isExp&&(
                              <tr>
                                <td colSpan={isGroupMode?17:16} style={{padding:0}}>
                                  <window.TransactionIntelPanel row={r} pConv={pConv} sConv={sConv} txType={r.txType} txMeta={txMeta}/>
                                </td>
                              </tr>
                            )}
                          </React.Fragment>
                        );
                      })}
                </tbody>
                {transportFiltered.length>0&&(
                  <tfoot>
                    <tr>
                      <td colSpan={isGroupMode?9:8} style={{fontWeight:700,color:'var(--txt2)',background:'var(--or-lt)',padding:'9px 14px',fontSize:12,borderTop:'2px solid var(--or-bdr)'}}>
                        TOTALS — {transportFiltered.length} records
                      </td>
                      <td style={{fontWeight:700,background:'var(--or-lt)',padding:'9px 14px',fontSize:12,borderTop:'2px solid var(--or-bdr)',fontVariantNumeric:'tabular-nums'}}>{fmt3(transportFiltered.reduce((s,r)=>s+(r.purchaseQty||0),0))}</td>
                      <td style={{color:'var(--txt2)',background:'var(--or-lt)',padding:'9px 14px',fontSize:12,borderTop:'2px solid var(--or-bdr)'}}>Ton</td>
                      <td style={{fontWeight:700,background:'var(--or-lt)',padding:'9px 14px',fontSize:12,borderTop:'2px solid var(--or-bdr)',fontVariantNumeric:'tabular-nums'}}>{fmt3(transportFiltered.reduce((s,r)=>s+(r.saleQty||0),0))}</td>
                      <td style={{color:'var(--txt2)',background:'var(--or-lt)',padding:'9px 14px',fontSize:12,borderTop:'2px solid var(--or-bdr)'}}>Ton</td>
                      <td style={{fontWeight:700,background:'var(--or-lt)',padding:'9px 14px',fontSize:12,borderTop:'2px solid var(--or-bdr)',fontVariantNumeric:'tabular-nums',color:transportFiltered.reduce((s,r)=>s+(r.diff||0),0)>=0?'var(--ok)':'var(--err)'}}>{fmt3(transportFiltered.reduce((s,r)=>s+(r.diff||0),0))}</td>
                      <td style={{background:'var(--or-lt)',padding:'9px 14px',borderTop:'2px solid var(--or-bdr)'}}></td>
                      <td style={{fontWeight:700,background:'var(--or-lt)',padding:'9px 14px',fontSize:12,borderTop:'2px solid var(--or-bdr)',fontVariantNumeric:'tabular-nums'}}>{transportFiltered.reduce((s,r)=>s+(r.trips||0),0)}</td>
                    </tr>
                  </tfoot>
                )}
              </table>
            </div>
          </div>
          {Math.ceil(transportFiltered.length/PER)>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 {Math.ceil(transportFiltered.length/PER)}</span><button className="pg-b" onClick={()=>setPage(p=>p+1)} disabled={page===Math.ceil(transportFiltered.length/PER)}>›</button><button className="pg-b" onClick={()=>setPage(Math.ceil(transportFiltered.length/PER))} disabled={page===Math.ceil(transportFiltered.length/PER)}>»</button></div>}
        </>
      )}

      {/* ── REPORT 2: Trip Analysis (vehicle-wise) ── */}
      {rType==='trip'&&(
        <div>
          {tripFiltered.length===0
            ? <div className="card" style={{padding:40,textAlign:'center',color:'var(--txt2)'}}>No trip data for selected filters</div>
            : tripFiltered.slice((page-1)*Math.ceil(PER/3), page*Math.ceil(PER/3)).map(v=>(
              <div key={v.vehicle} className="card" style={{marginBottom:10}}>
                <div className="card-hd" style={{background:'#F9FAFB'}}>
                  <div>
                    <strong style={{fontSize:13,fontFamily:'var(--font)'}}>{v.vehicle}</strong>
                    <span style={{marginLeft:12,fontSize:11.5,color:'var(--txt2)'}}>{v.matCount} Material{v.matCount!==1?'s':''} Transported</span>
                    <span style={{marginLeft:12,fontSize:11.5,color:'var(--txt2)'}}>{v.totalTrips} Total Trips</span>
                  </div>
                  <div style={{fontSize:11,color:'var(--txt2)'}}>P:{v.pTrips} trips · S:{v.sTrips} trips</div>
                </div>
                <div className="tbl-w">
                  <table className="tbl">
                    <thead>
                      <tr>
                        <th style={{width:26,padding:'7px 4px'}}></th>
                        {isGroupMode&&<th>OM GROUP COMPANY</th>}
                        <th>MATERIAL</th><th>UOM</th><th>PICKUP QTY</th><th>DELIVERY QTY</th><th>DIFFERENCE</th><th>LOSS %</th><th>P.TRIPS</th><th>S.TRIPS</th><th>DETAILS</th>
                      </tr>
                    </thead>
                    <tbody>
                      {v.matRows.map((r,i)=>{
                        const tripKey   = v.vehicle+'||'+r.mat;
                        const isTripExp = tripMatExpand===tripKey;
                        const tripCols  = isGroupMode ? 11 : 10;
                        return (
                          <React.Fragment key={i}>
                            <tr style={{cursor:'pointer',background:isTripExp?'#FFF9F5':''}} onClick={()=>setTripMatExpand(isTripExp?null:tripKey)}>
                              <td style={{textAlign:'center',padding:'5px 4px',width:26,userSelect:'none'}}>
                                <span style={{color:'var(--or)',fontSize:9,display:'inline-block',transition:'transform .15s',transform:isTripExp?'rotate(90deg)':'none'}}>&#9658;</span>
                              </td>
                              {isGroupMode&&<td style={{fontSize:11,color:'var(--txt2)',whiteSpace:'nowrap'}}>{(r.companyNames||[]).join(', ')||'—'}</td>}
                              <td style={{fontWeight:500}}>{r.mat}</td>
                              <td style={{color:'var(--txt2)'}}>{r.uom}</td>
                              <td><window.ConvQtyCell qty={r.pQty} origQty={r.pOrigQty} origUom={r.pOrigUom} density={r.density}/></td>
                              <td><window.ConvQtyCell qty={r.sQty} origQty={r.sOrigQty} origUom={r.sOrigUom} density={r.density}/></td>
                              <td style={{fontWeight:600,color:r.diff>=0?'var(--ok)':'var(--err)'}}>{fmt3(r.diff)}</td>
                              <td><span className={`bdg ${parseFloat(r.lossP)>2?'bg-rd':parseFloat(r.lossP)>0?'bg-yw':'bg-gn'}`}>{r.lossP}%</span></td>
                              <td style={{color:'var(--txt2)'}}>{v.pTrips}</td>
                              <td style={{color:'var(--txt2)'}}>{v.sTrips}</td>
                              <td>
                                <button className="btn btn-gh btn-sm" onClick={e=>{e.stopPropagation();setTripMatExpand(isTripExp?null:tripKey);}} style={{fontSize:10.5,minWidth:100,gap:4}}>
                                  {isTripExp
                                    ?<>&#9650; Hide Details</>
                                    :<><span style={{background:'var(--or)',color:'#fff',borderRadius:9,padding:'0 5px',fontSize:9.5,fontWeight:700,lineHeight:'16px',display:'inline-block'}}>{(r.pTxList||[]).length+(r.sTxList||[]).length}</span> View Details</>}
                                </button>
                              </td>
                            </tr>
                            {isTripExp&&(
                              <tr>
                                <td colSpan={tripCols} style={{padding:0}}>
                                  <DrillDownPanel
                                    pTxList={r.pTxList||[]}
                                    sTxList={r.sTxList||[]}
                                    showLossBreakdown
                                    pQty={r.pQty} sQty={r.sQty} diff={r.diff} lossP={r.lossP}
                                    label={r.mat+' — Trip Detail for '+v.vehicle}
                                  />
                                </td>
                              </tr>
                            )}
                          </React.Fragment>
                        );
                      })}
                    </tbody>
                  </table>
                </div>
              </div>
            ))}
          {Math.ceil(tripFiltered.length/3)>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 {Math.ceil(tripFiltered.length/3)}</span><button className="pg-b" onClick={()=>setPage(p=>p+1)} disabled={page===Math.ceil(tripFiltered.length/3)}>›</button><button className="pg-b" onClick={()=>setPage(Math.ceil(tripFiltered.length/3))} disabled={page===Math.ceil(tripFiltered.length/3)}>»</button></div>}
        </div>
      )}

      {/* ── REPORT 3: Material Loss Summary ── */}
      {rType==='loss'&&(
        <div className="card">
          <div className="tbl-w">
            <table className="tbl">
              <thead>
                <tr>
                  <th style={{width:26,padding:'7px 4px'}}></th>
                  {isGroupMode&&<th>OM GROUP COMPANY</th>}
                  <th>MATERIAL</th><th>UOM</th><th>TOTAL PICKUP QTY</th><th>TOTAL DELIVERY QTY</th><th>TOTAL DIFFERENCE</th><th>PURCHASE TRIPS</th><th>SALE TRIPS</th><th>AVG LOSS %</th>
                </tr>
              </thead>
              <tbody>
                {lossFiltered.length===0
                  ? <tr className="empty"><td colSpan={isGroupMode?9:8} style={{textAlign:'center',padding:36,color:'var(--txt2)'}}>No data</td></tr>
                  : lossFiltered.map(r=>{
                      const isLossExp = lossExpand===r.matId;
                      const lossCols  = isGroupMode ? 10 : 9;
                      return (
                        <React.Fragment key={r.matId}>
                          <tr style={{cursor:'pointer',background:isLossExp?'#FFF9F5':''}} onClick={()=>setLossExpand(isLossExp?null:r.matId)}>
                            <td style={{textAlign:'center',padding:'5px 4px',width:26,userSelect:'none'}}>
                              <span style={{color:'var(--or)',fontSize:9,display:'inline-block',transition:'transform .15s',transform:isLossExp?'rotate(90deg)':'none'}}>&#9658;</span>
                            </td>
                            {isGroupMode&&<td style={{fontSize:11,color:'var(--txt2)',whiteSpace:'nowrap'}}>{(r.companyNames||[]).join(', ')||'—'}</td>}
                            <td><strong style={{color:isLossExp?'var(--or)':'inherit'}}>{r.name}</strong></td>
                            <td style={{color:'var(--txt2)'}}>{r.uom}</td>
                            <td><window.ConvQtyCell qty={r.pQty} origQty={r.pOrigQty} origUom={r.pOrigUom} density={r.density}/></td>
                            <td><window.ConvQtyCell qty={r.sQty} origQty={r.sOrigQty} origUom={r.sOrigUom} density={r.density}/></td>
                            <td style={{fontWeight:600,color:r.diff>=0?'var(--ok)':'var(--err)',cursor:'pointer'}}>{fmt3(r.diff)}</td>
                            <td style={{color:'var(--txt2)'}}>{r.pTrips}</td>
                            <td style={{color:'var(--txt2)'}}>{r.sTrips}</td>
                            <td><span className={`bdg ${parseFloat(r.avgLoss)>2?'bg-rd':parseFloat(r.avgLoss)>0?'bg-yw':'bg-gn'}`} style={{cursor:'pointer'}}>{r.avgLoss}%</span></td>
                          </tr>
                          {isLossExp&&(
                            <tr>
                              <td colSpan={lossCols} style={{padding:0}}>
                                <DrillDownPanel
                                  pTxList={r.pTxList||[]}
                                  sTxList={r.sTxList||[]}
                                  showLossBreakdown
                                  pQty={r.pQty} sQty={r.sQty} diff={r.diff} lossP={r.avgLoss}
                                  label={r.name+' — Loss Analysis'}
                                />
                              </td>
                            </tr>
                          )}
                        </React.Fragment>
                      );
                    })}
              </tbody>
              {lossFiltered.length>0&&(
                <tfoot>
                  <tr>
                    <td colSpan={isGroupMode?4:3} style={{fontWeight:700,color:'var(--txt2)'}}>TOTALS</td>
                    <td style={{fontWeight:700}}>{fmt3(lossFiltered.reduce((s,r)=>s+r.pQty,0))}</td>
                    <td style={{fontWeight:700}}>{fmt3(lossFiltered.reduce((s,r)=>s+r.sQty,0))}</td>
                    <td style={{fontWeight:700,color:'var(--or)'}}>{fmt3(lossFiltered.reduce((s,r)=>s+r.diff,0))}</td>
                    <td style={{fontWeight:700}}>{lossFiltered.reduce((s,r)=>s+r.pTrips,0)}</td>
                    <td style={{fontWeight:700}}>{lossFiltered.reduce((s,r)=>s+r.sTrips,0)}</td>
                    <td></td>
                  </tr>
                </tfoot>
              )}
            </table>
          </div>
        </div>
      )}

      {/* ── REPORT 4: Customer Summary ── */}
      {rType==='customer'&&(
        <div className="card">
          <div className="tbl-w">
            <table className="tbl">
              <thead>
                <tr>
                  <th style={{width:26,padding:'7px 4px'}}></th>
                  <th>SR</th>{isGroupMode&&<th>OM GROUP COMPANY</th>}<th>CUSTOMER NAME</th><th>MATERIAL</th><th>QUANTITY</th><th>UNIT</th><th>CONVERTED QTY (TONS)</th><th>VEHICLE COUNT</th>
                </tr>
              </thead>
              <tbody>
                {custFiltered.length===0
                  ? <tr className="empty"><td colSpan={isGroupMode?8:7} style={{textAlign:'center',padding:36,color:'var(--txt2)'}}>No data</td></tr>
                  : custFiltered.slice((page-1)*PER, page*PER).map((r,i)=>{
                      const custKey   = r.custId+'|'+r.matId;
                      const isCustExp = custExpand===custKey;
                      const custCols  = isGroupMode ? 9 : 8;
                      return (
                        <React.Fragment key={i}>
                          <tr style={{cursor:'pointer',background:isCustExp?'#FFF9F5':''}} onClick={()=>setCustExpand(isCustExp?null:custKey)}>
                            <td style={{textAlign:'center',padding:'5px 4px',width:26,userSelect:'none'}}>
                              <span style={{color:'var(--or)',fontSize:9,display:'inline-block',transition:'transform .15s',transform:isCustExp?'rotate(90deg)':'none'}}>&#9658;</span>
                            </td>
                            <td style={{color:'var(--txt2)'}}>{(page-1)*PER+i+1}</td>
                            {isGroupMode&&<td><span className="bdg bg-or" style={{fontSize:10,padding:'1px 5px',whiteSpace:'nowrap'}}>{Store.name('companies',r.companyId)||'—'}</span></td>}
                            <td><strong style={{fontSize:12,color:isCustExp?'var(--or)':'inherit'}}>{r.custName}</strong></td>
                            <td>{r.matName}</td>
                            <td style={{fontWeight:600}}>{fmt3(r.qty)}</td>
                            <td style={{color:'var(--txt2)'}}>{r.uom}</td>
                            <td style={{color:'var(--or)'}}><window.ConvQtyCell qty={r.convQty} origQty={r.qty} origUom={r.uom} density={r.density}/></td>
                            <td style={{fontWeight:600}}>{r.vehicleCount}</td>
                          </tr>
                          {isCustExp&&(
                            <tr>
                              <td colSpan={custCols} style={{padding:0}}>
                                <DrillDownPanel
                                  txList={r.txList||[]}
                                  label={r.custName+' — '+r.matName}
                                />
                              </td>
                            </tr>
                          )}
                        </React.Fragment>
                      );
                    })}
              </tbody>
              {custFiltered.length>0&&(
                <tfoot>
                  <tr>
                    <td colSpan={isGroupMode?5:4} style={{fontWeight:700,color:'var(--txt2)'}}>TOTAL</td>
                    <td style={{fontWeight:700,color:'var(--or)'}}>{fmt3(custFiltered.reduce((s,r)=>s+r.qty,0))}</td>
                    <td></td>
                    <td style={{fontWeight:700,color:'var(--or)'}}>{fmt3(custFiltered.reduce((s,r)=>s+r.convQty,0))}</td>
                    <td style={{fontWeight:700}}>{custFiltered.reduce((s,r)=>s+r.vehicleCount,0)}</td>
                  </tr>
                </tfoot>
              )}
            </table>
          </div>
          {Math.ceil(custFiltered.length/PER)>1&&<div className="pag" style={{padding:'6px 10px'}}><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 {Math.ceil(custFiltered.length/PER)}</span><button className="pg-b" onClick={()=>setPage(p=>p+1)} disabled={page===Math.ceil(custFiltered.length/PER)}>›</button><button className="pg-b" onClick={()=>setPage(Math.ceil(custFiltered.length/PER))} disabled={page===Math.ceil(custFiltered.length/PER)}>»</button></div>}
        </div>
      )}
    </div>
  );
}

window.CompaniesPage = CompaniesPage;
window.UsersPage     = UsersPage;
window.AuditPage     = AuditPage;
window.ReportsPage   = ReportsPage;
