<?php
/**
 * Report viewer — PowerBI/Tableau-style.
 *
 * Tabs: Dashboard · Summary · Pivot (Look Up) · Analytics · Detail · History
 *
 * Features:
 *  - Cross-filtering (click a chart bar/segment → filters whole view)
 *  - Drill-down (click month → adds period filter)
 *  - Comparison mode (?compare=<upload_id>) shows MoM/period deltas vs another snapshot
 *  - Bookmarks (saved filter + tab states, localStorage per user)
 *  - Conditional formatting (in-cell data bars on Summary tables)
 *  - Forecast overlay (simple linear regression, next 3 months)
 *  - Heatmap, treemap, funnel, gauge, day-of-week (Analytics tab)
 *  - PNG/CSV export on charts, full-screen toggle
 *  - Keyboard shortcuts: 1-6 = tabs, F = full-screen, B = open bookmarks
 */
require_once __DIR__ . '/../includes/config.php';
$me = require_login('internal');

$pdo       = db();
$reportId  = (int) ($_GET['id'] ?? 0);
if ($reportId > 0) require_report_access($reportId);   // SysAdmin-granted per-report access
$uploadId  = (int) ($_GET['upload'] ?? 0);
$compareId = (int) ($_GET['compare'] ?? 0);
$tab       = $_GET['tab'] ?? 'dashboard';
$fFacility = trim((string) ($_GET['facility'] ?? ''));
$fPeriod   = trim((string) ($_GET['period'] ?? ''));
$fProvider = trim((string) ($_GET['provider'] ?? ''));

$rep = $pdo->prepare('SELECT r.*, p.name AS pname, c.name AS cname, c.id AS cid, v.name AS vname
    FROM reports r JOIN processes p ON p.id = r.process_id
    JOIN clients c ON c.id = p.client_id JOIN verticals v ON v.id = c.vertical_id
    WHERE r.id=? AND r.deleted_at IS NULL');
$rep->execute([$reportId]);
$report = $rep->fetch();
if (!$report) { flash('error','Report not found.'); redirect('/admin/report-builder.php'); }

$latest = $pdo->prepare("SELECT * FROM report_uploads WHERE report_id=? AND status='completed' ORDER BY created_at DESC LIMIT 1");
$latest->execute([$reportId]); $latest = $latest->fetch();

$activeUpload = null;
if ($uploadId) {
    $u = $pdo->prepare('SELECT * FROM report_uploads WHERE id=? AND report_id=?');
    $u->execute([$uploadId, $reportId]); $activeUpload = $u->fetch();
}
if (!$activeUpload) $activeUpload = $latest;

/* ============= LOAD ROWS ============= */
function load_rows_for_report(PDO $pdo, int $reportId, ?int $uploadId = null): array {
    if ($uploadId) {
        // Load from archive if not the latest active set
        $st = $pdo->prepare('SELECT data_json, period_label FROM report_data WHERE report_id=? AND upload_id=?');
        $st->execute([$reportId, $uploadId]);
        $rows = [];
        while ($r = $st->fetch()) {
            $row = json_decode($r['data_json'], true) ?: [];
            $row['_period'] = $r['period_label'];
            $rows[] = $row;
        }
        if ($rows) return $rows;
        // Fallback: archive (try both upload_id and original_upload_id)
        $st = $pdo->prepare('SELECT data_json, period_label FROM report_data_archive
                             WHERE report_id=? AND (upload_id=? OR original_upload_id=?)');
        $st->execute([$reportId, $uploadId, $uploadId]);
        while ($r = $st->fetch()) {
            $row = json_decode($r['data_json'], true) ?: [];
            $row['_period'] = $r['period_label'];
            $rows[] = $row;
        }
        return $rows;
    }
    $st = $pdo->prepare('SELECT data_json, period_label FROM report_data WHERE report_id=? AND is_active=1');
    $st->execute([$reportId]);
    $rows = [];
    while ($r = $st->fetch()) {
        $row = json_decode($r['data_json'], true) ?: [];
        $row['_period'] = $r['period_label'];
        $rows[] = $row;
    }
    return $rows;
}

$allRows = $activeUpload ? load_rows_for_report($pdo, $reportId, (int) $activeUpload['id']) : [];
if (!$allRows && $activeUpload) {
    // Some setups store all rows under is_active=1 without per-upload tag — fall back
    $allRows = load_rows_for_report($pdo, $reportId);
}

/* ============= HELPER FUNCTIONS ============= */
function mlabel($dos): ?string {
    if ($dos === null || $dos === '') return null;
    if (is_numeric($dos) && $dos > 1 && $dos < 100000) {
        $unix = -2208988800 + ($dos - 1) * 86400;
        if ($dos >= 60) $unix -= 86400;
        return gmdate('M', (int) round($unix));
    }
    $s = (string) $dos;
    foreach (['Y-m-d','Y-m-d H:i:s','m/d/Y','d/m/Y','d-m-Y','d-M-Y'] as $fmt) {
        $dt = DateTime::createFromFormat($fmt, $s);
        if ($dt !== false) return $dt->format('M');
    }
    $ts = strtotime($s);
    return $ts ? date('M', $ts) : null;
}
function dos_normalize($dos): ?string {
    if ($dos === null || $dos === '') return null;
    if (is_numeric($dos) && $dos > 1 && $dos < 100000) {
        $unix = -2208988800 + ($dos - 1) * 86400;
        if ($dos >= 60) $unix -= 86400;
        return gmdate('Y-m-d', (int) round($unix));
    }
    $s = (string) $dos;
    foreach (['Y-m-d','Y-m-d H:i:s','m/d/Y','d/m/Y','d-m-Y','d-M-Y'] as $fmt) {
        $dt = DateTime::createFromFormat($fmt, $s);
        if ($dt !== false) return $dt->format('Y-m-d');
    }
    $ts = strtotime($s);
    return $ts ? date('Y-m-d', $ts) : null;
}
function fmt_money($v) { return '$' . number_format((float)$v, 2); }
function dollar_cells($v): string {
    $v = (float) $v;
    if ($v == 0) return '<td class="dollar-col">$</td><td class="dollar-num">-</td>';
    return '<td class="dollar-col">$</td><td class="dollar-num">' . number_format($v, 2) . '</td>';
}
/* Client wants the FULL accurate $ amount everywhere — not K/M abbreviated. */
function fmt_money_short($v) {
    return '$' . number_format((float) $v, 2);
}
function fmt_int($v) { return number_format((int)$v); }
function pct($num, $den) { return $den > 0 ? ($num/$den)*100 : 0; }
function pct_delta($cur, $prev) {
    if ($prev == 0) return $cur > 0 ? 100 : 0;
    return (($cur - $prev) / abs($prev)) * 100;
}
/** Simple linear regression: returns [slope, intercept] */
function linear_fit(array $ys): array {
    $n = count($ys); if ($n < 2) return [0, $ys ? $ys[0] : 0];
    $sx = $sy = $sxx = $sxy = 0;
    for ($i = 0; $i < $n; $i++) {
        $sx += $i; $sy += $ys[$i]; $sxx += $i*$i; $sxy += $i*$ys[$i];
    }
    $den = $n*$sxx - $sx*$sx;
    if ($den == 0) return [0, $sy/$n];
    $m = ($n*$sxy - $sx*$sy) / $den;
    $b = ($sy - $m*$sx) / $n;
    return [$m, $b];
}

/* ============= AGGREGATE CURRENT ROWS ============= */
function aggregate(array $rows): array {
    $monthBuckets = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
    $byMonth = [];
    foreach ($rows as $r) {
        $m = mlabel($r['dos'] ?? null); if (!$m) continue;
        if (!isset($byMonth[$m])) $byMonth[$m] = ['claims'=>0,'charge'=>0,'pri'=>0,'sec'=>0,'ter'=>0,'pat_paid'=>0,'bal'=>0,'pat_bal'=>0,'expected'=>0,'paid'=>0,'unpaid'=>0];
        $byMonth[$m]['claims']++;
        $byMonth[$m]['charge']   += (float)($r['charge_amount'] ?? 0);
        $byMonth[$m]['pri']      += (float)($r['primary_insurance_paid'] ?? 0);
        $byMonth[$m]['sec']      += (float)($r['secondary_insurance_paid'] ?? 0);
        $byMonth[$m]['ter']      += (float)($r['tertiary_insurance_paid'] ?? 0);
        $byMonth[$m]['pat_paid'] += (float)($r['patient_payment_amount'] ?? 0);
        $byMonth[$m]['bal']      += (float)($r['insurance_balance'] ?? 0);
        $byMonth[$m]['pat_bal']  += (float)($r['patient_balance'] ?? 0);
        $byMonth[$m]['expected'] += (float)($r['amount_allowed'] ?? 0);
        if ((float)($r['primary_insurance_paid'] ?? 0) > 0) $byMonth[$m]['paid']++; else $byMonth[$m]['unpaid']++;
    }
    uksort($byMonth, fn($a,$b) => array_search($a, $monthBuckets) <=> array_search($b, $monthBuckets));
    $totals = ['claims'=>0,'charge'=>0,'pri'=>0,'sec'=>0,'ter'=>0,'pat_paid'=>0,'bal'=>0,'pat_bal'=>0,'expected'=>0,'paid'=>0,'unpaid'=>0];
    foreach ($byMonth as $m) foreach ($totals as $k=>$v) $totals[$k] += $m[$k];
    return [$byMonth, $totals];
}

/* ============= APPLY FILTERS ============= */
$rows = $allRows;
if ($fFacility !== '') $rows = array_values(array_filter($rows, fn($r) => ($r['facility'] ?? '') === $fFacility));
if ($fPeriod !== '')   $rows = array_values(array_filter($rows, fn($r) => ($r['_period'] ?? '') === $fPeriod));
if ($fProvider !== '') $rows = array_values(array_filter($rows, fn($r) => ($r['provider_name'] ?? '') === $fProvider));

$facilities = array_values(array_unique(array_filter(array_column($allRows, 'facility')))); sort($facilities);
$providers  = array_values(array_unique(array_filter(array_column($allRows, 'provider_name')))); sort($providers);
$periods    = array_values(array_unique(array_filter(array_column($allRows, '_period'))));   sort($periods);

[$byMonth, $totals] = aggregate($rows);

/* ============= COMPARISON MODE ============= */
$cmpRows = $cmpByMonth = $cmpTotals = null; $cmpUpload = null;
if ($compareId && $compareId != ($activeUpload['id'] ?? 0)) {
    $st = $pdo->prepare('SELECT * FROM report_uploads WHERE id=? AND report_id=?');
    $st->execute([$compareId, $reportId]); $cmpUpload = $st->fetch();
    if ($cmpUpload) {
        $cmpAll = load_rows_for_report($pdo, $reportId, (int) $cmpUpload['id']);
        $cmpFiltered = $cmpAll;
        if ($fFacility !== '') $cmpFiltered = array_values(array_filter($cmpFiltered, fn($r) => ($r['facility'] ?? '') === $fFacility));
        if ($fPeriod !== '')   $cmpFiltered = array_values(array_filter($cmpFiltered, fn($r) => ($r['_period'] ?? '') === $fPeriod));
        if ($fProvider !== '') $cmpFiltered = array_values(array_filter($cmpFiltered, fn($r) => ($r['provider_name'] ?? '') === $fProvider));
        [$cmpByMonth, $cmpTotals] = aggregate($cmpFiltered);
    }
}

/* ============= AUTO-INSIGHTS ============= */
$insights = [];
if ($byMonth) {
    $maxM=$minM=null; $maxV=-INF; $minV=INF;
    foreach ($byMonth as $m=>$v) {
        if ($v['charge'] > $maxV) { $maxV=$v['charge']; $maxM=$m; }
        if ($v['charge'] < $minV) { $minV=$v['charge']; $minM=$m; }
    }
    $vals = array_map(fn($x) => $x['charge'], array_values($byMonth));
    $mean = $vals ? array_sum($vals)/count($vals) : 0;
    $sd = 0;
    if ($vals) { $variance = array_sum(array_map(fn($v)=>pow($v-$mean,2), $vals))/count($vals); $sd = sqrt($variance); }
    $monthsArr = array_values($byMonth);
    $trend = 'flat';
    if (count($monthsArr) >= 2) {
        $last = end($monthsArr)['charge']; $prev = prev($monthsArr)['charge'];
        if ($prev > 0) {
            $delta = (($last - $prev) / $prev) * 100;
            $trend = $delta > 5 ? 'up' : ($delta < -5 ? 'down' : 'flat');
        }
    }
    $insights = [
        'best_month'  => ['m'=>$maxM,'v'=>$maxV],
        'worst_month' => ['m'=>$minM,'v'=>$minV],
        'mean'        => $mean, 'sd' => $sd, 'trend' => $trend,
        'collection_pct' => pct($totals['paid'] ?? 0, $totals['claims'] ?? 0),
        'outstanding_pct'=> pct($totals['bal'] + $totals['pat_bal'], $totals['charge']),
    ];
    $anomalies = [];
    foreach ($byMonth as $m=>$v) {
        if ($sd > 0 && abs($v['charge'] - $mean) > 2 * $sd) {
            $anomalies[] = ['m'=>$m, 'val'=>$v['charge'], 'dir'=>$v['charge']>$mean?'+':'-'];
        }
    }
    $insights['anomalies'] = $anomalies;
}

/* ============= PER-FACILITY (top 10) ============= */
$byFacility = [];
foreach ($rows as $r) {
    $f = $r['facility'] ?? '(unknown)';
    if (!isset($byFacility[$f])) $byFacility[$f] = ['charge'=>0,'visits'=>0,'bal'=>0,'pri'=>0,'sec'=>0];
    $byFacility[$f]['charge'] += (float)($r['charge_amount'] ?? 0);
    $byFacility[$f]['visits']++;
    $byFacility[$f]['bal']    += (float)($r['insurance_balance'] ?? 0);
    $byFacility[$f]['pri']    += (float)($r['primary_insurance_paid'] ?? 0);
    $byFacility[$f]['sec']    += (float)($r['secondary_insurance_paid'] ?? 0);
}
uasort($byFacility, fn($a,$b) => $b['charge'] <=> $a['charge']);
$byFacility10 = array_slice($byFacility, 0, 10, true);

/* ============= PER-PROVIDER (top 10) ============= */
$byProvider = [];
foreach ($rows as $r) {
    $p = $r['provider_name'] ?? '';
    if (!$p) continue;
    if (!isset($byProvider[$p])) $byProvider[$p] = ['charge'=>0,'visits'=>0];
    $byProvider[$p]['charge'] += (float)($r['charge_amount'] ?? 0);
    $byProvider[$p]['visits']++;
}
uasort($byProvider, fn($a,$b) => $b['charge'] <=> $a['charge']);
$byProvider10 = array_slice($byProvider, 0, 10, true);

/* ============= DAY-OF-WEEK PATTERN ============= */
$byDow = ['Mon'=>0,'Tue'=>0,'Wed'=>0,'Thu'=>0,'Fri'=>0,'Sat'=>0,'Sun'=>0];
$dowMap = [1=>'Mon',2=>'Tue',3=>'Wed',4=>'Thu',5=>'Fri',6=>'Sat',7=>'Sun'];
foreach ($rows as $r) {
    $d = dos_normalize($r['dos'] ?? null); if (!$d) continue;
    $w = (int) date('N', strtotime($d));
    if (isset($dowMap[$w])) $byDow[$dowMap[$w]] += (float)($r['charge_amount'] ?? 0);
}

/* ============= FACILITY × MONTH HEATMAP ============= */
$monthOrder = array_keys($byMonth);
$heatmap = []; // [facility => [month => charge]]
foreach ($rows as $r) {
    $f = $r['facility'] ?? '(unknown)';
    $m = mlabel($r['dos'] ?? null);
    if (!$m) continue;
    if (!isset($heatmap[$f])) $heatmap[$f] = [];
    if (!isset($heatmap[$f][$m])) $heatmap[$f][$m] = 0;
    $heatmap[$f][$m] += (float)($r['charge_amount'] ?? 0);
}
// Take top 12 facilities for heatmap
$heatFacilities = array_keys(array_slice($byFacility, 0, 12, true));
$heatSeries = [];
foreach ($heatFacilities as $f) {
    $data = [];
    foreach ($monthOrder as $m) {
        $data[] = ['x' => $m, 'y' => round($heatmap[$f][$m] ?? 0, 2)];
    }
    $heatSeries[] = ['name' => mb_substr($f, 0, 32), 'data' => $data];
}

/* ============= PIVOT (Facility → Month → Day) ============= */
$pivot = [];
foreach ($rows as $r) {
    $f = $r['facility'] ?? '(unknown)';
    $dos = dos_normalize($r['dos'] ?? null); if (!$dos) continue;
    $m = mlabel($dos); $d = date('j-M', strtotime($dos));
    $pivot[$f][$m][$d][] = [
        'visits'=>1, 'charge'=>(float)($r['charge_amount']??0), 'pri'=>(float)($r['primary_insurance_paid']??0),
        'sec'=>(float)($r['secondary_insurance_paid']??0), 'bal'=>(float)($r['insurance_balance']??0),
    ];
}

/* ============= FORECAST (next 3 months from monthly charge series) ============= */
$forecast = [];
if (count($byMonth) >= 3) {
    $monthBuckets = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
    $hist = array_values(array_map(fn($x)=>$x['charge'], $byMonth));
    [$slope, $intercept] = linear_fit($hist);
    $lastIdx = count($hist) - 1;
    $lastMonth = array_key_last($byMonth);
    $lastIdxInYear = array_search($lastMonth, $monthBuckets);
    for ($i = 1; $i <= 3; $i++) {
        $val = max(0, $intercept + $slope * ($lastIdx + $i));
        $nextMonth = $monthBuckets[($lastIdxInYear + $i) % 12];
        $forecast[$nextMonth] = $val;
    }
}

/* ============= SUMMARY SUB-TABLES ============= */
$unbilled = []; $unpaid = []; $hold = [];
foreach ($byMonth as $m=>$_) { $unbilled[$m]=['c'=>0,'exp'=>0]; $unpaid[$m]=['c'=>0,'charge'=>0,'exp'=>0]; $hold[$m]=['c'=>0,'exp'=>0]; }
foreach ($rows as $r) {
    $m = mlabel($r['dos'] ?? null); if (!$m) continue;
    if (!isset($unbilled[$m])) { $unbilled[$m]=['c'=>0,'exp'=>0]; $unpaid[$m]=['c'=>0,'charge'=>0,'exp'=>0]; $hold[$m]=['c'=>0,'exp'=>0]; }
    $charge = (float)($r['charge_amount'] ?? 0);
    $pri    = (float)($r['primary_insurance_paid'] ?? 0);
    $sec    = (float)($r['secondary_insurance_paid'] ?? 0);
    $bal    = (float)($r['insurance_balance'] ?? 0);
    $allowed= (float)($r['amount_allowed'] ?? 0);
    $woAmt  = (float)($r['wo_amount'] ?? 0);
    if ($woAmt > 0 && $pri == 0 && $sec == 0) {
        $unbilled[$m]['c']++; $unbilled[$m]['exp'] += $allowed;
    }
    if ($pri == 0 && $bal > 0) {
        if ($bal < $charge * 0.4 && $charge > 0) {
            $hold[$m]['c']++; $hold[$m]['exp'] += $allowed;
        } else {
            $unpaid[$m]['c']++; $unpaid[$m]['charge'] += $charge; $unpaid[$m]['exp'] += $allowed;
        }
    }
}
$sumA = ['c'=>0,'exp'=>0]; $sumB = ['c'=>0,'charge'=>0,'exp'=>0]; $sumC = ['c'=>0,'exp'=>0];
foreach ($unbilled as $v) { $sumA['c']+=$v['c']; $sumA['exp']+=$v['exp']; }
foreach ($unpaid as $v)   { $sumB['c']+=$v['c']; $sumB['charge']+=$v['charge']; $sumB['exp']+=$v['exp']; }
foreach ($hold as $v)     { $sumC['c']+=$v['c']; $sumC['exp']+=$v['exp']; }

/* Helpers for cross-filter URL building */
function rv_url(int $reportId, array $extra = []): string {
    global $tab, $activeUpload, $fFacility, $fPeriod, $fProvider, $compareId;
    $params = ['id' => $reportId, 'tab' => $tab, 'upload' => $activeUpload['id'] ?? 0];
    if ($fFacility !== '') $params['facility'] = $fFacility;
    if ($fPeriod   !== '') $params['period']   = $fPeriod;
    if ($fProvider !== '') $params['provider'] = $fProvider;
    if ($compareId)        $params['compare']  = $compareId;
    foreach ($extra as $k => $v) {
        if ($v === null || $v === '') unset($params[$k]); else $params[$k] = $v;
    }
    return url('/admin/report-view.php?' . http_build_query($params));
}

$pageTitle = $report['name'];
require __DIR__ . '/../includes/header.php';
?>
<style>
.rv-title-bar { padding:14px 0 10px; border-bottom: 1px solid var(--m-border); margin-bottom:14px; }
.rv-title-bar .title { font-size: 1.45rem; font-weight: 700; line-height:1.2; color: var(--m-text); }
.rv-title-bar .crumbs { font-size: .82rem; color: var(--m-text-soft); margin-top:4px; }
.rv-title-bar .crumbs .sep { opacity:.4; margin: 0 6px; }

/* INSIGHT BANNER */
.rv-insights {
    background: linear-gradient(135deg, #1f2937 0%, #1e3a8a 100%);
    color:#fff; border-radius:12px; padding:16px 20px; margin-bottom:14px;
    box-shadow: var(--m-shadow-md);
}
.rv-insights .insight-stat { padding-right: 18px; border-right: 1px solid rgba(255,255,255,.12); margin-right: 12px; }
.rv-insights .insight-stat:last-child { border-right: 0; }
.rv-insights .lbl { font-size:.7rem; text-transform: uppercase; letter-spacing: .04em; opacity: .65; }
.rv-insights .val { font-size:1.15rem; font-weight: 700; line-height: 1.2; margin-top:2px; }
.rv-insights .trend-up   { color:#86efac; }
.rv-insights .trend-down { color:#fca5a5; }
.rv-insights .trend-flat { color:#cbd5e1; }
.rv-insights .anomaly { background: rgba(245, 158, 11, .15); padding:2px 8px; border-radius:12px; font-size:.75rem; margin-right:6px; }

/* KPI STRIP */
.kpi-strip .kpi { background: var(--m-surface); border:1px solid var(--m-border); border-radius:10px; padding:11px 13px; transition: all .12s; }
.kpi-strip .kpi:hover { border-color: var(--m-border-strong); box-shadow: var(--m-shadow-md); }
.kpi-strip .kpi .lbl { font-size:.65rem; text-transform: uppercase; color: var(--m-text-soft); letter-spacing:.04em; }
.kpi-strip .kpi .val { font-size:1.4rem; font-weight:700; line-height:1.1; color: var(--m-text); margin-top:2px; font-variant-numeric: tabular-nums; }
.kpi-strip .kpi .delta { font-size:.72rem; margin-top:2px; }
.kpi-strip .kpi .delta.up   { color: var(--m-good); }
.kpi-strip .kpi .delta.down { color: var(--m-bad); }
.kpi-strip .kpi .spark { height: 32px; margin-top:4px; }

/* FILTER BAR */
.rv-filters { background: var(--m-surface); border:1px solid var(--m-border); border-radius:10px; padding:10px 14px; margin-bottom:14px; }
.rv-filters .form-select-sm, .rv-filters .form-control-sm { font-size:.82rem; }
.filter-chips { display:inline-flex; gap:6px; flex-wrap:wrap; }
.filter-chip {
    display:inline-flex; align-items:center; gap:6px;
    background: var(--m-surface-2); border:1px solid var(--m-border);
    padding: 3px 8px 3px 10px; border-radius:14px;
    font-size:.78rem; color: var(--m-text);
}
.filter-chip a { color: var(--m-text-soft); text-decoration:none; }
.filter-chip a:hover { color: var(--m-bad); }

/* TABS */
.rv-tabs { border-bottom: 2px solid var(--m-border); margin-bottom:14px; }
.rv-tabs .nav-link { padding: 9px 16px; font-size:.88rem; color: var(--m-text-soft); border-radius:6px 6px 0 0; }
.rv-tabs .nav-link:hover { color: var(--m-text); }
.rv-tabs .nav-link.active { color:var(--tblr-primary); border-bottom: 2px solid var(--tblr-primary); margin-bottom:-2px; background:transparent; font-weight: 600; }
.rv-tabs .nav-link kbd { background: var(--m-surface-2); border: 1px solid var(--m-border); padding: 0 4px; border-radius: 3px; font-size: .65rem; color: var(--m-text-soft); margin-left: 6px; font-family: inherit; }

/* CHART CARD */
.chart-card { position: relative; }
.chart-card .chart-actions {
    position: absolute; top: 8px; right: 8px;
    display: flex; gap: 4px; z-index: 5;
    opacity: 0; transition: opacity .15s;
}
.chart-card:hover .chart-actions { opacity: 1; }
.chart-card .chart-actions button {
    background: var(--m-surface-2); border: 1px solid var(--m-border);
    color: var(--m-text-soft); width: 26px; height: 26px;
    border-radius: 5px; display: inline-flex; align-items: center; justify-content: center;
    cursor: pointer; transition: all .12s;
}
.chart-card .chart-actions button:hover { color: var(--tblr-primary); border-color: var(--tblr-primary); }

/* CONDITIONAL FORMATTING */
.cell-bar {
    display: block; position: relative;
    padding: 2px 6px;
}
.cell-bar::before {
    content: ''; position: absolute; left:0; top:0; bottom:0;
    background: linear-gradient(90deg, rgba(32,107,196,.18), rgba(32,107,196,.06));
    z-index: 0;
}
.cell-bar > span { position: relative; z-index: 1; }

/* DELTA PILL (comparison mode) */
.delta-pill {
    display:inline-block; padding:1px 6px; border-radius:4px;
    font-size:.72rem; font-weight:600; margin-left:6px;
    font-variant-numeric: tabular-nums;
}
.delta-pill.up   { background:#dcfce7; color:#166534; }
.delta-pill.down { background:#fee2e2; color:#991b1b; }
.delta-pill.flat { background: var(--m-surface-2); color: var(--m-text-soft); }
html[data-bs-theme="dark"] .delta-pill.up { background:#0c4a32; color:#86efac; }
html[data-bs-theme="dark"] .delta-pill.down { background:#4a1a1a; color:#fca5a5; }

/* BOOKMARKS DROPDOWN */
.bm-list { max-height: 280px; overflow-y: auto; }
.bm-item { display:flex; align-items:center; gap:8px; padding:6px 10px; cursor:pointer; }
.bm-item:hover { background: rgba(32,107,196,.08); }
.bm-item .ti { color: var(--m-text-soft); }
.bm-item .name { flex-grow:1; font-size: .85rem; }
.bm-item .del { color: var(--m-text-soft); cursor: pointer; }
.bm-item .del:hover { color: var(--m-bad); }

/* FULLSCREEN */
.rv-fullscreen { position: fixed; inset: 0; background: var(--m-bg); z-index: 1500; padding: 20px; overflow: auto; }

/* In-table data bar (Summary) */
.databar { position: relative; display: inline-block; min-width: 60px; padding-left: 4px; }
.databar .bar { position: absolute; left:0; top: 50%; transform: translateY(-50%); height: 16px; border-radius: 2px; opacity: .25; pointer-events: none; }
.databar .v { position: relative; z-index: 1; font-variant-numeric: tabular-nums; }

/* Snapshot/compare badge */
.snap-badge { display:inline-flex; align-items:center; gap:6px; font-size:.78rem; padding:3px 9px; border-radius:99px; background: var(--m-surface-2); border:1px solid var(--m-border); color: var(--m-text-soft); }
</style>

<div class="container-xl">

<!-- =============== TITLE BAR =============== -->
<div class="rv-title-bar">
    <div class="row align-items-center g-3">
        <div class="col">
            <a href="<?= e(url('/admin/reports.php')) ?>" class="text-secondary small text-decoration-none"><i class="ti ti-chevron-left"></i> Reports</a>
            <div class="title mt-1"><?= e($report['name']) ?>
                <code class="ms-2 text-secondary fw-normal" style="font-size:.6em"><?= e($report['code']) ?></code>
            </div>
            <div class="crumbs">
                <a href="<?= e(url('/admin/verticals.php')) ?>"><i class="ti ti-building me-1"></i><?= e($report['vname']) ?></a>
                <span class="sep">›</span>
                <a href="<?= e(url('/admin/clients.php')) ?>"><?= e($report['cname']) ?></a>
                <span class="sep">›</span>
                <a href="<?= e(url('/admin/processes.php')) ?>"><?= e($report['pname']) ?></a>
                <?php if ($activeUpload): ?>
                    <span class="sep">·</span>
                    <span class="snap-badge"><i class="ti ti-camera"></i> Snapshot <?= e(fmt_dt($activeUpload['completed_at'] ?? $activeUpload['created_at'])) ?></span>
                <?php endif; ?>
                <?php if ($cmpUpload): ?>
                    <span class="snap-badge" style="margin-left:4px;background:#fef3c7;color:#92400e;border-color:#fde68a"><i class="ti ti-arrows-diff"></i> Comparing vs <?= e(fmt_date($cmpUpload['completed_at'] ?? $cmpUpload['created_at'])) ?></span>
                <?php endif; ?>
            </div>
        </div>
        <div class="col-auto">
            <div class="btn-group btn-group-sm me-1" role="group">
                <a href="<?= e(url('/admin/upload.php?report_id='.$reportId.'&mode=append')) ?>" class="btn btn-success" title="Add new rows on top of existing data">
                    <i class="ti ti-plus me-1"></i>Append
                </a>
                <a href="<?= e(url('/admin/upload.php?report_id='.$reportId.'&mode=replace_by_period')) ?>" class="btn btn-warning" title="Wipe rows for the periods detected in your file, keep all others">
                    <i class="ti ti-refresh me-1"></i>Replace period
                </a>
                <a href="<?= e(url('/admin/upload.php?report_id='.$reportId.'&mode=replace_all')) ?>" class="btn btn-danger" title="Wipe ALL data and load fresh — current data is auto-archived">
                    <i class="ti ti-trash me-1"></i>Replace all
                </a>
            </div>

            <div class="btn-group btn-group-sm me-1">
                <button type="button" class="btn btn-outline-primary dropdown-toggle" data-bs-toggle="dropdown" title="Bookmarks">
                    <i class="ti ti-bookmark me-1"></i>Views
                </button>
                <div class="dropdown-menu dropdown-menu-end" style="min-width:280px" id="bm_menu">
                    <h6 class="dropdown-header">Saved views</h6>
                    <div class="bm-list" id="bm_list"><div class="text-secondary small px-3 py-2">No saved views yet.</div></div>
                    <div class="dropdown-divider"></div>
                    <button class="dropdown-item" onclick="bmSaveCurrent()"><i class="ti ti-bookmark-plus me-2"></i>Save current view…</button>
                </div>
            </div>

            <div class="btn-group btn-group-sm">
                <a href="<?= e(url('/admin/export.php?id='.$reportId.'&output=0&format=xlsx_legacy')) ?>" class="btn btn-outline-success" title="Export full Excel"><i class="ti ti-file-spreadsheet me-1"></i>Excel</a>
                <a href="<?= e(url('/admin/export.php?id='.$reportId.'&output=0&format=csv_dashboard')) ?>" class="btn btn-outline-success" title="Export dashboard CSV"><i class="ti ti-file-text me-1"></i>CSV</a>
                <a href="<?= e(url('/admin/export.php?id='.$reportId.'&output=0&format=print_legacy')) ?>" target="_blank" class="btn btn-outline-secondary" title="Print-ready PDF view"><i class="ti ti-printer me-1"></i>PDF</a>
            </div>
        </div>
    </div>
</div>

<?php
$missingExt = array_filter(['zip','fileinfo','mbstring'], fn($x) => !extension_loaded($x));
if ($missingExt): ?>
    <div class="alert alert-danger d-flex align-items-center mb-3">
        <i class="ti ti-alert-octagon me-2"></i>
        <div>
            <strong>Apache PHP is missing required extensions:</strong> <?= e(implode(', ', $missingExt)) ?>.
            <span class="small">Excel uploads will fail until enabled. <a href="<?= e(url('/admin/upload.php?report_id='.$reportId)) ?>" class="alert-link">See fix &rarr;</a></span>
        </div>
    </div>
<?php endif; ?>

<?php if (!$activeUpload): ?>
    <div class="card border-warning text-center p-5">
        <div style="font-size:3rem;color:#f59e0b">📊</div>
        <h3 class="mt-3">No data yet</h3>
        <p class="text-secondary mb-4">Upload your first dataset to see the dashboard, summary, pivot, and analytics tabs come to life.</p>
        <div><a href="<?= e(url('/admin/upload.php?report_id='.$reportId)) ?>" class="btn btn-primary"><i class="ti ti-upload me-1"></i>Upload first file</a></div>
    </div>
<?php else: ?>

    <?php
    /* Sparkline data */
    $sparkClaims = array_map(fn($x)=>$x['claims'], array_values($byMonth));
    $sparkCharge = array_map(fn($x)=>round($x['charge'],2), array_values($byMonth));
    $sparkPaid   = array_map(fn($x)=>round(($x['pri'] ?? 0)+($x['sec'] ?? 0)+($x['ter'] ?? 0)+($x['pat_paid'] ?? 0),2), array_values($byMonth));
    $sparkBal    = array_map(fn($x)=>round($x['bal'],2), array_values($byMonth));
    $sparkExp    = array_map(fn($x)=>round($x['expected'],2), array_values($byMonth));
    ?>

    <!-- ============= FILTER BAR ============= -->
    <form method="GET" class="rv-filters">
        <input type="hidden" name="id"  value="<?= $reportId ?>">
        <input type="hidden" name="tab" value="<?= e($tab) ?>">
        <?php if ($compareId): ?><input type="hidden" name="compare" value="<?= (int)$compareId ?>"><?php endif; ?>
        <div class="row g-2 align-items-center">
            <div class="col-auto small text-secondary"><i class="ti ti-filter me-1"></i><strong>Filters:</strong></div>

            <?php
            $allUploads = $pdo->prepare("SELECT id, completed_at, valid_rows, created_at FROM report_uploads WHERE report_id=? AND status='completed' ORDER BY created_at DESC LIMIT 30");
            $allUploads->execute([$reportId]); $allUploads = $allUploads->fetchAll();
            ?>
            <div class="col-md-3">
                <select name="upload" class="form-select form-select-sm" onchange="this.form.submit()">
                    <?php foreach ($allUploads as $au): ?>
                        <option value="<?= $au['id'] ?>" <?= $au['id']==$activeUpload['id']?'selected':'' ?>>
                            📸 <?= e(fmt_dt($au['completed_at'] ?? $au['created_at'])) ?> · <?= number_format((int)$au['valid_rows']) ?> rows<?= $au['id']==($latest['id']??0)?' (latest)':'' ?>
                        </option>
                    <?php endforeach; ?>
                </select>
            </div>

            <div class="col-md-2">
                <select name="facility" class="form-select form-select-sm" onchange="this.form.submit()">
                    <option value="">All facilities (<?= count($facilities) ?>)</option>
                    <?php foreach ($facilities as $f): ?>
                        <option <?= $f===$fFacility?'selected':'' ?>><?= e($f) ?></option>
                    <?php endforeach; ?>
                </select>
            </div>

            <?php if ($providers): ?>
            <div class="col-md-2">
                <select name="provider" class="form-select form-select-sm" onchange="this.form.submit()">
                    <option value="">All providers (<?= count($providers) ?>)</option>
                    <?php foreach ($providers as $p): ?>
                        <option <?= $p===$fProvider?'selected':'' ?>><?= e($p) ?></option>
                    <?php endforeach; ?>
                </select>
            </div>
            <?php endif; ?>

            <div class="col-md-2">
                <select name="period" class="form-select form-select-sm" onchange="this.form.submit()">
                    <option value="">All periods</option>
                    <?php foreach ($periods as $p): ?>
                        <option <?= $p===$fPeriod?'selected':'' ?>><?= e($p) ?></option>
                    <?php endforeach; ?>
                </select>
            </div>

            <div class="col-md-2">
                <select class="form-select form-select-sm" onchange="rvSetCompare(this.value)">
                    <option value="">No comparison</option>
                    <?php foreach ($allUploads as $au): if ($au['id'] == $activeUpload['id']) continue; ?>
                        <option value="<?= $au['id'] ?>" <?= $au['id']==$compareId?'selected':'' ?>>
                            ⇋ vs <?= e(fmt_dt($au['completed_at'] ?? $au['created_at'])) ?>
                        </option>
                    <?php endforeach; ?>
                </select>
            </div>

            <div class="col-auto ms-auto">
                <?php if ($fFacility || $fPeriod || $fProvider): ?>
                    <a href="?id=<?= $reportId ?>&tab=<?= e($tab) ?>&upload=<?= $activeUpload['id'] ?><?= $compareId ? '&compare='.(int)$compareId : '' ?>" class="btn btn-sm btn-ghost-secondary"><i class="ti ti-x me-1"></i>Clear</a>
                <?php endif; ?>
            </div>
        </div>

        <?php if ($fFacility || $fPeriod || $fProvider): ?>
        <div class="mt-2 filter-chips">
            <?php if ($fFacility): ?>
                <span class="filter-chip"><i class="ti ti-building"></i><?= e($fFacility) ?>
                    <a href="<?= e(rv_url($reportId, ['facility'=>null])) ?>" title="Remove"><i class="ti ti-x"></i></a></span>
            <?php endif; ?>
            <?php if ($fProvider): ?>
                <span class="filter-chip"><i class="ti ti-stethoscope"></i><?= e($fProvider) ?>
                    <a href="<?= e(rv_url($reportId, ['provider'=>null])) ?>" title="Remove"><i class="ti ti-x"></i></a></span>
            <?php endif; ?>
            <?php if ($fPeriod): ?>
                <span class="filter-chip"><i class="ti ti-calendar"></i><?= e($fPeriod) ?>
                    <a href="<?= e(rv_url($reportId, ['period'=>null])) ?>" title="Remove"><i class="ti ti-x"></i></a></span>
            <?php endif; ?>
        </div>
        <?php endif; ?>
    </form>

    <?php if ($activeUpload['id'] != ($latest['id'] ?? 0)): ?>
        <div class="alert alert-warning py-2 small">
            <i class="ti ti-eye me-1"></i>Viewing snapshot from <?= e($activeUpload['completed_at']) ?> &mdash; not current data.
            <a href="?id=<?= $reportId ?>&tab=<?= e($tab) ?>" class="alert-link">Back to latest</a>
        </div>
    <?php endif; ?>

    <!-- ============= TABS ============= -->
    <ul class="nav rv-tabs">
        <?php $tabs = [
            ['key'=>'dashboard','label'=>'Dashboard','icon'=>'chart-pie-2','k'=>'1'],
            ['key'=>'summary','label'=>'Summary','icon'=>'table','k'=>'2'],
            ['key'=>'pivot','label'=>'Pivot (Look Up)','icon'=>'list-tree','k'=>'3'],
            ['key'=>'analytics','label'=>'Analytics','icon'=>'sparkles','k'=>'4'],
            ['key'=>'detail','label'=>'Detail (Raw)','icon'=>'database','k'=>'5'],
            ['key'=>'history','label'=>'History','icon'=>'history','k'=>'6'],
        ]; foreach ($tabs as $t): ?>
            <li class="nav-item">
                <a class="nav-link <?= $tab===$t['key']?'active':'' ?>"
                   href="<?= e(rv_url($reportId, ['tab' => $t['key']])) ?>" data-tab-key="<?= $t['k'] ?>">
                    <i class="ti ti-<?= $t['icon'] ?> me-1"></i><?= $t['label'] ?>
                    <kbd><?= $t['k'] ?></kbd>
                </a>
            </li>
        <?php endforeach; ?>
    </ul>

    <?php if ($tab === 'dashboard'): ?>

        <!-- ============= INSIGHTS BANNER ============= -->
        <div class="rv-insights mb-3">
            <div class="d-flex flex-wrap align-items-center">
                <div class="insight-stat">
                    <div class="lbl"><i class="ti ti-bulb me-1"></i>Period covered</div>
                    <div class="val"><?php $allDos = array_filter(array_column($allRows, 'dos')); echo $allDos ? e(min($allDos)) . ' &rarr; ' . e(max($allDos)) : '--'; ?></div>
                </div>
                <div class="insight-stat">
                    <div class="lbl">Collection rate</div>
                    <div class="val"><?= number_format($insights['collection_pct'] ?? 0, 1) ?>%
                        <span class="trend-<?= $insights['trend'] ?? 'flat' ?>"><?= ['up'=>'<i class="ti ti-trending-up"></i>','down'=>'<i class="ti ti-trending-down"></i>','flat'=>'<i class="ti ti-minus"></i>'][$insights['trend'] ?? 'flat'] ?></span>
                    </div>
                </div>
                <div class="insight-stat">
                    <div class="lbl">Total Balance</div>
                    <div class="val"><?= number_format($insights['outstanding_pct'] ?? 0, 1) ?>% of charge</div>
                </div>
                <div class="insight-stat">
                    <div class="lbl">Best month (charge)</div>
                    <div class="val"><?= e((string) ($insights['best_month']['m'] ?? '--')) ?>
                        <small style="opacity:.7"><?= isset($insights['best_month']['v']) ? fmt_money_short($insights['best_month']['v']) : '' ?></small>
                    </div>
                </div>
                <div class="insight-stat">
                    <div class="lbl">Lowest month</div>
                    <div class="val"><?= e((string) ($insights['worst_month']['m'] ?? '--')) ?>
                        <small style="opacity:.7"><?= isset($insights['worst_month']['v']) ? fmt_money_short($insights['worst_month']['v']) : '' ?></small>
                    </div>
                </div>
                <div class="insight-stat">
                    <div class="lbl">Top facility</div>
                    <div class="val"><?php $topF = $byFacility10 ? array_key_first($byFacility10) : null; echo $topF ? e(mb_substr($topF, 0, 28)) : '--'; ?></div>
                </div>
                <div class="ms-auto text-end small" style="opacity:.85">
                    <div><i class="ti ti-database me-1"></i><?= number_format(count($rows)) ?> of <?= number_format(count($allRows)) ?> rows</div>
                    <div><i class="ti ti-clock me-1"></i><?= e($activeUpload['completed_at']) ?></div>
                </div>
            </div>
            <?php if (!empty($insights['anomalies'])): ?>
                <div class="mt-2 small">
                    <i class="ti ti-alert-triangle me-1 text-warning"></i><strong>Anomalies (>2σ):</strong>
                    <?php foreach ($insights['anomalies'] as $a): ?>
                        <span class="anomaly"><?= e($a['m']) ?> <?= $a['dir'] ?><?= fmt_money_short(abs($a['val'] - $insights['mean'])) ?></span>
                    <?php endforeach; ?>
                </div>
            <?php endif; ?>
        </div>

        <!-- ============= KPI STRIP (with comparison deltas) ============= -->
        <div class="row row-cards kpi-strip mb-3">
            <?php
            $kpis = [
                ['lbl'=>'Claims',          'cur'=>$totals['claims'],                  'prev'=>$cmpTotals['claims'] ?? null,                 'fmt'=>'int',   'spark'=>'spark1', 'data'=>$sparkClaims, 'color'=>'#206bc4'],
                ['lbl'=>'Charge Amount',   'cur'=>$totals['charge'],                  'prev'=>$cmpTotals['charge'] ?? null,                 'fmt'=>'money', 'spark'=>'spark2', 'data'=>$sparkCharge, 'color'=>'#2fb344'],
                ['lbl'=>'Total Paid',  'cur'=>($totals['pri'] ?? 0)+($totals['sec'] ?? 0)+($totals['ter'] ?? 0)+($totals['pat_paid'] ?? 0),      'prev'=>$cmpTotals ? (($cmpTotals['pri'] ?? 0)+($cmpTotals['sec'] ?? 0)+($cmpTotals['ter'] ?? 0)+($cmpTotals['pat_paid'] ?? 0)) : null, 'fmt'=>'money', 'spark'=>'spark3', 'data'=>$sparkPaid, 'color'=>'#0ea5e9'],
                ['lbl'=>'Insurance Balance','cur'=>$totals['bal'],                    'prev'=>$cmpTotals['bal'] ?? null,                    'fmt'=>'money', 'spark'=>'spark4', 'data'=>$sparkBal,    'color'=>'#f76707'],
                ['lbl'=>'Patient Balance', 'cur'=>$totals['pat_bal'],                 'prev'=>$cmpTotals['pat_bal'] ?? null,                'fmt'=>'money', 'spark'=>null],
                ['lbl'=>'Avg / Claim',     'cur'=>$totals['claims']>0 ? $totals['charge']/$totals['claims'] : 0,
                                            'prev'=> ($cmpTotals && $cmpTotals['claims']>0) ? $cmpTotals['charge']/$cmpTotals['claims'] : null,
                                            'fmt'=>'money', 'spark'=>null],
            ];
            foreach ($kpis as $k):
                $valStr = $k['fmt'] === 'int' ? fmt_int($k['cur']) : fmt_money_short($k['cur']);
                $delta = ($k['prev'] !== null) ? pct_delta($k['cur'], $k['prev']) : null;
                $deltaClass = $delta === null ? '' : ($delta > 1 ? 'up' : ($delta < -1 ? 'down' : ''));
            ?>
                <div class="col"><div class="kpi">
                    <div class="lbl"><?= e($k['lbl']) ?></div>
                    <div class="val"><?= $valStr ?></div>
                    <?php if ($delta !== null): ?>
                        <div class="delta <?= $deltaClass ?>"><i class="ti ti-trending-<?= $delta > 1 ? 'up' : ($delta < -1 ? 'down' : 'flat') ?>"></i> <?= number_format($delta, 1) ?>% vs prior</div>
                    <?php endif; ?>
                    <?php if (!empty($k['spark'])): ?>
                        <div class="spark" id="<?= $k['spark'] ?>"></div>
                    <?php endif; ?>
                </div></div>
            <?php endforeach; ?>
        </div>

        <!-- ============= MAIN CHARTS ============= -->
        <div class="row row-deck row-cards mb-3">
            <div class="col-md-8">
                <div class="card chart-card">
                    <div class="chart-actions">
                        <button onclick="rvDownloadPng('chart_monthly')" title="Download PNG"><i class="ti ti-download"></i></button>
                        <button onclick="rvFullscreen('chart_monthly_card')" title="Full-screen"><i class="ti ti-arrows-maximize"></i></button>
                    </div>
                    <div class="card-header py-2"><h3 class="card-title small mb-0"><i class="ti ti-chart-line me-1 text-primary"></i>Monthly Revenue Trend
                        <?php if ($forecast): ?><span class="badge bg-purple-lt text-purple ms-2">+ Forecast</span><?php endif; ?>
                    </h3></div>
                    <div class="card-body p-2" id="chart_monthly_card"><div id="chart_monthly" style="min-height:300px"></div></div>
                </div>
            </div>
            <div class="col-md-4">
                <div class="card chart-card">
                    <div class="chart-actions">
                        <button onclick="rvDownloadPng('chart_donut')" title="Download PNG"><i class="ti ti-download"></i></button>
                        <button onclick="rvFullscreen('chart_donut_card')" title="Full-screen"><i class="ti ti-arrows-maximize"></i></button>
                    </div>
                    <div class="card-header py-2"><h3 class="card-title small mb-0"><i class="ti ti-chart-donut-2 me-1 text-success"></i>Revenue Breakdown</h3></div>
                    <div class="card-body p-2" id="chart_donut_card"><div id="chart_donut" style="min-height:300px"></div></div>
                </div>
            </div>
            <div class="col-12">
                <div class="card chart-card">
                    <div class="chart-actions">
                        <button onclick="rvDownloadPng('chart_monthly_full')" title="Download PNG"><i class="ti ti-download"></i></button>
                        <button onclick="rvFullscreen('chart_monthly_full_card')" title="Full-screen"><i class="ti ti-arrows-maximize"></i></button>
                    </div>
                    <div class="card-header py-2"><h3 class="card-title small mb-0"><i class="ti ti-chart-bar me-1 text-info"></i>Monthly Summary &mdash; All metrics</h3></div>
                    <div class="card-body p-2" id="chart_monthly_full_card"><div id="chart_monthly_full" style="min-height:340px"></div></div>
                </div>
            </div>
        </div>

        <!-- ============= LEGACY OVERALL TABLE ============= -->
        <div class="legacy-title mb-0"><?= e(strtoupper($report['cname'])) ?> OVERALL REVENUE SUMMARY REPORT</div>
        <div class="card mb-3"><div class="table-responsive"><table class="table table-bordered table-legacy mb-0">
            <thead><tr>
                <th>Month</th>
                <th>Total claims Billed</th>
                <th colspan="2">Total Charge Amount</th>
                <th colspan="2">Primary Insurance Paid</th>
                <th colspan="2">Secondary Insurance Paid</th>
                <th colspan="2">Insurance Balance</th>
                <th colspan="2">Total Expected Payment</th>
                <?php if ($cmpByMonth): ?><th>Δ Charge vs Comp</th><?php endif; ?>
            </tr></thead>
            <tbody>
            <?php foreach ($byMonth as $m=>$v):
                $cmpV = $cmpByMonth[$m] ?? null;
                $deltaCharge = $cmpV ? pct_delta($v['charge'], $cmpV['charge']) : null;
            ?>
                <tr>
                    <td class="text-center"><a href="<?= e(rv_url($reportId, ['period' => null])) ?>"
                                                onclick="event.preventDefault(); rvDrillMonth('<?= e($m) ?>')"
                                                style="color:inherit;text-decoration:none"><strong><?= e($m) ?></strong></a></td>
                    <td class="num"><?= fmt_int($v['claims']) ?></td>
                    <?= dollar_cells($v['charge']) ?>
                    <?= dollar_cells($v['pri']) ?>
                    <?= dollar_cells($v['sec']) ?>
                    <?= dollar_cells($v['bal']) ?>
                    <?= dollar_cells($v['expected']) ?>
                    <?php if ($cmpByMonth): ?>
                        <td class="num">
                            <?php if ($deltaCharge !== null): ?>
                                <span class="delta-pill <?= $deltaCharge > 1 ? 'up' : ($deltaCharge < -1 ? 'down' : 'flat') ?>"><?= number_format($deltaCharge, 1) ?>%</span>
                            <?php else: ?>--<?php endif; ?>
                        </td>
                    <?php endif; ?>
                </tr>
            <?php endforeach; ?>
                <tr class="total-row">
                    <td class="text-center">TOTAL</td>
                    <td class="num"><?= fmt_int($totals['claims']) ?></td>
                    <?= dollar_cells($totals['charge']) ?>
                    <?= dollar_cells($totals['pri']) ?>
                    <?= dollar_cells($totals['sec']) ?>
                    <?= dollar_cells($totals['bal']) ?>
                    <?= dollar_cells($totals['expected']) ?>
                    <?php if ($cmpTotals): $totDelta = pct_delta($totals['charge'], $cmpTotals['charge']); ?>
                        <td class="num"><span class="delta-pill <?= $totDelta > 1 ? 'up' : ($totDelta < -1 ? 'down' : 'flat') ?>"><?= number_format($totDelta, 1) ?>%</span></td>
                    <?php endif; ?>
                </tr>
            </tbody>
        </table></div></div>

    <?php elseif ($tab === 'summary'): ?>
        <?php
        // Compute max values for in-cell data bars
        $maxCharge = 0; foreach ($byMonth as $v) $maxCharge = max($maxCharge, $v['charge']);
        $maxBal    = 0; foreach ($byMonth as $v) $maxBal    = max($maxBal,    $v['bal']);
        ?>
        <div class="legacy-title mb-0"><?= e(strtoupper($report['cname'])) ?> ALL FACILITIES REVENUE AND BALANCES SUMMARY REPORT FOR <?= date('Y') ?> DOS</div>
        <div class="card mb-3"><div class="table-responsive"><table class="table table-bordered table-legacy mb-0">
            <thead><tr>
                <th>Month</th><th>Total Claims</th><th>Paid Claims</th><th>Unpaid Claims</th>
                <th>Total Charge</th><th>Primary Paid</th><th>Secondary Paid</th>
                <th>Total Paid</th><th>$ per Paid Claim</th>
                <th title="Insurance paid divided by ALL claims (paid + unpaid)">$ per Claim (Overall)</th>
                <th>Insurance Balance</th>
                <th>Patient Balance</th>
                <th>Total Expected Payment</th><th>Collection %</th>
            </tr></thead>
            <tbody>
            <?php foreach ($byMonth as $m=>$v):
                $totPaid    = ($v['pri'] ?? 0)+($v['sec'] ?? 0)+($v['ter'] ?? 0)+($v['pat_paid'] ?? 0);
                $perPaid    = $v['paid']  > 0 ? $totPaid/$v['paid']   : 0;
                $perOverall = $v['claims']> 0 ? $totPaid/$v['claims'] : 0;
                // Collection % = paid claims ÷ total claims
                $colPct     = $v['claims'] > 0 ? ($v['paid']/$v['claims'])*100 : 0;
                $chargeBarW = $maxCharge > 0 ? ($v['charge']/$maxCharge)*100 : 0;
                $balBarW    = $maxBal    > 0 ? ($v['bal']/$maxBal)*100 : 0;
                $colColor   = $colPct >= 70 ? '#16a34a' : ($colPct >= 40 ? '#f59e0b' : '#dc2626');
            ?>
                <tr>
                    <td><strong><?= e($m) ?></strong></td>
                    <td class="num"><?= fmt_int($v['claims']) ?></td>
                    <td class="num"><?= fmt_int($v['paid']) ?></td>
                    <td class="num"><?= fmt_int($v['unpaid']) ?></td>
                    <td class="num">
                        <span class="databar"><span class="bar" style="width:<?= number_format($chargeBarW,1) ?>%;background:#206bc4"></span><span class="v"><?= fmt_money($v['charge']) ?></span></span>
                    </td>
                    <td class="num"><?= fmt_money($v['pri']) ?></td>
                    <td class="num"><?= fmt_money($v['sec']) ?></td>
                    <td class="num"><?= fmt_money($totPaid) ?></td>
                    <td class="num"><?= fmt_money($perPaid) ?></td>
                    <td class="num"><?= fmt_money($perOverall) ?></td>
                    <td class="num">
                        <span class="databar"><span class="bar" style="width:<?= number_format($balBarW,1) ?>%;background:#f76707"></span><span class="v"><?= fmt_money($v['bal']) ?></span></span>
                    </td>
                    <td class="num"><?= fmt_money($v['pat_bal']) ?></td>
                    <td class="num"><?= fmt_money($v['expected']) ?></td>
                    <td class="num"><span style="color:<?= $colColor ?>;font-weight:600"><?= number_format($colPct, 1) ?>%</span></td>
                </tr>
            <?php endforeach;
            $tPaid       = ($totals['pri'] ?? 0)+($totals['sec'] ?? 0)+($totals['ter'] ?? 0)+($totals['pat_paid'] ?? 0);
            $tPerPaid    = $totals['paid']  > 0 ? $tPaid/$totals['paid']   : 0;
            $tPerOverall = $totals['claims']> 0 ? $tPaid/$totals['claims'] : 0;
            // Collection % = paid claims ÷ total claims
            $tColPct     = $totals['claims'] > 0 ? ($totals['paid']/$totals['claims'])*100 : 0;
            ?>
                <tr class="total-row">
                    <td>TOTAL</td>
                    <td class="num"><?= fmt_int($totals['claims']) ?></td>
                    <td class="num"><?= fmt_int($totals['paid']) ?></td>
                    <td class="num"><?= fmt_int($totals['unpaid']) ?></td>
                    <td class="num"><?= fmt_money($totals['charge']) ?></td>
                    <td class="num"><?= fmt_money($totals['pri']) ?></td>
                    <td class="num"><?= fmt_money($totals['sec']) ?></td>
                    <td class="num"><?= fmt_money($tPaid) ?></td>
                    <td class="num"><?= fmt_money($tPerPaid) ?></td>
                    <td class="num"><?= fmt_money($tPerOverall) ?></td>
                    <td class="num"><?= fmt_money($totals['bal']) ?></td>
                    <td class="num"><?= fmt_money($totals['pat_bal']) ?></td>
                    <td class="num"><?= fmt_money($totals['expected']) ?></td>
                    <td class="num"><strong><?= number_format($tColPct, 1) ?>%</strong></td>
                </tr>
            </tbody>
        </table></div></div>

        <div class="row g-3">
            <div class="col-md-4">
                <div class="legacy-title mb-0" style="font-size:.85rem">Total Unbilled Claims (excl. Deductible)</div>
                <table class="table table-bordered table-legacy mb-0">
                    <thead><tr><th>Month</th><th>Claims</th><th colspan="2">Total Expected Payment</th></tr></thead>
                    <tbody>
                    <?php foreach ($unbilled as $m=>$v): ?>
                        <tr><td class="text-center"><?= e($m) ?></td><td class="num"><?= fmt_int($v['c']) ?></td><?= dollar_cells($v['exp']) ?></tr>
                    <?php endforeach; ?>
                        <tr class="total-row"><td class="text-center">TOTAL</td><td class="num"><?= fmt_int($sumA['c']) ?></td><?= dollar_cells($sumA['exp']) ?></tr>
                    </tbody>
                </table>
            </div>

            <div class="col-md-5">
                <div class="legacy-title mb-0" style="font-size:.85rem">Total Unpaid / Appealed / Follow-up Claims</div>
                <table class="table table-bordered table-legacy mb-0">
                    <thead><tr>
                        <th>Month</th><th>Claims</th>
                        <th colspan="2">Charge Amount</th>
                        <th colspan="2">Total Expected Payment</th>
                        <th>% of Expected</th>
                    </tr></thead>
                    <tbody>
                    <?php foreach ($unpaid as $m=>$v):
                        $pct = $v['charge'] > 0 ? ($v['exp'] / $v['charge']) * 100 : 0; ?>
                        <tr>
                            <td class="text-center"><?= e($m) ?></td>
                            <td class="num"><?= fmt_int($v['c']) ?></td>
                            <?= dollar_cells($v['charge']) ?>
                            <?= dollar_cells($v['exp']) ?>
                            <td class="num"><?= number_format($pct, 1) ?>%</td>
                        </tr>
                    <?php endforeach;
                    $totPct = $sumB['charge'] > 0 ? ($sumB['exp'] / $sumB['charge']) * 100 : 0; ?>
                        <tr class="total-row">
                            <td class="text-center">TOTAL</td>
                            <td class="num"><?= fmt_int($sumB['c']) ?></td>
                            <?= dollar_cells($sumB['charge']) ?>
                            <?= dollar_cells($sumB['exp']) ?>
                            <td class="num"><?= number_format($totPct, 1) ?>%</td>
                        </tr>
                    </tbody>
                </table>
            </div>

            <div class="col-md-3">
                <div class="legacy-title mb-0" style="font-size:.85rem">Claims on Hold for Deductible</div>
                <table class="table table-bordered table-legacy mb-0">
                    <thead><tr><th>Month</th><th>Claims</th><th colspan="2">Total Expected Payment</th></tr></thead>
                    <tbody>
                    <?php foreach ($hold as $m=>$v): ?>
                        <tr><td class="text-center"><?= e($m) ?></td><td class="num"><?= fmt_int($v['c']) ?></td><?= dollar_cells($v['exp']) ?></tr>
                    <?php endforeach; ?>
                        <tr class="total-row"><td class="text-center">TOTAL</td><td class="num"><?= fmt_int($sumC['c']) ?></td><?= dollar_cells($sumC['exp']) ?></tr>
                    </tbody>
                </table>
            </div>
        </div>

    <?php elseif ($tab === 'pivot'):
        ksort($pivot);
        $monthBuckets = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
        $gT = ['v'=>0,'c'=>0,'p'=>0,'s'=>0,'b'=>0];
        foreach ($pivot as $months) foreach ($months as $days) foreach ($days as $rs) foreach ($rs as $r) {
            $gT['v']++; $gT['c']+=$r['charge']; $gT['p']+=$r['pri']; $gT['s']+=$r['sec']; $gT['b']+=$r['bal'];
        }
    ?>
        <div class="legacy-title mb-0"><?= e(strtoupper($report['cname'])) ?> &mdash; LOOK UP DATA (Facility / Month / Day)</div>
        <div class="card mb-0">
            <div class="card-body py-2 d-flex flex-wrap gap-2 align-items-center" style="border-bottom:1px solid var(--m-border)">
                <input type="text" id="pivot_search" class="form-control form-control-sm" placeholder="Search facility name..." style="max-width:300px">
                <select id="pivot_month" class="form-select form-select-sm" style="max-width:160px">
                    <option value="">All months</option>
                    <?php foreach (array_keys($byMonth) as $m): ?><option><?= e($m) ?></option><?php endforeach; ?>
                </select>
                <button class="btn btn-sm btn-outline-secondary" onclick="pivotExpandAll()"><i class="ti ti-square-plus me-1"></i>Expand all</button>
                <button class="btn btn-sm btn-outline-secondary" onclick="pivotCollapseAll()"><i class="ti ti-square-minus me-1"></i>Collapse all</button>
                <span class="ms-auto small text-secondary">Click any <strong>facility</strong> or <strong>month</strong> row to expand/collapse</span>
            </div>
        </div>
        <div class="card mb-3"><div class="table-responsive" style="max-height:700px;overflow:auto">
        <table id="pivot_table" class="table table-sm table-bordered table-legacy mb-0" style="font-size:13px">
            <thead style="position:sticky; top:0; z-index:10"><tr>
                <th style="text-align:left; min-width:340px">Row Labels</th>
                <th>Count of DOS</th>
                <th colspan="2">Sum of Charge Amount</th>
                <th colspan="2">Sum of Primary Paid</th>
                <th colspan="2">Sum of Secondary Paid</th>
                <th colspan="2">Sum of Insurance Balance</th>
            </tr></thead>
            <tbody>
            <?php foreach ($pivot as $facility => $months):
                $facilityKey = preg_replace('/[^a-z0-9]/i', '_', $facility);
                $fT = ['v'=>0,'c'=>0,'p'=>0,'s'=>0,'b'=>0];
                foreach ($months as $mr) foreach ($mr as $dr) foreach ($dr as $r) {
                    $fT['v']++; $fT['c']+=$r['charge']; $fT['p']+=$r['pri']; $fT['s']+=$r['sec']; $fT['b']+=$r['bal'];
                }
            ?>
                <tr class="pivot-fac pivot-facility pivot-row" data-key="<?= e($facilityKey) ?>" data-fac="<?= e($facilityKey) ?>" data-name="<?= e(strtolower($facility)) ?>"
                    onclick="pivotToggle(this.dataset.key)">
                    <td><i class="ti ti-chevron-right pivot-arrow" id="arrow-<?= e($facilityKey) ?>"></i> <strong><?= e($facility) ?></strong></td>
                    <td class="num"><strong><?= fmt_int($fT['v']) ?></strong></td>
                    <?= dollar_cells($fT['c']) ?><?= dollar_cells($fT['p']) ?><?= dollar_cells($fT['s']) ?><?= dollar_cells($fT['b']) ?>
                </tr>
                <?php uksort($months, fn($a,$b)=>array_search($a, $monthBuckets) <=> array_search($b, $monthBuckets));
                foreach ($months as $m=>$days):
                    $monKey = $facilityKey . '_' . $m;
                    $mT = ['v'=>0,'c'=>0,'p'=>0,'s'=>0,'b'=>0];
                    foreach ($days as $dr) foreach ($dr as $r) {
                        $mT['v']++; $mT['c']+=$r['charge']; $mT['p']+=$r['pri']; $mT['s']+=$r['sec']; $mT['b']+=$r['bal'];
                    } ?>
                    <tr class="pivot-mon pivot-month pivot-row" data-key="<?= e($monKey) ?>" data-parent="<?= e($facilityKey) ?>" data-mon="<?= e($monKey) ?>" data-month="<?= e($m) ?>"
                        onclick="event.stopPropagation(); pivotToggle(this.dataset.key)">
                        <td style="padding-left:30px"><i class="ti ti-chevron-right pivot-arrow" id="arrow-<?= e($monKey) ?>"></i> <strong><?= e($m) ?></strong></td>
                        <td class="num"><strong><?= fmt_int($mT['v']) ?></strong></td>
                        <?= dollar_cells($mT['c']) ?><?= dollar_cells($mT['p']) ?><?= dollar_cells($mT['s']) ?><?= dollar_cells($mT['b']) ?>
                    </tr>
                    <?php uksort($days, fn($a,$b)=>(int)$a <=> (int)$b);
                    foreach ($days as $d=>$rs):
                        $dT = ['v'=>0,'c'=>0,'p'=>0,'s'=>0,'b'=>0];
                        foreach ($rs as $r) { $dT['v']++; $dT['c']+=$r['charge']; $dT['p']+=$r['pri']; $dT['s']+=$r['sec']; $dT['b']+=$r['bal']; } ?>
                        <tr class="pivot-day pivot-row" data-parent="<?= e($monKey) ?>" data-grand="<?= e($facilityKey) ?>" data-month="<?= e($m) ?>">
                            <td style="padding-left:60px"><?= e($d) ?></td>
                            <td class="num"><?= fmt_int($dT['v']) ?></td>
                            <?= dollar_cells($dT['c']) ?><?= dollar_cells($dT['p']) ?><?= dollar_cells($dT['s']) ?><?= dollar_cells($dT['b']) ?>
                        </tr>
                    <?php endforeach; endforeach; endforeach; ?>
                <tr class="pivot-grand total-row">
                    <td><strong>Grand Total</strong></td>
                    <td class="num"><strong><?= fmt_int($gT['v']) ?></strong></td>
                    <?= dollar_cells($gT['c']) ?><?= dollar_cells($gT['p']) ?><?= dollar_cells($gT['s']) ?><?= dollar_cells($gT['b']) ?>
                </tr>
            </tbody>
        </table></div></div>

        <style>
        #pivot_table tr.pivot-mon { display: none; }
        #pivot_table tr.pivot-day { display: none; }
        #pivot_table tr.pivot-mon.open { display: table-row; }
        #pivot_table tr.pivot-day.open { display: table-row; }
        #pivot_table tr.month-hidden { display: none !important; }
        .pivot-arrow { display:inline-block; width:14px; transition: transform .15s; }
        </style>
        <script>
        function pivotToggle(key) {
            const arrow = document.getElementById('arrow-' + key);
            const row = document.querySelector('#pivot_table tr.pivot-row[data-key="' + CSS.escape(key) + '"]');
            const isOpen = row && row.classList.contains('expanded');
            const children = document.querySelectorAll('#pivot_table tr[data-parent="' + CSS.escape(key) + '"]');
            if (isOpen) {
                row.classList.remove('expanded');
                if (arrow) arrow.classList.replace('ti-chevron-down','ti-chevron-right');
                children.forEach(el => {
                    el.classList.remove('open');
                    if (el.classList.contains('expanded')) pivotToggle(el.dataset.key);
                });
            } else {
                if (row) row.classList.add('expanded');
                if (arrow) arrow.classList.replace('ti-chevron-right','ti-chevron-down');
                children.forEach(el => el.classList.add('open'));
            }
        }
        function pivotExpandAll() {
            document.querySelectorAll('#pivot_table tr.pivot-fac, #pivot_table tr.pivot-mon').forEach(tr => {
                if (!tr.classList.contains('expanded')) pivotToggle(tr.dataset.key);
            });
        }
        function pivotCollapseAll() {
            document.querySelectorAll('#pivot_table tr.pivot-mon.expanded').forEach(tr => pivotToggle(tr.dataset.key));
            document.querySelectorAll('#pivot_table tr.pivot-fac.expanded').forEach(tr => pivotToggle(tr.dataset.key));
        }
        document.getElementById('pivot_search').addEventListener('input', function() {
            const q = this.value.toLowerCase().trim();
            document.querySelectorAll('#pivot_table tr.pivot-fac').forEach(tr => {
                const match = !q || tr.dataset.name.includes(q);
                tr.style.display = match ? '' : 'none';
                if (!match && tr.classList.contains('expanded')) pivotToggle(tr.dataset.key);
            });
        });
        document.getElementById('pivot_month').addEventListener('change', function() {
            const sel = this.value;
            document.querySelectorAll('#pivot_table tr.pivot-mon, #pivot_table tr.pivot-day').forEach(tr => {
                if (!sel || tr.dataset.month === sel) tr.classList.remove('month-hidden');
                else tr.classList.add('month-hidden');
            });
            document.querySelectorAll('#pivot_table tr.pivot-fac').forEach(tr => {
                const k = tr.dataset.key;
                const anyMonth = document.querySelector('#pivot_table tr.pivot-mon[data-parent="' + CSS.escape(k) + '"]:not(.month-hidden)');
                tr.style.display = (sel && !anyMonth) ? 'none' : '';
            });
            if (sel) {
                document.querySelectorAll('#pivot_table tr.pivot-fac').forEach(tr => {
                    if (tr.style.display !== 'none' && !tr.classList.contains('expanded')) pivotToggle(tr.dataset.key);
                });
            }
        });
        </script>

    <?php elseif ($tab === 'analytics'): ?>
        <!-- ============= ANALYTICS TAB ============= -->
        <div class="row row-deck row-cards mb-3">
            <div class="col-12">
                <div class="card chart-card">
                    <div class="chart-actions"><button onclick="rvDownloadPng('chart_heatmap')" title="Download PNG"><i class="ti ti-download"></i></button></div>
                    <div class="card-header py-2">
                        <h3 class="card-title small mb-0"><i class="ti ti-grid-pattern me-1 text-primary"></i>Facility × Month heatmap (top <?= count($heatSeries) ?> facilities by charge)</h3>
                        <span class="ms-auto small text-secondary">Darker = higher charge volume</span>
                    </div>
                    <div class="card-body p-2"><div id="chart_heatmap" style="min-height:<?= max(280, count($heatSeries)*32 + 60) ?>px"></div></div>
                </div>
            </div>

            <div class="col-md-6">
                <div class="card chart-card">
                    <div class="chart-actions"><button onclick="rvDownloadPng('chart_treemap')" title="Download PNG"><i class="ti ti-download"></i></button></div>
                    <div class="card-header py-2"><h3 class="card-title small mb-0"><i class="ti ti-layout-dashboard me-1 text-success"></i>Top facilities by charge (treemap)</h3></div>
                    <div class="card-body p-2"><div id="chart_treemap" style="min-height:340px"></div></div>
                </div>
            </div>

            <div class="col-md-6">
                <div class="card chart-card">
                    <div class="chart-actions"><button onclick="rvDownloadPng('chart_funnel')" title="Download PNG"><i class="ti ti-download"></i></button></div>
                    <div class="card-header py-2"><h3 class="card-title small mb-0"><i class="ti ti-filter me-1 text-warning"></i>Collection lifecycle funnel</h3></div>
                    <div class="card-body p-2"><div id="chart_funnel" style="min-height:340px"></div></div>
                </div>
            </div>

            <?php if ($byProvider10): ?>
            <div class="col-md-6">
                <div class="card chart-card">
                    <div class="chart-actions"><button onclick="rvDownloadPng('chart_providers')" title="Download PNG"><i class="ti ti-download"></i></button></div>
                    <div class="card-header py-2"><h3 class="card-title small mb-0"><i class="ti ti-stethoscope me-1 text-info"></i>Top 10 providers by charge</h3></div>
                    <div class="card-body p-2"><div id="chart_providers" style="min-height:380px"></div></div>
                </div>
            </div>
            <?php endif; ?>

            <div class="col-md-6">
                <div class="card chart-card">
                    <div class="chart-actions"><button onclick="rvDownloadPng('chart_dow')" title="Download PNG"><i class="ti ti-download"></i></button></div>
                    <div class="card-header py-2"><h3 class="card-title small mb-0"><i class="ti ti-calendar-week me-1 text-purple"></i>Day-of-week pattern</h3></div>
                    <div class="card-body p-2"><div id="chart_dow" style="min-height:380px"></div></div>
                </div>
            </div>

            <div class="col-md-6">
                <div class="card">
                    <div class="card-header py-2"><h3 class="card-title small mb-0"><i class="ti ti-gauge me-1 text-success"></i>Collection rate</h3></div>
                    <div class="card-body p-2"><div id="chart_gauge" style="min-height:240px"></div></div>
                </div>
            </div>

            <?php if ($forecast): ?>
            <div class="col-md-6">
                <div class="card">
                    <div class="card-header py-2"><h3 class="card-title small mb-0"><i class="ti ti-crystal-ball me-1 text-warning"></i>Forecast — next 3 months</h3></div>
                    <div class="card-body p-2">
                        <table class="table table-sm mb-0" style="font-size:.85rem">
                            <thead><tr><th>Month</th><th class="text-end">Projected charge</th><th class="text-end">vs current avg</th></tr></thead>
                            <tbody>
                            <?php $avgCharge = $insights['mean'] ?? 0; foreach ($forecast as $fm => $fv):
                                $delta = pct_delta($fv, $avgCharge); ?>
                                <tr>
                                    <td><strong><?= e($fm) ?></strong></td>
                                    <td class="text-end"><?= fmt_money_short($fv) ?></td>
                                    <td class="text-end"><span class="delta-pill <?= $delta > 1 ? 'up' : ($delta < -1 ? 'down' : 'flat') ?>"><?= number_format($delta, 1) ?>%</span></td>
                                </tr>
                            <?php endforeach; ?>
                            </tbody>
                        </table>
                        <div class="small text-secondary mt-2"><i class="ti ti-info-circle me-1"></i>Linear regression on monthly charge series. For directional guidance only.</div>
                    </div>
                </div>
            </div>
            <?php endif; ?>
        </div>

    <?php elseif ($tab === 'detail'): ?>
        <?php $displayRows = array_slice($rows, 0, 1000); ?>
        <div class="card"><div class="card-header py-2"><h3 class="card-title small mb-0">Raw rows <span class="text-secondary">(showing first <?= count($displayRows) ?> of <?= number_format(count($rows)) ?>)</span></h3>
            <div class="card-actions small text-secondary">
                <i class="ti ti-info-circle"></i> Use the column selector and Excel/CSV buttons inside the table.
            </div>
        </div>
        <div class="card-body p-0">
        <table id="dt_detail" class="table table-sm table-vcenter card-table" style="font-size:12px">
            <thead><tr>
                <th>Facility</th><th>Provider</th><th>Patient</th><th>DOS</th>
                <th>Charge Code</th><th class="text-end">Units</th>
                <th class="text-end">Charge</th><th class="text-end">Pri Paid</th>
                <th class="text-end">Sec Paid</th><th class="text-end">Ins Balance</th>
            </tr></thead>
            <tbody>
            <?php foreach ($displayRows as $r): ?>
                <tr>
                    <td class="text-truncate" style="max-width:180px" title="<?= e($r['facility'] ?? '') ?>"><?= e($r['facility'] ?? '') ?></td>
                    <td class="text-truncate" style="max-width:140px"><?= e($r['provider_name'] ?? '') ?></td>
                    <td><?= e($r['patient_full_name'] ?? '') ?></td>
                    <td class="text-nowrap"><?= e($r['dos'] ?? '') ?></td>
                    <td><?= e($r['charge_code'] ?? '') ?></td>
                    <td class="text-end"><?= e((string)($r['units'] ?? '')) ?></td>
                    <td class="text-end"><?= fmt_money($r['charge_amount'] ?? 0) ?></td>
                    <td class="text-end"><?= fmt_money($r['primary_insurance_paid'] ?? 0) ?></td>
                    <td class="text-end"><?= fmt_money($r['secondary_insurance_paid'] ?? 0) ?></td>
                    <td class="text-end"><?= fmt_money($r['insurance_balance'] ?? 0) ?></td>
                </tr>
            <?php endforeach; ?>
            </tbody>
        </table></div></div>
        <script>
        $(function(){
            $('#dt_detail').DataTable({
                pageLength: 25,
                order: [[3,'desc']],
                dom: '<"row"<"col-md-6"B><"col-md-6"f>>rt<"row"<"col-md-6"i><"col-md-6"p>>',
                buttons: [
                    { extend: 'colvis', text: '<i class="ti ti-columns-3"></i> Columns' },
                    { extend: 'csv',    text: '<i class="ti ti-file-text"></i> CSV' },
                    { extend: 'excel',  text: '<i class="ti ti-file-spreadsheet"></i> Excel' },
                    { extend: 'print',  text: '<i class="ti ti-printer"></i> Print' },
                ],
                fixedHeader: true,
                deferRender: true,
            });
        });
        </script>

    <?php elseif ($tab === 'history'): ?>
        <?php
        $hist = $pdo->prepare('SELECT u.*, usr.name AS user_name FROM report_uploads u
            LEFT JOIN users usr ON usr.id = u.uploaded_by WHERE u.report_id=? ORDER BY u.created_at DESC');
        $hist->execute([$reportId]); $hist = $hist->fetchAll(); ?>
        <div class="card"><div class="card-header py-2"><h3 class="card-title small mb-0">Upload history</h3></div>
        <div class="table-responsive"><table class="table card-table table-sm">
            <thead><tr><th>When</th><th>By</th><th>File</th><th>Mode</th><th>Rows</th><th>Status</th><th></th></tr></thead><tbody>
            <?php foreach ($hist as $h): ?>
                <tr>
                    <td class="small text-secondary"><?= e($h['created_at']) ?></td>
                    <td><?= e($h['user_name'] ?? '--') ?></td>
                    <td class="small text-truncate" style="max-width:240px"><?= e($h['file_name']) ?></td>
                    <td><span class="badge bg-secondary-lt"><?= e($h['upload_mode_used']) ?></span></td>
                    <td><?= (int)$h['valid_rows'] ?> ok / <?= (int)$h['error_rows'] ?> err</td>
                    <td><span class="badge bg-<?= ['completed'=>'success','failed'=>'danger','processing'=>'info','archived'=>'secondary'][$h['status']] ?? 'secondary' ?>-lt"><?= e($h['status']) ?></span></td>
                    <td>
                        <a href="?id=<?= $reportId ?>&upload=<?= $h['id'] ?>" class="btn btn-sm">View</a>
                        <a href="?id=<?= $reportId ?>&upload=<?= $activeUpload['id'] ?>&compare=<?= $h['id'] ?>" class="btn btn-sm btn-outline-warning"><i class="ti ti-arrows-diff me-1"></i>Compare</a>
                        <?php if (user_has_role((int)$me['id'],'sysadmin') && $h['status']==='completed'): ?>
                        <form method="POST" action="<?= e(url('/admin/restore.php')) ?>" style="display:inline" onsubmit="return confirm('Restore this snapshot?');">
                            <?= csrf_field() ?><input type="hidden" name="report_id" value="<?= $reportId ?>"><input type="hidden" name="upload_id" value="<?= $h['id'] ?>">
                            <button class="btn btn-sm btn-ghost-warning"><i class="ti ti-history me-1"></i>Restore</button>
                        </form>
                        <?php endif; ?>
                    </td>
                </tr>
            <?php endforeach; ?>
            </tbody></table></div></div>
    <?php endif; ?>

<?php endif; /* end of activeUpload guard */ ?>

</div>

<?php if ($activeUpload && $tab === 'dashboard'): ?>
<script>
/* ====================== DASHBOARD CHARTS ====================== */
(function(){
    const months = <?= json_encode(array_keys($byMonth)) ?>;
    const sparkClaims = <?= json_encode($sparkClaims) ?>;
    const sparkCharge = <?= json_encode($sparkCharge) ?>;
    const sparkPaid   = <?= json_encode($sparkPaid) ?>;
    const sparkBal    = <?= json_encode($sparkBal) ?>;
    const monthlyExp  = <?= json_encode($sparkExp) ?>;
    const forecastObj = <?= json_encode($forecast) ?>;
    const cmpByMonth  = <?= json_encode($cmpByMonth) ?>;
    const allCharge   = sparkCharge.concat(Object.values(forecastObj));
    const allMonths   = months.concat(Object.keys(forecastObj));
    const reportId    = <?= (int)$reportId ?>;

    function isDark() { return document.documentElement.getAttribute('data-bs-theme') === 'dark'; }
    function gridColor() { return isDark() ? '#1e2a44' : '#eef0f3'; }
    function axisColor() { return isDark() ? '#97a2b6' : '#6c7a89'; }

    // Sparklines
    function sparkOpts(data, color) {
        return {
            chart: { type:'area', height:32, sparkline:{enabled:true} },
            theme: { mode: isDark() ? 'dark' : 'light' },
            series: [{ data }], colors: [color], stroke: { curve:'smooth', width:2 },
            fill: { type:'gradient', gradient: { shadeIntensity:1, opacityFrom:.35, opacityTo:.05 } },
            tooltip: { fixed:{enabled:false}, x:{show:false}, marker:{show:false} },
        };
    }
    const sparks = [
        ['#spark1', sparkClaims, '#206bc4'],
        ['#spark2', sparkCharge, '#2fb344'],
        ['#spark3', sparkPaid,   '#0ea5e9'],
        ['#spark4', sparkBal,    '#f76707'],
    ];
    sparks.forEach(([sel, data, color]) => {
        const el = document.querySelector(sel);
        if (el) new ApexCharts(el, sparkOpts(data, color)).render();
    });

    // Monthly trend with forecast overlay + cross-filter on click
    const monthlyChart = new ApexCharts(document.querySelector('#chart_monthly'), {
        chart: { type:'line', height:300, toolbar:{ show:true, tools:{ download:false } }, fontFamily:'inherit', background: 'transparent',
                 events: {
                     dataPointSelection: function(_e, _ctx, cfg) {
                         const m = allMonths[cfg.dataPointIndex];
                         if (m) rvDrillMonth(m);
                     },
                 } },
        theme: { mode: isDark() ? 'dark' : 'light' },
        series: [
            { name:'Charge Amount',     type:'column', data: allCharge.map((v,i) => i < sparkCharge.length ? v : null) },
            <?php if ($forecast): ?>{ name:'Forecast',  type:'column', data: allCharge.map((v,i) => i >= sparkCharge.length ? v : null) },<?php endif; ?>
            { name:'Total Paid',    type:'line',   data: sparkPaid.concat(allMonths.slice(sparkCharge.length).map(()=>null)) },
            { name:'Insurance Balance', type:'line',   data: sparkBal.concat(allMonths.slice(sparkCharge.length).map(()=>null)) },
            <?php if ($cmpByMonth): ?>{ name:'Compare', type:'line', data: months.map(m => cmpByMonth[m] ? cmpByMonth[m].charge : 0).concat(allMonths.slice(sparkCharge.length).map(()=>null)) },<?php endif; ?>
        ],
        stroke: { curve:'smooth', width: <?= $forecast ? '[0,0,3,3' . ($cmpByMonth ? ',2' : '') . ']' : '[0,3,3' . ($cmpByMonth ? ',2' : '') . ']' ?>, dashArray: <?= $forecast ? '[0,5,0,0' . ($cmpByMonth ? ',6' : '') . ']' : '[0,0,0' . ($cmpByMonth ? ',6' : '') . ']' ?> },
        colors: <?= $forecast ? "['#206bc4','#a855f7','#2fb344','#f76707'" . ($cmpByMonth ? ",'#94a3b8'" : '') . "]" : "['#206bc4','#2fb344','#f76707'" . ($cmpByMonth ? ",'#94a3b8'" : '') . "]" ?>,
        xaxis: { categories: allMonths, labels: { style: { colors: axisColor() } } },
        yaxis: { labels: { style: { colors: axisColor() }, formatter: v => '$' + Math.round(v).toLocaleString() } },
        tooltip: { y: { formatter: v => v == null ? '--' : '$' + v.toLocaleString(undefined,{minimumFractionDigits:2,maximumFractionDigits:2}) } },
        legend: { position:'top', labels: { colors: axisColor() } },
        grid: { borderColor: gridColor() },
    });
    monthlyChart.render();
    window._rvCharts = window._rvCharts || {};
    window._rvCharts['chart_monthly'] = monthlyChart;

    // Donut breakdown
    const donutChart = new ApexCharts(document.querySelector('#chart_donut'), {
        chart: { type:'donut', height:300, fontFamily:'inherit', background: 'transparent' },
        theme: { mode: isDark() ? 'dark' : 'light' },
        series: [<?= round($totals['pri'],2) ?>, <?= round($totals['sec'],2) ?>, <?= round($totals['bal'],2) ?>, <?= round($totals['pat_bal'],2) ?>],
        labels: ['Primary Paid','Secondary Paid','Insurance Balance','Patient Balance'],
        colors: ['#2fb344','#206bc4','#f76707','#ae3ec9'],
        legend: { position:'bottom', labels: { colors: axisColor() } },
        dataLabels: { enabled:true, formatter: v => v.toFixed(1)+'%' },
        plotOptions: { pie: { donut: { labels: { show: true, total: { show: true, label:'Total', formatter: () => '$' + (<?= round($totals['pri']+$totals['sec']+$totals['bal']+$totals['pat_bal'],2) ?>).toLocaleString() } } } } },
    });
    donutChart.render();
    window._rvCharts['chart_donut'] = donutChart;

    // All-metrics chart
    const monthlyPri = <?= json_encode(array_map(fn($x)=>round($x['pri'],2),  array_values($byMonth))) ?>;
    const monthlySec = <?= json_encode(array_map(fn($x)=>round($x['sec'],2),  array_values($byMonth))) ?>;
    const fullChart = new ApexCharts(document.querySelector('#chart_monthly_full'), {
        chart: { type:'line', height:340, toolbar:{ show:true }, fontFamily:'inherit', background: 'transparent' },
        theme: { mode: isDark() ? 'dark' : 'light' },
        series: [
            { name:'Total Charge Amount',     type:'column', data: sparkCharge },
            { name:'Insurance Balance',       type:'column', data: sparkBal },
            { name:'Primary Insurance Paid',  type:'line',   data: monthlyPri },
            { name:'Secondary Insurance Paid',type:'line',   data: monthlySec },
            { name:'Total Expected Payment',        type:'line',   data: monthlyExp },
            { name:'Total Claims Billed',     type:'line',   data: sparkClaims, yAxisIndex: 1 },
        ],
        stroke: { curve:'smooth', width:[0,0,3,3,3,3] },
        markers: { size:[0,0,5,5,5,5] },
        colors: ['#475569','#f59e0b','#16a34a','#0ea5e9','#7c3aed','#dc2626'],
        xaxis: { categories: months, labels: { style: { colors: axisColor() } } },
        yaxis: [
            { title: { text: 'Amount ($)', style: { fontSize:'11px', color: axisColor() } },
              labels: { style: { colors: axisColor() }, formatter: v => '$' + Math.round(v).toLocaleString() } },
            { opposite: true, title: { text: 'Claims (count)', style: { fontSize:'11px', color: axisColor() } },
              labels: { style: { colors: axisColor() }, formatter: v => Math.round(v).toLocaleString() } },
        ],
        plotOptions: { bar: { borderRadius:3, columnWidth:'45%' } },
        dataLabels: { enabled:false },
        legend: { position:'top', fontSize:'11px', labels: { colors: axisColor() } },
        tooltip: { shared:true, y: { formatter: (v, { seriesIndex }) =>
            seriesIndex === 5 ? Math.round(v).toLocaleString() + ' claims' : '$' + v.toLocaleString(undefined,{minimumFractionDigits:2,maximumFractionDigits:2})
        } },
        grid: { borderColor: gridColor() },
    });
    fullChart.render();
    window._rvCharts['chart_monthly_full'] = fullChart;

    // Drill-down helper
    window.rvDrillMonth = function(monthLabel){
        const url = new URL(window.location.href);
        // Find a period whose label starts with the given month abbreviation
        const periodSelect = document.querySelector('select[name="period"]');
        if (periodSelect) {
            for (const opt of periodSelect.options) {
                if (opt.text && (opt.text.toLowerCase().includes(monthLabel.toLowerCase()) ||
                                 opt.text.toLowerCase().startsWith(monthLabel.toLowerCase()))) {
                    url.searchParams.set('period', opt.value);
                    window.location.href = url.toString();
                    return;
                }
            }
        }
        // No specific period match — just toast
        if (window.mToast) mToast('No period column matches "' + monthLabel + '"', 'error');
    };
})();
</script>
<?php endif; ?>

<?php if ($activeUpload && $tab === 'analytics'): ?>
<script>
(function(){
    function isDark() { return document.documentElement.getAttribute('data-bs-theme') === 'dark'; }
    const charts = {};

    // Heatmap
    charts.heat = new ApexCharts(document.querySelector('#chart_heatmap'), {
        chart: { type:'heatmap', height: <?= max(280, count($heatSeries)*32 + 60) ?>, toolbar:{show:false}, fontFamily:'inherit', background:'transparent' },
        theme: { mode: isDark() ? 'dark' : 'light' },
        series: <?= json_encode($heatSeries) ?>,
        dataLabels: { enabled: false },
        colors: ['#206bc4'],
        plotOptions: { heatmap: { shadeIntensity: .65,
            colorScale: { ranges: [
                { from: 0,           to: 1,       color: '#f1f5f9', name: 'none' },
                { from: 1,           to: 50000,   color: '#bfdbfe', name: 'low' },
                { from: 50000,       to: 200000,  color: '#60a5fa', name: 'medium' },
                { from: 200000,      to: 1000000, color: '#1d4ed8', name: 'high' },
                { from: 1000000,     to: 1e12,    color: '#1e3a8a', name: 'very high' },
            ]} } },
        xaxis: { categories: <?= json_encode($monthOrder) ?> },
        tooltip: { y: { formatter: v => '$' + v.toLocaleString(undefined,{maximumFractionDigits:0}) } },
    });
    charts.heat.render();
    window._rvCharts = window._rvCharts || {};
    window._rvCharts['chart_heatmap'] = charts.heat;

    // Treemap
    const treeData = <?= json_encode(array_map(fn($f, $v) => ['x'=>$f, 'y'=>round($v['charge'],2)], array_keys($byFacility10), array_values($byFacility10))) ?>;
    charts.tree = new ApexCharts(document.querySelector('#chart_treemap'), {
        chart: { type:'treemap', height: 340, toolbar:{show:false}, background:'transparent' },
        theme: { mode: isDark() ? 'dark' : 'light' },
        series: [{ data: treeData }],
        colors: ['#206bc4','#2fb344','#f76707','#ae3ec9','#0ea5e9','#dc2626','#16a34a','#7c3aed','#f59e0b','#475569'],
        plotOptions: { treemap: { distributed: true, enableShades: false } },
        dataLabels: { formatter: function(t, op){ return [t, '$' + op.value.toLocaleString(undefined,{maximumFractionDigits:0})]; } },
        tooltip: { y: { formatter: v => '$' + v.toLocaleString(undefined,{maximumFractionDigits:0}) } },
    });
    charts.tree.render();
    window._rvCharts['chart_treemap'] = charts.tree;

    // Funnel (bar with descending values)
    const funnelData = [
        { name: 'Charge',            value: <?= round($totals['charge'],2) ?> },
        { name: 'Expected',          value: <?= round($totals['expected'],2) ?> },
        { name: 'Total Paid',    value: <?= round(($totals['pri'] ?? 0)+($totals['sec'] ?? 0)+($totals['ter'] ?? 0)+($totals['pat_paid'] ?? 0),2) ?> },
        { name: 'Insurance Balance', value: <?= round($totals['bal'],2) ?> },
        { name: 'Patient Balance',   value: <?= round($totals['pat_bal'],2) ?> },
    ];
    charts.funnel = new ApexCharts(document.querySelector('#chart_funnel'), {
        chart: { type:'bar', height: 340, toolbar:{show:false}, background:'transparent' },
        theme: { mode: isDark() ? 'dark' : 'light' },
        series: [{ name:'Amount', data: funnelData.map(f=>f.value) }],
        plotOptions: { bar: { horizontal: true, borderRadius: 4, distributed: true, dataLabels: { position: 'top' } } },
        colors: ['#1d4ed8','#7c3aed','#16a34a','#f76707'],
        dataLabels: { enabled: true, offsetX: -8, style: { colors: ['#fff'] }, formatter: v => '$' + v.toLocaleString(undefined,{maximumFractionDigits:0}) },
        xaxis: { categories: funnelData.map(f => f.name) },
        legend: { show: false },
        tooltip: { y: { formatter: v => '$' + v.toLocaleString(undefined,{maximumFractionDigits:2}) } },
    });
    charts.funnel.render();
    window._rvCharts['chart_funnel'] = charts.funnel;

    <?php if ($byProvider10): ?>
    charts.providers = new ApexCharts(document.querySelector('#chart_providers'), {
        chart: { type:'bar', height: 380, toolbar:{show:false}, background:'transparent' },
        theme: { mode: isDark() ? 'dark' : 'light' },
        series: [{ name:'Charge', data: <?= json_encode(array_values(array_map(fn($v)=>round($v['charge'],2), $byProvider10))) ?> }],
        plotOptions: { bar: { horizontal: true, borderRadius: 3 } },
        colors: ['#0ea5e9'],
        dataLabels: { enabled: false },
        xaxis: { categories: <?= json_encode(array_map(fn($p)=>mb_substr($p,0,30), array_keys($byProvider10))) ?>,
                 labels: { formatter: v => '$' + (typeof v === 'number' ? v.toLocaleString(undefined,{maximumFractionDigits:0}) : v) } },
        tooltip: { y: { formatter: v => '$' + v.toLocaleString(undefined,{maximumFractionDigits:0}) } },
    });
    charts.providers.render();
    window._rvCharts['chart_providers'] = charts.providers;
    <?php endif; ?>

    // Day-of-week
    charts.dow = new ApexCharts(document.querySelector('#chart_dow'), {
        chart: { type:'bar', height: 380, toolbar:{show:false}, background:'transparent' },
        theme: { mode: isDark() ? 'dark' : 'light' },
        series: [{ name:'Charge', data: <?= json_encode(array_values($byDow)) ?> }],
        colors: ['#7c3aed'],
        plotOptions: { bar: { columnWidth: '60%', borderRadius: 4 } },
        dataLabels: { enabled: false },
        xaxis: { categories: <?= json_encode(array_keys($byDow)) ?> },
        yaxis: { labels: { formatter: v => '$' + Math.round(v).toLocaleString() } },
        tooltip: { y: { formatter: v => '$' + v.toLocaleString(undefined,{maximumFractionDigits:2}) } },
    });
    charts.dow.render();
    window._rvCharts['chart_dow'] = charts.dow;

    // Gauge (radial bar) for collection rate
    charts.gauge = new ApexCharts(document.querySelector('#chart_gauge'), {
        chart: { type:'radialBar', height: 240, background:'transparent' },
        theme: { mode: isDark() ? 'dark' : 'light' },
        series: [<?= round($insights['collection_pct'] ?? 0, 1) ?>],
        plotOptions: { radialBar: {
            startAngle: -135, endAngle: 135, hollow: { size: '65%' },
            track: { background: isDark() ? '#1e2a44' : '#e2e8f0', strokeWidth: '100%' },
            dataLabels: {
                name: { offsetY: 24, color: isDark() ? '#97a2b6' : '#6c7a89', fontSize: '12px' },
                value: { formatter: v => v.toFixed(1) + '%', fontSize: '28px', fontWeight: 700,
                         color: isDark() ? '#e7ecf5' : '#0f172a' },
            },
        } },
        fill: { type: 'gradient', gradient: { shade: 'dark', type: 'horizontal',
                shadeIntensity: 0.4, gradientToColors: ['#2fb344'], inverseColors: false,
                opacityFrom: 1, opacityTo: 1, stops: [0, 100] } },
        labels: ['Collection rate'],
    });
    charts.gauge.render();
    window._rvCharts['chart_gauge'] = charts.gauge;
})();
</script>
<?php endif; ?>

<script>
/* ====================== GLOBAL REPORT VIEWER ====================== */
window.rvDownloadPng = function(chartId) {
    const chart = (window._rvCharts || {})[chartId];
    if (chart && chart.dataURI) {
        chart.dataURI().then(({ imgURI }) => {
            const a = document.createElement('a');
            a.href = imgURI; a.download = chartId + '.png'; document.body.appendChild(a); a.click(); a.remove();
        });
    }
};
window.rvFullscreen = function(cardId) {
    const el = document.getElementById(cardId);
    if (!el) return;
    if (el.classList.contains('rv-fullscreen')) {
        el.classList.remove('rv-fullscreen');
    } else {
        el.classList.add('rv-fullscreen');
    }
    setTimeout(() => window.dispatchEvent(new Event('resize')), 50);
};
window.rvSetCompare = function(uid) {
    const url = new URL(window.location.href);
    if (uid) url.searchParams.set('compare', uid);
    else     url.searchParams.delete('compare');
    window.location.href = url.toString();
};

/* ====================== BOOKMARKS (localStorage) ====================== */
(function(){
    const KEY = 'rv_bookmarks_<?= $reportId ?>';
    function load() { try { return JSON.parse(localStorage.getItem(KEY) || '[]'); } catch(e) { return []; } }
    function save(list) { try { localStorage.setItem(KEY, JSON.stringify(list)); } catch(e){} }
    function render() {
        const list = load(), container = document.getElementById('bm_list');
        if (!container) return;
        if (!list.length) { container.innerHTML = '<div class="text-secondary small px-3 py-2">No saved views yet.</div>'; return; }
        container.innerHTML = list.map((b, i) =>
            '<div class="bm-item"><i class="ti ti-bookmark"></i>'
            + '<span class="name" onclick="bmGo(' + i + ')">' + b.name + '</span>'
            + '<i class="ti ti-x del" onclick="bmDel(' + i + '); event.stopPropagation()"></i></div>'
        ).join('');
    }
    window.bmSaveCurrent = function(){
        const name = prompt('Name this view:', 'View ' + (load().length + 1));
        if (!name) return;
        const list = load();
        list.push({ name: name, url: window.location.search, savedAt: Date.now() });
        save(list); render();
        if (window.mToast) mToast('View saved', 'success');
    };
    window.bmGo = function(i){
        const b = load()[i]; if (!b) return;
        window.location.search = b.url;
    };
    window.bmDel = function(i){
        const list = load();
        if (confirm('Delete view "' + (list[i] && list[i].name) + '"?')) {
            list.splice(i, 1); save(list); render();
        }
    };
    render();
})();

/* ====================== KEYBOARD SHORTCUTS ====================== */
document.addEventListener('keydown', function(e){
    if (['INPUT','TEXTAREA','SELECT'].includes(document.activeElement.tagName)) return;
    if (e.ctrlKey || e.metaKey || e.altKey) return;
    const tabKeys = { '1':'dashboard', '2':'summary', '3':'pivot', '4':'analytics', '5':'detail', '6':'history' };
    if (tabKeys[e.key]) {
        const link = document.querySelector('.rv-tabs .nav-link[data-tab-key="' + e.key + '"]');
        if (link) { e.preventDefault(); window.location.href = link.href; }
    }
});

/* ====================== THEME RE-RENDER ====================== */
window.addEventListener('m-theme-change', function(e){
    const dark = e.detail.theme === 'dark';
    Object.values(window._rvCharts || {}).forEach(c => {
        try { c.updateOptions({ theme: { mode: dark ? 'dark' : 'light' } }, false, true); } catch(err){}
    });
});
</script>

<?php require __DIR__ . '/../includes/footer.php'; ?>
