<?php
require_once 'includes/config.php';
require_once 'includes/functions.php';
requireLogin();
$uid = $_SESSION['user_id'];
$currentUser = getCurrentUser();
$userIsPro = isProUser($currentUser);
$groqApiKey = defined('GROQ_API_KEY') ? GROQ_API_KEY : ''; // server-side only now, never sent to client

// ── AJAX ─────────────────────────────────────────────────────────
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_SERVER['HTTP_X_REQUESTED_WITH'])) {
    $action = $_POST['action'] ?? '';

    // ── Server-side AI proxy: keeps GROQ_API_KEY off the client and enforces quota ──
    if ($action === 'ai_generate') {
        $quota = checkAiQuota($uid, $currentUser);
        if (!$quota['allowed']) {
            jsonResponse(['success' => false, 'quota_exceeded' => true, 'message' => "Daily free AI limit reached ({$quota['limit']}/day). Upgrade to Pro for unlimited access."]);
        }
        $sys = $_POST['sys'] ?? 'You are an expert A/L study coach for Sri Lankan students.';
        $usr = $_POST['usr'] ?? '';
        $tokens = min(1500, max(100, (int)($_POST['tokens'] ?? 800)));
        if (!$usr) jsonResponse(['success' => false, 'message' => 'No prompt provided.']);
        try {
            $reply = callGroqServer([
                ['role' => 'system', 'content' => $sys],
                ['role' => 'user', 'content' => $usr],
            ], $tokens, 0.65);
            logAiUsage($uid, 'ai_analysis');
            $quota2 = checkAiQuota($uid, $currentUser);
            jsonResponse(['success' => true, 'reply' => $reply, 'quota' => $quota2]);
        } catch (Exception $e) {
            jsonResponse(['success' => false, 'message' => $e->getMessage()]);
        }
    }

    if ($action === 'get_full_data') {
        $d = [];

        // User
        $q = $pdo->prepare("SELECT name, created_at, study_goal_minutes FROM users WHERE id=?");
        $q->execute([$uid]); $d['user'] = $q->fetch();

        // Weekly hours — last 12 weeks
        $q = $pdo->prepare("
            SELECT DATE_FORMAT(MIN(date),'%b %d') as week_label,
                   ROUND(SUM(duration_minutes)/60,2) as hours
            FROM study_sessions WHERE user_id=?
            AND date >= DATE_SUB(CURDATE(),INTERVAL 12 WEEK)
            GROUP BY YEARWEEK(date,1) ORDER BY MIN(date)
        ");
        $q->execute([$uid]); $d['weekly_hours'] = $q->fetchAll();

        // Daily last 30 days
        $daily = [];
        for ($i = 29; $i >= 0; $i--) {
            $dt = date('Y-m-d', strtotime("-$i days"));
            $q  = $pdo->prepare("SELECT COALESCE(SUM(duration_minutes),0) FROM study_sessions WHERE user_id=? AND date=?");
            $q->execute([$uid, $dt]);
            $daily[] = ['date' => $dt, 'label' => date('M j', strtotime($dt)), 'mins' => (int)$q->fetchColumn()];
        }
        $d['daily'] = $daily;

        // Subject totals
        $q = $pdo->prepare("
            SELECT s.name, s.color,
                   COALESCE(SUM(ss.duration_minutes),0) as total_mins,
                   COUNT(DISTINCT ss.date) as study_days,
                   COALESCE(AVG(m.marks_obtained/m.total_marks*100),0) as avg_mark,
                   COALESCE(MAX(m.marks_obtained/m.total_marks*100),0) as best_mark,
                   COUNT(m.id) as exam_count
            FROM subjects s
            LEFT JOIN study_sessions ss ON s.id=ss.subject_id
            LEFT JOIN marks m ON s.id=m.subject_id AND m.user_id=?
            WHERE s.user_id=?
            GROUP BY s.id ORDER BY total_mins DESC
        ");
        $q->execute([$uid, $uid]); $d['subjects'] = $q->fetchAll();

        // Marks trend
        $q = $pdo->prepare("
            SELECT m.exam_date, m.exam_name, s.name as subject, s.color,
                   ROUND(m.marks_obtained/m.total_marks*100,1) as pct,
                   m.marks_obtained, m.total_marks
            FROM marks m JOIN subjects s ON m.subject_id=s.id
            WHERE m.user_id=? ORDER BY m.exam_date ASC LIMIT 40
        ");
        $q->execute([$uid]); $d['marks'] = $q->fetchAll();

        // Marks by subject (for radar)
        $q = $pdo->prepare("
            SELECT s.name, ROUND(AVG(m.marks_obtained/m.total_marks*100),1) as avg_pct
            FROM marks m JOIN subjects s ON m.subject_id=s.id
            WHERE m.user_id=? GROUP BY s.id ORDER BY avg_pct DESC
        ");
        $q->execute([$uid]); $d['marks_by_subject'] = $q->fetchAll();

        // Study time by hour of day (from session created_at)
        $q = $pdo->prepare("
            SELECT HOUR(created_at) as hr, COUNT(*) as cnt
            FROM study_sessions WHERE user_id=?
            GROUP BY hr ORDER BY hr
        ");
        $q->execute([$uid]); $d['hour_dist'] = $q->fetchAll();

        // Goals
        $q = $pdo->prepare("SELECT title,type,target_value,current_value,unit,status,deadline FROM goals WHERE user_id=? ORDER BY created_at DESC LIMIT 10");
        $q->execute([$uid]); $d['goals'] = $q->fetchAll();

        // Tasks
        $q = $pdo->prepare("SELECT title,priority,status,due_date FROM tasks WHERE user_id=? ORDER BY created_at DESC LIMIT 20");
        $q->execute([$uid]); $d['tasks'] = $q->fetchAll();

        // Streak
        $q = $pdo->prepare("SELECT date,minutes_studied FROM study_streaks WHERE user_id=? ORDER BY date DESC LIMIT 30");
        $q->execute([$uid]); $d['streaks'] = $q->fetchAll();

        // Class attendance
        $q = $pdo->prepare("
            SELECT COUNT(*) as total, SUM(attended) as attended
            FROM class_hours WHERE user_id=?
        ");
        $q->execute([$uid]); $d['class_att'] = $q->fetch();

        // Aggregate
        $q = $pdo->prepare("SELECT COALESCE(SUM(duration_minutes),0) FROM study_sessions WHERE user_id=? AND date>=DATE_SUB(CURDATE(),INTERVAL 7 DAY)"); $q->execute([$uid]); $d['week_mins']      = (int)$q->fetchColumn();
        $q = $pdo->prepare("SELECT COALESCE(SUM(duration_minutes),0) FROM study_sessions WHERE user_id=?");                                                $q->execute([$uid]); $d['total_mins']     = (int)$q->fetchColumn();
        $q = $pdo->prepare("SELECT COALESCE(AVG(marks_obtained/total_marks*100),0) FROM marks WHERE user_id=?");                                           $q->execute([$uid]); $d['avg_mark']       = round($q->fetchColumn(),1);
        $q = $pdo->prepare("SELECT COUNT(*) FROM study_sessions WHERE user_id=?");                                                                         $q->execute([$uid]); $d['total_sessions'] = (int)$q->fetchColumn();
        $q = $pdo->prepare("SELECT COUNT(*) FROM tasks WHERE user_id=? AND status='completed'");                                                           $q->execute([$uid]); $d['tasks_done']     = (int)$q->fetchColumn();
        $q = $pdo->prepare("SELECT COUNT(*) FROM tasks WHERE user_id=? AND status!='completed'");                                                          $q->execute([$uid]); $d['tasks_pending']  = (int)$q->fetchColumn();

        jsonResponse(['success' => true, 'data' => $d]);
    }
    jsonResponse(['success' => false]);
}

// ── Page stats ───────────────────────────────────────────────────
$q = $pdo->prepare("SELECT COALESCE(SUM(duration_minutes),0)/60 FROM study_sessions WHERE user_id=? AND date>=DATE_SUB(CURDATE(),INTERVAL 7 DAY)"); $q->execute([$uid]); $weekH = round($q->fetchColumn(),1);
$q = $pdo->prepare("SELECT COALESCE(AVG(marks_obtained/total_marks*100),0) FROM marks WHERE user_id=?");                                            $q->execute([$uid]); $avgM  = round($q->fetchColumn(),1);
$q = $pdo->prepare("SELECT COUNT(*) FROM study_sessions WHERE user_id=?");                                                                          $q->execute([$uid]); $sess  = (int)$q->fetchColumn();
$q = $pdo->prepare("SELECT COALESCE(SUM(duration_minutes),0)/60 FROM study_sessions WHERE user_id=?");                                              $q->execute([$uid]); $totalH= round($q->fetchColumn(),1);

// streak calc
$streakQ = $pdo->prepare("SELECT date FROM study_streaks WHERE user_id=? ORDER BY date DESC");
$streakQ->execute([$uid]); $streakDates = $streakQ->fetchAll(PDO::FETCH_COLUMN);
$streak = 0; $check = new DateTime('today');
foreach ($streakDates as $sd) { if ($sd === $check->format('Y-m-d')) { $streak++; $check->modify('-1 day'); } elseif ($sd < $check->format('Y-m-d')) break; }

$hasKey     = !empty($groqApiKey);
$userName   = $_SESSION['user_name'] ?? 'Student';
$userInitial= strtoupper($userName[0]);

require_once 'includes/header.php';
renderHeader('AI Analysis', 'ai-analysis');
?>

<style>
/* ══ Layout ══════════════════════════════════════════════════════ */
.aia-header {
  background: linear-gradient(135deg,rgba(99,102,241,.13),rgba(168,85,247,.08),rgba(6,182,212,.05));
  border: 1px solid rgba(99,102,241,.22); border-radius: 20px;
  padding: 26px 28px 22px; margin-bottom: 24px; position: relative; overflow: hidden;
}
.aia-header::after {
  content:''; position:absolute; top:-80px; right:-80px;
  width:220px; height:220px;
  background:radial-gradient(circle,rgba(168,85,247,.18),transparent 70%);
  pointer-events:none;
}
.aia-title  { font-size:23px; font-weight:800; font-family:'Sora',sans-serif; }
.aia-sub    { font-size:13px; color:var(--text-muted); margin-top:4px 0 18px; }
.kpi-row    { display:flex; gap:14px; flex-wrap:wrap; margin-top:18px; }
.kpi        { background:rgba(255,255,255,.045); border:1px solid rgba(255,255,255,.07);
              border-radius:12px; padding:10px 18px; min-width:90px; }
.kpi-val    { font-size:22px; font-weight:800; color:var(--text-primary); }
.kpi-lbl    { font-size:11px; color:var(--text-muted); margin-top:1px; }

/* ── Section title ──────────────────────────────────────────────── */
.sec-hd     { font-size:15px; font-weight:700; color:var(--text-primary);
              display:flex; align-items:center; gap:8px; margin-bottom:14px; }
.sec-badge  { font-size:10px; font-weight:700; padding:2px 8px; border-radius:20px;
              background:rgba(99,102,241,.15); color:#a78bfa; border:1px solid rgba(99,102,241,.25); }

/* ── Chart cards ────────────────────────────────────────────────── */
.chart-card { background:var(--bg-card); border:1px solid var(--border); border-radius:16px;
              padding:18px 20px; margin-bottom:20px; overflow:hidden; min-width:0; }
.chart-card .ch-title  { font-size:13px; font-weight:700; color:var(--text-primary); margin-bottom:4px; }
.chart-card .ch-sub    { font-size:11px; color:var(--text-muted); margin-bottom:14px; }
.charts-2col { display:grid; grid-template-columns:1fr 1fr; gap:16px; margin-bottom:20px; min-width:0; }
.charts-3col { display:grid; grid-template-columns:repeat(3,1fr); gap:16px; margin-bottom:20px; min-width:0; }
.charts-2col > *, .charts-3col > * { min-width:0; overflow:hidden; }
@media(max-width:900px){.charts-3col{grid-template-columns:1fr 1fr}}
@media(max-width:768px){.charts-2col,.charts-3col{grid-template-columns:1fr}}
canvas { display:block; max-width:100%; }
.chart-wrap { position:relative; width:100%; overflow:hidden; }

/* ── Subject bars ───────────────────────────────────────────────── */
.sub-row { display:flex; align-items:center; gap:10px; margin-bottom:10px; }
.sub-dot { width:10px; height:10px; border-radius:50%; flex-shrink:0; }
.sub-name{ font-size:12px; color:var(--text-secondary); min-width:80px; flex-shrink:0; }
.sub-bar-wrap { flex:1; height:8px; background:var(--border); border-radius:4px; overflow:hidden; }
.sub-bar-fill { height:100%; border-radius:4px; transition:width 1.2s cubic-bezier(.4,0,.2,1); }
.sub-pct { font-size:11px; color:var(--text-muted); min-width:36px; text-align:right; }

/* ── AI section ─────────────────────────────────────────────────── */
.ai-tabs { display:flex; gap:6px; flex-wrap:wrap; margin-bottom:16px; }
.ai-tab  { padding:7px 14px; border-radius:20px; border:1px solid var(--border);
           background:var(--bg-secondary); color:var(--text-muted);
           font-size:12px; font-weight:600; cursor:pointer; transition:all .2s; }
.ai-tab:hover  { border-color:#6366f1; color:#a78bfa; }
.ai-tab.active { background:rgba(99,102,241,.15); border-color:#6366f1; color:#a78bfa; }

.ai-panel { display:none; }
.ai-panel.show { display:block; animation:fadeUp .3s ease; }
@keyframes fadeUp { from{opacity:0;transform:translateY(8px)} to{opacity:1;transform:none} }

.ai-output-box { background:var(--bg-secondary); border:1px solid var(--border); border-radius:12px;
                 padding:16px 18px; min-height:100px; font-size:13.5px; line-height:1.85;
                 color:var(--text-secondary); white-space:pre-wrap; }
.ai-output-box.loading { display:flex; align-items:center; gap:10px; color:var(--text-muted); }

.skel { background:linear-gradient(90deg,var(--border) 25%,var(--border-light,#333348) 50%,var(--border) 75%);
        background-size:200% 100%; animation:sk 1.4s infinite; border-radius:6px; height:13px; margin-bottom:9px; }
.skel.w80{width:80%} .skel.w60{width:60%} .skel.w90{width:90%} .skel.w50{width:50%} .skel.w70{width:70%}
@keyframes sk{ 0%{background-position:200%} 100%{background-position:-200%} }

/* ── Insight cards row ──────────────────────────────────────────── */
.insight-grid { display:grid; grid-template-columns:repeat(auto-fill,minmax(260px,1fr)); gap:14px; margin-bottom:20px; }
.insight-card { background:var(--bg-card); border:1px solid var(--border); border-radius:14px; padding:16px; transition:border-color .2s; }
.insight-card:hover { border-color:rgba(99,102,241,.35); }
.insight-icon { font-size:22px; margin-bottom:8px; }
.insight-title{ font-size:12px; font-weight:700; color:var(--text-muted); text-transform:uppercase; letter-spacing:.5px; margin-bottom:6px; }
.insight-text { font-size:13px; color:var(--text-secondary); line-height:1.7; }
.insight-text.loading .skel { margin-bottom:6px; }

/* ── Buttons ────────────────────────────────────────────────────── */
.gen-btn { display:inline-flex; align-items:center; gap:8px;
           background:linear-gradient(135deg,#6366f1,#a855f7); color:#fff;
           border:none; border-radius:11px; padding:10px 20px; font-size:13px; font-weight:700;
           cursor:pointer; transition:opacity .2s, transform .1s; }
.gen-btn:hover   { opacity:.88; }
.gen-btn:active  { transform:scale(.97); }
.gen-btn:disabled{ opacity:.4; cursor:not-allowed; }
.gen-btn .spin   { width:14px;height:14px;border:2px solid rgba(255,255,255,.3);border-top-color:#fff;border-radius:50%;animation:rot .7s linear infinite; }
@keyframes rot { to{transform:rotate(360deg)} }

.lang-toggle { display:flex; gap:6px; }
.lang-btn { padding:5px 12px; border-radius:20px; font-size:11px; font-weight:600;
            border:1px solid var(--border); background:var(--bg-secondary); color:var(--text-muted); cursor:pointer; transition:all .2s; }
.lang-btn.on { background:rgba(99,102,241,.15); border-color:#6366f1; color:#a78bfa; }

.copy-btn { padding:5px 12px; border-radius:8px; font-size:11px; font-weight:600;
            border:1px solid var(--border); background:var(--bg-secondary); color:var(--text-muted); cursor:pointer; transition:all .2s; }
.copy-btn:hover { border-color:#6366f1; color:#a78bfa; }

/* ── Score ring ─────────────────────────────────────────────────── */
.score-ring-wrap { display:flex; flex-direction:column; align-items:center; justify-content:center; gap:6px; padding:8px 0; }
.score-ring { position:relative; width:110px; height:110px; }
.score-ring svg { transform:rotate(-90deg); }
.score-ring-val { position:absolute; inset:0; display:flex; flex-direction:column; align-items:center; justify-content:center; }
.score-ring-num { font-size:26px; font-weight:800; color:var(--text-primary); }
.score-ring-lbl { font-size:10px; color:var(--text-muted); margin-top:-2px; }
.score-grade    { font-size:13px; font-weight:700; padding:3px 10px; border-radius:20px; }

/* ── Heatmap ────────────────────────────────────────────────────── */
.heatmap-mini { display:flex; gap:3px; flex-wrap:wrap; }
.hm-cell { width:13px; height:13px; border-radius:3px; background:var(--bg-secondary); border:1px solid var(--border); cursor:default; transition:transform .1s; }
.hm-cell:hover { transform:scale(1.3); }
.hm-cell[data-l="1"]{ background:rgba(99,102,241,.25); border-color:rgba(99,102,241,.3); }
.hm-cell[data-l="2"]{ background:rgba(99,102,241,.5);  border-color:rgba(99,102,241,.5); }
.hm-cell[data-l="3"]{ background:rgba(99,102,241,.75); border-color:rgba(99,102,241,.6); }
.hm-cell[data-l="4"]{ background:#6366f1; border-color:#818cf8; }
</style>

<?php $aiaQuota = checkAiQuota($uid, $currentUser); ?>
<?php if (!$userIsPro): ?>
<div style="display:flex;align-items:center;justify-content:space-between;gap:14px;flex-wrap:wrap;background:linear-gradient(135deg,rgba(245,158,11,.12),rgba(245,158,11,.04));border:1px solid rgba(245,158,11,.28);border-radius:14px;padding:13px 18px;margin-bottom:16px;font-size:13px;">
  <span style="color:var(--text-secondary);">🔒 Free plan: <b id="quotaText"><?= $aiaQuota['used'] ?>/<?= $aiaQuota['limit'] ?></b> AI requests used today</span>
  <a href="<?= SITE_URL ?>/upgrade" style="background:linear-gradient(135deg,#f59e0b,#f97316);color:#fff;font-weight:700;padding:8px 16px;border-radius:9px;text-decoration:none;white-space:nowrap;">⚡ Upgrade to Pro</a>
</div>
<?php else: ?>
<div style="display:inline-flex;align-items:center;gap:8px;background:linear-gradient(135deg,rgba(16,185,129,.14),rgba(16,185,129,.05));border:1px solid rgba(16,185,129,.3);color:#10b981;font-weight:700;font-size:12.5px;padding:7px 14px;border-radius:999px;margin-bottom:16px;">✨ Pro — Unlimited AI access</div>
<?php endif; ?>

<!-- ══ HEADER ════════════════════════════════════════════════════ -->
<div class="aia-header">
  <div style="display:flex;align-items:flex-start;justify-content:space-between;flex-wrap:wrap;gap:12px">
    <div>
      <div class="aia-title">🧠 AI Study Analysis</div>
      <div class="aia-sub">Deep insights from your complete study history</div>
    </div>
    <div style="display:flex;flex-direction:column;align-items:flex-end;gap:8px">
      <div class="lang-toggle">
        <button class="lang-btn on" data-l="si" onclick="setLang('si',this)">🇱🇰 සිංහල</button>
        <button class="lang-btn"   data-l="en" onclick="setLang('en',this)">🇬🇧 English</button>
      </div>
      <button class="gen-btn" id="masterBtn" onclick="runAll()">
        <svg width="14" height="14" fill="none" stroke="currentColor" stroke-width="2.5" viewBox="0 0 24 24"><path d="M12 2v4M12 18v4M4.93 4.93l2.83 2.83M16.24 16.24l2.83 2.83M2 12h4M18 12h4M4.93 19.07l2.83-2.83M16.24 7.76l2.83-2.83"/></svg>
        Full Analysis
      </button>
    </div>
  </div>
  <div class="kpi-row">
    <div class="kpi"><div class="kpi-val"><?= $weekH ?>h</div><div class="kpi-lbl">This Week</div></div>
    <div class="kpi"><div class="kpi-val"><?= $totalH ?>h</div><div class="kpi-lbl">Total Hours</div></div>
    <div class="kpi"><div class="kpi-val"><?= $avgM ?>%</div><div class="kpi-lbl">Avg Marks</div></div>
    <div class="kpi"><div class="kpi-val"><?= $sess ?></div><div class="kpi-lbl">Sessions</div></div>
    <div class="kpi"><div class="kpi-val"><?= $streak ?>🔥</div><div class="kpi-lbl">Day Streak</div></div>
  </div>
</div>

<?php if (!$hasKey): ?>
<div class="alert alert-warning" style="margin-bottom:18px">
  ⚙️ Add <code>define('GROQ_API_KEY','...');</code> to <code>includes/config.php</code> for AI analysis.
  Free key: <a href="https://console.groq.com" target="_blank" style="color:#fbbf24">console.groq.com</a>
</div>
<?php endif; ?>

<!-- ══ CHARTS SECTION ════════════════════════════════════════════ -->
<div class="sec-hd">📊 Charts & Data <span class="sec-badge">LIVE</span></div>

<!-- Row 1: Study Hours Line + Subject Donut -->
<div class="charts-2col">
  <div class="chart-card">
    <div class="ch-title">📈 Weekly Study Hours</div>
    <div class="ch-sub">Last 12 weeks trend</div>
    <div class="chart-wrap" style="height:200px"><canvas id="weeklyChart"></canvas></div>
  </div>
  <div class="chart-card">
    <div class="ch-title">🥧 Subject Distribution</div>
    <div class="ch-sub">Total time per subject</div>
    <div style="display:flex;gap:16px;align-items:center">
      <div style="width:140px;height:140px;flex-shrink:0"><canvas id="pieChart"></canvas></div>
      <div style="flex:1;min-width:0" id="pieLegend"></div>
    </div>
  </div>
</div>

<!-- Row 2: Daily bars + Marks scatter -->
<div class="charts-2col">
  <div class="chart-card">
    <div class="ch-title">📅 Daily Study (Last 30 Days)</div>
    <div class="ch-sub">Minutes per day</div>
    <div class="chart-wrap" style="height:180px"><canvas id="dailyChart"></canvas></div>
  </div>
  <div class="chart-card">
    <div class="ch-title">📝 Marks Trend</div>
    <div class="ch-sub">Score % over time</div>
    <div class="chart-wrap" style="height:180px"><canvas id="marksChart"></canvas></div>
  </div>
</div>

<!-- Row 3: Radar + Hour Distribution + Subject performance bars -->
<div class="charts-3col">
  <div class="chart-card">
    <div class="ch-title">🕸️ Subject Radar</div>
    <div class="ch-sub">Average marks by subject</div>
    <div class="chart-wrap" style="height:200px"><canvas id="radarChart"></canvas></div>
  </div>
  <div class="chart-card">
    <div class="ch-title">🕐 Study Time of Day</div>
    <div class="ch-sub">When you usually study</div>
    <div class="chart-wrap" style="height:200px"><canvas id="hourChart"></canvas></div>
  </div>
  <div class="chart-card">
    <div class="ch-title">📚 Subject Performance</div>
    <div class="ch-sub">Avg mark % per subject</div>
    <div id="subPerfBars" style="padding-top:8px"></div>
  </div>
</div>

<!-- Heatmap -->
<div class="chart-card" style="margin-bottom:20px">
  <div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:12px;flex-wrap:wrap;gap:8px">
    <div><div class="ch-title">🗓️ Study Heatmap</div><div class="ch-sub">Last 84 days consistency</div></div>
    <div style="display:flex;align-items:center;gap:6px;font-size:11px;color:var(--text-muted)">
      Less
      <div style="width:12px;height:12px;border-radius:3px;background:var(--bg-secondary);border:1px solid var(--border)"></div>
      <div style="width:12px;height:12px;border-radius:3px;background:rgba(99,102,241,.3)"></div>
      <div style="width:12px;height:12px;border-radius:3px;background:rgba(99,102,241,.55)"></div>
      <div style="width:12px;height:12px;border-radius:3px;background:rgba(99,102,241,.8)"></div>
      <div style="width:12px;height:12px;border-radius:3px;background:#6366f1"></div>
      More
    </div>
  </div>
  <div class="heatmap-mini" id="heatmapEl"></div>
</div>

<!-- ══ AI INSIGHT CARDS ══════════════════════════════════════════ -->
<div class="sec-hd" style="margin-bottom:14px">🤖 AI Insights <span class="sec-badge">Groq · LLaMA 3.3 70B</span></div>

<div class="insight-grid">
  <div class="insight-card" id="ic-score">
    <div class="insight-icon">🎯</div>
    <div class="insight-title">Performance Score</div>
    <div class="insight-text" id="it-score"><div class="skel w80"></div><div class="skel w60"></div><div class="skel w70"></div></div>
  </div>
  <div class="insight-card" id="ic-habit">
    <div class="insight-icon">📅</div>
    <div class="insight-title">Study Habit</div>
    <div class="insight-text" id="it-habit"><div class="skel w90"></div><div class="skel w60"></div><div class="skel w80"></div></div>
  </div>
  <div class="insight-card" id="ic-weak">
    <div class="insight-icon">⚠️</div>
    <div class="insight-title">Weak Areas</div>
    <div class="insight-text" id="it-weak"><div class="skel w70"></div><div class="skel w90"></div><div class="skel w50"></div></div>
  </div>
  <div class="insight-card" id="ic-exam">
    <div class="insight-icon">📝</div>
    <div class="insight-title">Exam Readiness</div>
    <div class="insight-text" id="it-exam"><div class="skel w80"></div><div class="skel w60"></div><div class="skel w70"></div></div>
  </div>
</div>

<!-- ══ DEEP AI ANALYSIS TABS ═════════════════════════════════════ -->
<div class="chart-card" style="margin-bottom:20px">
  <div style="display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:10px;margin-bottom:16px">
    <div><div class="ch-title" style="font-size:15px">🧬 Deep AI Analysis</div><div class="ch-sub">Select a topic for detailed analysis</div></div>
    <div style="display:flex;gap:8px;align-items:center">
      <button class="copy-btn" onclick="copyActive()">📋 Copy</button>
    </div>
  </div>
  <div class="ai-tabs">
    <button class="ai-tab active" data-tab="overview"  onclick="switchTab('overview',this)">📋 Overview</button>
    <button class="ai-tab"        data-tab="marks"     onclick="switchTab('marks',this)">📊 Marks Analysis</button>
    <button class="ai-tab"        data-tab="subjects"  onclick="switchTab('subjects',this)">📚 Subject Strategy</button>
    <button class="ai-tab"        data-tab="schedule"  onclick="switchTab('schedule',this)">⏰ Schedule Review</button>
    <button class="ai-tab"        data-tab="goals"     onclick="switchTab('goals',this)">🏆 Goals & Tasks</button>
    <button class="ai-tab"        data-tab="predict"   onclick="switchTab('predict',this)">🔮 Prediction</button>
    <button class="ai-tab"        data-tab="report"    onclick="switchTab('report',this)">📄 Full Report</button>
  </div>
  <div id="tab-overview"  class="ai-panel show"><div class="ai-output-box" id="out-overview"><div class="skel w90"></div><div class="skel w70"></div><div class="skel w80"></div><div class="skel w60"></div></div></div>
  <div id="tab-marks"     class="ai-panel"><div class="ai-output-box" id="out-marks"></div></div>
  <div id="tab-subjects"  class="ai-panel"><div class="ai-output-box" id="out-subjects"></div></div>
  <div id="tab-schedule"  class="ai-panel"><div class="ai-output-box" id="out-schedule"></div></div>
  <div id="tab-goals"     class="ai-panel"><div class="ai-output-box" id="out-goals"></div></div>
  <div id="tab-predict"   class="ai-panel"><div class="ai-output-box" id="out-predict"></div></div>
  <div id="tab-report"    class="ai-panel"><div class="ai-output-box" id="out-report"></div></div>
</div>

<!-- ══ RATE LIMIT POPUP ══════════════════════════════════════════ -->
<div id="rateLimitOverlay" style="display:none;position:fixed;inset:0;z-index:99999;background:rgba(0,0,0,.65);backdrop-filter:blur(6px);align-items:center;justify-content:center;padding:20px">
  <div style="background:var(--bg-card);border:1px solid rgba(245,158,11,.3);border-radius:20px;padding:36px 32px;max-width:420px;width:100%;text-align:center;box-shadow:0 24px 64px rgba(0,0,0,.4);animation:popIn .25s ease">
    <div style="width:68px;height:68px;border-radius:50%;background:rgba(245,158,11,.12);border:2px solid rgba(245,158,11,.3);display:flex;align-items:center;justify-content:center;font-size:32px;margin:0 auto 18px">⏳</div>
    <div style="font-size:20px;font-weight:800;color:var(--text-primary);margin-bottom:10px;font-family:'Sora',sans-serif">Rate Limit Reached</div>
    <div style="font-size:14px;color:var(--text-secondary);line-height:1.7;margin-bottom:8px">Groq API rate limit exceeded. Please wait a moment and try again.</div>
    <div id="rateLimitMsg" style="font-size:12px;color:var(--text-muted);background:var(--bg-secondary);border-radius:10px;padding:10px 14px;margin:14px 0 22px;line-height:1.6"></div>
    <div style="display:flex;gap:10px;justify-content:center">
      <button onclick="closeRateLimit()" style="padding:10px 22px;border-radius:10px;border:1px solid var(--border);background:var(--bg-secondary);color:var(--text-secondary);font-size:13px;font-weight:600;cursor:pointer">Close</button>
      <a href="<?= SITE_URL ?>/upgrade" style="padding:10px 22px;border-radius:10px;border:none;background:linear-gradient(135deg,#f59e0b,#f97316);color:#fff;font-size:13px;font-weight:700;cursor:pointer;text-decoration:none">⚡ Upgrade to Pro</a>
    </div>
  </div>
</div>
@keyframes popIn { from{opacity:0;transform:scale(.92)} to{opacity:1;transform:scale(1)} }

<?php require_once 'includes/footer.php'; renderFooter(); ?>

<script>
const IS_PRO = <?= json_encode($userIsPro) ?>;
let userLang  = 'si';
let userData  = null;
let loaded    = false;
const tabDone = {};

// ── Language ─────────────────────────────────────────────────────
function setLang(l, btn) {
  userLang = l;
  document.querySelectorAll('.lang-btn').forEach(b => b.classList.remove('on'));
  btn.classList.add('on');
}
function li() {
  return userLang === 'si'
    ? 'IMPORTANT: Reply ENTIRELY in Sinhala script (සිංහල). Do not use any English words in your response.'
    : 'IMPORTANT: Reply entirely in English.';
}

// ── Data fetch ───────────────────────────────────────────────────
async function getData() {
  if (loaded) return userData;
  const fd = new FormData(); fd.append('action','get_full_data');
  const r  = await fetch(location.href,{method:'POST',headers:{'X-Requested-With':'XMLHttpRequest'},body:fd});
  const j  = await r.json();
  if (j.success) { userData = j.data; loaded = true; }
  return userData;
}

// ── Groq ─────────────────────────────────────────────────────────
let _lastRetryFn = null;

function updateQuotaUI(q){
  if(IS_PRO||!q)return;
  const t=document.getElementById('quotaText');if(t)t.textContent=q.used+'/'+q.limit;
}

async function groq(sys, usr, tokens = 800, retryFn = null) {
  const fd = new FormData();
  fd.append('action','ai_generate'); fd.append('sys', sys); fd.append('usr', usr); fd.append('tokens', tokens);
  const r = await fetch(location.href, { method:'POST', headers:{'X-Requested-With':'XMLHttpRequest'}, body: fd });
  const d = await r.json();

  if (d.quota_exceeded) {
    _lastRetryFn = retryFn;
    showQuotaLimit(d.message);
    throw new Error('QUOTA');
  }
  if (!d.success) {
    const msg = d.message || 'Groq error';
    if (msg.toLowerCase().includes('rate limit') || msg.toLowerCase().includes('rate_limit')) {
      _lastRetryFn = retryFn;
      showRateLimit(msg);
      throw new Error('RATE_LIMIT');
    }
    throw new Error(msg);
  }
  updateQuotaUI(d.quota);
  return d.reply || '';
}

async function showQuotaLimit(msg) {
  const el = document.getElementById('rateLimitMsg');
  if (el) el.textContent = (msg || 'Daily free AI limit reached.') + ' Upgrade to Pro for unlimited access.';
  const ov = document.getElementById('rateLimitOverlay');
  if (ov) {
    ov.style.display = 'flex';
  } else {
    if (await stConfirm((msg||'Daily free AI limit reached.') + ' Go to Upgrade page now?', {title:'Limit Reached', icon:'🚀', okLabel:'Upgrade', okStyle:'primary'})) location.href = '<?= SITE_URL ?>/upgrade';
  }
}

function showRateLimit(msg) {
  document.getElementById('rateLimitMsg').textContent = msg || 'Too many requests. Please wait 30–60 seconds before trying again.';
  const ov = document.getElementById('rateLimitOverlay');
  ov.style.display = 'flex';
}
function closeRateLimit() {
  document.getElementById('rateLimitOverlay').style.display = 'none';
  window.history.length > 1 ? window.history.back() : window.location.href = 'dashboard';
}
function retryLast() {
  closeRateLimit();
  if (_lastRetryFn) { _lastRetryFn(); _lastRetryFn = null; }
  else runAll();
}

// ── Data summary ─────────────────────────────────────────────────
function summary(d) {
  const subs  = (d.subjects||[]).map(s=>`  ${s.name}: ${(s.total_mins/60).toFixed(1)}h studied, avg mark ${Math.round(s.avg_mark)}%, best ${Math.round(s.best_mark)}%`).join('\n');
  const marks = (d.marks||[]).map(m=>`  ${m.subject} - ${m.exam_name}: ${m.pct}% (${m.exam_date})`).join('\n');
  const goals = (d.goals||[]).map(g=>`  ${g.title}: ${g.current_value}/${g.target_value} ${g.unit} [${g.status}]`).join('\n');
  const tasks = (d.tasks||[]).map(t=>`  [${t.status}] ${t.title} (${t.priority} priority)`).join('\n');
  const wkH   = (d.week_mins/60).toFixed(1);
  const totH  = (d.total_mins/60).toFixed(1);
  const att   = d.class_att;
  const attPct= att?.total > 0 ? Math.round(att.attended/att.total*100) : 'N/A';
  return `STUDENT: ${d.user?.name||'Student'} | Goal: ${d.user?.study_goal_minutes||120}min/day
STATS: ${wkH}h this week | ${totH}h total | ${d.total_sessions} sessions | avg mark ${d.avg_mark}% | streak days ${(d.streaks||[]).length}
TASKS: ${d.tasks_done} done, ${d.tasks_pending} pending | CLASS ATTENDANCE: ${attPct}%

SUBJECTS:
${subs||'None'}

MARKS:
${marks||'None'}

GOALS:
${goals||'None'}

TASKS:
${tasks||'None'}`;
}

// ── Tab prompts ───────────────────────────────────────────────────
const PROMPTS = {
  overview:  d => `${li()}\nYou are an expert A/L study coach. ${summary(d)}\n\nGive a comprehensive overview: performance score /10, key strengths, main weaknesses, 3 most important improvements. Be specific with numbers.`,
  marks:     d => `${li()}\nYou are an expert A/L exam analyst. ${summary(d)}\n\nDeep-analyse the marks data: trends (improving/declining), best/worst subjects, consistency, what scores suggest about exam readiness. Give specific actionable advice per subject.`,
  subjects:  d => `${li()}\nYou are an expert A/L study strategist. ${summary(d)}\n\nAnalyse subject time distribution. Is it balanced? Which subjects are under-studied vs over-studied relative to marks? Give a rebalancing strategy with specific hour recommendations per subject per week.`,
  schedule:  d => `${li()}\nYou are an A/L schedule expert. ${summary(d)}\n\nAnalyse study patterns and daily goal adherence. Suggest an optimal weekly schedule with specific time blocks. What adjustments would most improve results?`,
  goals:     d => `${li()}\nYou are a productivity coach. ${summary(d)}\n\nAnalyse goal progress and task completion. Are goals realistic? Are tasks being managed well? What specific habits should change? Give a priority action list for this week.`,
  predict:   d => `${li()}\nYou are an A/L performance predictor. ${summary(d)}\n\nBased on current trends, predict: (1) likely exam performance per subject if trend continues (2) what grade is achievable with focused effort (3) what must change to reach an 'A' grade. Be honest but motivating.`,
  report:    d => `${li()}\nYou are an expert A/L academic advisor writing a full report. ${summary(d)}\n\nWrite a FULL COMPREHENSIVE REPORT with these sections:\n1. Executive Summary\n2. Academic Performance Analysis\n3. Study Behaviour & Habits\n4. Subject-wise Deep Dive\n5. Risk Areas & Red Flags\n6. Exam Readiness Rating (X/10 with justification)\n7. 30-Day Action Plan\n8. Long-term Recommendations\n\nBe thorough, specific, data-driven.`,
};

// ── Insight cards ─────────────────────────────────────────────────
const INSIGHTS = {
  score:   d => [`${li()} Be concise, 3-4 sentences.`, `${summary(d)}\n\nRate overall performance /10 and explain in 3-4 sentences. Start with the score.`],
  habit:   d => [`${li()} Be concise, 3-4 sentences.`, `${summary(d)}\n\nDescribe this student's study habit quality in 3-4 sentences. Is it consistent?`],
  weak:    d => [`${li()} Be concise, 3-4 sentences.`, `${summary(d)}\n\nIdentify the top 2 weak areas and give one specific fix each. Max 4 sentences.`],
  exam:    d => [`${li()} Be concise, 3-4 sentences.`, `${summary(d)}\n\nHow exam-ready is this student? Give a readiness level and the single most important action. Max 4 sentences.`],
};

function setSkel(id) {
  document.getElementById(id).innerHTML = '<div class="skel w90"></div><div class="skel w70"></div><div class="skel w80"></div><div class="skel w50"></div>';
}
function setOut(id, txt) {
  document.getElementById(id).innerHTML = esc(txt);
}
function setErr(id, msg) {
  document.getElementById(id).innerHTML = `<span style="color:var(--danger)">⚠️ ${esc(msg)}</span>`;
}
function esc(s) {
  return String(s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;')
    .replace(/\n/g,'<br>').replace(/\*\*(.*?)\*\*/g,'<strong>$1</strong>');
}

// ── Run insight cards ─────────────────────────────────────────────
async function runInsights(d) {
  for (const [key, fn] of Object.entries(INSIGHTS)) {
    setSkel('it-'+key);
    try {
      const [sys,usr] = fn(d);
      const txt = await groq(sys, usr, 300, () => runInsights(d));
      document.getElementById('it-'+key).innerHTML = esc(txt);
    } catch(e) {
      if (e.message !== 'RATE_LIMIT') setErr('it-'+key, e.message);
    }
  }
}

// ── Tab system ───────────────────────────────────────────────────
let activeTab = 'overview';

function switchTab(name, btn) {
  document.querySelectorAll('.ai-tab').forEach(b => b.classList.remove('active'));
  btn.classList.add('active');
  document.querySelectorAll('.ai-panel').forEach(p => p.classList.remove('show'));
  document.getElementById('tab-'+name).classList.add('show');
  activeTab = name;
  if (!tabDone[name]) runTab(name);
}

async function runTab(name) {
  const outEl = document.getElementById('out-'+name);
  outEl.innerHTML = '<div class="skel w90"></div><div class="skel w70"></div><div class="skel w80"></div><div class="skel w60"></div><div class="skel w90"></div>';
  try {
    const d   = await getData();
    const tokens = name === 'report' ? 1800 : 900;
    const txt = await groq(`You are an expert A/L study coach for Sri Lankan students.`, PROMPTS[name](d), tokens, () => runTab(name));
    outEl.innerHTML = esc(txt);
    tabDone[name] = true;
  } catch(e) {
    if (e.message !== 'RATE_LIMIT') outEl.innerHTML = `<span style="color:var(--danger)">⚠️ ${esc(e.message)}</span>`;
  }
}

function copyActive() {
  const el = document.getElementById('out-'+activeTab);
  if (!el) return;
  navigator.clipboard.writeText(el.innerText);
  event.target.textContent = '✅ Copied!';
  setTimeout(() => event.target.textContent = '📋 Copy', 2000);
}

// ── Run all ───────────────────────────────────────────────────────
async function runAll() {
  const btn = document.getElementById('masterBtn');
  btn.disabled = true;
  btn.innerHTML = '<span class="spin"></span> Analysing...';
  try {
    const d = await getData();
    await Promise.all([
      runInsights(d),
      runTab('overview'),
    ]);
  } catch(e) {}
  btn.disabled = false;
  btn.innerHTML = '<svg width="14" height="14" fill="none" stroke="currentColor" stroke-width="2.5" viewBox="0 0 24 24"><path d="M12 2v4M12 18v4M4.93 4.93l2.83 2.83M16.24 16.24l2.83 2.83M2 12h4M18 12h4M4.93 19.07l2.83-2.83M16.24 7.76l2.83-2.83"/></svg> Full Analysis';
}

// ══ CHARTS ══════════════════════════════════════════════════════
function buildCharts(d) {
  const isDark = document.documentElement.getAttribute('data-theme') !== 'light';
  const gridC  = isDark ? 'rgba(42,42,61,0.6)' : 'rgba(203,213,225,0.5)';
  const tickC  = isDark ? '#64748b' : '#94a3b8';
  const cardBg = isDark ? '#16161f' : '#ffffff';

  Chart.defaults.color = tickC;
  Chart.defaults.borderColor = gridC;

  const baseOpts = {
    responsive: true, maintainAspectRatio: false,
    plugins: { legend: { display: false } },
    scales: {
      x: { grid:{display:false}, ticks:{color:tickC}, border:{display:false} },
      y: { grid:{color:gridC},   ticks:{color:tickC}, border:{display:false} }
    }
  };

  // 1. Weekly hours line
  const wk = d.weekly_hours || [];
  new Chart(document.getElementById('weeklyChart'), {
    type: 'line',
    data: { labels: wk.map(w=>w.week_label), datasets:[{
      label:'Hours', data: wk.map(w=>w.hours),
      borderColor:'#6366f1', backgroundColor:'rgba(99,102,241,.1)',
      tension:.45, fill:true, pointBackgroundColor:'#6366f1', pointRadius:5, pointHoverRadius:7
    }]},
    options: { ...baseOpts,
      plugins: { legend:{display:false}, tooltip:{callbacks:{label:c=>` ${c.raw}h`}} }
    }
  });

  // 2. Pie / doughnut
  const subs = (d.subjects||[]).filter(s=>s.total_mins>0);
  if (subs.length) {
    new Chart(document.getElementById('pieChart'),{
      type:'doughnut',
      data:{ labels:subs.map(s=>s.name), datasets:[{ data:subs.map(s=>s.total_mins),
        backgroundColor: subs.map(s=>s.color||'#6366f1'), borderWidth:2, borderColor:cardBg }]},
      options:{ responsive:true, maintainAspectRatio:false, cutout:'62%',
        plugins:{ legend:{display:false}, tooltip:{callbacks:{label:c=>' '+c.label+': '+Math.floor(c.raw/60)+'h '+c.raw%60+'m'}} } }
    });
    // Legend
    const tot = subs.reduce((a,s)=>a+s.total_mins,0);
    document.getElementById('pieLegend').innerHTML = subs.map(s=>{
      const pct = tot ? Math.round(s.total_mins/tot*100) : 0;
      return `<div style="display:flex;align-items:center;gap:7px;margin-bottom:7px">
        <div style="width:10px;height:10px;border-radius:50%;background:${s.color};flex-shrink:0"></div>
        <span style="font-size:12px;color:var(--text-secondary);flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap">${s.name}</span>
        <span style="font-size:11px;color:var(--text-muted)">${pct}%</span>
      </div>`;
    }).join('');
  }

  // 3. Daily bars
  const daily = d.daily || [];
  new Chart(document.getElementById('dailyChart'),{
    type:'bar',
    data:{ labels:daily.map(dd=>dd.label), datasets:[{
      data: daily.map(dd=>dd.mins),
      backgroundColor: daily.map(dd=>dd.mins>0?'rgba(99,102,241,.55)':'rgba(99,102,241,.1)'),
      borderRadius:4, hoverBackgroundColor:'#6366f1'
    }]},
    options:{ ...baseOpts, plugins:{legend:{display:false},tooltip:{callbacks:{label:c=>` ${Math.floor(c.raw/60)}h ${c.raw%60}m`}}} }
  });

  // 4. Marks scatter
  const marks = d.marks || [];
  new Chart(document.getElementById('marksChart'),{
    type:'line',
    data:{ labels:marks.map(m=>m.exam_date), datasets:[{
      label:'Score %', data:marks.map(m=>m.pct),
      borderColor:'#a855f7', backgroundColor:'rgba(168,85,247,.1)',
      pointBackgroundColor: marks.map(m=>m.pct>=75?'#10b981':m.pct>=55?'#f59e0b':'#ef4444'),
      pointRadius:7, pointHoverRadius:9, tension:.3, fill:true
    }]},
    options:{ ...baseOpts,
      scales:{ x:{...baseOpts.scales.x, ticks:{color:tickC,maxTicksLimit:6}}, y:{...baseOpts.scales.y, min:0,max:100, ticks:{color:tickC,callback:v=>v+'%'}} },
      plugins:{ legend:{display:false}, tooltip:{callbacks:{label:c=>` ${c.raw}% — ${marks[c.dataIndex]?.subject}`}} }
    }
  });

  // 5. Radar — subject avg marks
  const mbs = d.marks_by_subject || [];
  if (mbs.length >= 3) {
    new Chart(document.getElementById('radarChart'),{
      type:'radar',
      data:{ labels:mbs.map(m=>m.name), datasets:[{
        label:'Avg %', data:mbs.map(m=>m.avg_pct),
        backgroundColor:'rgba(99,102,241,.2)', borderColor:'#6366f1',
        pointBackgroundColor:'#6366f1', pointRadius:4
      }]},
      options:{ responsive:true, maintainAspectRatio:false,
        scales:{ r:{ min:0,max:100, grid:{color:gridC}, angleLines:{color:gridC},
          ticks:{color:tickC, backdropColor:'transparent', stepSize:25},
          pointLabels:{color:tickC, font:{size:11}} } },
        plugins:{ legend:{display:false} }
      }
    });
  } else {
    document.getElementById('radarChart').parentElement.innerHTML += `<div style="text-align:center;color:var(--text-muted);font-size:12px;padding:20px 0">Need marks in 3+ subjects for radar chart</div>`;
    document.getElementById('radarChart').style.display='none';
  }

  // 6. Hour distribution bar
  const hours = Array(24).fill(0);
  (d.hour_dist||[]).forEach(h => { hours[h.hr] = h.cnt; });
  const hourLabels = Array.from({length:24},(_,i)=>i%3===0?(i<12?`${i||12}am`:`${i===12?12:i-12}pm`):'');
  new Chart(document.getElementById('hourChart'),{
    type:'bar',
    data:{ labels:hourLabels, datasets:[{
      data:hours, backgroundColor:'rgba(6,182,212,.5)', borderRadius:3, hoverBackgroundColor:'#06b6d4'
    }]},
    options:{ ...baseOpts, plugins:{legend:{display:false},tooltip:{callbacks:{label:c=>` ${c.raw} sessions`}}} }
  });

  // 7. Subject performance horizontal bars
  const sp = (d.subjects||[]).filter(s=>s.avg_mark>0);
  if (sp.length) {
    document.getElementById('subPerfBars').innerHTML = sp.map(s=>{
      const pct = Math.round(s.avg_mark);
      const col = pct>=75?'#10b981':pct>=55?'#f59e0b':'#ef4444';
      return `<div class="sub-row">
        <div class="sub-dot" style="background:${s.color||'#6366f1'}"></div>
        <div class="sub-name" title="${s.name}">${s.name.length>12?s.name.slice(0,10)+'…':s.name}</div>
        <div class="sub-bar-wrap"><div class="sub-bar-fill" style="width:0%;background:${col}" data-w="${pct}"></div></div>
        <div class="sub-pct">${pct}%</div>
      </div>`;
    }).join('');
    // Animate bars
    setTimeout(()=>{ document.querySelectorAll('.sub-bar-fill').forEach(el=>{ el.style.width=el.dataset.w+'%'; }); }, 200);
  } else {
    document.getElementById('subPerfBars').innerHTML = '<div style="color:var(--text-muted);font-size:12px;text-align:center;padding:20px 0">No marks data yet</div>';
  }

  // 8. Heatmap
  const hm = document.getElementById('heatmapEl');
  const heatMap = {};
  (d.streaks||[]).forEach(s => { heatMap[s.date] = s.minutes_studied >= 180 ? 4 : s.minutes_studied >= 120 ? 3 : s.minutes_studied >= 60 ? 2 : 1; });
  const start = Date.now() - 83 * 86400000;
  let hmHtml = '';
  for (let i=0; i<84; i++) {
    const dt  = new Date(start + i*86400000);
    const key = dt.toISOString().split('T')[0];
    const lv  = heatMap[key] || 0;
    const min = d.daily?.find(dd=>dd.date===key)?.mins || 0;
    hmHtml += `<div class="hm-cell" data-l="${lv}" title="${key}: ${min?Math.floor(min/60)+'h '+min%60+'m':'No study'}"></div>`;
  }
  hm.innerHTML = hmHtml;
}

// ══ INIT ════════════════════════════════════════════════════════
document.addEventListener('keydown', e => { if(e.key==='Escape' && document.getElementById('rateLimitOverlay').style.display==='flex') closeRateLimit(); });

window.addEventListener('DOMContentLoaded', async () => {
  const d = await getData();
  if (d) buildCharts(d);
  <?php if ($hasKey): ?>
  runAll();
  <?php endif; ?>
});
</script>