import { useState, useEffect, useMemo, useRef } from 'react';
import { AreaChart, Area, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer, PieChart, Pie, Cell } from 'recharts';
import { DashboardBanner } from '../../lib/dashboardBanner';
import { useLocation, useNavigate } from 'react-router-dom';
import Layout from '../../components/Layout';
import SortTh from '../../components/SortTh';
import StatusBadge from '../../components/StatusBadge';
import { useSortable } from '../../hooks/useSortable';
import { supabase } from '../../lib/supabase';
import { useAuth } from '../../context/AuthContext';
import { readPageCache, writePageCache } from '../../lib/pageCache';
import { exportCPAPackage, generateSubcontractorPOPDF, generateInvoicePDF } from '../../lib/invoice';
import { withTimeout } from '../../lib/withTimeout';
import LoadingButton from '../../components/LoadingButton';
import { blobToEmailAttachment, sendEmail } from '../../lib/email';
import { popupOverlayStyle, popupSurfaceStyle } from '../../lib/popupStyles';
import FileAttachment from '../../components/FileAttachment';
import { isReviewShadowDescription } from '../../lib/taskVersions';
import { getRevisionChargeQuantity, isCompletedVersionEligible, isInitialVersionEligible } from '../../lib/invoiceVersionRules';
import { TeamInvoiceDetailPanel } from './TeamInvoiceDetail';
import InvoiceDetailPopup, { POPUP_FIELD_LABEL } from '../../components/InvoiceDetailPopup';
import InvoicePopupTable from '../../components/InvoicePopupTable';

const CATEGORIES = ['Software', 'Contractor', 'Advertising', 'Office', 'Travel', 'Meals', 'Equipment', 'Other'];
const statusColor = { draft: 'not_started', sent: 'in_progress', paid: 'client_approved' };
const poStatusColor = {
  draft: 'not_started',
  sent: 'in_progress',
  approved: 'client_approved',
  ready_to_pay: 'in_progress',
  paid: 'client_approved',
  cancelled: 'needs_revision',
};
const poStatusLabel = {
  draft: 'Draft',
  sent: 'Sent',
  approved: 'Approved',
  ready_to_pay: 'Ready to Pay',
  paid: 'Paid',
  cancelled: 'Cancelled',
};
const invoiceStatusBadgeLabel = (status) => {
  if (status === 'sent') return 'Invoiced';
  return status ? status.charAt(0).toUpperCase() + status.slice(1) : '—';
};
const RECEIPT_BUCKET = 'expense-receipts';
const FIELD_LABEL_STYLE = { fontSize: 11, fontWeight: 500, color: 'var(--text-secondary)', textTransform: 'uppercase', letterSpacing: 0.8, display: 'block', marginBottom: 4 };
const FIELD_INPUT_STYLE = { minHeight: 42, margin: 0 };
const FINANCE_MODAL_INPUT_STYLE = {
  ...FIELD_INPUT_STYLE,
  width: '100%',
  padding: '0 10px',
  fontSize: 13,
  color: 'var(--text-primary)',
  background: 'var(--card-bg-2)',
  border: '1px solid var(--border)',
  borderRadius: 6,
  fontFamily: 'inherit',
  boxSizing: 'border-box',
};
const FINANCE_MODAL_TEXTAREA_STYLE = {
  ...FINANCE_MODAL_INPUT_STYLE,
  minHeight: 72,
  padding: '10px',
  resize: 'vertical',
};
const FINANCE_MODAL_LINE_ITEM_INPUT_STYLE = {
  ...FINANCE_MODAL_INPUT_STYLE,
  minHeight: 32,
  padding: '0 8px',
};
const FINANCE_MODAL_NUMBER_INPUT_STYLE = {
  ...FINANCE_MODAL_LINE_ITEM_INPUT_STYLE,
  fontVariantNumeric: 'tabular-nums',
};
const FINANCE_MODAL_AMOUNT_FIELD_STYLE = {
  display: 'flex',
  alignItems: 'center',
  gap: 8,
  minHeight: 42,
  width: '100%',
  padding: '0 12px',
  background: 'var(--card-bg-2)',
  border: '1px solid var(--border)',
  borderRadius: 6,
  boxSizing: 'border-box',
};
const FINANCE_MODAL_AMOUNT_PREFIX_STYLE = {
  flexShrink: 0,
  fontSize: 16,
  fontWeight: 500,
  lineHeight: 1,
  color: 'var(--text-secondary)',
};
const FINANCE_MODAL_AMOUNT_INPUT_STYLE = {
  flex: 1,
  minWidth: 0,
  margin: 0,
  padding: 0,
  border: 'none',
  outline: 'none',
  background: 'transparent',
  boxShadow: 'none',
  fontFamily: 'inherit',
  fontSize: 22,
  fontWeight: 500,
  lineHeight: 1.1,
  textAlign: 'right',
  color: 'var(--text-primary)',
  fontVariantNumeric: 'tabular-nums',
  appearance: 'textfield',
};
const FINANCE_MODAL_TOTAL_VALUE_STYLE = {
  fontSize: 24,
  fontWeight: 500,
  lineHeight: 1.1,
  color: 'var(--accent)',
  fontVariantNumeric: 'tabular-nums',
};

function parseSubInvoiceItemVersionNumber(item) {
  if (Number.isFinite(Number(item?.version_number))) return Number(item.version_number);
  const match = String(item?.description || '').match(/\bR(\d{2})\b/i);
  return match ? Number(match[1]) : 0;
}

function subInvoiceItemVersionLabel(item) {
  return `R${String(parseSubInvoiceItemVersionNumber(item)).padStart(2, '0')}`;
}

function subInvoiceItemWorkLabel(item) {
  return parseSubInvoiceItemVersionNumber(item) > 0 ? 'Revision' : 'New';
}

function cleanSubInvoiceItemDescription(item) {
  return String(item?.description || '—').replace(/\s*[–-]\s*R\d{2}\b/i, '').trim() || '—';
}

function asArray(value) {
  if (Array.isArray(value)) return value;
  if (value == null) return [];
  return typeof value === 'object' ? [value] : [];
}

async function fetchSubInvoiceTaskTypeMap(taskIds) {
  const uniqueTaskIds = [...new Set((taskIds || []).filter(Boolean))];
  if (uniqueTaskIds.length === 0) return {};
  const { data, error } = await supabase
    .from('tasks')
    .select('id, title, submissions(service_type, type)')
    .in('id', uniqueTaskIds);
  if (error) throw error;
  const next = {};
  for (const task of (data || [])) {
    const submissions = asArray(task.submissions);
    const initial = submissions.find((submission) => submission?.type === 'initial' && submission?.service_type);
    const fallback = submissions.find((submission) => submission?.service_type);
    next[task.id] = initial?.service_type || fallback?.service_type || task.title || 'Other';
  }
  return next;
}

function CurrencyInput({ value, onChange, placeholder = '0.00', required = false, min = '0', step = '0.01' }) {
  return (
    <div style={FINANCE_MODAL_AMOUNT_FIELD_STYLE}>
      <span style={FINANCE_MODAL_AMOUNT_PREFIX_STYLE}>$</span>
      <input
        type="number"
        min={min}
        step={step}
        required={required}
        placeholder={placeholder}
        value={value}
        onChange={onChange}
        style={FINANCE_MODAL_AMOUNT_INPUT_STYLE}
      />
    </div>
  );
}

const INV_TODAY = new Date().toISOString().split('T')[0];
const INV_NET30 = new Date(Date.now() + 30 * 24 * 60 * 60 * 1000).toISOString().split('T')[0];
const invNewItem = (description = '', unit_price = '', quantity = 1, task_id = null, submission_id = null) =>
  ({ id: crypto.randomUUID(), description, unit_price, quantity, task_id, submission_id });

const invBuildNewItemDescription = (task) => {
  const projectName = task.project?.name || 'No Project';
  const taskTitle = task.title || task.service_type || 'Untitled';
  return `${projectName} • ${taskTitle}`;
};

const invBuildRevisionItemDescription = (revision) => {
  const projectName = revision.task?.project?.name || 'No Project';
  const taskTitle = revision.task?.title || revision.service_type || 'Revision';
  const versionLabel = 'R' + String(revision.version_number || 0).padStart(2, '0');
  return `${projectName} • ${taskTitle} • Revision ${versionLabel}`;
};

const blankExpense = () => ({
  date: new Date().toISOString().slice(0, 10),
  description: '',
  category: 'Other',
  amount: '',
  notes: '',
  receipt: null,
  receipt_path: null,
  receipt_name: null,
  removeReceipt: false,
});

function getFileExt(name = '') {
  const clean = String(name).split('.').pop()?.toLowerCase();
  return clean && clean !== name ? clean.replace(/[^a-z0-9]/g, '') : 'bin';
}

const MONTHS = ['January','February','March','April','May','June','July','August','September','October','November','December'];

function FinancesChartTooltip({ active, payload, label, year }) {
  if (!active || !payload?.length) return null;
  return (
    <div style={{ background: 'var(--card-bg)', border: '1px solid var(--border)', borderRadius: 4, padding: '10px 14px', fontSize: 12 }}>
      <div style={{ fontWeight: 600, marginBottom: 6, color: 'var(--text-primary)' }}>{label} {year}</div>
      {payload.map(p => (
        <div key={p.dataKey} style={{ color: p.color, marginBottom: 2 }}>{p.name}: <strong>${p.value.toLocaleString('en-US', { minimumFractionDigits: 2 })}</strong></div>
      ))}
    </div>
  );
}

export default function Invoices() {
  const { currentUser } = useAuth();
  const navigate = useNavigate();
  const location = useLocation();
  const cached = readPageCache('team_invoices');
  const [invoices, setInvoices] = useState(() => cached?.invoices || []);
  const [loading, setLoading] = useState(() => !cached);
  const [activeTab, setActiveTab] = useState(() => location.state?.tab || 'invoices');
  const [financeTab, setFinanceTab] = useState('overview');
  const [filter, setFilter] = useState('all');
  const { sortKey: invSortKey, sortDir: invSortDir, toggle: invToggle, sort: invSort } = useSortable('invoice_date', 'desc');
  const { sortKey: expSortKey, sortDir: expSortDir, toggle: expToggle, sort: expSort } = useSortable('date', 'desc');
  const { sortKey: subSortKey, sortDir: subSortDir, toggle: subToggle, sort: subSort } = useSortable('submitted_at');
  const { sortKey: ovExpKey, sortDir: ovExpDir, toggle: ovExpToggle } = useSortable('date');
  const { sortKey: ovSubKey, sortDir: ovSubDir, toggle: ovSubToggle } = useSortable('date');
  const { sortKey: ovInvKey, sortDir: ovInvDir, toggle: ovInvToggle } = useSortable('invoice_date');
  const { sortKey: subPopupKey, sortDir: subPopupDir, toggle: subPopupToggle, sort: subPopupSort } = useSortable('description');
  const [filterCompany, setFilterCompany] = useState('');
  const initMonth = () => { const n = new Date(); return { month: n.getMonth(), year: n.getFullYear() }; };
  const [ovMonth1, setOvMonth1] = useState(initMonth);
  const [ovMonth2, setOvMonth2] = useState(initMonth);
  const [ovMonth3, setOvMonth3] = useState(initMonth);
  const [exportYear, setExportYear] = useState(new Date().getFullYear());
  const [exporting, setExporting] = useState(false);

  const [expenses, setExpenses] = useState([]);
  const [expensesLoading, setExpensesLoading] = useState(true);
  const [expensesError, setExpensesError] = useState('');
  const [newExpense, setNewExpense] = useState(blankExpense());
  const [addingExpense, setAddingExpense] = useState(false);
  const [editingExpenseId, setEditingExpenseId] = useState('');
  const [showExpenseForm, setShowExpenseForm] = useState(false);
  const [expenseFilter, setExpenseFilter] = useState('all');
  const [viewingExpense, setViewingExpense] = useState(null);
  const [expensePreviewUrl, setExpensePreviewUrl] = useState(null);
  const [expenseDetailEditing, setExpenseDetailEditing] = useState(false);
  const [expYearFilter, setExpYearFilter] = useState(String(new Date().getFullYear()));
  const [expYearMenuOpen, setExpYearMenuOpen] = useState(false);
  const expYearMenuRef = useRef(null);
  const [invYearFilter, setInvYearFilter] = useState(String(new Date().getFullYear()));
  const [invCompanyFilter, setInvCompanyFilter] = useState('all');
  const [invYearMenuOpen, setInvYearMenuOpen] = useState(false);
  const invYearMenuRef = useRef(null);
  const [subcontractorPOs, setSubcontractorPOs] = useState([]);
  const [subcontractorLoading, setSubcontractorLoading] = useState(true);
  const [subcontractorError, setSubcontractorError] = useState('');
  const [selectedSubcontractorPOId, setSelectedSubcontractorPOId] = useState('');
  const [subInvoices, setSubInvoices] = useState([]);
  const [subInvoicesLoading, setSubInvoicesLoading] = useState(true);
  const [subInvoicesError, setSubInvoicesError] = useState('');
  const [markingPaid, setMarkingPaid] = useState('');
  const [viewingSubInvoice, setViewingSubInvoice] = useState(null);
  const [viewingSubInvoiceTaskTypeMap, setViewingSubInvoiceTaskTypeMap] = useState({});
  const [viewingInvoice, setViewingInvoice] = useState(null);
  const [expandedSubInvoiceId, setExpandedSubInvoiceId] = useState(null);

  // ── New Invoice form ──────────────────────────────────────────────────────
  const [showInvoiceForm, setShowInvoiceForm] = useState(false);
  const [invCompanies, setInvCompanies] = useState([]);
  const [invCompanyId, setInvCompanyId] = useState('');
  const [invBillTo, setInvBillTo] = useState('');
  const [invEmail, setInvEmail] = useState('');
  const [invRecipients, setInvRecipients] = useState([]);
  const [invUnbilledTasks, setInvUnbilledTasks] = useState([]);
  const [invUnbilledRevisions, setInvUnbilledRevisions] = useState([]);
  const [invPriceList, setInvPriceList] = useState([]);
  const [invItems, setInvItems] = useState([invNewItem()]);
  const [invNotes, setInvNotes] = useState('');
  const [invSaving, setInvSaving] = useState(false);
  const [invLoadingTasks, setInvLoadingTasks] = useState(false);
  const invDragItem = useRef(null);
  const pageLoading = loading || expensesLoading || subcontractorLoading || subInvoicesLoading;

  useEffect(() => {
    supabase.from('companies').select('id, name, contact_email').order('name').then(({ data }) => setInvCompanies(data || []));
  }, []);

  useEffect(() => {
    let cancelled = false;
    async function loadSubInvoiceTaskTypes() {
      if (!viewingSubInvoice?.items?.length) {
        setViewingSubInvoiceTaskTypeMap({});
        return;
      }
      try {
        const map = await fetchSubInvoiceTaskTypeMap(asArray(viewingSubInvoice.items).map((item) => item.task_id));
        if (!cancelled) setViewingSubInvoiceTaskTypeMap(map);
      } catch {
        if (!cancelled) setViewingSubInvoiceTaskTypeMap({});
      }
    }
    loadSubInvoiceTaskTypes();
    return () => { cancelled = true; };
  }, [viewingSubInvoice]);

  useEffect(() => {
    if (!invCompanyId) { setInvUnbilledTasks([]); setInvUnbilledRevisions([]); setInvPriceList([]); setInvItems([invNewItem()]); setInvBillTo(''); setInvEmail(''); setInvRecipients([]); return; }
    const co = invCompanies.find(c => c.id === invCompanyId);
    setInvBillTo(co?.name || '');
    setInvLoadingTasks(true);
    Promise.all([
      supabase.from('projects').select('id').eq('company_id', invCompanyId),
      supabase.from('company_prices').select('*').eq('company_id', invCompanyId),
      supabase.from('profiles').select('id, name, email, role').eq('company_id', invCompanyId).in('role', ['client', 'external']).order('name'),
    ]).then(async ([{ data: projects }, { data: prices }, { data: users }]) => {
      setInvPriceList(prices || []);
      setInvRecipients(users || []);
      setInvEmail((users || [])[0]?.email || co?.contact_email || '');
      if (projects?.length > 0) {
        const pids = projects.map(p => p.id);
        const { data: companyTasks } = await supabase
          .from('tasks')
          .select('*, project:projects(name), submissions(service_type, type, version_number)')
          .in('project_id', pids)
          .in('status', ['not_started', 'in_progress', 'on_hold', 'client_review', 'client_approved', 'invoiced', 'paid']);
        const revisionTaskIds = (companyTasks || []).map(t => t.id).filter(Boolean);
        const { data: revisions } = revisionTaskIds.length > 0
          ? await supabase
            .from('submissions')
            .select('*, task:tasks(id, title, status, current_version, project:projects(name), submissions(service_type, type))')
            .eq('type', 'revision')
            .eq('invoiced', false)
            .in('task_id', revisionTaskIds)
            .order('submitted_at', { ascending: false })
          : { data: [] };
        const uninvoicedTasks = (companyTasks || []).filter(isInitialVersionEligible);
        setInvUnbilledTasks(uninvoicedTasks.map(t => {
          const ini = (t.submissions || []).find(s => s.type === 'initial') || t.submissions?.[0];
          return { ...t, service_type: ini?.service_type || t.title };
        }));
        const revMap = new Map();
        for (const r of (revisions || []).filter(r => !isReviewShadowDescription(r.description))) {
          if (!isCompletedVersionEligible(r.task, r.version_number)) continue;
          const k = `${r.task_id}:${r.version_number}`;
          if (!revMap.has(k)) revMap.set(k, r);
        }
        setInvUnbilledRevisions([...revMap.values()]);
      } else { setInvUnbilledTasks([]); setInvUnbilledRevisions([]); }
      setInvLoadingTasks(false);
    });
  }, [invCompanyId, invCompanies]);

  const invAddTask = (task) => {
    const price = invPriceList.find(p => p.service_type === task.service_type && p.price_type === 'new');
    const desc = invBuildNewItemDescription(task);
    setInvItems(prev => prev.length === 1 && !prev[0].description && !prev[0].unit_price ? [invNewItem(desc, price?.price || '', 1, task.id)] : [...prev, invNewItem(desc, price?.price || '', 1, task.id)]);
  };
  const invAddRevision = (rev) => {
    const ini = (rev.task?.submissions || []).find(s => s.type === 'initial') || rev.task?.submissions?.[0];
    const svcType = ini?.service_type || rev.service_type || rev.task?.title || 'Revision';
    const price = invPriceList.find(p => p.service_type === svcType && p.price_type === 'revision');
    const revisionChargeQty = getRevisionChargeQuantity(rev?.version_number);
    const qty = revisionChargeQty > 0 ? revisionChargeQty : 1;
    const unitPrice = revisionChargeQty > 0 ? (price?.price || '') : 0;
    const desc = invBuildRevisionItemDescription(rev);
    setInvItems(prev => prev.length === 1 && !prev[0].description && !prev[0].unit_price ? [invNewItem(desc, unitPrice, qty, rev.task_id, rev.id)] : [...prev, invNewItem(desc, unitPrice, qty, rev.task_id, rev.id)]);
  };
  const invUpdateItem = (id, field, val) => setInvItems(prev => prev.map(it => it.id === id ? { ...it, [field]: val } : it));
  const invRemoveItem = (id) => setInvItems(prev => prev.filter(it => it.id !== id));
  const invHandleDrop = (targetIdx) => {
    if (invDragItem.current === null || invDragItem.current === targetIdx) { invDragItem.current = null; return; }
    setInvItems(prev => { const next = [...prev]; const [moved] = next.splice(invDragItem.current, 1); next.splice(targetIdx, 0, moved); return next; });
    invDragItem.current = null;
  };
  const invTotal = invItems.reduce((s, it) => s + (Number(it.quantity) || 0) * (Number(it.unit_price) || 0), 0);
  const invSelectedCompany = invCompanies.find(c => c.id === invCompanyId);

  const invClose = () => { setShowInvoiceForm(false); setInvCompanyId(''); setInvBillTo(''); setInvEmail(''); setInvRecipients([]); setInvUnbilledTasks([]); setInvUnbilledRevisions([]); setInvPriceList([]); setInvItems([invNewItem()]); setInvNotes(''); };

  const invHandleSave = async (status) => {
    if (!invCompanyId) return alert('Select a company.');
    if (invItems.every(i => !i.description)) return alert('Add at least one line item.');
    if (status === 'sent' && !invEmail.trim()) return alert('Enter an email recipient before sending.');
    setInvSaving(true);
    try {
      const year = new Date().getFullYear();
      const { count } = await supabase.from('invoices').select('*', { count: 'exact', head: true }).gte('created_at', `${year}-01-01`);
      const invoiceNumber = `INV-${year}-${String((count || 0) + 1).padStart(3, '0')}`;
      const { data: invoice, error } = await supabase.from('invoices').insert({ company_id: invCompanyId, invoice_number: invoiceNumber, invoice_date: INV_TODAY, due_date: INV_NET30, status: status === 'sent' ? 'draft' : status, bill_to: invBillTo || null, invoice_email: invEmail.trim() || null, notes: invNotes || null, total: invTotal, created_by: currentUser?.id }).select().single();
      if (error || !invoice) throw error || new Error('Invoice not created.');
      const validItems = invItems.filter(i => i.description);
      if (validItems.length > 0) await supabase.from('invoice_items').insert(validItems.map(it => ({ invoice_id: invoice.id, task_id: it.task_id || null, submission_id: it.submission_id || null, description: it.description, quantity: Number(it.quantity) || 1, unit_price: Number(it.unit_price) || 0 })));
      const taskIds = [...new Set(validItems.filter(i => i.task_id && !i.submission_id).map(i => i.task_id))];
      if (taskIds.length > 0) await supabase.from('tasks').update({ invoiced: true, status: 'invoiced' }).in('id', taskIds).eq('status', 'client_approved');
      const subIds = [...new Set(validItems.filter(i => i.submission_id).map(i => i.submission_id))];
      if (subIds.length > 0) await supabase.from('submissions').update({ invoiced: true }).in('id', subIds);
      if (status === 'sent') {
        try {
          const dueDate = new Date(INV_NET30).toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric' });
          const payUrl = `https://portal.fourgebranding.com/pay/${encodeURIComponent(invoiceNumber)}`;
          const pdfItems = validItems.map(it => ({ description: it.description, quantity: Number(it.quantity) || 1, unit_price: Number(it.unit_price) || 0 }));
          let attachments = [];
          try { const pdf = await withTimeout(generateInvoicePDF({ ...invoice, status: 'sent' }, invSelectedCompany, pdfItems, { save: false }), 8000, 'PDF'); attachments = [await withTimeout(blobToEmailAttachment(pdf, `${invoiceNumber}.pdf`), 5000, 'Attachment')]; } catch { /* PDF attach failed — send email without attachment */ }
          await withTimeout(sendEmail('invoice_sent', invEmail.trim(), { invoiceNumber, billTo: invBillTo || invSelectedCompany?.name, total: `$${invTotal.toFixed(2)}`, dueDate, payUrl, notes: invNotes || '' }, attachments), 12000, 'Email');
          await supabase.from('invoices').update({ status: 'sent' }).eq('id', invoice.id);
        } catch (e) { alert(`Invoice saved as draft — email failed: ${e.message}`); }
      }
      const createdInvoice = {
        ...invoice,
        company: invSelectedCompany ? { id: invSelectedCompany.id, name: invSelectedCompany.name } : null,
      };
      setInvoices(prev => [createdInvoice, ...prev]);
      invClose();
      setViewingInvoice(createdInvoice);
    } catch (e) { alert(`Failed to save invoice: ${e.message || 'Unknown error'}`); }
    setInvSaving(false);
  };

  useEffect(() => {
    async function load() {
      const { data } = await supabase
        .from('invoices')
        .select('*, company:companies(name)')
        .order('created_at', { ascending: false });
      setInvoices(data || []);
      writePageCache('team_invoices', { invoices: data || [] });
      setLoading(false);
    }
    load();
  }, []);

  useEffect(() => {
    async function loadExpenses() {
      const [{ data, error }, { data: purchaseOrders, error: purchaseOrdersError }] = await Promise.all([
        supabase.from('expenses').select('*').order('date', { ascending: false }),
        supabase
          .from('subcontractor_payments')
          .select('*, profile:profiles!subcontractor_payments_profile_id_fkey(id, name, email), project:projects(id, name, company:companies(name)), items:subcontractor_po_items(*, task:tasks(id, title))')
          .order('date', { ascending: false }),
      ]);
      if (error) {
        console.error('Failed to load expenses:', error);
        setExpensesError(error.message || 'Failed to load expenses.');
        setExpenses([]);
      } else {
        setExpenses(data || []);
        setExpensesError('');
      }
      if (purchaseOrdersError) {
        console.error('Failed to load subcontractor POs:', purchaseOrdersError);
        setSubcontractorError(purchaseOrdersError.message || 'Failed to load subcontractor POs.');
        setSubcontractorPOs([]);
      } else {
        setSubcontractorPOs(purchaseOrders || []);
        setSubcontractorError('');
      }
      setExpensesLoading(false);
      setSubcontractorLoading(false);
    }
    loadExpenses();
  }, []);

  useEffect(() => {
    if (!expYearMenuOpen) return;
    const handler = e => { if (expYearMenuRef.current && !expYearMenuRef.current.contains(e.target)) setExpYearMenuOpen(false); };
    document.addEventListener('mousedown', handler);
    return () => document.removeEventListener('mousedown', handler);
  }, [expYearMenuOpen]);

  useEffect(() => {
    if (!invYearMenuOpen) return;
    const handler = e => { if (invYearMenuRef.current && !invYearMenuRef.current.contains(e.target)) setInvYearMenuOpen(false); };
    document.addEventListener('mousedown', handler);
    return () => document.removeEventListener('mousedown', handler);
  }, [invYearMenuOpen]);

  useEffect(() => {
    setExpensePreviewUrl(null);
    setExpenseDetailEditing(false);
    if (!viewingExpense?.receipt_path) return;
    supabase.storage.from(RECEIPT_BUCKET).createSignedUrl(viewingExpense.receipt_path, 3600)
      .then(({ data }) => { if (data?.signedUrl) setExpensePreviewUrl(data.signedUrl); });
  }, [viewingExpense]);

  useEffect(() => {
    async function loadSubInvoices() {
      const { data, error: err } = await supabase
        .from('subcontractor_invoices')
        .select('*, profile:profiles!subcontractor_invoices_profile_id_fkey(id, name, email), items:subcontractor_invoice_items(*)')
        .order('created_at', { ascending: false });
      if (err) { setSubInvoicesError(err.message); setSubInvoicesLoading(false); return; }
      setSubInvoices(data || []);
      setSubInvoicesLoading(false);
    }
    loadSubInvoices();
  }, []);


  const cancelExpenseEdit = () => {
    setEditingExpenseId('');
    setNewExpense(blankExpense());
    setExpensesError('');
    setShowExpenseForm(false);
  };

  const saveExpense = async () => {
    if (!newExpense.description.trim() || !newExpense.amount) return;
    setAddingExpense(true);
    setExpensesError('');
    try {
      const existingExpense = editingExpenseId ? expenses.find(expense => expense.id === editingExpenseId) : null;
      let receiptPath = existingExpense?.receipt_path || newExpense.receipt_path || null;
      let receiptName = existingExpense?.receipt_name || newExpense.receipt_name || null;
      if (newExpense.removeReceipt && existingExpense?.receipt_path) {
        await supabase.storage.from(RECEIPT_BUCKET).remove([existingExpense.receipt_path]);
        receiptPath = null; receiptName = null;
      }
      if (newExpense.receipt) {
        const ext = getFileExt(newExpense.receipt.name);
        receiptName = newExpense.receipt.name;
        receiptPath = `${newExpense.date}/${Date.now()}-${crypto.randomUUID()}.${ext}`;
        const { error: uploadError } = await supabase.storage.from(RECEIPT_BUCKET).upload(receiptPath, newExpense.receipt, { upsert: false });
        if (uploadError) throw uploadError;
        if (existingExpense?.receipt_path) await supabase.storage.from(RECEIPT_BUCKET).remove([existingExpense.receipt_path]);
      }
      const payload = { date: newExpense.date, description: newExpense.description.trim(), category: newExpense.category, amount: Number(newExpense.amount), notes: newExpense.notes.trim(), receipt_path: receiptPath, receipt_name: receiptName };
      const query = editingExpenseId ? supabase.from('expenses').update(payload).eq('id', editingExpenseId) : supabase.from('expenses').insert(payload);
      const { data, error } = await query.select().single();
      if (error) { if (newExpense.receipt && receiptPath) await supabase.storage.from(RECEIPT_BUCKET).remove([receiptPath]); throw error; }
      if (data) {
        setExpenses(prev => editingExpenseId ? prev.map(expense => expense.id === editingExpenseId ? data : expense) : [data, ...prev]);
        setNewExpense(blankExpense()); setEditingExpenseId(''); setShowExpenseForm(false);
      }
    } catch (error) {
      console.error(`Failed to ${editingExpenseId ? 'update' : 'add'} expense:`, error);
      setExpensesError(error.message || `Failed to ${editingExpenseId ? 'update' : 'add'} expense.`);
      alert(`Failed to ${editingExpenseId ? 'update' : 'add'} expense: ${error.message || 'unknown error'}`);
    }
    setAddingExpense(false);
  };

  const handleAddExpense = async (e) => {
    e.preventDefault();
    await saveExpense();
  };

  const handleDeleteExpense = async (id) => {
    if (!window.confirm('Delete this expense?')) return;
    const expense = expenses.find(e => e.id === id);
    if (expense?.receipt_path) {
      await supabase.storage.from(RECEIPT_BUCKET).remove([expense.receipt_path]);
    }
    await supabase.from('expenses').delete().eq('id', id);
    setExpenses(prev => prev.filter(e => e.id !== id));
  };

  const handleViewReceipt = async (expense) => {
    if (!expense.receipt_path) return;
    const win = window.open('', '_blank', 'noopener,noreferrer');
    const { data, error } = await supabase.storage.from(RECEIPT_BUCKET).createSignedUrl(expense.receipt_path, 3600);
    if (error || !data?.signedUrl) {
      win?.close();
      const message = error?.message || 'Failed to open receipt.';
      setExpensesError(message);
      alert(message);
      return;
    }
    win.location.href = data.signedUrl;
  };

  const updateSubcontractorPO = async (po, updates, errorLabel = 'Failed to update PO') => {
    const { data, error } = await supabase
      .from('subcontractor_payments')
      .update(updates)
      .eq('id', po.id)
      .select('*, profile:profiles!subcontractor_payments_profile_id_fkey(id, name, email), project:projects(id, name, company:companies(name)), items:subcontractor_po_items(*, task:tasks(id, title))')
      .single();
    if (error) {
      alert(`${errorLabel}: ${error.message}`);
      return null;
    }
    if (data) {
      setSubcontractorPOs(prev => prev.map(row => row.id === po.id ? data : row));
      setSelectedSubcontractorPOId(current => current === po.id ? data.id : current);
    }
    return data;
  };

  const handleSendSubcontractorPO = async (po) => {
    await updateSubcontractorPO(po, { status: 'sent', sent_at: new Date().toISOString() }, 'Failed to send PO');
  };

  const handleReadyToPaySubcontractorPO = (po) => {
    updateSubcontractorPO(po, { status: 'ready_to_pay' }, 'Failed to mark ready to pay');
  };

  const handleMarkSubcontractorPaid = async (po) => {
    const paidAt = new Date().toISOString().slice(0, 10);
    updateSubcontractorPO(po, { status: 'paid', paid_at: paidAt }, 'Failed to mark as paid');
  };

  const handleMarkSubInvoicePaid = async (invoice) => {
    setMarkingPaid(invoice.id);
    try {
      const paidAt = new Date().toISOString();
      const { error } = await supabase.from('subcontractor_invoices').update({ status: 'paid', paid_at: paidAt }).eq('id', invoice.id);
      if (error) throw error;
      const items = invoice.items || [];
      const total = items.reduce((s, i) => s + Number(i.unit_price || 0) * Number(i.quantity || 1), 0);
      let pdfBlob = null;
      try {
        pdfBlob = await generateSubcontractorPOPDF({
          po_number: invoice.invoice_number,
          status: 'paid',
          profile: invoice.profile,
          project: { name: 'Subcontractor Invoice', company: { name: 'Fourge Branding' } },
          date: invoice.created_at?.split('T')[0],
          due_date: paidAt.split('T')[0],
          amount: total,
          description: 'Payment for completed subcontractor work.',
          notes: invoice.notes,
          items: items.map((item, idx) => ({
            description: item.description,
            amount: Number(item.unit_price) * Number(item.quantity || 1),
            sort_order: item.sort_order ?? idx,
          })),
        }, { output: 'blob' });
      } catch (pdfErr) {
        console.error('PDF generation failed:', pdfErr);
      }
      if (invoice.profile?.email) {
        try {
          const attachments = pdfBlob ? [await blobToEmailAttachment(pdfBlob, `${invoice.invoice_number}-receipt.pdf`)] : [];
          await sendEmail('receipt_sent', invoice.profile.email, {
            invoiceNumber: invoice.invoice_number,
            billTo: invoice.profile.name || invoice.profile.email,
            total: total.toFixed(2),
            paidDate: new Date(paidAt).toLocaleDateString('en-US', { month: 'long', day: 'numeric', year: 'numeric' }),
          }, attachments);
        } catch (emailErr) {
          console.error('Email failed:', emailErr);
          alert(`Marked paid, but email failed: ${emailErr.message || 'unknown error'}`);
        }
      }
      setSubInvoices(prev => prev.map(i => i.id === invoice.id ? { ...i, status: 'paid', paid_at: paidAt } : i));
    } catch (err) {
      alert(`Failed to mark as paid: ${err.message}`);
    }
    setMarkingPaid('');
  };

  const handleDownloadSubInvoiceReceipt = async (invoice) => {
    const items = invoice.items || [];
    const total = items.reduce((s, i) => s + Number(i.unit_price || 0) * Number(i.quantity || 1), 0);
    try {
      await generateSubcontractorPOPDF({
        po_number: invoice.invoice_number,
        status: 'paid',
        profile: invoice.profile,
        project: { name: 'Subcontractor Invoice', company: { name: 'Fourge Branding' } },
        date: invoice.created_at?.split('T')[0],
        due_date: (invoice.paid_at || new Date().toISOString()).split('T')[0],
        amount: total,
        description: 'Payment for completed subcontractor work.',
        notes: invoice.notes,
        items: items.map((item, idx) => ({
          description: item.description,
          amount: Number(item.unit_price) * Number(item.quantity || 1),
          sort_order: item.sort_order ?? idx,
        })),
      });
    } catch (err) {
      alert(`Failed to download receipt: ${err.message || 'unknown error'}`);
    }
  };

  const handleDownloadSubInvoice = async (invoice) => {
    const items = invoice.items || [];
    const total = items.reduce((s, i) => s + Number(i.unit_price || 0) * Number(i.quantity || 1), 0);
    try {
      await generateSubcontractorPOPDF({
        po_number: invoice.invoice_number,
        status: invoice.status || 'draft',
        profile: invoice.profile,
        project: { name: 'Subcontractor Invoice', company: { name: 'Fourge Branding' } },
        date: invoice.created_at?.split('T')[0],
        due_date: (invoice.paid_at || invoice.submitted_at || invoice.created_at || new Date().toISOString()).split('T')[0],
        amount: total,
        description: invoice.status === 'paid' ? 'Payment for completed subcontractor work.' : 'Subcontractor invoice for completed work.',
        notes: invoice.notes,
        items: items.map((item, idx) => ({
          description: item.description,
          amount: Number(item.unit_price || 0) * Number(item.quantity || 1),
          sort_order: item.sort_order ?? idx,
        })),
      });
    } catch (err) {
      alert(`Failed to download invoice: ${err.message || 'unknown error'}`);
    }
  };

  const handleReopenSubcontractorPO = async (po) => {
    updateSubcontractorPO(po, { status: 'draft', paid_at: null, cancelled_at: null }, 'Failed to reopen PO');
  };

  const handleCancelSubcontractorPO = async (po) => {
    if (!window.confirm(`Cancel ${po.po_number || 'this PO'}?`)) return;
    updateSubcontractorPO(po, { status: 'cancelled', cancelled_at: new Date().toISOString() }, 'Failed to cancel PO');
  };

  const handleDeleteSubcontractorPO = async (id) => {
    if (!window.confirm('Delete this subcontractor PO?')) return;
    await supabase.from('subcontractor_payments').delete().eq('id', id);
    setSubcontractorPOs(prev => prev.filter(po => po.id !== id));
    setSelectedSubcontractorPOId(current => current === id ? '' : current);
  };

  const handleDownloadSubcontractorPO = async (po) => {
    try {
      await generateSubcontractorPOPDF(po);
    } catch (error) {
      console.error('Failed to download subcontractor PO:', error);
      alert(`Failed to download PO: ${error.message || 'unknown error'}`);
    }
  };

  const handleCPAExport = async () => {
    setExporting(true);
    try {
      const yearInvoices = invoices.filter(inv =>
        inv.status === 'paid' && new Date(inv.invoice_date).getFullYear() === exportYear
      );
      const yearExpenses = expenses.filter(exp =>
        new Date(exp.date).getFullYear() === exportYear
      );
      const yearSubcontractorExpenses = subcontractorPOs
        .filter(po => po.status === 'paid' && new Date(po.paid_at || po.date).getFullYear() === exportYear)
        .map(po => ({
          date: po.paid_at || po.date,
          category: 'Contractor',
          description: `Subcontractor: ${po.profile?.name || 'External'} — ${po.items?.length ? po.items.map(item => item.description).join('; ') : po.description}`,
          amount: po.amount,
          notes: [po.po_number, po.project?.name, po.notes || po.profile?.email || ''].filter(Boolean).join(' · '),
        }));
      const exportExpenses = [...yearExpenses, ...yearSubcontractorExpenses];
      if (!yearInvoices.length && !exportExpenses.length) {
        alert(`No data found for ${exportYear}.`);
        return;
      }
      const { data: allItems } = yearInvoices.length ? await supabase
        .from('invoice_items')
        .select('invoice_id, description')
        .in('invoice_id', yearInvoices.map(i => i.id)) : { data: [] };
      const itemsByInvoice = (allItems || []).reduce((acc, item) => {
        (acc[item.invoice_id] = acc[item.invoice_id] || []).push(item);
        return acc;
      }, {});
      await exportCPAPackage(yearInvoices, itemsByInvoice, exportExpenses, exportYear);
    } finally {
      setExporting(false);
    }
  };

  const paidYears = [...new Set(
    invoices.filter(i => i.status === 'paid').map(i => new Date(i.invoice_date).getFullYear())
  )].sort((a, b) => b - a);

  const companyNames = [...new Set(invoices.map(inv => inv.company?.name).filter(Boolean))].sort();
  const filtered = invoices.filter(inv => {
    if (filter !== 'all' && inv.status !== filter) return false;
    if (filterCompany && inv.company?.name !== filterCompany) return false;
    return true;
  });

  const totals = {
    all: invoices.reduce((s, i) => s + Number(i.total), 0),
    draft: invoices.filter(i => i.status === 'draft').reduce((s, i) => s + Number(i.total), 0),
    sent: invoices.filter(i => i.status === 'sent').reduce((s, i) => s + Number(i.total), 0),
    paid: invoices.filter(i => i.status === 'paid').reduce((s, i) => s + Number(i.total), 0),
    netReceived: invoices.filter(i => i.status === 'paid').reduce((s, i) => s + Number(i.total) - Number(i.stripe_fee || 0), 0),
  };

  const expenseYears = [...new Set(expenses.map(e => e.date?.slice(0, 4)).filter(Boolean))].sort((a, b) => b - a);
  const filteredExpenses = expenses.filter(e => {
    if (expYearFilter !== 'all' && e.date?.slice(0, 4) !== expYearFilter) return false;
    if (expenseFilter !== 'all' && e.category !== expenseFilter) return false;
    return true;
  });
  const paidSubcontractorPOs = subcontractorPOs.filter(po => po.status === 'paid');
  const payableSubcontractorPOs = subcontractorPOs.filter(po => ['approved', 'ready_to_pay'].includes(po.status));
  const selectedSubcontractorPO = subcontractorPOs.find(po => po.id === selectedSubcontractorPOId);
  const subInvoiceItemTotal = (inv) => (inv.items || []).reduce((a, x) => a + Number(x.unit_price || 0) * Number(x.quantity || 1), 0);
  const paidSubInvoices = subInvoices.filter(i => i.status === 'paid');
  const totalPaidSubInvoices = paidSubInvoices.reduce((s, i) => s + subInvoiceItemTotal(i), 0);
  const totalPaidSubcontractors = paidSubcontractorPOs.reduce((s, po) => s + Number(po.amount), 0) + totalPaidSubInvoices;
  const totalPayableSubcontractorPOs = payableSubcontractorPOs.reduce((s, po) => s + Number(po.amount), 0);
  const totalPayableSubInvoices = subInvoices.filter(i => i.status === 'submitted').reduce((s, i) => s + subInvoiceItemTotal(i), 0);
  const totalPayableSubcontractors = totalPayableSubcontractorPOs + totalPayableSubInvoices;
  const payableSubcontractorCount = payableSubcontractorPOs.length + subInvoices.filter(i => i.status === 'submitted').length;
  const totalExpenses = filteredExpenses.reduce((s, e) => s + Number(e.amount), 0);
  const currentYear = new Date().getFullYear();
  const yearExpenses = expenses.filter(e => new Date(e.date).getFullYear() === currentYear);
  const currentYearExpenseTotal = yearExpenses.reduce((s, e) => s + Number(e.amount), 0);
  const currentYearPaidSubcontractorPOs = paidSubcontractorPOs
    .filter(po => new Date(po.paid_at || po.date).getFullYear() === currentYear)
    .reduce((s, po) => s + Number(po.amount), 0);
  const currentYearPaidSubInvoices = paidSubInvoices
    .filter(i => new Date(i.paid_at).getFullYear() === currentYear)
    .reduce((s, i) => s + subInvoiceItemTotal(i), 0);
  const currentYearTotalExpenses = currentYearExpenseTotal + currentYearPaidSubcontractorPOs + currentYearPaidSubInvoices;
  const revenue = totals.paid;
  const profit = totals.netReceived - expenses.reduce((s, e) => s + Number(e.amount), 0) - totalPaidSubcontractors;

  const chartYear = exportYear;
  const chartData = useMemo(() => MONTHS.map((month, mi) => {
    const paidInvs = invoices.filter(inv => inv.status === 'paid' && new Date(inv.invoice_date).getFullYear() === chartYear && new Date(inv.invoice_date).getMonth() === mi);
    const paid = paidInvs.reduce((s, inv) => s + Number(inv.total || 0), 0);
    const netPaid = paidInvs.reduce((s, inv) => s + Number(inv.total || 0) - Number(inv.stripe_fee || 0), 0);
    const outstanding = invoices
      .filter(inv => inv.status === 'sent' && new Date(inv.invoice_date).getFullYear() === chartYear && new Date(inv.invoice_date).getMonth() === mi)
      .reduce((s, inv) => s + Number(inv.total || 0), 0);
    const exp = expenses
      .filter(e => new Date(e.date).getFullYear() === chartYear && new Date(e.date).getMonth() === mi)
      .reduce((s, e) => s + Number(e.amount || 0), 0);
    const subExp = subInvoices
      .filter(i => i.status === 'paid' && new Date(i.created_at).getFullYear() === chartYear && new Date(i.created_at).getMonth() === mi)
      .reduce((s, i) => s + (i.items || []).reduce((a, x) => a + Number(x.unit_price || 0) * Number(x.quantity || 1), 0), 0);
    const totalExp = exp + subExp;
    return { month, Revenue: +paid.toFixed(2), Outstanding: +outstanding.toFixed(2), Expenses: +totalExp.toFixed(2), Profit: +(netPaid - totalExp).toFixed(2) };
  }), [invoices, expenses, subInvoices, chartYear]);


  return (
    <Layout loading={pageLoading}>
      <div style={{ flex: 1, minHeight: 0, display: 'flex', flexDirection: 'column', overflow: 'hidden' }}>
      {/* Top row: 60% chart + 40% stat cards */}
      {(() => {
        const yr = chartData.reduce((s, m) => s + m.Revenue, 0);
        const yp = chartData.reduce((s, m) => s + m.Profit, 0);
        const ye = chartData.reduce((s, m) => s + m.Expenses, 0);
        const yo = chartData.reduce((s, m) => s + m.Outstanding, 0);
        const fmt = v => v >= 100000 ? `$${(v/1000).toLocaleString('en-US')}k` : `$${v.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`;
        const CARD = { background: 'var(--card-bg)', border: '1px solid var(--border)', borderRadius: 8, padding: '18px 21px', backdropFilter: 'blur(12px)', WebkitBackdropFilter: 'blur(12px)' };
        const StatCard = ({ label, value, sub, iconBg, iconColor, iconSvg }) => (
          <div style={{ ...CARD, display: 'flex', alignItems: 'stretch', gap: 21, minHeight: 120 }}>
            <div style={{ flex: 1, display: 'flex', flexDirection: 'column' }}>
              <div style={{ fontSize: 11, fontWeight: 500, color: 'var(--text-secondary)', letterSpacing: 0.8, textTransform: 'uppercase', marginBottom: 5 }}>{label}</div>
              <div style={{ flex: 1, display: 'flex', alignItems: 'center' }}>
                <div style={{ fontSize: 30, fontWeight: 400, color: 'var(--text-primary)', letterSpacing: -0.5, lineHeight: 1.1 }}>{value}</div>
              </div>
              {sub && <div style={{ fontSize: 12, color: 'var(--text-muted)', marginTop: 5 }}>{sub}</div>}
            </div>
            <div style={{ flexShrink: 0, display: 'flex', flexDirection: 'column', alignItems: 'flex-end', justifyContent: 'flex-start' }}>
              <div style={{ width: 27, height: 27, borderRadius: '50%', background: iconBg, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke={iconColor} strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">{iconSvg}</svg>
              </div>
            </div>
          </div>
        );
        return (
          <div style={{ display: 'grid', gridTemplateColumns: '3fr 2fr', gap: 24, flexShrink: 0 }}>
            <div style={{ ...CARD }}>
              <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 16 }}>
                <span style={{ fontSize: 11, fontWeight: 500, color: 'var(--text-secondary)', letterSpacing: 0.8, textTransform: 'uppercase' }}>Revenue Overview</span>
                <select className="filter-select" value={chartYear} onChange={e => setExportYear(Number(e.target.value))} style={{ width: 90, borderRadius: 8, fontSize: 11, fontWeight: 500 }}>
                  {(paidYears.length > 0 ? paidYears : [new Date().getFullYear()]).map(y => <option key={y} value={y}>{y}</option>)}
                </select>
              </div>
              <ResponsiveContainer width="100%" height={160}>
                <AreaChart data={chartData} margin={{ top: 4, right: 8, left: 0, bottom: 0 }}>
                  <defs>
                    <linearGradient id="gc2Revenue" x1="0" y1="0" x2="0" y2="1"><stop offset="5%" stopColor="#F5A523" stopOpacity={0.25}/><stop offset="95%" stopColor="#F5A523" stopOpacity={0}/></linearGradient>
                    <linearGradient id="gc2Profit" x1="0" y1="0" x2="0" y2="1"><stop offset="5%" stopColor="#4ade80" stopOpacity={0.25}/><stop offset="95%" stopColor="#4ade80" stopOpacity={0}/></linearGradient>
                    <linearGradient id="gc2Expenses" x1="0" y1="0" x2="0" y2="1"><stop offset="5%" stopColor="#ef4444" stopOpacity={0.2}/><stop offset="95%" stopColor="#ef4444" stopOpacity={0}/></linearGradient>
                    <linearGradient id="gc2Outstanding" x1="0" y1="0" x2="0" y2="1"><stop offset="5%" stopColor="#60a5fa" stopOpacity={0.2}/><stop offset="95%" stopColor="#60a5fa" stopOpacity={0}/></linearGradient>
                  </defs>
                  <CartesianGrid strokeDasharray="3 3" stroke="var(--border)" vertical={false} />
                  <XAxis dataKey="month" tick={{ fontSize: 11, fill: 'var(--text-muted)' }} axisLine={false} tickLine={false} />
                  <YAxis tick={{ fontSize: 11, fill: 'var(--text-muted)' }} axisLine={false} tickLine={false} tickFormatter={v => `$${v >= 1000 ? (v/1000).toFixed(0)+'k' : v}`} width={45} />
                  <Tooltip content={<FinancesChartTooltip year={chartYear} />} />
                  <Legend wrapperStyle={{ fontSize: 11, paddingTop: 8 }} />
                  <Area type="monotone" dataKey="Revenue" stroke="#F5A523" strokeWidth={2} fill="url(#gc2Revenue)" dot={false} activeDot={{ r: 4 }} />
                  <Area type="monotone" dataKey="Profit" stroke="#4ade80" strokeWidth={2} fill="url(#gc2Profit)" dot={false} activeDot={{ r: 4 }} />
                  <Area type="monotone" dataKey="Expenses" stroke="#ef4444" strokeWidth={2} fill="url(#gc2Expenses)" dot={false} activeDot={{ r: 4 }} />
                  <Area type="monotone" dataKey="Outstanding" stroke="#60a5fa" strokeWidth={2} fill="url(#gc2Outstanding)" dot={false} activeDot={{ r: 4 }} />
                </AreaChart>
              </ResponsiveContainer>
            </div>
            <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 24, alignContent: 'start' }}>
              <StatCard label="Revenue" value={fmt(yr)} sub={`${chartYear} · paid invoices`} iconBg="rgba(245,165,35,0.15)" iconColor="#F5A523" iconSvg={<><line x1="12" y1="19" x2="12" y2="5"/><polyline points="5,12 12,5 19,12"/></>} />
              <StatCard label="Outstanding" value={fmt(yo)} sub={`${chartYear} · sent & unpaid`} iconBg="rgba(96,165,250,0.15)" iconColor="#60a5fa" iconSvg={<><circle cx="12" cy="12" r="8"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/></>} />
              <StatCard label="Expenses" value={fmt(ye)} sub={`${chartYear} · total spend`} iconBg="rgba(239,68,68,0.15)" iconColor="#ef4444" iconSvg={<><line x1="12" y1="5" x2="12" y2="19"/><polyline points="19,12 12,19 5,12"/></>} />
              <StatCard label="Net Profit" value={fmt(yp)} sub={`${chartYear} · after expenses`} iconBg="rgba(74,222,128,0.15)" iconColor="#4ade80" iconSvg={<><polyline points="4,13 9,18 20,7"/></>} />
            </div>
          </div>
        );
      })()}

      <div style={{ display: 'grid', gridTemplateColumns: '7fr 3fr', gap: 24, marginTop: 24, marginBottom: 10, flexShrink: 0, alignItems: 'center' }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 4, minHeight: 'var(--btn-height)' }}>
          {[
            { id: 'overview',       label: 'Overview' },
            { id: 'expenses',       label: 'Expenses' },
            { id: 'subcontractors', label: 'Subcontractors' },
            { id: 'invoices',       label: 'Invoices' },
          ].map(t => (
            <button
              key={t.id}
              type="button"
              onClick={() => setFinanceTab(t.id)}
              className={`section-tab-btn${financeTab === t.id ? ' is-active' : ''}`}
            >{t.label}</button>
          ))}
          {financeTab === 'expenses' && (
            <div style={{ marginLeft: 'auto', display: 'flex', alignItems: 'center', gap: 8 }}>
              <button className="btn btn-outline" onClick={() => { setEditingExpenseId(''); setNewExpense(blankExpense()); setExpensesError(''); setShowExpenseForm(true); }}>+ Expense</button>
              <div style={{ position: 'relative', display: 'flex', alignItems: 'center' }} ref={expYearMenuRef}>
                <button className="btn btn-outline" onClick={() => setExpYearMenuOpen(o => !o)} style={{ display: 'inline-flex', alignItems: 'center', gap: 6 }} title="Filter by year">
                  <svg viewBox="0 0 16 16" width="13" height="13" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"><path d="M2 4h12M4 8h8M6 12h4" /></svg>
                </button>
                {expYearMenuOpen && (
                  <div className="site-header-avatar-menu" style={{ position: 'absolute', top: 'calc(100% + 4px)', right: 0, zIndex: 220, minWidth: 130 }}>
                    <button onClick={() => { setExpYearFilter('all'); setExpYearMenuOpen(false); }} className="site-header-avatar-item" style={{ background: expYearFilter === 'all' ? 'rgba(245,165,35,0.08)' : 'transparent', color: expYearFilter === 'all' ? 'var(--accent)' : 'var(--text-primary)' }}>All Years</button>
                    {expenseYears.map(y => (
                      <button key={y} onClick={() => { setExpYearFilter(y); setExpYearMenuOpen(false); }} className="site-header-avatar-item" style={{ background: expYearFilter === y ? 'rgba(245,165,35,0.08)' : 'transparent', color: expYearFilter === y ? 'var(--accent)' : 'var(--text-primary)' }}>{y}</button>
                    ))}
                  </div>
                )}
              </div>
            </div>
          )}
          {financeTab === 'invoices' && (
            <div style={{ marginLeft: 'auto', display: 'flex', alignItems: 'center', gap: 8 }}>
              <button className="btn btn-outline" onClick={() => setShowInvoiceForm(true)}>+ Invoice</button>
              <div style={{ position: 'relative', display: 'flex', alignItems: 'center' }} ref={invYearMenuRef}>
                <button className="btn btn-outline" onClick={() => setInvYearMenuOpen(o => !o)} style={{ display: 'inline-flex', alignItems: 'center', gap: 6 }} title="Filter by year">
                  <svg viewBox="0 0 16 16" width="13" height="13" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"><path d="M2 4h12M4 8h8M6 12h4" /></svg>
                </button>
                {invYearMenuOpen && (
                  <div className="site-header-avatar-menu" style={{ position: 'absolute', top: 'calc(100% + 4px)', right: 0, zIndex: 220, minWidth: 150 }}>
                    <div style={{ fontSize: 10, fontWeight: 500, textTransform: 'uppercase', letterSpacing: 0.8, color: 'var(--text-muted)', padding: '6px 14px 4px' }}>Year</div>
                    <button onClick={() => setInvYearFilter('all')} className="site-header-avatar-item" style={{ background: invYearFilter === 'all' ? 'rgba(245,165,35,0.08)' : 'transparent', color: invYearFilter === 'all' ? 'var(--accent)' : 'var(--text-primary)' }}>All Years</button>
                    {[...new Set(invoices.map(i => i.invoice_date?.slice(0,4)).filter(Boolean))].sort((a,b) => b-a).map(y => (
                      <button key={y} onClick={() => setInvYearFilter(y)} className="site-header-avatar-item" style={{ background: invYearFilter === y ? 'rgba(245,165,35,0.08)' : 'transparent', color: invYearFilter === y ? 'var(--accent)' : 'var(--text-primary)' }}>{y}</button>
                    ))}
                    <div style={{ borderTop: '1px solid var(--border)', margin: '4px 0' }} />
                    <div style={{ fontSize: 10, fontWeight: 500, textTransform: 'uppercase', letterSpacing: 0.8, color: 'var(--text-muted)', padding: '4px 14px 4px' }}>Company</div>
                    <button onClick={() => setInvCompanyFilter('all')} className="site-header-avatar-item" style={{ background: invCompanyFilter === 'all' ? 'rgba(245,165,35,0.08)' : 'transparent', color: invCompanyFilter === 'all' ? 'var(--accent)' : 'var(--text-primary)' }}>All Companies</button>
                    {[...new Set(invoices.map(i => i.company?.name || i.bill_to).filter(Boolean))].sort().map(c => (
                      <button key={c} onClick={() => setInvCompanyFilter(c)} className="site-header-avatar-item" style={{ background: invCompanyFilter === c ? 'rgba(245,165,35,0.08)' : 'transparent', color: invCompanyFilter === c ? 'var(--accent)' : 'var(--text-primary)' }}>{c}</button>
                    ))}
                  </div>
                )}
              </div>
            </div>
          )}
        </div>
        <div />
      </div>

      {financeTab === 'overview' && (() => {
        const CARD = { background: 'var(--card-bg)', border: '1px solid var(--border)', borderRadius: 8, padding: '18px 21px', backdropFilter: 'blur(12px)', WebkitBackdropFilter: 'blur(12px)' };
        const TH = { fontSize: 10, fontWeight: 500, color: 'var(--text-muted)', textTransform: 'uppercase', letterSpacing: 0.6, padding: '0 0 12px 0', border: 'none', background: 'transparent', textAlign: 'left' };
        const TD = { fontSize: 13, color: 'var(--text-primary)', padding: '5px 0', border: 'none', background: 'transparent', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' };
        const sortRows = (arr, key, dir, getter) => [...arr].sort((a, b) => {
          const av = getter(a, key), bv = getter(b, key);
          if (av < bv) return dir === 'asc' ? -1 : 1;
          if (av > bv) return dir === 'asc' ? 1 : -1;
          return 0;
        });
        const fmtDate = d => d ? new Date(d).toLocaleDateString('en-US', { month: 'short', day: 'numeric' }) : '—';
        const fmtAmt = v => `$${Number(v).toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`;

        const now = new Date();
        const curM = now.getMonth(), curY = now.getFullYear();
        const stepMonth = (p, dir) => dir === -1
          ? (p.month === 0 ? { month: 11, year: p.year - 1 } : { month: p.month - 1, year: p.year })
          : (p.month === 11 ? { month: 0, year: p.year + 1 } : { month: p.month + 1, year: p.year });
        const MonthNav = ({ m, setter }) => {
          const atCurrent = m.month === curM && m.year === curY;
          return (
            <div style={{ display: 'flex', alignItems: 'center', gap: 0, flexShrink: 0 }}>
              <button type="button" onClick={() => setter(p => stepMonth(p, -1))} style={{ background: 'none', border: 'none', padding: '0 6px', cursor: 'pointer', color: 'var(--text-secondary)', fontSize: 18, lineHeight: 1 }}>‹</button>
              <button type="button" onClick={() => setter(p => stepMonth(p, 1))} disabled={atCurrent} style={{ background: 'none', border: 'none', padding: '0 6px', cursor: atCurrent ? 'default' : 'pointer', color: 'var(--text-secondary)', fontSize: 18, lineHeight: 1, opacity: atCurrent ? 0.25 : 1 }}>›</button>
            </div>
          );
        };

        // Card 1: Expenses
        const m1 = ovMonth1.month, y1 = ovMonth1.year;
        const thisMonthExp = expenses.filter(e => e.date && parseInt(e.date.slice(0,4)) === y1 && parseInt(e.date.slice(5,7)) - 1 === m1);
        const thisMonthTotal = thisMonthExp.reduce((s, e) => s + Number(e.amount || 0), 0);
        const thisCatTotals = CATEGORIES.map(cat => ({ cat, total: thisMonthExp.filter(e => e.category === cat).reduce((s, e) => s + Number(e.amount || 0), 0) })).filter(c => c.total > 0).sort((a, b) => b.total - a.total).slice(0, 4);

        // Card 2: Sub payments this month (paid sub invoices)
        const ovInvTotal = inv => (inv.items || []).reduce((s, i) => s + Number(i.unit_price || 0) * Number(i.quantity || 1), 0);
        const m2 = ovMonth2.month, y2 = ovMonth2.year;
        const pendingSubs = [...subInvoices.filter(i => { const d = new Date(i.paid_at || i.submitted_at); return d.getFullYear() === y2 && d.getMonth() === m2; })].sort((a, b) => new Date(b.paid_at || b.submitted_at) - new Date(a.paid_at || a.submitted_at));
        const pendingSubsTotal = pendingSubs.reduce((s, i) => s + ovInvTotal(i), 0);

        // Card 3: All invoices issued this month
        const m3 = ovMonth3.month, y3 = ovMonth3.year;
        const monthInvoices = [...invoices.filter(i => i.invoice_date && parseInt(i.invoice_date.slice(0,4)) === y3 && parseInt(i.invoice_date.slice(5,7)) - 1 === m3)];
        const outstandingTotal = monthInvoices.reduce((s, i) => s + Number(i.total || 0), 0);

        const PIE_COLORS = ['#F5A523', '#4ade80', '#60a5fa', '#c084fc', '#f472b6', '#fb923c', '#34d399', '#a78bfa'];

        // pie by subcontractor
        const subPieData = Object.values(pendingSubs.reduce((acc, inv) => {
          const name = inv.profile?.name || 'Unknown';
          if (!acc[name]) acc[name] = { name, value: 0 };
          acc[name].value += ovInvTotal(inv);
          return acc;
        }, {})).sort((a, b) => b.value - a.value);

        // pie by company (outstanding invoices)
        const invPieData = Object.values(monthInvoices.reduce((acc, inv) => {
          const name = inv.company?.name || inv.bill_to || 'Unknown';
          if (!acc[name]) acc[name] = { name, value: 0 };
          acc[name].value += Number(inv.total || 0);
          return acc;
        }, {})).sort((a, b) => b.value - a.value);

        const PieTooltipContent = ({ active, payload }) => {
          if (!active || !payload?.length) return null;
          return (
            <div style={{ background: 'var(--card-bg)', border: '1px solid var(--border)', borderRadius: 4, padding: '8px 12px', fontSize: 12 }}>
              <div style={{ color: payload[0].payload.fill, fontWeight: 500 }}>{payload[0].name}</div>
              <div style={{ color: 'var(--text-primary)' }}>{fmtAmt(payload[0].value)}</div>
            </div>
          );
        };

        const PieLegend = ({ data, colors }) => (
          <div style={{ display: 'flex', flexDirection: 'column', gap: 6, marginTop: 14 }}>
            {data.map((d, i) => (
              <div key={d.name} style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 8 }}>
                <div style={{ display: 'flex', alignItems: 'center', gap: 6, minWidth: 0 }}>
                  <div style={{ width: 8, height: 8, borderRadius: '50%', background: colors[i % colors.length], flexShrink: 0 }} />
                  <span style={{ fontSize: 12, color: 'var(--text-primary)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{d.name}</span>
                </div>
                <span style={{ fontSize: 12, color: 'var(--text-primary)', fontVariantNumeric: 'tabular-nums', flexShrink: 0 }}>{fmtAmt(d.value)}</span>
              </div>
            ))}
          </div>
        );

        return (
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 24, flex: 1, minHeight: 0 }}>
            {/* Card 1: This Month Expenses by category */}
            <div style={{ ...CARD, display: 'flex', flexDirection: 'column', minHeight: 0, overflowY: 'auto' }}>
              <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 5, flexShrink: 0 }}>
                <span style={{ fontSize: 11, fontWeight: 500, color: 'var(--text-secondary)', letterSpacing: 0.8, textTransform: 'uppercase' }}>{MONTHS[m1]} {y1 !== curY ? y1 : ''} Expenses</span>
                <MonthNav m={ovMonth1} setter={setOvMonth1} />
              </div>
              <div style={{ fontSize: 30, fontWeight: 400, letterSpacing: -0.5, lineHeight: 1.1, color: '#ef4444', fontVariantNumeric: 'tabular-nums', marginBottom: 14, flexShrink: 0 }}>{fmtAmt(thisMonthTotal)}</div>
              <div style={{ position: 'relative' }}>
                <ResponsiveContainer width="100%" height={260}>
                  <PieChart>
                    <Pie data={thisCatTotals.length ? thisCatTotals : [{ cat: 'None', total: 1 }]} dataKey="total" nameKey="cat" cx="50%" cy="50%" innerRadius={72} outerRadius={115} strokeWidth={0}>
                      {thisCatTotals.length ? thisCatTotals.map((_, i) => <Cell key={i} fill={PIE_COLORS[i % PIE_COLORS.length]} />) : <Cell fill="var(--border)" />}
                    </Pie>
                    {thisCatTotals.length > 0 && <Tooltip content={({ active, payload }) => {
                      if (!active || !payload?.length) return null;
                      return <div style={{ background: 'var(--card-bg)', border: '1px solid var(--border)', borderRadius: 4, padding: '8px 12px', fontSize: 12 }}><div style={{ color: payload[0].payload.fill, fontWeight: 500 }}>{payload[0].name}</div><div style={{ color: 'var(--text-primary)' }}>{fmtAmt(payload[0].value)}</div></div>;
                    }} />}
                  </PieChart>
                </ResponsiveContainer>
                <div style={{ position: 'absolute', top: '50%', left: '50%', transform: 'translate(-50%, -50%)', textAlign: 'center', pointerEvents: 'none' }}>
                  <div style={{ fontSize: 22, fontWeight: 500, color: 'var(--text-primary)', lineHeight: 1.1 }}>{thisMonthExp.length}</div>
                  <div style={{ fontSize: 10, color: 'var(--text-muted)', textTransform: 'uppercase', letterSpacing: 0.6 }}>items</div>
                </div>
              </div>
              {thisCatTotals.length > 0 && <PieLegend data={thisCatTotals.map(c => ({ name: c.cat, value: c.total }))} colors={PIE_COLORS} />}
            </div>

            {/* Card 2: Pending Sub Payments by subcontractor */}
            <div style={{ ...CARD, display: 'flex', flexDirection: 'column', minHeight: 0, overflowY: 'auto' }}>
              <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 5, flexShrink: 0 }}>
                <span style={{ fontSize: 11, fontWeight: 500, color: 'var(--text-secondary)', letterSpacing: 0.8, textTransform: 'uppercase' }}>{MONTHS[m2]} {y2 !== curY ? y2 : ''} Sub Payments</span>
                <MonthNav m={ovMonth2} setter={setOvMonth2} />
              </div>
              <div style={{ fontSize: 30, fontWeight: 400, letterSpacing: -0.5, lineHeight: 1.1, color: '#F5A523', fontVariantNumeric: 'tabular-nums', marginBottom: 14, flexShrink: 0 }}>{fmtAmt(pendingSubsTotal)}</div>
              <div style={{ position: 'relative' }}>
                <ResponsiveContainer width="100%" height={260}>
                  <PieChart>
                    <Pie data={subPieData.length ? subPieData : [{ name: 'None', value: 1 }]} dataKey="value" nameKey="name" cx="50%" cy="50%" innerRadius={72} outerRadius={115} strokeWidth={0}>
                      {subPieData.length ? subPieData.map((_, i) => <Cell key={i} fill={PIE_COLORS[i % PIE_COLORS.length]} />) : <Cell fill="var(--border)" />}
                    </Pie>
                    {subPieData.length > 0 && <Tooltip content={({ active, payload }) => {
                      if (!active || !payload?.length) return null;
                      return <div style={{ background: 'var(--card-bg)', border: '1px solid var(--border)', borderRadius: 4, padding: '8px 12px', fontSize: 12 }}><div style={{ color: payload[0].payload.fill, fontWeight: 500 }}>{payload[0].name}</div><div style={{ color: 'var(--text-primary)' }}>{fmtAmt(payload[0].value)}</div></div>;
                    }} />}
                  </PieChart>
                </ResponsiveContainer>
                <div style={{ position: 'absolute', top: '50%', left: '50%', transform: 'translate(-50%, -50%)', textAlign: 'center', pointerEvents: 'none' }}>
                  <div style={{ fontSize: 22, fontWeight: 500, color: 'var(--text-primary)', lineHeight: 1.1 }}>{pendingSubs.length}</div>
                  <div style={{ fontSize: 10, color: 'var(--text-muted)', textTransform: 'uppercase', letterSpacing: 0.6 }}>invoices</div>
                </div>
              </div>
              {subPieData.length > 0 && <PieLegend data={subPieData} colors={PIE_COLORS} />}
            </div>

            {/* Card 3: Invoiced this month by company */}
            <div style={{ ...CARD, display: 'flex', flexDirection: 'column', minHeight: 0, overflowY: 'auto' }}>
              <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 5, flexShrink: 0 }}>
                <span style={{ fontSize: 11, fontWeight: 500, color: 'var(--text-secondary)', letterSpacing: 0.8, textTransform: 'uppercase' }}>{MONTHS[m3]} {y3 !== curY ? y3 : ''} Invoiced</span>
                <MonthNav m={ovMonth3} setter={setOvMonth3} />
              </div>
              <div style={{ fontSize: 30, fontWeight: 400, letterSpacing: -0.5, lineHeight: 1.1, color: '#4ade80', fontVariantNumeric: 'tabular-nums', marginBottom: 14, flexShrink: 0 }}>{fmtAmt(outstandingTotal)}</div>
              <div style={{ position: 'relative' }}>
                <ResponsiveContainer width="100%" height={260}>
                  <PieChart>
                    <Pie data={invPieData.length ? invPieData : [{ name: 'None', value: 1 }]} dataKey="value" nameKey="name" cx="50%" cy="50%" innerRadius={72} outerRadius={115} strokeWidth={0}>
                      {invPieData.length ? invPieData.map((_, i) => <Cell key={i} fill={PIE_COLORS[i % PIE_COLORS.length]} />) : <Cell fill="var(--border)" />}
                    </Pie>
                    {invPieData.length > 0 && <Tooltip content={({ active, payload }) => {
                      if (!active || !payload?.length) return null;
                      return <div style={{ background: 'var(--card-bg)', border: '1px solid var(--border)', borderRadius: 4, padding: '8px 12px', fontSize: 12 }}><div style={{ color: payload[0].payload.fill, fontWeight: 500 }}>{payload[0].name}</div><div style={{ color: 'var(--text-primary)' }}>{fmtAmt(payload[0].value)}</div></div>;
                    }} />}
                  </PieChart>
                </ResponsiveContainer>
                <div style={{ position: 'absolute', top: '50%', left: '50%', transform: 'translate(-50%, -50%)', textAlign: 'center', pointerEvents: 'none' }}>
                  <div style={{ fontSize: 22, fontWeight: 500, color: 'var(--text-primary)', lineHeight: 1.1 }}>{monthInvoices.length}</div>
                  <div style={{ fontSize: 10, color: 'var(--text-muted)', textTransform: 'uppercase', letterSpacing: 0.6 }}>invoices</div>
                </div>
              </div>
              {invPieData.length > 0 && <PieLegend data={invPieData} colors={PIE_COLORS} />}
            </div>
          </div>
        );
      })()}

      {financeTab === 'expenses' && (() => {
        const CARD = { background: 'var(--card-bg)', border: '1px solid var(--border)', borderRadius: 8, padding: '18px 21px', backdropFilter: 'blur(12px)', WebkitBackdropFilter: 'blur(12px)' };
        const TH = { fontSize: 10, fontWeight: 500, color: 'var(--text-muted)', textTransform: 'uppercase', letterSpacing: 0.6, padding: '0 0 12px 0', border: 'none', background: 'transparent', textAlign: 'left' };
        const TD = { fontSize: 13, color: 'var(--text-primary)', padding: '5px 0', border: 'none', background: 'transparent', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' };
        const fmtDate = d => d ? new Date(d + 'T12:00:00').toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' }) : '—';
        const fmtAmt = v => `$${Number(v).toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`;
        const sortedExpenses = expSort(filteredExpenses, (exp, key) => {
          if (key === 'amount') return Number(exp.amount) || 0;
          if (key === 'date') return exp.date || '';
          return exp[key] || '';
        });
        const categoryTotals = CATEGORIES
          .map(cat => ({ cat, total: filteredExpenses.filter(e => e.category === cat).reduce((s, e) => s + Number(e.amount || 0), 0) }))
          .sort((a, b) => b.total - a.total);
        const grandTotal = filteredExpenses.reduce((s, e) => s + Number(e.amount || 0), 0);
        return (
          <div style={{ display: 'flex', flexDirection: 'column', gap: 0, flex: 1, minHeight: 0 }}>
            <div style={{ display: 'grid', gridTemplateColumns: '7fr 3fr', gap: 24, flex: 1, minHeight: 0 }}>
            {/* Left: expense list */}
            <div style={{ ...CARD, display: 'flex', flexDirection: 'column', minHeight: 0 }}>
              {expenses.length === 0 ? <div className="card-empty-center">No expenses</div> : (
                <div className="scrollbar-thin-theme table-scroll-hidden" style={{ flex: 1, minHeight: 0, overflowY: 'auto' }}>
                  <table className="table-sticky-head" style={{ width: '100%', borderCollapse: 'collapse', tableLayout: 'fixed' }}>
                    <colgroup>
                      <col style={{ width: '14%' }} />
                      <col style={{ width: '34%' }} />
                      <col style={{ width: '16%' }} />
                      <col style={{ width: '24%' }} />
                      <col style={{ width: '12%' }} />
                    </colgroup>
                    <thead><tr>
                      <SortTh col="date"        sortKey={expSortKey} sortDir={expSortDir} onSort={expToggle} style={TH}>Date</SortTh>
                      <SortTh col="description" sortKey={expSortKey} sortDir={expSortDir} onSort={expToggle} style={TH}>Description</SortTh>
                      <SortTh col="category"    sortKey={expSortKey} sortDir={expSortDir} onSort={expToggle} style={TH}>Category</SortTh>
                      <SortTh col="notes"       sortKey={expSortKey} sortDir={expSortDir} onSort={expToggle} style={TH}>Notes</SortTh>
                      <SortTh col="amount"      sortKey={expSortKey} sortDir={expSortDir} onSort={expToggle} style={{ ...TH, textAlign: 'right' }}>Amount</SortTh>
                    </tr></thead>
                    <tbody>{sortedExpenses.map(exp => (
                      <tr key={exp.id}>
                        <td style={{ ...TD, fontSize: 12 }}>{fmtDate(exp.date)}</td>
                        <td style={{ ...TD }}>
                          <button type="button" className="dashboard-inline-link" onClick={() => setViewingExpense(exp)} style={{ fontSize: 13, fontWeight: 400 }}>
                            {exp.description || '—'}
                          </button>
                        </td>
                        <td style={{ ...TD, fontSize: 12 }}>{exp.category || '—'}</td>
                        <td style={{ ...TD, fontSize: 12 }}>{exp.notes || '—'}</td>
                        <td style={{ ...TD, textAlign: 'right', color: '#ef4444' }}>{fmtAmt(exp.amount)}</td>
                      </tr>
                    ))}</tbody>
                  </table>
                </div>
              )}
            </div>
            {/* Right: category breakdown */}
            <div style={{ ...CARD, display: 'flex', flexDirection: 'column', minHeight: 0 }}>
              <div style={{ fontSize: 11, fontWeight: 500, color: 'var(--text-secondary)', letterSpacing: 0.8, textTransform: 'uppercase', marginBottom: 5, flexShrink: 0 }}>Category</div>
              <div style={{ fontSize: 30, fontWeight: 400, letterSpacing: -0.5, lineHeight: 1.1, color: '#ef4444', fontVariantNumeric: 'tabular-nums', marginBottom: 14, flexShrink: 0 }}>{fmtAmt(grandTotal)}</div>
              {categoryTotals.length === 0 ? <div className="card-empty-center">No expenses</div> : (
                <div className="scrollbar-thin-theme table-scroll-hidden" style={{ flex: 1, minHeight: 0, overflowY: 'auto' }}>
                  <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
                    {categoryTotals.map(({ cat, total }) => {
                      const pct = grandTotal > 0 ? (total / grandTotal) * 100 : 0;
                      return (
                        <div key={cat}>
                          <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 5 }}>
                            <span style={{ fontSize: 12, color: 'var(--text-primary)' }}>{cat}</span>
                            <span style={{ fontSize: 12, color: '#ef4444', fontVariantNumeric: 'tabular-nums' }}>{fmtAmt(total)}</span>
                          </div>
                          <div style={{ height: 4, borderRadius: 2, background: 'var(--border)', overflow: 'hidden' }}>
                            <div style={{ height: '100%', width: `${pct}%`, background: '#ef4444', borderRadius: 2, opacity: 0.7, transition: 'width 400ms ease' }} />
                          </div>
                        </div>
                      );
                    })}
                  </div>
                </div>
              )}
            </div>
            </div>
          </div>
        );
      })()}

      {financeTab === 'subcontractors' && (() => {
        const CARD = { background: 'var(--card-bg)', border: '1px solid var(--border)', borderRadius: 8, padding: '18px 21px', backdropFilter: 'blur(12px)', WebkitBackdropFilter: 'blur(12px)' };
        const TH = { fontSize: 10, fontWeight: 500, color: 'var(--text-muted)', textTransform: 'uppercase', letterSpacing: 0.6, padding: '0 0 12px 0', border: 'none', background: 'transparent', textAlign: 'left' };
        const TD = { fontSize: 13, color: 'var(--text-primary)', padding: '5px 0', border: 'none', background: 'transparent', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' };
        const fmtDate = d => d ? new Date(d).toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' }) : '—';
        const fmtAmt = v => `$${Number(v).toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`;
        const subInvoiceStatusColor = { draft: 'not_started', submitted: 'in_progress', paid: 'client_approved' };
        const invTotal = inv => (inv.items || []).reduce((s, i) => s + Number(i.unit_price || 0) * Number(i.quantity || 1), 0);

        const yearFiltered = subInvoices;

        const sortedInvoices = subSort(yearFiltered, (inv, key) => {
          if (key === 'total') return invTotal(inv);
          if (key === 'subcontractor') return inv.profile?.name || '';
          if (key === 'submitted_at') return inv.submitted_at ? new Date(inv.submitted_at).getTime() : 0;
          if (key === 'paid_at') return inv.paid_at ? new Date(inv.paid_at).getTime() : 0;
          return inv[key] || '';
        });

        const bySubcontractor = Object.values(yearFiltered.reduce((acc, inv) => {
          const key = inv.profile?.id || 'unknown';
          if (!acc[key]) acc[key] = { name: inv.profile?.name || 'Unknown', invoices: [] };
          acc[key].invoices.push(inv);
          return acc;
        }, {})).map(g => ({
          ...g,
          total: g.invoices.reduce((s, i) => s + invTotal(i), 0),
          paid: g.invoices.filter(i => i.status === 'paid').reduce((s, i) => s + invTotal(i), 0),
          pending: g.invoices.filter(i => i.status === 'submitted').reduce((s, i) => s + invTotal(i), 0),
        })).sort((a, b) => b.total - a.total);

        const grandTotal = bySubcontractor.reduce((s, g) => s + g.total, 0);

        return (
          <div style={{ display: 'flex', flexDirection: 'column', gap: 0, flex: 1, minHeight: 0 }}>
            <div style={{ display: 'grid', gridTemplateColumns: '7fr 3fr', gap: 24, flex: 1, minHeight: 0 }}>
              {/* Left: invoice list */}
              <div style={{ ...CARD, display: 'flex', flexDirection: 'column', minHeight: 0 }}>
                {subInvoicesLoading ? (
                  <div style={{ fontSize: 13, color: 'var(--text-muted)' }}>Loading…</div>
                ) : subInvoicesError ? (
                  <div style={{ fontSize: 13, color: 'var(--danger)' }}>{subInvoicesError}</div>
                ) : yearFiltered.length === 0 ? (
                  <div className="card-empty-center">No invoices</div>
                ) : (
                  <div className="scrollbar-thin-theme table-scroll-hidden" style={{ flex: 1, minHeight: 0, overflowY: 'auto' }}>
                    <table className="table-sticky-head" style={{ width: '100%', borderCollapse: 'collapse', tableLayout: 'fixed' }}>
                      <colgroup>
                        <col style={{ width: '14%' }} />
                        <col style={{ width: '26%' }} />
                        <col style={{ width: '16%' }} />
                        <col style={{ width: '16%' }} />
                        <col style={{ width: '14%' }} />
                        <col style={{ width: '14%' }} />
                      </colgroup>
                      <thead><tr>
                        <SortTh col="invoice_number" sortKey={subSortKey} sortDir={subSortDir} onSort={subToggle} style={TH}>Invoice #</SortTh>
                        <SortTh col="subcontractor"  sortKey={subSortKey} sortDir={subSortDir} onSort={subToggle} style={TH}>Subcontractor</SortTh>
                        <SortTh col="submitted_at"   sortKey={subSortKey} sortDir={subSortDir} onSort={subToggle} style={TH}>Submitted</SortTh>
                        <SortTh col="paid_at"        sortKey={subSortKey} sortDir={subSortDir} onSort={subToggle} style={TH}>Paid</SortTh>
                        <SortTh col="status"         sortKey={subSortKey} sortDir={subSortDir} onSort={subToggle} style={TH}>Status</SortTh>
                        <SortTh col="total"          sortKey={subSortKey} sortDir={subSortDir} onSort={subToggle} style={{ ...TH, textAlign: 'right' }}>Amount</SortTh>
                      </tr></thead>
                      <tbody>{sortedInvoices.map(inv => {
                        const total = invTotal(inv);
                        return (
                          <tr key={inv.id}>
                            <td style={{ ...TD }}>
                              <button type="button" className="table-link" onClick={() => setViewingSubInvoice(inv)}>
                                {inv.invoice_number || '—'}
                              </button>
                            </td>
                            <td style={{ ...TD }}>{inv.profile?.name || '—'}</td>
                            <td style={{ ...TD, fontSize: 12, color: 'var(--text-muted)' }}>{fmtDate(inv.submitted_at)}</td>
                            <td style={{ ...TD, fontSize: 12, color: 'var(--text-muted)' }}>{fmtDate(inv.paid_at)}</td>
                            <td style={{ ...TD }}>
                              <StatusBadge
                                status={subInvoiceStatusColor[inv.status] || 'not_started'}
                                label={inv.status ? inv.status.charAt(0).toUpperCase() + inv.status.slice(1) : '—'}
                              />
                            </td>
                            <td style={{ ...TD, textAlign: 'right', color: inv.status === 'paid' ? '#4ade80' : inv.status === 'submitted' ? '#F5A523' : 'var(--text-primary)' }}>
                              {fmtAmt(total)}
                            </td>
                          </tr>
                        );
                      })}</tbody>
                    </table>
                  </div>
                )}
              </div>
              {/* Right: by subcontractor */}
              <div style={{ ...CARD, display: 'flex', flexDirection: 'column', minHeight: 0 }}>
                <div style={{ fontSize: 11, fontWeight: 500, color: 'var(--text-secondary)', letterSpacing: 0.8, textTransform: 'uppercase', marginBottom: 5, flexShrink: 0 }}>Subcontractors</div>
                <div style={{ fontSize: 30, fontWeight: 400, letterSpacing: -0.5, lineHeight: 1.1, color: '#F5A523', fontVariantNumeric: 'tabular-nums', marginBottom: 14, flexShrink: 0 }}>{fmtAmt(grandTotal)}</div>
                {bySubcontractor.length === 0 ? <div className="card-empty-center">No data</div> : (
                  <div className="scrollbar-thin-theme table-scroll-hidden" style={{ flex: 1, minHeight: 0, overflowY: 'auto' }}>
                    <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
                      {bySubcontractor.map(g => {
                        const pct = grandTotal > 0 ? (g.total / grandTotal) * 100 : 0;
                        return (
                          <div key={g.name}>
                            <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 5 }}>
                              <span style={{ fontSize: 12, color: 'var(--text-primary)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', maxWidth: '65%' }}>{g.name}</span>
                              <span style={{ fontSize: 12, color: '#F5A523', fontVariantNumeric: 'tabular-nums', flexShrink: 0 }}>{fmtAmt(g.total)}</span>
                            </div>
                            <div style={{ height: 4, borderRadius: 2, background: 'var(--border)', overflow: 'hidden' }}>
                              <div style={{ height: '100%', width: `${pct}%`, background: '#F5A523', borderRadius: 2, opacity: 0.7, transition: 'width 400ms ease' }} />
                            </div>
                            <div style={{ fontSize: 11, color: 'var(--text-muted)', marginTop: 3 }}><span style={{ color: g.pending > 0 ? '#F5A523' : 'var(--text-muted)' }}>{fmtAmt(g.pending)} pending</span> · {fmtAmt(g.paid)} paid</div>
                          </div>
                        );
                      })}
                    </div>
                  </div>
                )}
              </div>
            </div>
          </div>
        );
      })()}

      {financeTab === 'invoices' && (() => {
        const CARD = { background: 'var(--card-bg)', border: '1px solid var(--border)', borderRadius: 8, padding: '18px 21px', backdropFilter: 'blur(12px)', WebkitBackdropFilter: 'blur(12px)' };
        const TH = { fontSize: 10, fontWeight: 500, color: 'var(--text-muted)', textTransform: 'uppercase', letterSpacing: 0.6, padding: '0 0 12px 0', border: 'none', background: 'transparent', textAlign: 'left' };
        const TD = { fontSize: 13, color: 'var(--text-primary)', padding: '5px 0', border: 'none', background: 'transparent', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' };
        const fmtDate = d => d ? new Date(d).toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' }) : '—';
        const fmtAmt = v => `$${Number(v).toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`;
        const statusColor = { draft: 'not_started', sent: 'in_progress', paid: 'client_approved' };

        const filteredInvoices = invoices.filter(i => {
          if (invYearFilter !== 'all' && i.invoice_date?.slice(0,4) !== invYearFilter) return false;
          if (invCompanyFilter !== 'all' && (i.company?.name || i.bill_to) !== invCompanyFilter) return false;
          return true;
        });

        const sorted = invSort(filteredInvoices, (inv, key) => {
          if (key === 'total' || key === 'stripe_fee') return Number(inv[key]) || 0;
          if (key === 'invoice_date' || key === 'due_date') return new Date(inv[key]).getTime();
          if (key === 'company') return inv.company?.name || '';
          return inv[key] || '';
        });

        const byCompany = Object.values(filteredInvoices.reduce((acc, inv) => {
          const name = inv.company?.name || inv.bill_to || 'Unknown';
          if (!acc[name]) acc[name] = { name, total: 0, paid: 0, outstanding: 0, fees: 0 };
          acc[name].total += Number(inv.total) || 0;
          if (inv.status === 'paid') {
            acc[name].paid += Number(inv.total) || 0;
            acc[name].fees += Number(inv.stripe_fee) || 0;
          } else if (inv.status === 'sent') acc[name].outstanding += Number(inv.total) || 0;
          return acc;
        }, {})).sort((a, b) => b.total - a.total);

        const grandTotal = byCompany.reduce((s, g) => s + g.total, 0);

        return (
          <div style={{ display: 'flex', flexDirection: 'column', gap: 0, flex: 1, minHeight: 0 }}>
            <div style={{ display: 'grid', gridTemplateColumns: '7fr 3fr', gap: 24, flex: 1, minHeight: 0 }}>
              <div style={{ ...CARD, display: 'flex', flexDirection: 'column', minHeight: 0 }}>
                {loading ? (
                  <div style={{ fontSize: 13, color: 'var(--text-muted)' }}>Loading…</div>
                ) : invoices.length === 0 ? (
                  <div className="card-empty-center">No invoices</div>
                ) : (
                  <div className="scrollbar-thin-theme table-scroll-hidden" style={{ flex: 1, minHeight: 0, overflowY: 'auto' }}>
                    <table className="table-sticky-head" style={{ width: '100%', borderCollapse: 'collapse', tableLayout: 'fixed' }}>
                      <colgroup>
                        <col style={{ width: '18%' }} />
                        <col style={{ width: '24%' }} />
                        <col style={{ width: '13%' }} />
                        <col style={{ width: '13%' }} />
                        <col style={{ width: '12%' }} />
                        <col style={{ width: '10%' }} />
                        <col style={{ width: '10%' }} />
                      </colgroup>
                      <thead><tr>
                        <SortTh col="invoice_number" sortKey={invSortKey} sortDir={invSortDir} onSort={invToggle} style={TH}>Invoice #</SortTh>
                        <SortTh col="company"        sortKey={invSortKey} sortDir={invSortDir} onSort={invToggle} style={TH}>Company</SortTh>
                        <SortTh col="invoice_date"   sortKey={invSortKey} sortDir={invSortDir} onSort={invToggle} style={TH}>Date</SortTh>
                        <SortTh col="due_date"       sortKey={invSortKey} sortDir={invSortDir} onSort={invToggle} style={TH}>Due</SortTh>
                        <SortTh col="status"         sortKey={invSortKey} sortDir={invSortDir} onSort={invToggle} style={{ ...TH, textAlign: 'center' }}>Status</SortTh>
                        <SortTh col="stripe_fee"     sortKey={invSortKey} sortDir={invSortDir} onSort={invToggle} style={{ ...TH, textAlign: 'right' }}>Fees</SortTh>
                        <SortTh col="total"          sortKey={invSortKey} sortDir={invSortDir} onSort={invToggle} style={{ ...TH, textAlign: 'right' }}>Total</SortTh>
                      </tr></thead>
                      <tbody>{sorted.map(inv => (
                        <tr key={inv.id}>
                          <td style={{ ...TD }}>
                            <button type="button" className="dashboard-inline-link" onClick={() => setViewingInvoice(inv)}>{inv.invoice_number}</button>
                          </td>
                          <td style={{ ...TD }}>
                            <button type="button" className="dashboard-inline-link" onClick={() => inv.company?.id && navigate(`/company/${inv.company.id}`)}>{inv.company?.name || inv.bill_to || '—'}</button>
                          </td>
                          <td style={{ ...TD, fontSize: 12 }}>{fmtDate(inv.invoice_date)}</td>
                          <td style={{ ...TD, fontSize: 12, color: inv.status !== 'paid' && new Date(inv.due_date) < new Date() ? 'var(--danger)' : 'var(--text-primary)' }}>{fmtDate(inv.due_date)}</td>
                          <td style={{ ...TD, textAlign: 'center' }}>
                            <StatusBadge status={statusColor[inv.status] || 'not_started'} label={invoiceStatusBadgeLabel(inv.status)} />
                          </td>
                          <td style={{ ...TD, textAlign: 'right', fontSize: 12, color: Number(inv.stripe_fee) > 0 ? '#ef4444' : 'var(--text-muted)' }}>
                            {Number(inv.stripe_fee) > 0 ? `-${fmtAmt(inv.stripe_fee)}` : '$0.00'}
                          </td>
                          <td style={{ ...TD, textAlign: 'right', color: inv.status === 'paid' ? '#4ade80' : inv.status === 'sent' ? '#F5A523' : 'var(--text-primary)' }}>
                            {fmtAmt(inv.total)}
                          </td>
                        </tr>
                      ))}</tbody>
                    </table>
                  </div>
                )}
              </div>
              <div style={{ ...CARD, display: 'flex', flexDirection: 'column', minHeight: 0 }}>
                <div style={{ fontSize: 11, fontWeight: 500, color: 'var(--text-secondary)', letterSpacing: 0.8, textTransform: 'uppercase', marginBottom: 5, flexShrink: 0 }}>Companies</div>
                <div style={{ fontSize: 30, fontWeight: 400, letterSpacing: -0.5, lineHeight: 1.1, color: '#4ade80', fontVariantNumeric: 'tabular-nums', marginBottom: 14, flexShrink: 0 }}>{fmtAmt(grandTotal)}</div>
                {byCompany.length === 0 ? <div className="card-empty-center">No data</div> : (
                  <div className="scrollbar-thin-theme table-scroll-hidden" style={{ flex: 1, minHeight: 0, overflowY: 'auto' }}>
                    <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
                      {byCompany.map(g => {
                        const pct = grandTotal > 0 ? (g.total / grandTotal) * 100 : 0;
                        return (
                          <div key={g.name}>
                            <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 5 }}>
                              <span style={{ fontSize: 12, color: 'var(--text-primary)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', maxWidth: '65%' }}>{g.name}</span>
                              <span style={{ fontSize: 12, color: '#4ade80', fontVariantNumeric: 'tabular-nums', flexShrink: 0 }}>{fmtAmt(g.total)}</span>
                            </div>
                            <div style={{ height: 4, borderRadius: 2, background: 'var(--border)', overflow: 'hidden' }}>
                              <div style={{ height: '100%', width: `${pct}%`, background: '#4ade80', borderRadius: 2, opacity: 0.7, transition: 'width 400ms ease' }} />
                            </div>
                            <div style={{ fontSize: 11, color: 'var(--text-muted)', marginTop: 3 }}>
                              <span style={{ color: g.outstanding > 0 ? '#F5A523' : 'var(--text-muted)' }}>{fmtAmt(g.outstanding)} outstanding</span>
                              {' · '}{fmtAmt(g.paid)} paid
                              {g.fees > 0 && <span style={{ color: '#ef4444' }}> · -{fmtAmt(g.fees)} fees</span>}
                            </div>
                          </div>
                        );
                      })}
                    </div>
                  </div>
                )}
              </div>
            </div>
          </div>
        );
      })()}

      {financeTab === 'legacy' && <div>
      <div style={{ display: 'flex', alignItems: 'center', gap: 4, marginBottom: 10, minHeight: 'var(--btn-height)' }}>
        {[
          { id: 'invoices', label: 'INVOICES' },
          { id: 'expenses', label: 'EXPENSES' },
          { id: 'sub-invoices', label: 'SUBCONTRACTOR INVOICES' },
        ].map((t, i, arr) => (
          <button
            key={t.id}
            type="button"
            onClick={() => setActiveTab(t.id)}
            className={`section-tab-btn${activeTab === t.id ? ' is-active' : ''}`}
          >{t.label}</button>
        ))}
      </div>

      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 12, marginBottom: 10, minHeight: 'var(--btn-height)', flexWrap: 'wrap' }}>
        <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap' }}>
          {companyNames.length > 0 && activeTab === 'invoices' && (
            <select className="filter-select" style={{ width: 120 }} value={filterCompany} onChange={e => setFilterCompany(e.target.value)}>
              <option value="">All Companies</option>
              {companyNames.map(name => <option key={name} value={name}>{name}</option>)}
            </select>
          )}
        </div>
        {activeTab === 'invoices' && (
          <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
            <select className="filter-select" style={{ width: 120 }} value={filter} onChange={e => setFilter(e.target.value)}>
              <option value="all">All</option>
              <option value="draft">Draft</option>
              <option value="sent">Sent</option>
              <option value="paid">Paid</option>
            </select>
            <button className="btn btn-primary btn-sm" onClick={() => setShowInvoiceForm(true)}>+ New Invoice</button>
          </div>
        )}
        {activeTab === 'expenses' && (
          <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
            <select className="filter-select" style={{ width: 120 }} value={expenseFilter} onChange={e => setExpenseFilter(e.target.value)}>
              <option value="all">All</option>
              {CATEGORIES.filter(c => expenses.some(ex => ex.category === c)).map(c => (
                <option key={c} value={c}>{c}</option>
              ))}
            </select>
            <button className="btn btn-primary btn-sm" onClick={() => { setEditingExpenseId(''); setNewExpense(blankExpense()); setExpensesError(''); setShowExpenseForm(true); }}>+ Add Expense</button>
          </div>
        )}
      </div>

      {activeTab === 'invoices' && (
      <div>

        {/* ── Invoices ── */}
        <div>
          {loading ? (
            <p style={{ color: 'var(--text-muted)' }}>Loading...</p>
          ) : filtered.length === 0 ? (
            <div className="card card-empty-center">No invoices</div>
          ) : (
            <div className="table-wrapper">
              <table className="table-sticky-head">
                <thead>
                  <tr>
                    <SortTh col="invoice_number" sortKey={invSortKey} sortDir={invSortDir} onSort={invToggle}>Invoice #</SortTh>
                    <SortTh col="bill_to" sortKey={invSortKey} sortDir={invSortDir} onSort={invToggle}>Bill To</SortTh>
                    <SortTh col="invoice_date" sortKey={invSortKey} sortDir={invSortDir} onSort={invToggle}>Date</SortTh>
                    <SortTh col="due_date" sortKey={invSortKey} sortDir={invSortDir} onSort={invToggle}>Due</SortTh>
                    <SortTh col="status" sortKey={invSortKey} sortDir={invSortDir} onSort={invToggle}>Status</SortTh>
                    <SortTh col="total" sortKey={invSortKey} sortDir={invSortDir} onSort={invToggle}>Total</SortTh>
                  </tr>
                </thead>
                <tbody>
                  {invSort(filtered, (inv, key) => {
                    if (key === 'total') return Number(inv.total) || 0;
                    if (key === 'invoice_date' || key === 'due_date') return new Date(inv[key]).getTime();
                    return inv[key] || inv.company?.name || '';
                  }).map(inv => (
                    <tr key={inv.id} onClick={() => setViewingInvoice(inv)} style={{ cursor: 'pointer' }}>
                      <td style={{ fontWeight: 400 }}>{inv.invoice_number}</td>
                      <td style={{ fontWeight: 400 }}>{inv.bill_to || inv.company?.name}</td>
                      <td style={{ color: 'var(--text-muted)' }}>{new Date(inv.invoice_date).toLocaleDateString()}</td>
                      <td>
                        <span style={{ color: inv.status !== 'paid' && new Date(inv.due_date) < new Date() ? 'var(--danger)' : 'var(--text-muted)' }}>
                          {new Date(inv.due_date).toLocaleDateString()}
                        </span>
                      </td>
                      <td style={{ textAlign: 'center' }}>
                        <StatusBadge
                          status={statusColor[inv.status] || 'not_started'}
                          label={invoiceStatusBadgeLabel(inv.status)}
                        />
                      </td>
                      <td style={{ fontWeight: 400, color: 'var(--accent)' }}>${Number(inv.total).toFixed(2)}</td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>
          )}
        </div>
      </div>
      )}

      {activeTab === 'expenses' && (
      <div style={{ display: 'flex', flexDirection: 'column', gap: 24 }}>
        <div>
            <div style={{ marginBottom: 10 }}>

            {expensesLoading ? (
              <p style={{ color: 'var(--text-muted)', fontSize: 13 }}>Loading...</p>
            ) : expensesError ? (
              <p style={{ color: 'var(--danger)', fontSize: 13 }}>{expensesError}</p>
            ) : filteredExpenses.length === 0 ? (
              <div className="card card-empty-center">No expenses</div>
            ) : (
              <div className="table-wrapper">
                <table className="table-sticky-head">
                  <thead>
                    <tr>
                      <SortTh col="date" sortKey={expSortKey} sortDir={expSortDir} onSort={expToggle}>Date</SortTh>
                      <SortTh col="description" sortKey={expSortKey} sortDir={expSortDir} onSort={expToggle}>Description</SortTh>
                      <SortTh col="category" sortKey={expSortKey} sortDir={expSortDir} onSort={expToggle}>Category</SortTh>
                      <SortTh col="notes" sortKey={expSortKey} sortDir={expSortDir} onSort={expToggle}>Notes</SortTh>
                      <SortTh col="amount" sortKey={expSortKey} sortDir={expSortDir} onSort={expToggle} style={{ textAlign: 'right' }}>Amount</SortTh>
                      <th style={{ width: 140, textAlign: 'right' }}>Action</th>
                    </tr>
                  </thead>
                  <tbody>
                    {expSort(filteredExpenses, (exp, key) => {
                      if (key === 'amount') return Number(exp.amount) || 0;
                      if (key === 'date') return exp.date || '';
                      return exp[key] || '';
                    }).map(exp => (
                      <tr key={exp.id} style={{ cursor: 'pointer' }} onClick={() => setViewingExpense(exp)}>
                        <td>{new Date(exp.date + 'T12:00:00').toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' })}</td>
                        <td style={{ fontWeight: 400 }}>{exp.description}</td>
                        <td>{exp.category}</td>
                        <td style={{ color: 'var(--text-muted)' }}>
                          {exp.notes || exp.receipt_path ? (
                            <div style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>
                              <span>{exp.notes || '—'}</span>
                              {exp.receipt_path && (
                                <button
                                  className="btn btn-outline btn-sm"
                                  style={{ width: 'fit-content' }}
                                  onClick={e => { e.stopPropagation(); handleViewReceipt(exp); }}
                                >
                                  View Receipt
                                </button>
                              )}
                            </div>
                          ) : '—'}
                        </td>
                        <td style={{ textAlign: 'right', fontWeight: 400 }}>${Number(exp.amount).toFixed(2)}</td>
                        <td style={{ textAlign: 'right' }}>
                          <button
                            className="btn-icon btn-icon-danger"
                            title="Delete"
                            onClick={e => { e.stopPropagation(); handleDeleteExpense(exp.id); }}
                          >
                            ✕
                          </button>
                        </td>
                      </tr>
                    ))}
                  </tbody>
                </table>
              </div>
            )}
          </div>

        </div>

      </div>
      )}

      {activeTab === 'sub-invoices' && (
      <div>
        <div style={{ marginBottom: 10 }}>
          {subInvoicesLoading ? (
            <p style={{ color: 'var(--text-muted)', fontSize: 13 }}>Loading...</p>
          ) : subInvoicesError ? (
            <p style={{ color: 'var(--danger)', fontSize: 13 }}>{subInvoicesError}</p>
          ) : subInvoices.length === 0 ? (
            <div className="card card-empty-center">No sub invoices</div>
          ) : (
            <div className="table-wrapper">
              <table className="table-sticky-head">
                <thead>
                  <tr>
                    <SortTh col="invoice_number" sortKey={subSortKey} sortDir={subSortDir} onSort={subToggle}>Invoice #</SortTh>
                    <SortTh col="subcontractor" sortKey={subSortKey} sortDir={subSortDir} onSort={subToggle}>Subcontractor</SortTh>
                    <SortTh col="submitted_at" sortKey={subSortKey} sortDir={subSortDir} onSort={subToggle}>Submitted</SortTh>
                    <SortTh col="status" sortKey={subSortKey} sortDir={subSortDir} onSort={subToggle}>Status</SortTh>
                    <SortTh col="total" sortKey={subSortKey} sortDir={subSortDir} onSort={subToggle} style={{ textAlign: 'right' }}>Total</SortTh>
                    <th style={{ textAlign: 'right' }}>Actions</th>
                  </tr>
                </thead>
                <tbody>
                  {subSort(subInvoices, (inv, key) => {
                    if (key === 'total') return (inv.items || []).reduce((s, i) => s + Number(i.unit_price || 0) * Number(i.quantity || 1), 0);
                    if (key === 'subcontractor') return inv.profile?.name || '';
                    if (key === 'submitted_at') return inv.submitted_at ? new Date(inv.submitted_at).getTime() : 0;
                    return inv[key] || '';
                  }).map(inv => {
                    const total = (inv.items || []).reduce((s, i) => s + Number(i.unit_price || 0) * Number(i.quantity || 1), 0);
                    const subInvoiceStatusColor = { draft: 'not_started', submitted: 'in_progress', paid: 'client_approved' };
                    return (
                      <tr key={inv.id} style={{ cursor: 'pointer' }} onClick={() => setViewingSubInvoice(inv)}>
                        <td style={{ fontWeight: 400 }}>{inv.invoice_number}</td>
                        <td>
                          <div style={{ fontWeight: 400 }}>{inv.profile?.name || 'External'}</div>
                          <div style={{ color: 'var(--text-muted)', fontSize: 12 }}>{inv.profile?.email || '—'}</div>
                        </td>
                        <td style={{ color: 'var(--text-muted)' }}>{inv.submitted_at ? new Date(inv.submitted_at).toLocaleDateString() : '—'}</td>
                        <td>
                          <StatusBadge
                            status={subInvoiceStatusColor[inv.status] || 'not_started'}
                            label={inv.status ? inv.status.charAt(0).toUpperCase() + inv.status.slice(1) : '—'}
                          />
                        </td>
                        <td style={{ textAlign: 'right', fontWeight: 400, color: 'var(--accent)' }}>${total.toFixed(2)}</td>
                        <td />
                      </tr>
                    );
                  })}
                </tbody>
              </table>
            </div>
          )}
        </div>
      </div>
      )}
      </div>}{/* end legacy wrapper */}

      {viewingSubInvoice && (() => {
        const invoice = viewingSubInvoice;
        const baseItems = [...(invoice.items || [])].sort((a, b) => (a.sort_order ?? 0) - (b.sort_order ?? 0));
        const total = baseItems.reduce((s, item) => s + Number(item.unit_price || 0) * Number(item.quantity || 1), 0);
        const invoiceStatus = invoice.status ? invoice.status.charAt(0).toUpperCase() + invoice.status.slice(1) : '—';
        const subInvoiceStatusColor = { draft: 'not_started', submitted: 'in_progress', paid: 'client_approved' };
        const tableItems = subPopupSort(baseItems.map(item => ({
          ...item,
          _inferredType: { label: subInvoiceItemWorkLabel(item), badgeClass: subInvoiceItemWorkLabel(item) === 'New' ? 'badge-initial' : 'badge-client_revision' },
          description: cleanSubInvoiceItemDescription(item),
        })), (item, key) => {
          if (key === 'type') return item._inferredType?.label || '';
          if (key === 'description') return item.description || '';
          if (key === 'quantity') return Number(item.quantity || 0);
          if (key === 'unit_price') return Number(item.unit_price || 0);
          if (key === 'line_total') return Number(item.unit_price || 0) * Number(item.quantity || 1);
          return '';
        });
        const F = POPUP_FIELD_LABEL;
        return (
          <InvoiceDetailPopup
            title={invoice.invoice_number || 'Subcontractor Invoice'}
            subtitle={`${invoice.profile?.name || 'External'}${invoice.profile?.email ? ` · ${invoice.profile.email}` : ''}`}
            headerRight={<StatusBadge status={subInvoiceStatusColor[invoice.status] || 'not_started'} label={invoiceStatus} />}
            onClose={() => { if (!markingPaid) setViewingSubInvoice(null); }}
            blockClose={Boolean(markingPaid)}
            metaContent={<>
              <div><div style={F}>Submitted</div><div style={{ fontSize: 13, color: 'var(--text-primary)' }}>{invoice.submitted_at ? new Date(invoice.submitted_at).toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' }) : '—'}</div></div>
              <div><div style={F}>Paid</div><div style={{ fontSize: 13, color: 'var(--text-primary)' }}>{invoice.paid_at ? new Date(invoice.paid_at).toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' }) : '—'}</div></div>
              <div><div style={F}>Line Items</div><div style={{ fontSize: 13, color: 'var(--text-primary)' }}>{baseItems.length}</div></div>
              <div><div style={F}>Total</div><div style={{ fontSize: 18, fontWeight: 500, color: 'var(--accent)', lineHeight: 1.1 }}>${total.toFixed(2)}</div></div>
            </>}
            footerActions={<>
              <button type="button" className="btn btn-outline" onClick={() => handleDownloadSubInvoice(invoice)}>Download Invoice</button>
              {invoice.status === 'submitted' && (
                <LoadingButton className="btn btn-outline" onClick={async () => {
                  await handleMarkSubInvoicePaid(invoice);
                  setViewingSubInvoice(current => current?.id === invoice.id ? { ...current, status: 'paid', paid_at: new Date().toISOString() } : current);
                }} loading={markingPaid === invoice.id} loadingText="Processing…">Mark as Paid</LoadingButton>
              )}
              {invoice.status === 'paid' && (
                <button type="button" className="btn btn-outline" onClick={() => handleDownloadSubInvoiceReceipt(invoice)}>Download Receipt</button>
              )}
              <button type="button" className="btn btn-outline" onClick={() => setViewingSubInvoice(null)}>Close</button>
            </>}
          >
            <InvoicePopupTable sortKey={subPopupKey} sortDir={subPopupDir} onSort={subPopupToggle} items={tableItems} notes={invoice.notes} />
          </InvoiceDetailPopup>
        );
      })()}

      {viewingInvoice && (
        <TeamInvoiceDetailPanel
          invoiceId={viewingInvoice.id}
          initialInvoice={viewingInvoice}
          embedded
          onClose={() => setViewingInvoice(null)}
          onInvoiceUpdated={(updatedInvoice) => {
            setViewingInvoice(updatedInvoice);
            setInvoices((current) => current.map((invoice) => (invoice.id === updatedInvoice.id ? { ...invoice, ...updatedInvoice } : invoice)));
          }}
          onInvoiceDeleted={(deletedId) => {
            setInvoices((current) => current.filter((invoice) => invoice.id !== deletedId));
            setViewingInvoice((current) => (current?.id === deletedId ? null : current));
          }}
        />
      )}

      {viewingExpense && (() => {
        const LABEL = { ...FIELD_LABEL_STYLE, marginBottom: 3 };
        const INPUT = FINANCE_MODAL_INPUT_STYLE;
        const isPdf = viewingExpense.receipt_name?.toLowerCase().endsWith('.pdf');
        const isDirty = expenseDetailEditing && (
          newExpense.amount !== String(viewingExpense.amount ?? '') ||
          newExpense.description !== (viewingExpense.description || '') ||
          newExpense.date !== (viewingExpense.date || '') ||
          newExpense.category !== (viewingExpense.category || 'Other') ||
          newExpense.notes !== (viewingExpense.notes || '') ||
          newExpense.receipt != null ||
          newExpense.removeReceipt === true
        );
        return (
          <div style={popupOverlayStyle} onClick={() => { setViewingExpense(null); setExpenseDetailEditing(false); }}>
            <div style={{ ...popupSurfaceStyle, background: 'var(--card-bg)', width: '80vw', height: '80vh', display: 'flex', flexDirection: 'column', gap: 0 }} onClick={e => e.stopPropagation()}>
              {/* Main content row */}
              <div style={{ display: 'flex', gap: 24, alignItems: 'stretch', flex: 1, minHeight: 0 }}>
                {/* Left: details (editable in-place) */}
                <div style={{ display: 'flex', flexDirection: 'column', gap: 14, flex: '0 0 260px', overflowY: 'auto' }}>
                  <div style={LABEL}>Expense Detail</div>
                  {expenseDetailEditing ? (
                    <CurrencyInput
                      value={newExpense.amount}
                      required
                      onChange={e => setNewExpense(p => ({ ...p, amount: e.target.value }))}
                    />
                  ) : (
                    <div style={{ ...FINANCE_MODAL_TOTAL_VALUE_STYLE, color: 'var(--danger)' }}>
                      ${Number(viewingExpense.amount).toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
                    </div>
                  )}
                  <div>
                    <div style={LABEL}>Description</div>
                    {expenseDetailEditing
                      ? <input type="text" required style={INPUT} value={newExpense.description} onChange={e => setNewExpense(p => ({ ...p, description: e.target.value }))} />
                      : <div style={{ fontSize: 13 }}>{viewingExpense.description || '—'}</div>}
                  </div>
                  <div>
                    <div style={LABEL}>Date</div>
                    {expenseDetailEditing
                      ? <input type="date" required style={INPUT} value={newExpense.date} onChange={e => setNewExpense(p => ({ ...p, date: e.target.value }))} />
                      : <div style={{ fontSize: 13 }}>{viewingExpense.date ? new Date(viewingExpense.date + 'T12:00:00').toLocaleDateString('en-US', { month: 'long', day: 'numeric', year: 'numeric' }) : '—'}</div>}
                  </div>
                  <div>
                    <div style={LABEL}>Category</div>
                    {expenseDetailEditing
                      ? <select style={INPUT} value={newExpense.category} onChange={e => setNewExpense(p => ({ ...p, category: e.target.value }))}>{CATEGORIES.map(c => <option key={c} value={c}>{c}</option>)}</select>
                      : <div style={{ fontSize: 13 }}>{viewingExpense.category || '—'}</div>}
                  </div>
                  <div>
                    <div style={LABEL}>Notes</div>
                    {expenseDetailEditing
                      ? <input type="text" style={INPUT} value={newExpense.notes} onChange={e => setNewExpense(p => ({ ...p, notes: e.target.value }))} />
                      : <div style={{ fontSize: 13 }}>{viewingExpense.notes || '—'}</div>}
                  </div>
                  {expenseDetailEditing && (
                    <div>
                      <div style={LABEL}>Receipt / Photo</div>
                      <input type="file" accept="image/*,.pdf" style={{ ...INPUT, padding: '4px 10px' }} onChange={e => setNewExpense(p => ({ ...p, receipt: e.target.files?.[0] || null, removeReceipt: false }))} />
                      {!newExpense.receipt && newExpense.receipt_path && (
                        <div style={{ marginTop: 6, display: 'flex', alignItems: 'center', gap: 8 }}>
                          <span style={{ fontSize: 12, color: 'var(--text-muted)' }}>{newExpense.receipt_name || 'Existing receipt'}</span>
                          <button type="button" className="btn btn-outline" style={{ fontSize: 11, color: 'var(--danger)' }} onClick={() => setNewExpense(p => ({ ...p, removeReceipt: true, receipt_path: null, receipt_name: null }))}>Remove</button>
                        </div>
                      )}
                    </div>
                  )}
                </div>
                {/* Right: receipt preview — fixed to left column height, item scales inside */}
                {viewingExpense.receipt_path && (
                  <div style={{ display: 'flex', flexDirection: 'column', gap: 8, flex: 1, minHeight: 0, alignSelf: 'stretch' }}>
                    <div style={LABEL}>Receipt</div>
                    {expensePreviewUrl ? (
                      isPdf
                        ? <embed src={`${expensePreviewUrl}#toolbar=0&navpanes=0&scrollbar=0`} type="application/pdf" style={{ flex: 1, width: '100%', minHeight: 0, border: '1px solid var(--border)', borderRadius: 6 }} />
                        : <img src={expensePreviewUrl} alt="Receipt" style={{ flex: 1, width: '100%', minHeight: 0, height: 0, objectFit: 'contain', objectPosition: 'top center', display: 'block', border: '1px solid var(--border)', borderRadius: 6, background: 'var(--card-bg-2)' }} />
                    ) : (
                      <div style={{ fontSize: 12, color: 'var(--text-muted)' }}>Loading preview…</div>
                    )}
                  </div>
                )}
              </div>
              {/* Footer: buttons bottom-right */}
              <div className="modal-action-row" style={{ paddingTop: 14, marginTop: 14, flexShrink: 0 }}>
                {expenseDetailEditing ? (
                  <>
                    <button className="btn btn-outline" disabled={!isDirty || addingExpense} onClick={async () => { await saveExpense(); setExpenseDetailEditing(false); setViewingExpense(null); }}>{addingExpense ? 'Saving…' : 'Save'}</button>
                    <button className="btn btn-outline" onClick={() => setExpenseDetailEditing(false)}>Cancel</button>
                  </>
                ) : (
                  <>
                    {expensePreviewUrl && (
                      <a href={expensePreviewUrl} download={viewingExpense.receipt_name || 'receipt'} className="btn btn-outline" style={{ display: 'inline-flex' }}>Download Receipt</a>
                    )}
                    <button type="button" className="btn btn-outline" onClick={() => { setEditingExpenseId(viewingExpense.id); setNewExpense({ date: viewingExpense.date, description: viewingExpense.description || '', category: viewingExpense.category || 'Other', amount: String(viewingExpense.amount ?? ''), notes: viewingExpense.notes || '', receipt: null, receipt_path: viewingExpense.receipt_path || null, receipt_name: viewingExpense.receipt_name || null }); setExpensesError(''); setExpenseDetailEditing(true); }}>Edit</button>
                    <button type="button" className="btn btn-outline" onClick={() => setViewingExpense(null)}>Cancel</button>
                  </>
                )}
              </div>
            </div>
          </div>
        );
      })()}

      {showExpenseForm && (() => {
        const LABEL = { ...FIELD_LABEL_STYLE, marginBottom: 3 };
        const INPUT = FINANCE_MODAL_INPUT_STYLE;
        return (
          <div style={popupOverlayStyle} onClick={cancelExpenseEdit}>
            <div style={{ ...popupSurfaceStyle, background: 'var(--card-bg)', width: '80vw', height: '80vh', display: 'flex', flexDirection: 'column', gap: 0 }} onClick={e => e.stopPropagation()}>
              <form onSubmit={handleAddExpense} style={{ display: 'flex', flexDirection: 'column', flex: 1, minHeight: 0, gap: 0 }}>
                {/* Main content row */}
                <div style={{ display: 'flex', gap: 24, alignItems: 'stretch', flex: 1, minHeight: 0 }}>
                  {/* Left: fields */}
                  <div style={{ display: 'flex', flexDirection: 'column', gap: 14, flex: '0 0 260px', overflowY: 'auto' }}>
                    <div style={LABEL}>New Expense</div>
                    <CurrencyInput
                      value={newExpense.amount}
                      required
                      onChange={e => setNewExpense(p => ({ ...p, amount: e.target.value }))}
                    />
                    <div>
                      <div style={LABEL}>Description</div>
                      <input type="text" required placeholder="What was this for?" style={INPUT} value={newExpense.description} onChange={e => setNewExpense(p => ({ ...p, description: e.target.value }))} />
                    </div>
                    <div>
                      <div style={LABEL}>Date</div>
                      <input type="date" required style={INPUT} value={newExpense.date} onChange={e => setNewExpense(p => ({ ...p, date: e.target.value }))} />
                    </div>
                    <div>
                      <div style={LABEL}>Category</div>
                      <select style={INPUT} value={newExpense.category} onChange={e => setNewExpense(p => ({ ...p, category: e.target.value }))}>{CATEGORIES.map(c => <option key={c} value={c}>{c}</option>)}</select>
                    </div>
                    <div>
                      <div style={LABEL}>Notes</div>
                      <input type="text" placeholder="Any extra details" style={INPUT} value={newExpense.notes} onChange={e => setNewExpense(p => ({ ...p, notes: e.target.value }))} />
                    </div>
                    {expensesError && <div style={{ fontSize: 12, color: 'var(--danger)' }}>{expensesError}</div>}
                  </div>
                  {/* Right: file attach area */}
                  <div style={{ display: 'flex', flexDirection: 'column', flex: 1, minHeight: 0 }}>
                    <FileAttachment
                      files={newExpense.receipt ? [newExpense.receipt] : []}
                      onChange={files => setNewExpense(p => ({ ...p, receipt: files.length > 0 ? files[files.length - 1] : null }))}
                    />
                  </div>
                </div>
                {/* Footer */}
                <div className="modal-action-row" style={{ paddingTop: 14, marginTop: 14, flexShrink: 0 }}>
                  <button type="submit" className="btn btn-outline" disabled={addingExpense}>{addingExpense ? 'Saving…' : 'Save'}</button>
                  <button type="button" className="btn btn-outline" onClick={cancelExpenseEdit}>Cancel</button>
                </div>
              </form>
            </div>
          </div>
        );
      })()}

      </div>{/* end flex column wrapper */}

      {showInvoiceForm && (() => {
        const LABEL = { ...FIELD_LABEL_STYLE, marginBottom: 3 };
        const INPUT = FINANCE_MODAL_INPUT_STYLE;
        return (
          <div style={popupOverlayStyle} onClick={() => { if (!invSaving) invClose(); }}>
            <div style={{ ...popupSurfaceStyle, background: 'var(--card-bg)', width: '80vw', height: '80vh', display: 'flex', flexDirection: 'column', gap: 0 }} onClick={e => e.stopPropagation()}>
              <div style={{ display: 'flex', gap: 24, alignItems: 'stretch', flex: 1, minHeight: 0 }}>

                {/* Left: meta fields */}
                <div style={{ display: 'flex', flexDirection: 'column', gap: 14, flex: '0 0 260px', overflowY: 'auto' }}>
                  <div style={LABEL}>New Invoice</div>
                  <div>
                    <div style={LABEL}>Company *</div>
                    <select style={INPUT} value={invCompanyId} onChange={e => setInvCompanyId(e.target.value)}>
                      <option value="">Choose a company…</option>
                      {invCompanies.map(c => <option key={c.id} value={c.id}>{c.name}</option>)}
                    </select>
                  </div>
                  {invSelectedCompany && <>
                    <div>
                      <div style={LABEL}>Bill To</div>
                      <input style={INPUT} type="text" value={invBillTo} onChange={e => setInvBillTo(e.target.value)} placeholder={invSelectedCompany.name} />
                    </div>
                    <div>
                      <div style={LABEL}>Email To</div>
                      <input style={INPUT} type="email" list="inv-recipients" value={invEmail} onChange={e => setInvEmail(e.target.value)} placeholder="client@example.com" />
                      <datalist id="inv-recipients">{invRecipients.map(r => <option key={r.id} value={r.email}>{r.name} ({r.role})</option>)}</datalist>
                    </div>
                  </>}
                  <div>
                    <div style={LABEL}>Notes</div>
                    <textarea style={FINANCE_MODAL_TEXTAREA_STYLE} value={invNotes} onChange={e => setInvNotes(e.target.value)} placeholder="Payment terms, notes…" />
                  </div>
                  <div style={{ marginTop: 'auto', paddingTop: 8 }}>
                    <div style={LABEL}>Total</div>
                    <div style={FINANCE_MODAL_TOTAL_VALUE_STYLE}>${invTotal.toFixed(2)}</div>
                  </div>
                </div>

                {/* Right: unbilled tasks + line items */}
                <div style={{ display: 'flex', flexDirection: 'column', gap: 14, flex: 1, minHeight: 0, overflowY: 'auto' }}>
                  {/* Unbilled tasks */}
                  {invSelectedCompany && (
                    <div>
                      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 6 }}>
                        <div style={LABEL}>Unbilled Requests</div>
                        {invUnbilledTasks.length > 0 && <button type="button" className="btn btn-outline" style={{ fontSize: 11 }} onClick={() => invUnbilledTasks.forEach(t => { if (!invItems.some(i => i.task_id === t.id && !i.submission_id)) invAddTask(t); })}>+ All</button>}
                      </div>
                      {invLoadingTasks ? <div style={{ fontSize: 12, color: 'var(--text-muted)' }}>Loading…</div>
                        : invUnbilledTasks.length === 0 ? <div style={{ fontSize: 12, color: 'var(--text-muted)' }}>None</div>
                        : invUnbilledTasks.map(t => {
                          const price = invPriceList.find(p => p.service_type === t.service_type && p.price_type === 'new');
                          const added = invItems.some(i => i.task_id === t.id && !i.submission_id);
                          return (
                            <div key={t.id} style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '6px 10px', background: 'var(--card-bg-2)', borderRadius: 4, border: '1px solid var(--border)', marginBottom: 4 }}>
                              <div>
                                <div style={{ display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap' }}>
                                  <span className="badge badge-initial">New</span>
                                  <div style={{ fontSize: 12 }}>{t.project?.name} • {t.title || t.service_type}</div>
                                </div>
                                <div style={{ fontSize: 11, color: 'var(--text-muted)' }}>{price ? `$${Number(price.price).toFixed(2)}` : 'No price'}</div>
                              </div>
                              <button type="button" className="btn btn-outline" style={{ fontSize: 11 }} disabled={added} onClick={() => invAddTask(t)}>{added ? 'Added' : '+ Add'}</button>
                            </div>
                          );
                        })}
                    </div>
                  )}
                  {/* Unbilled revisions */}
                  {invSelectedCompany && invUnbilledRevisions.length > 0 && (
                    <div>
                      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 6 }}>
                        <div style={LABEL}>Unbilled Revisions</div>
                        <button type="button" className="btn btn-outline" style={{ fontSize: 11 }} onClick={() => invUnbilledRevisions.forEach(r => { if (!invItems.some(i => i.submission_id === r.id)) invAddRevision(r); })}>+ All</button>
                      </div>
                      {invUnbilledRevisions.map(r => {
                        const added = invItems.some(i => i.submission_id === r.id);
                        const revisionQty = getRevisionChargeQuantity(r?.version_number);
                        const initial = (r.task?.submissions || []).find(s => s.type === 'initial') || r.task?.submissions?.[0];
                        const revisionServiceType = initial?.service_type || r.service_type || r.task?.title || 'Revision';
                        const revisionPrice = invPriceList.find(p => p.service_type === revisionServiceType && p.price_type === 'revision');
                        const revisionLabel = revisionQty > 0 ? (revisionPrice ? `$${Number(revisionPrice.price).toFixed(2)}` : 'No price') : 'Free';
                        return (
                          <div key={r.id} style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '6px 10px', background: 'var(--card-bg-2)', borderRadius: 4, border: '1px solid var(--border)', marginBottom: 4 }}>
                            <div>
                              <div style={{ display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap' }}>
                                <span className="badge badge-client_revision">Revision</span>
                                <div style={{ fontSize: 12 }}>{r.task?.project?.name} • {r.task?.title} • R{String(r.version_number || 0).padStart(2, '0')}</div>
                              </div>
                              <div style={{ fontSize: 11, color: 'var(--text-muted)' }}>{revisionLabel}</div>
                            </div>
                            <button type="button" className="btn btn-outline" style={{ fontSize: 11 }} disabled={added} onClick={() => invAddRevision(r)}>{added ? 'Added' : '+ Add'}</button>
                          </div>
                        );
                      })}
                    </div>
                  )}
                  {/* Line items */}
                  <div style={{ flex: 1 }}>
                    <div style={LABEL}>Line Items</div>
                    <div style={{ display: 'grid', gridTemplateColumns: '20px 90px 1fr 60px 100px 90px 28px', gap: 6, marginBottom: 6 }}>
                      {['', 'Type', 'Description', 'Qty', 'Unit Price', 'Total', ''].map((h, i) => <div key={i} style={{ fontSize: 10, fontWeight: 500, textTransform: 'uppercase', letterSpacing: 0.5, color: 'var(--text-muted)', textAlign: i > 3 ? 'right' : 'left' }}>{h}</div>)}
                    </div>
                    {invItems.map((item, idx) => (
                      <div key={item.id} onDragOver={e => e.preventDefault()} onDrop={() => invHandleDrop(idx)} style={{ display: 'grid', gridTemplateColumns: '20px 90px 1fr 60px 100px 90px 28px', gap: 6, alignItems: 'center', marginBottom: 4 }}>
                        <div draggable onDragStart={() => { invDragItem.current = idx; }} style={{ cursor: 'grab', color: 'var(--text-muted)', fontSize: 12, textAlign: 'center', userSelect: 'none' }}>⠿</div>
                        <span className={`badge ${item.submission_id ? 'badge-client_revision' : 'badge-initial'}`}>
                          {item.submission_id ? 'Revision' : 'New'}
                        </span>
                        <input style={FINANCE_MODAL_LINE_ITEM_INPUT_STYLE} type="text" placeholder="Description…" value={item.description} onChange={e => invUpdateItem(item.id, 'description', e.target.value)} />
                        <input style={{ ...FINANCE_MODAL_NUMBER_INPUT_STYLE, textAlign: 'center' }} type="number" min="1" value={item.quantity} onChange={e => invUpdateItem(item.id, 'quantity', e.target.value)} />
                        <input style={{ ...FINANCE_MODAL_NUMBER_INPUT_STYLE, textAlign: 'right' }} type="number" min="0" step="0.01" placeholder="0.00" value={item.unit_price} onChange={e => invUpdateItem(item.id, 'unit_price', e.target.value)} />
                        <div style={{ minHeight: 32, display: 'flex', alignItems: 'center', justifyContent: 'flex-end', textAlign: 'right', fontSize: 13, color: 'var(--text-primary)', paddingRight: 2, fontVariantNumeric: 'tabular-nums' }}>${((Number(item.quantity) || 0) * (Number(item.unit_price) || 0)).toFixed(2)}</div>
                        <button type="button" onClick={() => invRemoveItem(item.id)} style={{ background: 'none', border: 'none', cursor: 'pointer', color: 'var(--danger)', fontSize: 14, padding: 2 }}>✕</button>
                      </div>
                    ))}
                    <button type="button" className="btn btn-outline" style={{ marginTop: 8, fontSize: 12 }} onClick={() => setInvItems(prev => [...prev, invNewItem()])}>+ Line Item</button>
                  </div>
                </div>
              </div>

              {/* Footer */}
              <div className="modal-action-row" style={{ paddingTop: 14, marginTop: 14, flexShrink: 0 }}>
                <button type="button" className="btn btn-outline" disabled={invSaving} onClick={() => invHandleSave('draft')}>{invSaving ? 'Saving…' : 'Save Draft'}</button>
                <LoadingButton className="btn btn-outline" style={{ color: 'var(--accent)', borderColor: 'var(--accent)' }} onClick={() => invHandleSave('sent')} loading={invSaving} loadingText="Sending…">Finalise & Send</LoadingButton>
                <button type="button" className="btn btn-outline" disabled={invSaving} onClick={invClose}>Cancel</button>
              </div>
            </div>
          </div>
        );
      })()}

    </Layout>
  );
}
