<?php
include "../classes/autoload.php";

$now = date('Y-m-d H:i:s');
$thisMonth = date('Y-m');

// Financial year runs 1 March → last day of February
// If current month is March (3) or later, FY started this calendar year; otherwise last year
$fyStartYear = (int)date('n') >= 3 ? (int)date('Y') : (int)date('Y') - 1;
$fyEndYear   = $fyStartYear + 1;
$fyStart     = $fyStartYear . '-03-01 00:00:00';
$fyEnd       = $fyEndYear   . '-02-28 23:59:59';
$fyLabel     = 'FY ' . $fyStartYear . '/' . substr($fyEndYear, 2);

$res = $db->query("invoices", "SELECT COUNT(i.record_id) AS cnt, COALESCE(SUM(il.price * il.qty), 0) AS total FROM invoices i LEFT JOIN invoice_list il ON il.invoice_id = i.record_id WHERE DATE_FORMAT(i.date_time_created, '%Y-%m') = '$thisMonth'");
$monthInv = $res->fetch_assoc();
$res = $db->query("quotes", "SELECT COUNT(q.record_id) AS cnt, COALESCE(SUM(ql.price * ql.qty), 0) AS total FROM quotes q LEFT JOIN quote_list ql ON ql.quote_id = q.record_id WHERE DATE_FORMAT(q.date_time_created, '%Y-%m') = '$thisMonth'");
$monthQuo = $res->fetch_assoc();
$res = $db->query("invoices", "SELECT COUNT(i.record_id) AS cnt, COALESCE(SUM(il.price * il.qty), 0) AS total FROM invoices i LEFT JOIN invoice_list il ON il.invoice_id = i.record_id WHERE i.date_time_created >= '$fyStart' AND i.date_time_created <= '$fyEnd'");
$ytdInv = $res->fetch_assoc();
$res = $db->query("quotes", "SELECT COUNT(q.record_id) AS cnt, COALESCE(SUM(ql.price * ql.qty), 0) AS total FROM quotes q LEFT JOIN quote_list ql ON ql.quote_id = q.record_id WHERE q.date_time_created >= '$fyStart' AND q.date_time_created <= '$fyEnd'");
$ytdQuo = $res->fetch_assoc();
// Payments — FY only
$res = $db->query("payments", "SELECT COUNT(*) AS cnt, COALESCE(SUM(amount), 0) AS total FROM payments WHERE date_time >= '$fyStart' AND date_time <= '$fyEnd'");
$payments = $res->fetch_assoc();

// Credit notes — FY only
$res = $db->query("credit_notes", "SELECT COUNT(cn.record_id) AS cnt, COALESCE(SUM(cnl.amount), 0) AS total FROM credit_notes cn LEFT JOIN credit_notes_list cnl ON cnl.credit_note_id = cn.record_id WHERE cn.date_time >= '$fyStart' AND cn.date_time <= '$fyEnd'");
$creditNotes = $res->fetch_assoc();

// Outstanding unpaid invoices — FY only
$res = $db->query("invoices",
    "SELECT COALESCE(SUM(il.price * il.qty), 0) - COALESCE((SELECT SUM(p.amount) FROM payments p WHERE p.invoice_id = i.record_id), 0) AS outstanding
     FROM invoices i
     LEFT JOIN invoice_list il ON il.invoice_id = i.record_id
     WHERE i.status NOT IN ('PAID','paid','Paid','CANCELLED','cancelled')
       AND i.date_time_created >= '$fyStart' AND i.date_time_created <= '$fyEnd'
     GROUP BY i.record_id
     HAVING outstanding > 0");
$outRows = [];
while ($row = $res->fetch_assoc()) { $outRows[] = $row; }
$outCount = count($outRows);
$outTotal = array_sum(array_column($outRows, 'outstanding'));

// Overdue (>30 days) — FY only
$res = $db->query("invoices",
    "SELECT COALESCE(SUM(il.price * il.qty), 0) - COALESCE((SELECT SUM(p.amount) FROM payments p WHERE p.invoice_id = i.record_id), 0) AS outstanding
     FROM invoices i
     LEFT JOIN invoice_list il ON il.invoice_id = i.record_id
     WHERE i.status NOT IN ('PAID','paid','Paid','CANCELLED','cancelled')
       AND i.date_time_created >= '$fyStart' AND i.date_time_created <= '$fyEnd'
       AND i.date_time_created < DATE_SUB(NOW(), INTERVAL 30 DAY)
     GROUP BY i.record_id
     HAVING outstanding > 0");
$outOverdue = 0;
while ($row = $res->fetch_assoc()) { $outOverdue += $row['outstanding']; }

// Paid last 30 days — FY only
$res = $db->query("payments", "SELECT COALESCE(SUM(amount), 0) AS total FROM payments WHERE date_time >= DATE_SUB(NOW(), INTERVAL 30 DAY) AND date_time >= '$fyStart' AND date_time <= '$fyEnd'");
$paid30 = $res->fetch_assoc()['total'];

// Client/stock counts — global (not FY-specific)
$res = $db->query("clients", "SELECT COUNT(*) AS cnt FROM clients");
$clientCount = $res->fetch_assoc()['cnt'];
$res = $db->query("stock", "SELECT COUNT(*) AS cnt FROM stock");
$stockCount = $res->fetch_assoc()['cnt'];

// Top clients — FY only
$res = $db->query("clients",
    "SELECT c.name, COALESCE(SUM(il.price * il.qty), 0) AS total
     FROM clients c
     JOIN invoices i ON i.client_id = c.record_id
     JOIN invoice_list il ON il.invoice_id = i.record_id
     WHERE i.date_time_created >= '$fyStart' AND i.date_time_created <= '$fyEnd'
     GROUP BY c.record_id
     ORDER BY total DESC
     LIMIT 5");
$topClients = [];
while ($row = $res->fetch_assoc()) { $topClients[] = $row; }

// ── Unpaid invoices — FY only, sorted by balance desc ──
$res = $db->query("invoices",
    "SELECT i.record_id, i.invoice_number, i.date_time_created, i.status,
            c.name AS client_name,
            COALESCE(SUM(il.price * il.qty), 0) AS inv_total,
            COALESCE((SELECT SUM(p.amount) FROM payments p WHERE p.invoice_id = i.record_id), 0) AS paid,
            COALESCE(SUM(il.price * il.qty), 0) - COALESCE((SELECT SUM(p.amount) FROM payments p WHERE p.invoice_id = i.record_id), 0) AS balance,
            DATEDIFF(NOW(), i.date_time_created) AS days_old
     FROM invoices i
     LEFT JOIN invoice_list il ON il.invoice_id = i.record_id
     LEFT JOIN clients c ON c.record_id = i.client_id
     WHERE i.status NOT IN ('PAID','paid','Paid','CANCELLED','cancelled')
       AND i.date_time_created >= '$fyStart' AND i.date_time_created <= '$fyEnd'
     GROUP BY i.record_id
     HAVING balance > 0
     ORDER BY balance DESC");
$unpaidInvoices = [];
while ($row = $res->fetch_assoc()) { $unpaidInvoices[] = $row; }

// ── Monthly breakdown for full FY ──
$fyMonths = []; $fyMonth = strtotime($fyStartYear . '-03-01');
$fyEndTs  = strtotime($fyEndYear . '-03-01');
while ($fyMonth < $fyEndTs) {
    $ym  = date('Y-m', $fyMonth);
    $lbl = date('M Y', $fyMonth);
    $r   = $db->query("invoices",
        "SELECT COUNT(i.record_id) AS cnt,
                COALESCE(SUM(il.price * il.qty), 0) AS inv_total
         FROM invoices i
         LEFT JOIN invoice_list il ON il.invoice_id = i.record_id
         WHERE DATE_FORMAT(i.date_time_created, '%Y-%m') = '$ym'");
    $mi  = $r->fetch_assoc();
    $r   = $db->query("payments",
        "SELECT COALESCE(SUM(amount), 0) AS pay_total
         FROM payments
         WHERE DATE_FORMAT(date_time, '%Y-%m') = '$ym'");
    $mp  = $r->fetch_assoc();
    $fyMonths[] = [
        'ym'        => $ym,
        'label'     => $lbl,
        'inv_count' => (int)$mi['cnt'],
        'inv_total' => (float)$mi['inv_total'],
        'pay_total' => (float)$mp['pay_total'],
        'balance'   => (float)$mi['inv_total'] - (float)$mp['pay_total'],
    ];
    $fyMonth = strtotime('+1 month', $fyMonth);
}

// ── Previous financial year ──
$prevFyStartYear = $fyStartYear - 1;
$prevFyEndYear   = $fyStartYear;
$prevFyStart     = $prevFyStartYear . '-03-01 00:00:00';
$prevFyEnd       = $prevFyEndYear   . '-02-28 23:59:59';
$prevFyLabel     = 'FY ' . $prevFyStartYear . '/' . substr($prevFyEndYear, 2);

$res = $db->query("invoices",
    "SELECT COUNT(i.record_id) AS cnt, COALESCE(SUM(il.price * il.qty), 0) AS total
     FROM invoices i LEFT JOIN invoice_list il ON il.invoice_id = i.record_id
     WHERE i.date_time_created >= '$prevFyStart' AND i.date_time_created <= '$prevFyEnd'");
$prevInv = $res->fetch_assoc();

$res = $db->query("payments",
    "SELECT COUNT(*) AS cnt, COALESCE(SUM(amount), 0) AS total
     FROM payments WHERE date_time >= '$prevFyStart' AND date_time <= '$prevFyEnd'");
$prevPay = $res->fetch_assoc();

$res = $db->query("invoices",
    "SELECT COALESCE(SUM(il.price * il.qty), 0) - COALESCE((SELECT SUM(p.amount) FROM payments p WHERE p.invoice_id = i.record_id), 0) AS outstanding
     FROM invoices i LEFT JOIN invoice_list il ON il.invoice_id = i.record_id
     WHERE i.status NOT IN ('PAID','paid','Paid','CANCELLED','cancelled')
       AND i.date_time_created >= '$prevFyStart' AND i.date_time_created <= '$prevFyEnd'
     GROUP BY i.record_id HAVING outstanding > 0");
$prevOutRows = [];
while ($row = $res->fetch_assoc()) { $prevOutRows[] = $row; }
$prevOutCount = count($prevOutRows);
$prevOutTotal = array_sum(array_column($prevOutRows, 'outstanding'));
$prevColRate  = ($prevPay['total'] + $prevOutTotal) > 0
    ? round($prevPay['total'] / ($prevPay['total'] + $prevOutTotal) * 100, 1) : 0;

$prevMonths = []; $prevFyMonth = strtotime($prevFyStartYear . '-03-01');
$prevFyEndTs = strtotime($prevFyEndYear . '-03-01');
while ($prevFyMonth < $prevFyEndTs) {
    $ym  = date('Y-m', $prevFyMonth);
    $lbl = date('M Y', $prevFyMonth);
    $r   = $db->query("invoices",
        "SELECT COUNT(i.record_id) AS cnt, COALESCE(SUM(il.price * il.qty), 0) AS inv_total
         FROM invoices i LEFT JOIN invoice_list il ON il.invoice_id = i.record_id
         WHERE DATE_FORMAT(i.date_time_created, '%Y-%m') = '$ym'");
    $mi  = $r->fetch_assoc();
    $r   = $db->query("payments",
        "SELECT COALESCE(SUM(amount), 0) AS pay_total FROM payments
         WHERE DATE_FORMAT(date_time, '%Y-%m') = '$ym'");
    $mp  = $r->fetch_assoc();
    $prevMonths[] = [
        'ym'        => $ym, 'label' => $lbl,
        'inv_count' => (int)$mi['cnt'],
        'inv_total' => (float)$mi['inv_total'],
        'pay_total' => (float)$mp['pay_total'],
        'balance'   => (float)$mi['inv_total'] - (float)$mp['pay_total'],
    ];
    $prevFyMonth = strtotime('+1 month', $prevFyMonth);
}

$res = $db->query("clients",
    "SELECT c.name, COALESCE(SUM(il.price * il.qty), 0) AS total
     FROM clients c
     JOIN invoices i ON i.client_id = c.record_id
     JOIN invoice_list il ON il.invoice_id = i.record_id
     WHERE i.date_time_created >= '$prevFyStart' AND i.date_time_created <= '$prevFyEnd'
     GROUP BY c.record_id ORDER BY total DESC LIMIT 5");
$prevTopClients = [];
while ($row = $res->fetch_assoc()) { $prevTopClients[] = $row; }

function rands($v) { return 'R&nbsp;' . number_format((float)$v, 2, '.', ','); }
function rands_raw($v) { return 'R ' . number_format((float)$v, 2, '.', ','); }
$collectionRate = ($payments['total'] + $outTotal) > 0 ? round($payments['total'] / ($payments['total'] + $outTotal) * 100, 1) : 0;
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Dashboard</title>
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.2/dist/chart.umd.min.js"></script>
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

:root {
    --orange:     #f15b23;
    --orange-bg:  #fff4f0;
    --navy:       #544F2A;
    --navy-bg:    #ADAD9D;
    --green:      #1e7e4a;
    --green-bg:   #edf7f2;
    --red:        #ff1900;
    --red-bg:     #fef0ee;
    --page-bg:    #f2f4f7;
    --white:      #ffffff;
    --border:     #e3e8ef;
    --text:       #1d2535;
    --text-2:     #4b5a72;
    --text-3:     #9aaabf;
    --shadow-sm:  0 1px 2px rgba(0,0,0,.05);
    --shadow:     0 1px 4px rgba(0,0,0,.06), 0 2px 8px rgba(0,0,0,.04);
    --shadow-md:  0 4px 16px rgba(0,0,0,.08);
    --r:          10px;
}

body {
    background: var(--page-bg);
    font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    font-size: 13px;
    color: var(--text);
    line-height: 1.5;
    min-height: 100vh;
}

/* ── Top bar ── */
.topbar {
    background: var(--navy);
    border-bottom: 1px solid var(--border);
    padding: 0 2rem;
    display: flex; align-items: center; justify-content: space-between;
    height: 56px;
    box-shadow: var(--shadow-sm);
}
.topbar-left { display: flex; align-items: center; gap: 1rem; }
.topbar-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--orange); flex-shrink: 0; }
.topbar-title { font-size: 1.8rem; font-weight: 700; color: var(--white); letter-spacing: -.2px; }
.topbar-sub { font-size: .65rem; color: var(--white); margin-left: .25rem; }
.topbar-right { display: flex; align-items: center; gap: .6rem; }
.topbar-pill {
    font-size: .62rem; font-weight: 600; color: var(--text-2);
    padding: 4px 12px; border: 1px solid var(--border); border-radius: 20px;
    background: var(--page-bg);
}
.topbar-pill.hi { background: var(--orange); border-color: var(--orange); color: #fff; }

/* ── Ticker ── */
.ticker {
    background: var(--orange);
    border-bottom: 1px solid var(--border);
    padding: .4rem 2rem;
    display: flex; gap: 0; overflow-x: auto; scrollbar-width: none;
    justify-content: space-evenly;
}
.ticker::-webkit-scrollbar { display: none; }
.ticker-item { display: flex; align-items: center; gap: .45rem; padding: 0 1.25rem; border-right: 1px solid var(--border); flex-shrink: 0; }
.ticker-item:first-child { padding-left: 0; }
.ticker-item:last-child { border-right: none; }
.ticker-label { font-size: .59rem; text-transform: uppercase; letter-spacing: .7px; color: var(--white); font-weight: 600; }
.ticker-val { font-size: .73rem; font-weight: 700; color: var(--text); font-variant-numeric: tabular-nums; }
.ticker-val.up { color: var(--green); }
.ticker-val.down { color: var(--red); }

/* ── Wrap ── */
.wrap { max-width: 1440px; margin: 0 auto; padding: 1.4rem 2rem 3rem; }

/* ── Section head ── */
.sec { display: flex; align-items: center; gap: .75rem; margin: 1.6rem 0 .75rem; }
.sec-title { font-size: .68rem; font-weight: 700; text-transform: uppercase; letter-spacing: .8px; color: var(--navy); white-space: nowrap; }
.sec-line { flex: 1; height: 1px; background: var(--border); }
.sec-sub { font-size: .59rem; font-weight: 600; text-transform: uppercase; letter-spacing: .6px; color: var(--text-3); white-space: nowrap; }

/* ── KPI grid ── */
.grid { display: grid; gap: .75rem; }
.g4 { grid-template-columns: repeat(4,1fr); }
.g5 { grid-template-columns: repeat(5,1fr); }
@media(max-width:1200px){ .g5{ grid-template-columns:repeat(3,1fr); } }
@media(max-width:960px){ .g4,.g5{ grid-template-columns:repeat(2,1fr); } }
@media(max-width:560px){ .g4,.g5{ grid-template-columns:1fr; } }

/* ── KPI Card ── */
.kpi {
    background: var(--white);
    border: 1px solid var(--border);
    border-radius: var(--r);
    box-shadow: var(--shadow);
    overflow: hidden;
    transition: box-shadow .15s, transform .15s;
}
.kpi:hover { box-shadow: var(--shadow-md); transform: translateY(-1px); }
.kpi-bar { height: 3px; }
.kpi-body { padding: 1rem 1.1rem 1rem; }
.kpi-label { font-size: .58rem; font-weight: 700; text-transform: uppercase; letter-spacing: .9px; color: var(--text-3); margin-bottom: .35rem; }
.kpi-val { font-size: 1.55rem; font-weight: 800; color: var(--text); font-variant-numeric: tabular-nums; line-height: 1.1; }
.kpi-note { font-size: .61rem; color: var(--text-3); margin-top: .2rem; }
.kpi-hr { border: none; border-top: 1px solid var(--border); margin: .65rem 0; }
.kpi-foot { display: flex; justify-content: space-between; align-items: center; }
.kpi-foot-label { font-size: .61rem; color: var(--text-3); }
.kpi-foot-val { font-size: .71rem; font-weight: 700; font-variant-numeric: tabular-nums; }

/* pills */
.pill { display: inline-flex; align-items: center; gap: 4px; font-size: .59rem; font-weight: 700; letter-spacing: .3px; text-transform: uppercase; padding: 3px 9px; border-radius: 20px; }
.pill::before { content: ''; width: 5px; height: 5px; border-radius: 50%; flex-shrink: 0; }
.p-green  { background: var(--green-bg);  color: var(--green); }
.p-green::before  { background: var(--green); }
.p-red    { background: var(--red-bg);    color: var(--red); }
.p-red::before    { background: var(--red); }
.p-navy   { background: var(--navy-bg);   color: var(--navy); }
.p-navy::before   { background: var(--navy); }
.p-orange { background: var(--orange-bg); color: var(--orange); }
.p-orange::before { background: var(--orange); }

/* ── Outstanding panel ── */
.outstanding {
    background: var(--navy);
    border-radius: var(--r);
    box-shadow: var(--shadow-md);
    overflow: hidden;
    position: relative;
}
.outstanding::after {
    content: '';
    position: absolute; bottom: 0; right: 0;
    width: 180px; height: 180px;
    background: radial-gradient(circle, rgba(255,255,255,.04) 0%, transparent 70%);
    pointer-events: none;
}
.out-top { background: var(--orange); padding: .35rem 1.2rem; display: flex; align-items: center; gap: .5rem; }
.out-top-label { font-size: .59rem; font-weight: 700; text-transform: uppercase; letter-spacing: .7px; color: rgba(255,255,255,.85); }
.out-body { padding: 1.2rem 1.4rem 1.4rem; }
.out-amount { font-size: 2rem; font-weight: 800; color: #fff; line-height: 1; font-variant-numeric: tabular-nums; margin-bottom: .15rem; }
.out-sub { font-size: .62rem; color: rgba(255,255,255,.45); margin-bottom: 1rem; }
.out-divider { border: none; border-top: 1px solid rgba(255,255,255,.1); margin: .7rem 0; }
.out-row { display: flex; justify-content: space-between; align-items: center; margin-bottom: .4rem; }
.out-row:last-child { margin-bottom: 0; }
.out-row-label { font-size: .62rem; color: rgba(255,255,255,.5); }
.out-row-val { font-size: .76rem; font-weight: 700; font-variant-numeric: tabular-nums; }
.v-danger  { color: #ffab91; }
.v-neutral { color: rgba(255,255,255,.85); }
.v-ok      { color: #a5d6a7; }
.rate-wrap { margin-top: .9rem; }
.rate-labels { display: flex; justify-content: space-between; font-size: .59rem; color: rgba(255,255,255,.4); margin-bottom: .35rem; }
.rate-track { height: 6px; background: rgba(255,255,255,.1); border-radius: 3px; overflow: hidden; }
.rate-fill { height: 100%; border-radius: 3px; background: var(--orange); transition: width .9s ease; }

/* ── Cards ── */
.card { background: var(--white); border: 1px solid var(--border); border-radius: var(--r); box-shadow: var(--shadow); overflow: hidden; }
.card-head { display: flex; align-items: center; justify-content: space-between; padding: .75rem 1.1rem; border-bottom: 1px solid var(--border); }
.card-title { font-size: .8rem; font-weight: 700; color: var(--text); }
.card-tag { font-size: .58rem; font-weight: 600; text-transform: uppercase; letter-spacing: .4px; color: var(--text-3); background: var(--page-bg); border: 1px solid var(--border); padding: 2px 10px; border-radius: 20px; }
.card-body { padding: 1.1rem; }

.cols3 { display: grid; grid-template-columns: 1.65fr 1fr 1fr; gap: .75rem; }
.cols2 { display: grid; grid-template-columns: 1fr 1fr; gap: .75rem; }
@media(max-width:1100px){ .cols3{ grid-template-columns:1fr 1fr; } }
@media(max-width:700px){ .cols3,.cols2{ grid-template-columns:1fr; } }

/* ── Clients table ── */
.ct { width: 100%; border-collapse: collapse; }
.ct th { font-size: .59rem; font-weight: 700; text-transform: uppercase; letter-spacing: .6px; color: #fff; background: var(--navy); padding: .55rem .7rem; text-align: left; }
.ct th:first-child { border-radius: 5px 0 0 0; }
.ct th:last-child  { border-radius: 0 5px 0 0; }
.ct td { padding: .55rem .7rem; font-size: .73rem; border-bottom: 1px solid var(--border); color: var(--text-2); }
.ct tr:last-child td { border-bottom: none; }
.ct tbody tr:hover td { background: var(--page-bg); }
.rank { display: inline-flex; align-items: center; justify-content: center; width: 22px; height: 22px; border-radius: 50%; font-size: .62rem; font-weight: 700; background: var(--page-bg); color: var(--text-3); border: 1px solid var(--border); }
.rank.g { background: #fff8e1; color: #b8860b; border-color: #f0c040; }
.rank.s { background: #f5f5f5; color: #666; border-color: #ccc; }
.rank.b { background: #fff1e6; color: #a05020; border-color: #e0a070; }
.mini-bar { width: 80px; }
.mini-bar-track { height: 5px; background: var(--border); border-radius: 3px; overflow: hidden; }
.mini-bar-fill { height: 100%; border-radius: 3px; background: var(--orange); }

@keyframes up { from { opacity:0; transform:translateY(6px); } to { opacity:1; transform:translateY(0); } }
.kpi,.card,.outstanding { animation: up .3s ease both; }
.kpi:nth-child(1){animation-delay:.03s} .kpi:nth-child(2){animation-delay:.06s}
.kpi:nth-child(3){animation-delay:.09s} .kpi:nth-child(4){animation-delay:.12s}
.kpi:nth-child(5){animation-delay:.15s}

/* ── Previous year section ── */
.prev-banner {
    background: var(--navy); border-radius: var(--r);
    padding: .5rem 1.2rem;
    display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: .5rem;
    margin-bottom: .75rem;
}
.prev-banner-title { font-size: .7rem; font-weight: 700; color: #fff; }
.prev-banner-sub   { font-size: .6rem; color: rgba(255,255,255,.5); margin-top: 1px; }
.prev-badge { font-size: .58rem; font-weight: 700; text-transform: uppercase; letter-spacing: .4px;
              padding: 3px 10px; border-radius: 20px; background: rgba(255,255,255,.1);
              color: rgba(255,255,255,.75); border: 1px solid rgba(255,255,255,.15); }
.vs-pill { display:inline-flex; align-items:center; gap:3px; font-size:.6rem; font-weight:700; padding:2px 8px; border-radius:20px; white-space:nowrap; }
.vs-up   { background:var(--green-bg); color:var(--green); }
.vs-down { background:var(--red-bg);   color:var(--red);   }
.vs-flat { background:var(--page-bg);  color:var(--text-3); }

/* ── Data tables (unpaid + monthly) ── */
.dt { width:100%; border-collapse:collapse; }
.dt th { font-size:.58rem; font-weight:700; text-transform:uppercase; letter-spacing:.6px;
         color:#fff; background:var(--navy); padding:.55rem .75rem; text-align:right; white-space:nowrap; }
.dt th:first-child { text-align:left; border-radius:5px 0 0 0; }
.dt th:last-child  { border-radius:0 5px 0 0; }
.dt td { padding:.5rem .75rem; font-size:.72rem; border-bottom:1px solid var(--border);
         color:var(--text-2); text-align:right; font-variant-numeric:tabular-nums; }
.dt td:first-child { text-align:left; font-weight:600; color:var(--text); }
.dt tbody tr:hover td { background:var(--page-bg); }
.dt tr:last-child td { border-bottom:none; }
.dt tfoot td { background:#f7f9fc; font-weight:700; color:var(--navy);
               border-top:2px solid var(--border); border-bottom:none; font-size:.72rem; }

/* overdue age badge */
.age-badge { display:inline-flex; align-items:center; gap:3px; font-size:.58rem; font-weight:700;
             text-transform:uppercase; letter-spacing:.4px; padding:2px 8px; border-radius:20px; white-space:nowrap; }
.age-fresh  { background:var(--green-bg); color:var(--green); }
.age-warn   { background:#fff8e1;         color:#b8860b;      }
.age-danger { background:var(--red-bg);   color:var(--red);   }

/* status badge */
.st-badge { display:inline-flex; align-items:center; gap:3px; font-size:.58rem; font-weight:700;
            text-transform:uppercase; letter-spacing:.4px; padding:2px 8px; border-radius:20px; white-space:nowrap; }
.st-badge::before { content:''; width:4px; height:4px; border-radius:50%; flex-shrink:0; }
.st-opened  { background:var(--navy-bg); color:var(--navy);   } .st-opened::before  { background:var(--navy); }
.st-pending { background:#fff8e1;        color:#b8860b;       } .st-pending::before { background:#b8860b; }
.st-other   { background:var(--page-bg); color:var(--text-3); } .st-other::before   { background:var(--text-3); }

/* month bar fill */
.mb-track { width:80px; height:5px; background:var(--border); border-radius:3px; overflow:hidden; display:inline-block; vertical-align:middle; }
.mb-fill  { height:100%; border-radius:3px; }
.val-red { color:var(--red)   !important; font-weight:700; }
.val-grn { color:var(--green) !important; font-weight:700; }
.val-ora { color:var(--orange)!important; font-weight:700; }

/* ── FY Tab switcher ── */
.fy-tabs {
    background: var(--white);
    border-bottom: 2px solid var(--border);
    padding: 0 2rem;
    display: flex; align-items: center; gap: 0;
}
.fy-tab {
    padding: .75rem 1.4rem;
    font-size: .68rem; font-weight: 700; text-transform: uppercase; letter-spacing: .6px;
    color: var(--text-3); cursor: pointer; border: none; background: none;
    border-bottom: 3px solid transparent; margin-bottom: -2px;
    transition: color .15s, border-color .15s;
    white-space: nowrap;
}
.fy-tab:hover { color: var(--navy); }
.fy-tab.active { color: var(--orange); border-bottom-color: var(--orange); }
.fy-tab-dot { display:inline-block; width:6px; height:6px; border-radius:50%; background:var(--green); margin-left:6px; vertical-align:middle; }

/* ── FY Panel ── */
.fy-panel { display: none; }
.fy-panel.active { display: block; }
</style>
</head>
<body>

<!-- Top bar -->
<div class="topbar">
    <div class="topbar-left">
        <span class="topbar-title">Financial Overview</span>
    </div>
    <div class="topbar-right">
        <span class="topbar-pill" id="js-date"></span>
        <span class="topbar-pill hi" id="js-year"></span>
    </div>
</div>

<!-- Ticker -->
<div class="ticker">
    <div class="ticker-item"><span class="ticker-label">Monthly Invoices</span><span class="ticker-val"><?= $monthInv['cnt'] ?></span></div>
    <div class="ticker-item"><span class="ticker-label">Monthly Value</span><span class="ticker-val"><?= rands_raw($monthInv['total']) ?></span></div>
    <div class="ticker-item"><span class="ticker-label">Outstanding</span><span class="ticker-val"><?= rands_raw($outTotal) ?></span></div>
    <div class="ticker-item"><span class="ticker-label">Collected</span><span class="ticker-val"><?= rands_raw($payments['total']) ?></span></div>
    <div class="ticker-item"><span class="ticker-label">Collection Rate</span><span class="ticker-val"><?= $collectionRate ?>%</span></div>
    <div class="ticker-item"><span class="ticker-label">Clients</span><span class="ticker-val"><?= $clientCount ?></span></div>
    <div class="ticker-item"><span class="ticker-label">Stock Items</span><span class="ticker-val"><?= $stockCount ?></span></div>
</div>

<!-- FY Tab Bar -->
<div class="fy-tabs">
    <button class="fy-tab active" onclick="switchFY('curr')" id="tab-curr">
        <?= $fyLabel ?><span class="fy-tab-dot"></span>
    </button>
    <button class="fy-tab" onclick="switchFY('prev')" id="tab-prev">
        <?= $prevFyLabel ?>
    </button>
</div>

<div class="wrap">

    <!-- ═══════════════════════════════ CURRENT FY PANEL ═══════════════════════════════ -->
    <div class="fy-panel active" id="panel-curr">

    <!-- This Month -->
    <div class="sec"><span class="sec-title">This Month</span><div class="sec-line"></div><span class="sec-sub"><?= date('F Y') ?></span></div>
    <div class="grid g4">
        <div class="kpi">
            <div class="kpi-bar" style="background:var(--orange)"></div>
            <div class="kpi-body">
                <div class="kpi-label">Invoices Issued</div>
                <div class="kpi-val"><?= number_format($monthInv['cnt']) ?></div>
                <div class="kpi-note">invoices this month</div>
                <hr class="kpi-hr">
                <div class="kpi-foot"><span class="kpi-foot-label">Total value</span><span class="kpi-foot-val" style="color:var(--orange)"><?= rands($monthInv['total']) ?></span></div>
            </div>
        </div>
        <div class="kpi">
            <div class="kpi-bar" style="background:var(--navy)"></div>
            <div class="kpi-body">
                <div class="kpi-label">Quotes Issued</div>
                <div class="kpi-val"><?= number_format($monthQuo['cnt']) ?></div>
                <div class="kpi-note">quotes this month</div>
                <hr class="kpi-hr">
                <div class="kpi-foot"><span class="kpi-foot-label">Total value</span><span class="kpi-foot-val" style="color:var(--navy)"><?= rands($monthQuo['total']) ?></span></div>
            </div>
        </div>
        <div class="kpi">
            <div class="kpi-bar" style="background:var(--green)"></div>
            <div class="kpi-body">
                <div class="kpi-label">YTD Invoice Value</div>
                <div class="kpi-val" style="font-size:1.2rem"><?= rands($ytdInv['total']) ?></div>
                <div class="kpi-note">year to date — <?= $fyLabel ?></div>
                <hr class="kpi-hr">
                <div class="kpi-foot"><span class="kpi-foot-label">Invoice count</span><span class="kpi-foot-val"><?= number_format($ytdInv['cnt']) ?></span></div>
            </div>
        </div>
        <div class="kpi">
            <div class="kpi-bar" style="background:#c87840"></div>
            <div class="kpi-body">
                <div class="kpi-label">YTD Quote Value</div>
                <div class="kpi-val" style="font-size:1.2rem"><?= rands($ytdQuo['total']) ?></div>
                <div class="kpi-note">year to date — <?= $fyLabel ?></div>
                <hr class="kpi-hr">
                <div class="kpi-foot"><span class="kpi-foot-label">Quote count</span><span class="kpi-foot-val"><?= number_format($ytdQuo['cnt']) ?></span></div>
            </div>
        </div>
    </div>

    <!-- Financials -->
    <div class="sec"><span class="sec-title">Financials</span><div class="sec-line"></div><span class="sec-sub"><?= $fyLabel ?></span></div>
    <div class="grid g5">
        <div class="kpi">
            <div class="kpi-bar" style="background:var(--green)"></div>
            <div class="kpi-body">
                <div class="kpi-label">Payments Received</div>
                <div class="kpi-val" style="font-size:1.15rem"><?= rands($payments['total']) ?></div>
                <div class="kpi-note"><?= number_format($payments['cnt']) ?> records</div>
                <hr class="kpi-hr"><div class="kpi-foot"><span class="pill p-green">Collected</span></div>
            </div>
        </div>
        <div class="kpi">
            <div class="kpi-bar" style="background:var(--navy)"></div>
            <div class="kpi-body">
                <div class="kpi-label">Credit Notes</div>
                <div class="kpi-val" style="font-size:1.15rem"><?= rands($creditNotes['total']) ?></div>
                <div class="kpi-note"><?= number_format($creditNotes['cnt']) ?> notes</div>
                <hr class="kpi-hr"><div class="kpi-foot"><span class="pill p-navy">Issued</span></div>
            </div>
        </div>
        <div class="kpi">
            <div class="kpi-bar" style="background:var(--red)"></div>
            <div class="kpi-body">
                <div class="kpi-label">Unpaid Invoices</div>
                <div class="kpi-val"><?= number_format($outCount) ?></div>
                <div class="kpi-note">with balance due</div>
                <hr class="kpi-hr"><div class="kpi-foot"><span class="pill p-red">Outstanding</span></div>
            </div>
        </div>
        <div class="kpi">
            <div class="kpi-bar" style="background:var(--green)"></div>
            <div class="kpi-body">
                <div class="kpi-label">Paid Last 30 Days</div>
                <div class="kpi-val" style="font-size:1.15rem"><?= rands($paid30) ?></div>
                <div class="kpi-note">recent activity</div>
                <hr class="kpi-hr"><div class="kpi-foot"><span class="pill p-green">Recent</span></div>
            </div>
        </div>
        <div class="kpi">
            <div class="kpi-bar" style="background:var(--orange)"></div>
            <div class="kpi-body">
                <div class="kpi-label">Collection Rate</div>
                <div class="kpi-val"><?= $collectionRate ?>%</div>
                <div class="kpi-note">payments vs invoiced</div>
                <hr class="kpi-hr">
                <div class="kpi-foot">
                    <span class="pill <?= $collectionRate>=80?'p-green':($collectionRate>=50?'p-orange':'p-red') ?>"><?= $collectionRate>=80?'Healthy':($collectionRate>=50?'Moderate':'Low') ?></span>
                </div>
            </div>
        </div>
    </div>

    <!-- Trend -->
    <div class="sec"><span class="sec-title">Trend &amp; Exposure</span><div class="sec-line"></div><span class="sec-sub"><?= $fyLabel ?></span></div>
    <div class="cols3">
        <div class="card">
            <div class="card-head"><span class="card-title">Monthly Invoices vs Payments</span><span class="card-tag"><?= $fyLabel ?></span></div>
            <div class="card-body"><canvas id="barChart_curr" height="200"></canvas></div>
        </div>
        <div class="outstanding">
            <div class="out-top"><span class="out-top-label">Outstanding Balance</span></div>
            <div class="out-body">
                <div class="out-amount"><?= rands_raw($outTotal) ?></div>
                <div class="out-sub"><?= number_format($outCount) ?> unpaid invoices</div>
                <hr class="out-divider">
                <div class="out-row"><span class="out-row-label">Overdue (&gt;30 days)</span><span class="out-row-val v-danger"><?= rands_raw($outOverdue) ?></span></div>
                <div class="out-row"><span class="out-row-label">Due within 30 days</span><span class="out-row-val v-neutral"><?= rands_raw($outTotal - $outOverdue) ?></span></div>
                <div class="out-row"><span class="out-row-label">Paid last 30 days</span><span class="out-row-val v-ok"><?= rands_raw($paid30) ?></span></div>
                <div class="rate-wrap">
                    <div class="rate-labels"><span>Collection rate</span><span><?= $collectionRate ?>%</span></div>
                    <div class="rate-track"><div class="rate-fill" id="rate-fill" style="width:0%"></div></div>
                </div>
            </div>
        </div>
        <div class="card">
            <div class="card-head"><span class="card-title">Payments Collected</span><span class="card-tag"><?= $fyLabel ?></span></div>
            <div class="card-body"><canvas id="payChart_curr" height="200"></canvas></div>
        </div>
    </div>

    <!-- Breakdown -->
    <div class="sec"><span class="sec-title">Breakdown &amp; Clients</span><div class="sec-line"></div><span class="sec-sub"><?= $fyLabel ?></span></div>
    <div class="cols2">
        <div class="card">
            <div class="card-head"><span class="card-title">Invoices vs Quotes — <?= $fyLabel ?></span><span class="card-tag">By value</span></div>
            <div class="card-body" style="display:flex;align-items:center;gap:1.5rem;flex-wrap:wrap;">
                <div style="position:relative;width:160px;height:160px;flex-shrink:0;margin:0 auto;">
                    <div style="position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);text-align:center;">
                        <div style="font-size:1.2rem;font-weight:800;color:var(--text)"><?= $ytdInv['cnt'] + $ytdQuo['cnt'] ?></div>
                        <div style="font-size:.55rem;color:var(--text-3);text-transform:uppercase;letter-spacing:.5px;margin-top:1px">Total</div>
                    </div>
                    <canvas id="donutChart_curr"></canvas>
                </div>
                <div style="flex:1;min-width:140px;">
                    <div style="font-size:.58rem;font-weight:700;text-transform:uppercase;letter-spacing:.7px;color:var(--text-3);margin-bottom:.6rem">Value breakdown</div>
                    <?php
                    $totalVal = $ytdInv['total'] + $ytdQuo['total'];
                    foreach ([
                        ['Invoice Value', $totalVal>0?round($ytdInv['total']/$totalVal*100):0, rands_raw($ytdInv['total']),   '#f15b23'],
                        ['Quote Value',   $totalVal>0?round($ytdQuo['total']/$totalVal*100):0, rands_raw($ytdQuo['total']),   '#384b71'],
                        ['Collected',     $ytdInv['total']>0?min(100,round($payments['total']/$ytdInv['total']*100)):0, rands_raw($payments['total']), '#1e7e4a'],
                        ['Outstanding',   $ytdInv['total']>0?min(100,round($outTotal/$ytdInv['total']*100)):0, rands_raw($outTotal), '#c0392b'],
                    ] as [$label,$pct,$val,$col]):
                    ?>
                    <div style="display:flex;align-items:center;gap:.6rem;margin-bottom:.5rem">
                        <span style="font-size:.66rem;color:var(--text-2);flex:1;min-width:80px"><?= $label ?></span>
                        <div style="width:80px;height:5px;background:var(--border);border-radius:3px;overflow:hidden;flex-shrink:0">
                            <div style="width:<?= $pct ?>%;height:100%;border-radius:3px;background:<?= $col ?>"></div>
                        </div>
                        <span style="font-size:.66rem;font-weight:700;width:88px;text-align:right;color:var(--text);font-variant-numeric:tabular-nums"><?= $val ?></span>
                    </div>
                    <?php endforeach; ?>
                </div>
            </div>
        </div>
        <div class="card">
            <div class="card-head"><span class="card-title">Top Clients by Invoice Value</span><span class="card-tag"><?= $fyLabel ?></span></div>
            <div class="card-body" style="padding:.4rem .8rem .8rem">
                <?php if(empty($topClients)): ?>
                    <div style="text-align:center;padding:2rem;color:var(--text-3);font-size:.72rem">No client data yet</div>
                <?php else: $maxVal=$topClients[0]['total']?:1; ?>
                    <table class="ct">
                        <thead><tr><th>#</th><th>Client</th><th>Total Value</th><th class="mini-bar"></th></tr></thead>
                        <tbody>
                        <?php foreach($topClients as $i=>$c): $rc=['g','s','b','',''][$i]??''; ?>
                        <tr>
                            <td><span class="rank <?= $rc ?>"><?= $i+1 ?></span></td>
                            <td style="font-weight:600;color:var(--text)"><?= htmlspecialchars($c['name']) ?></td>
                            <td style="font-weight:700;color:var(--orange);font-variant-numeric:tabular-nums"><?= rands($c['total']) ?></td>
                            <td class="mini-bar"><div class="mini-bar-track"><div class="mini-bar-fill" style="width:<?= round($c['total']/$maxVal*100) ?>%"></div></div></td>
                        </tr>
                        <?php endforeach; ?>
                        </tbody>
                    </table>
                <?php endif; ?>
            </div>
        </div>
    </div>

    <!-- Monthly Breakdown -->
    <div class="sec"><span class="sec-title">Monthly Breakdown</span><div class="sec-line"></div><span class="sec-sub"><?= $fyLabel ?></span></div>
    <div class="card">
        <div class="card-body" style="padding:.4rem .6rem .6rem">
            <table class="dt">
                <thead>
                    <tr>
                        <th>Month</th>
                        <th>Invoices</th>
                        <th>Invoiced Total</th>
                        <th>Payments Received</th>
                        <th>Collection %</th>
                        <th>Balance</th>
                        <th style="text-align:left">Progress</th>
                    </tr>
                </thead>
                <tbody>
                <?php
                $fyTotInv = 0; $fyTotPay = 0; $fyTotCnt = 0;
                $maxMonthInv = max(array_column($fyMonths, 'inv_total') ?: [1]);
                foreach ($fyMonths as $m):
                    $fyTotInv += $m['inv_total']; $fyTotPay += $m['pay_total']; $fyTotCnt += $m['inv_count'];
                    $colPct = $m['inv_total'] > 0 ? round($m['pay_total'] / $m['inv_total'] * 100, 1) : 0;
                    $barW   = $maxMonthInv > 0 ? round($m['inv_total'] / $maxMonthInv * 80) : 0;
                    $payW   = $m['inv_total'] > 0 ? round($m['pay_total'] / $m['inv_total'] * $barW) : 0;
                    $hasData = $m['inv_count'] > 0;
                ?>
                <tr<?= !$hasData ? ' style="opacity:.45"' : '' ?>>
                    <td><?= $m['label'] ?></td>
                    <td><?= $hasData ? number_format($m['inv_count']) : '—' ?></td>
                    <td class="val-ora"><?= $hasData ? rands($m['inv_total']) : '—' ?></td>
                    <td class="val-grn"><?= $hasData ? rands($m['pay_total']) : '—' ?></td>
                    <td><?= $hasData ? $colPct . '%' : '—' ?></td>
                    <td class="val-red"><?= $hasData ? rands($m['balance']) : '—' ?></td>
                    <td style="text-align:left">
                        <?php if ($hasData): ?>
                        <div style="display:inline-flex;align-items:center;gap:3px;position:relative;height:8px;">
                            <div class="mb-track" style="width:<?= $barW ?>px">
                                <div class="mb-fill" style="width:<?= $payW ?>px;background:var(--green)"></div>
                            </div>
                        </div>
                        <?php else: ?>—<?php endif; ?>
                    </td>
                </tr>
                <?php endforeach; ?>
                </tbody>
                <tfoot>
                    <tr>
                        <td>FY Total</td>
                        <td><?= number_format($fyTotCnt) ?></td>
                        <td><?= rands($fyTotInv) ?></td>
                        <td><?= rands($fyTotPay) ?></td>
                        <td><?= $fyTotInv > 0 ? round($fyTotPay / $fyTotInv * 100, 1) . '%' : '—' ?></td>
                        <td><?= rands($fyTotInv - $fyTotPay) ?></td>
                        <td></td>
                    </tr>
                </tfoot>
            </table>
        </div>
    </div>

    <!-- Unpaid Invoices -->
    <div class="sec"><span class="sec-title">Unpaid Invoices</span><div class="sec-line"></div><span class="sec-sub"><?= count($unpaidInvoices) ?> with balance due</span></div>
    <div class="card">
        <div class="card-body" style="padding:.4rem .6rem .6rem">
        <?php if (empty($unpaidInvoices)): ?>
            <div style="text-align:center;padding:2.5rem;color:var(--text-3);font-size:.75rem">🎉 All invoices are paid — no outstanding balance.</div>
        <?php else: ?>
            <table class="dt">
                <thead>
                    <tr>
                        <th>Invoice #</th>
                        <th style="text-align:left">Client</th>
                        <th>Date</th>
                        <th>Invoice Total</th>
                        <th>Paid</th>
                        <th>Balance Due</th>
                        <th style="text-align:left">Status</th>
                        <th style="text-align:left">Age</th>
                    </tr>
                </thead>
                <tbody>
                <?php
                $unpaidTotal = 0;
                foreach ($unpaidInvoices as $inv):
                    $unpaidTotal += $inv['balance'];
                    $days = (int)$inv['days_old'];
                    if ($days <= 14)      { $ageCls = 'age-fresh'; $ageTxt = $days . 'd'; }
                    elseif ($days <= 30)  { $ageCls = 'age-warn';  $ageTxt = $days . 'd'; }
                    else                  { $ageCls = 'age-danger'; $ageTxt = $days . 'd overdue'; }
                    $st = strtolower($inv['status']);
                    if (str_contains($st, 'pending'))    { $stCls = 'st-pending'; $stTxt = 'Pending'; }
                    elseif (str_contains($st, 'opened')) { $stCls = 'st-opened';  $stTxt = 'Opened'; }
                    else                                 { $stCls = 'st-other';   $stTxt = htmlspecialchars($inv['status']); }
                    $invNum = $inv['invoice_number'] ?: 'INV-' . $inv['record_id'];
                ?>
                <tr>
                    <td style="font-variant-numeric:tabular-nums"><?= htmlspecialchars($invNum) ?></td>
                    <td style="text-align:left;max-width:160px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap"><?= htmlspecialchars($inv['client_name'] ?? '—') ?></td>
                    <td><?= date('d M Y', strtotime($inv['date_time_created'])) ?></td>
                    <td><?= rands($inv['inv_total']) ?></td>
                    <td class="val-grn"><?= rands($inv['paid']) ?></td>
                    <td class="val-red"><?= rands($inv['balance']) ?></td>
                    <td style="text-align:left"><span class="st-badge <?= $stCls ?>"><?= $stTxt ?></span></td>
                    <td style="text-align:left"><span class="age-badge <?= $ageCls ?>"><?= $ageTxt ?></span></td>
                </tr>
                <?php endforeach; ?>
                </tbody>
                <tfoot>
                    <tr>
                        <td colspan="5">Total Outstanding (<?= count($unpaidInvoices) ?> invoices)</td>
                        <td><?= rands($unpaidTotal) ?></td>
                        <td colspan="2"></td>
                    </tr>
                </tfoot>
            </table>
        <?php endif; ?>
        </div>
    </div>

    </div><!-- /panel-curr -->

    <!-- ═══════════════════════════════ PREVIOUS FY PANEL ═══════════════════════════════ -->
    <div class="fy-panel" id="panel-prev">

    <?php
    $prevHasData = $prevInv['cnt'] > 0;
    $invDiff     = $prevHasData ? $ytdInv['total'] - $prevInv['total'] : 0;
    $payDiff     = $prevHasData ? $payments['total'] - $prevPay['total'] : 0;
    function vs_pill($curr, $prev) {
        if ($prev == 0) return '<span class="vs-pill vs-flat">—</span>';
        $pct = round(($curr - $prev) / $prev * 100, 1);
        $cls = $pct > 0 ? 'vs-up' : ($pct < 0 ? 'vs-down' : 'vs-flat');
        $arrow = $pct > 0 ? '▲' : ($pct < 0 ? '▼' : '');
        return '<span class="vs-pill '.$cls.'">'.$arrow.' '.abs($pct).'%</span>';
    }
    ?>
    <div class="sec">
        <span class="sec-title">Previous Financial Year</span>
        <div class="sec-line"></div>
        <span class="sec-sub"><?= $prevFyLabel ?></span>
        <span class="prev-badge"><?= $prevFyStartYear ?> / <?= $prevFyEndYear ?></span>
    </div>

    <?php if (!$prevHasData): ?>
    <div style="background:var(--white);border:1px solid var(--border);border-radius:var(--r);padding:2.5rem;text-align:center;color:var(--text-3);font-size:.78rem;box-shadow:var(--shadow)">
        No data found for <?= $prevFyLabel ?>
    </div>
    <?php else: ?>

    <!-- KPI comparison cards -->
    <div class="grid g4">
        <div class="kpi">
            <div class="kpi-bar" style="background:var(--orange)"></div>
            <div class="kpi-body">
                <div class="kpi-label">Total Invoiced</div>
                <div class="kpi-val" style="font-size:1.2rem;color:var(--orange)"><?= rands($prevInv['total']) ?></div>
                <div class="kpi-note"><?= number_format($prevInv['cnt']) ?> invoices — <?= $prevFyLabel ?></div>
                <hr class="kpi-hr">
                <div class="kpi-foot">
                    <span class="kpi-foot-label">vs current FY</span>
                    <?= vs_pill($ytdInv['total'], $prevInv['total']) ?>
                </div>
            </div>
        </div>
        <div class="kpi">
            <div class="kpi-bar" style="background:var(--green)"></div>
            <div class="kpi-body">
                <div class="kpi-label">Payments Received</div>
                <div class="kpi-val" style="font-size:1.2rem;color:var(--green)"><?= rands($prevPay['total']) ?></div>
                <div class="kpi-note"><?= number_format($prevPay['cnt']) ?> records — <?= $prevFyLabel ?></div>
                <hr class="kpi-hr">
                <div class="kpi-foot">
                    <span class="kpi-foot-label">vs current FY</span>
                    <?= vs_pill($payments['total'], $prevPay['total']) ?>
                </div>
            </div>
        </div>
        <div class="kpi">
            <div class="kpi-bar" style="background:var(--red)"></div>
            <div class="kpi-body">
                <div class="kpi-label">Outstanding Balance</div>
                <div class="kpi-val" style="font-size:1.2rem;color:var(--red)"><?= rands($prevOutTotal) ?></div>
                <div class="kpi-note"><?= number_format($prevOutCount) ?> unpaid invoices</div>
                <hr class="kpi-hr">
                <div class="kpi-foot">
                    <span class="kpi-foot-label">vs current FY</span>
                    <?= vs_pill($outTotal, $prevOutTotal) ?>
                </div>
            </div>
        </div>
        <div class="kpi">
            <div class="kpi-bar" style="background:<?= $prevColRate >= 70 ? 'var(--green)' : ($prevColRate >= 40 ? 'var(--orange)' : 'var(--red)') ?>"></div>
            <div class="kpi-body">
                <div class="kpi-label">Collection Rate</div>
                <div class="kpi-val"><?= $prevColRate ?>%</div>
                <div class="kpi-note">payments vs invoiced</div>
                <hr class="kpi-hr">
                <div class="kpi-foot">
                    <span class="kpi-foot-label">vs current FY</span>
                    <?= vs_pill($collectionRate, $prevColRate) ?>
                </div>
            </div>
        </div>
    </div>

    <!-- Monthly breakdown table -->
    <div class="sec" style="margin-top:1.2rem"><span class="sec-title">Trend</span><div class="sec-line"></div><span class="sec-sub"><?= $prevFyLabel ?></span></div>
    <div class="cols2">
        <div class="card">
            <div class="card-head"><span class="card-title">Monthly Invoices vs Payments</span><span class="card-tag"><?= $prevFyLabel ?></span></div>
            <div class="card-body"><canvas id="barChart_prev" height="200"></canvas></div>
        </div>
        <div class="card">
            <div class="card-head"><span class="card-title">Payments Collected</span><span class="card-tag"><?= $prevFyLabel ?></span></div>
            <div class="card-body"><canvas id="payChart_prev" height="200"></canvas></div>
        </div>
    </div>

    <!-- Monthly breakdown table -->
    <div class="sec" style="margin-top:1.2rem"><span class="sec-title">Monthly Breakdown</span><div class="sec-line"></div><span class="sec-sub"><?= $prevFyLabel ?></span></div>
    <div class="card">
        <div class="card-body" style="padding:.4rem .6rem .6rem">
            <table class="dt">
                <thead>
                    <tr>
                        <th>Month</th><th>Invoices</th><th>Invoiced Total</th>
                        <th>Payments Received</th><th>Collection %</th><th>Balance</th>
                        <th style="text-align:left">Progress</th>
                    </tr>
                </thead>
                <tbody>
                <?php
                $pTotInv = 0; $pTotPay = 0; $pTotCnt = 0;
                $pMaxInv = max(array_column($prevMonths, 'inv_total') ?: [1]);
                foreach ($prevMonths as $m):
                    $pTotInv += $m['inv_total']; $pTotPay += $m['pay_total']; $pTotCnt += $m['inv_count'];
                    $colPct = $m['inv_total'] > 0 ? round($m['pay_total'] / $m['inv_total'] * 100, 1) : 0;
                    $barW   = $pMaxInv > 0 ? round($m['inv_total'] / $pMaxInv * 80) : 0;
                    $payW   = $m['inv_total'] > 0 ? round($m['pay_total'] / $m['inv_total'] * $barW) : 0;
                    $hasData = $m['inv_count'] > 0;
                ?>
                <tr<?= !$hasData ? ' style="opacity:.45"' : '' ?>>
                    <td><?= $m['label'] ?></td>
                    <td><?= $hasData ? number_format($m['inv_count']) : '—' ?></td>
                    <td class="val-ora"><?= $hasData ? rands($m['inv_total']) : '—' ?></td>
                    <td class="val-grn"><?= $hasData ? rands($m['pay_total']) : '—' ?></td>
                    <td><?= $hasData ? $colPct . '%' : '—' ?></td>
                    <td class="val-red"><?= $hasData ? rands($m['balance']) : '—' ?></td>
                    <td style="text-align:left">
                        <?php if ($hasData): ?>
                        <div class="mb-track" style="width:<?= $barW ?>px">
                            <div class="mb-fill" style="width:<?= $payW ?>px;background:var(--green)"></div>
                        </div>
                        <?php else: ?>—<?php endif; ?>
                    </td>
                </tr>
                <?php endforeach; ?>
                </tbody>
                <tfoot>
                    <tr>
                        <td>FY Total</td>
                        <td><?= number_format($pTotCnt) ?></td>
                        <td><?= rands($pTotInv) ?></td>
                        <td><?= rands($pTotPay) ?></td>
                        <td><?= $pTotInv > 0 ? round($pTotPay / $pTotInv * 100, 1) . '%' : '—' ?></td>
                        <td><?= rands($pTotInv - $pTotPay) ?></td>
                        <td></td>
                    </tr>
                </tfoot>
            </table>
        </div>
    </div>

    <!-- Top clients previous year -->
    <div class="sec" style="margin-top:1.2rem"><span class="sec-title">Top Clients</span><div class="sec-line"></div><span class="sec-sub"><?= $prevFyLabel ?></span></div>
    <div class="card">
        <div class="card-body" style="padding:.4rem .8rem .8rem">
        <?php if (empty($prevTopClients)): ?>
            <div style="text-align:center;padding:2rem;color:var(--text-3);font-size:.72rem">No client data for <?= $prevFyLabel ?></div>
        <?php else: $pMaxVal = $prevTopClients[0]['total'] ?: 1; ?>
            <table class="ct">
                <thead><tr><th>#</th><th>Client</th><th>Total Value</th><th class="mini-bar"></th></tr></thead>
                <tbody>
                <?php foreach ($prevTopClients as $i => $c): $rc = ['g','s','b','',''][$i] ?? ''; ?>
                <tr>
                    <td><span class="rank <?= $rc ?>"><?= $i + 1 ?></span></td>
                    <td style="font-weight:600;color:var(--text)"><?= htmlspecialchars($c['name']) ?></td>
                    <td style="font-weight:700;color:var(--orange);font-variant-numeric:tabular-nums"><?= rands($c['total']) ?></td>
                    <td class="mini-bar"><div class="mini-bar-track"><div class="mini-bar-fill" style="width:<?= round($c['total'] / $pMaxVal * 100) ?>%"></div></div></td>
                </tr>
                <?php endforeach; ?>
                </tbody>
            </table>
        <?php endif; ?>
        </div>
    </div>

    <?php endif; // end prevHasData ?>

    </div><!-- /panel-prev -->

</div><!-- /wrap -->

<script>
    /* ── FY Tab switcher ── */
    const chartsInit = {};

    function switchFY(id) {
        document.querySelectorAll('.fy-panel').forEach(p => p.classList.remove('active'));
        document.querySelectorAll('.fy-tab').forEach(t => t.classList.remove('active'));
        document.getElementById('panel-' + id).classList.add('active');
        document.getElementById('tab-' + id).classList.add('active');
        if (!chartsInit[id]) { buildCharts(id); chartsInit[id] = true; }
    }

    const n = new Date();
    document.getElementById('js-date').textContent = n.toLocaleDateString('en-ZA',{weekday:'short',day:'2-digit',month:'short',year:'numeric'});
    document.getElementById('js-year').textContent = '<?= $fyLabel ?>';
    setTimeout(()=>{ document.getElementById('rate-fill').style.width='<?= $collectionRate ?>%'; },300);

    Chart.defaults.color = '#9aaabf';
    Chart.defaults.borderColor = '#e3e8ef';
    Chart.defaults.font.family = "system-ui,sans-serif";
    Chart.defaults.font.size = 11;

    const tt = { backgroundColor:'#fff', titleColor:'#1d2535', bodyColor:'#4b5a72', borderColor:'#e3e8ef', borderWidth:1, padding:10, cornerRadius:6 };
    const fmt = v => 'R ' + Number(v).toLocaleString('en-ZA',{minimumFractionDigits:2,maximumFractionDigits:2});

    <?php
    $chartLabels     = array_column($fyMonths,   'label');
    $chartInv        = array_column($fyMonths,   'inv_total');
    $chartPay        = array_column($fyMonths,   'pay_total');
    $prevChartLabels = array_column($prevMonths, 'label');
    $prevChartInv    = array_column($prevMonths, 'inv_total');
    $prevChartPay    = array_column($prevMonths, 'pay_total');
    ?>

    const chartData = {
        curr: {
            labels: <?= json_encode($chartLabels) ?>,
            inv:    <?= json_encode(array_map('floatval', $chartInv)) ?>,
            pay:    <?= json_encode(array_map('floatval', $chartPay)) ?>,
            donut:  [<?= (int)$ytdInv['cnt'] ?>, <?= (int)$ytdQuo['cnt'] ?>]
        },
        prev: {
            labels: <?= json_encode($prevChartLabels) ?>,
            inv:    <?= json_encode(array_map('floatval', $prevChartInv)) ?>,
            pay:    <?= json_encode(array_map('floatval', $prevChartPay)) ?>,
            donut:  [<?= (int)$prevInv['cnt'] ?>, 0]
        }
    };

    function buildCharts(id) {
        const d = chartData[id];
        const sfx = '_' + id;
        const barEl  = document.getElementById('barChart'  + sfx);
        const payEl  = document.getElementById('payChart'  + sfx);
        const donutEl= document.getElementById('donutChart'+ sfx);

        if (barEl) new Chart(barEl, {
            type:'bar',
            data:{ labels: d.labels, datasets:[
                {label:'Invoices', data:d.inv, backgroundColor:'rgba(241,91,35,.13)', borderColor:'#f15b23', borderWidth:1.5, borderRadius:5, borderSkipped:false},
                {label:'Payments', data:d.pay, backgroundColor:'rgba(30,126,74,.12)',  borderColor:'#1e7e4a', borderWidth:1.5, borderRadius:5, borderSkipped:false}
            ]},
            options:{responsive:true, plugins:{
                legend:{display:true, position:'top', labels:{boxWidth:8, boxHeight:8, usePointStyle:true, color:'#4b5a72'}},
                tooltip:{...tt, callbacks:{label:c=>' '+fmt(c.raw)}}
            }, scales:{
                x:{grid:{display:false}, border:{display:false}},
                y:{beginAtZero:true, grid:{color:'#f2f4f7'}, border:{display:false}, ticks:{maxTicksLimit:5, callback:v=>'R'+Number(v/1000).toFixed(0)+'k'}}
            }}
        });

        if (payEl) new Chart(payEl, {
            type:'line',
            data:{labels: d.labels, datasets:[{
                label:'Payments', data:d.pay,
                borderColor:'#1e7e4a', backgroundColor:'rgba(30,126,74,.07)',
                borderWidth:2, pointRadius:4, pointBackgroundColor:'#1e7e4a', tension:.35, fill:true
            }]},
            options:{responsive:true, plugins:{legend:{display:false}, tooltip:{...tt, callbacks:{label:c=>' '+fmt(c.raw)}}},
            scales:{x:{grid:{display:false}, border:{display:false}}, y:{beginAtZero:true, grid:{color:'#f2f4f7'}, border:{display:false}, ticks:{maxTicksLimit:5, callback:v=>'R'+Number(v/1000).toFixed(0)+'k'}}}}
        });

        if (donutEl) new Chart(donutEl, {
            type:'doughnut',
            data:{labels:['Invoices','Quotes'], datasets:[{data: d.donut, backgroundColor:['#f15b23','#384b71'], borderWidth:4, borderColor:'#fff', hoverOffset:5}]},
            options:{cutout:'74%', responsive:true, maintainAspectRatio:false, plugins:{legend:{display:false}, tooltip:{...tt}}}
        });
    }

    // Init current FY charts on load
    buildCharts('curr');
    chartsInit['curr'] = true;
</script>

</body>
</html>