<?php
require_once 'includes/config.php';
require_once 'topic-reviews.php';

// AJAX handler before any output
if ($_SERVER['REQUEST_METHOD']==='POST' && ($_SERVER['HTTP_X_REQUESTED_WITH']??'')==='XMLHttpRequest') {
    requireLogin();
    $uid = $_SESSION['user_id'];
    if (($_POST['action']??'')==='save_al_year') {
        $yr = (int)($_POST['al_year']??0);
        if ($yr>=2024 && $yr<=2030) {
            $pdo->prepare("UPDATE users SET al_year=? WHERE id=?")->execute([$yr,$uid]);
            $ex = $pdo->prepare("SELECT id FROM al_exam_dates WHERE YEAR(exam_date)=? LIMIT 1");
            $ex->execute([$yr]);
            if (!$ex->fetch()) {
                $pdo->prepare("INSERT INTO al_exam_dates (exam_name,exam_date,description,is_active) VALUES (?,?,?,1)")
                    ->execute(["A/L Examination $yr","$yr-08-15","Sri Lanka Advanced Level Examination"]);
            }
            header('Content-Type: application/json');
            echo json_encode(['success'=>true]); exit;
        }
        header('Content-Type: application/json');
        echo json_encode(['success'=>false]); exit;
    }
    if (($_POST['action']??'')==='sr_review_done') {
        $ok = advanceTopicReview($pdo, $uid, (int)($_POST['id']??0));
        header('Content-Type: application/json');
        echo json_encode(['success'=>$ok]); exit;
    }
    if (($_POST['action']??'')==='sr_mastered') {
        $ok = markTopicMastered($pdo, $uid, (int)($_POST['id']??0));
        header('Content-Type: application/json');
        echo json_encode(['success'=>$ok]); exit;
    }
}

requireLogin();
require_once 'includes/header.php';

$uid = $_SESSION['user_id'];
ensureTopicReviewsTable($pdo);

// Spaced repetition
$dueReviews      = getDueTopicReviews($pdo, $uid, 6);
$dueReviewCount  = countDueTopicReviews($pdo, $uid);
$upcomingReviews = getUpcomingTopicReviews($pdo, $uid, 7, 4);

// Stats
$totalStudy = $pdo->prepare("SELECT COALESCE(SUM(duration_minutes),0) FROM study_sessions WHERE user_id=? AND date >= DATE_SUB(CURDATE(),INTERVAL 30 DAY)");
$totalStudy->execute([$uid]); $monthMinutes = $totalStudy->fetchColumn();

$todayStudy = $pdo->prepare("SELECT COALESCE(SUM(duration_minutes),0) FROM study_sessions WHERE user_id=? AND date=CURDATE()");
$todayStudy->execute([$uid]); $todayMinutes = $todayStudy->fetchColumn();

$subjectCount = $pdo->prepare("SELECT COUNT(*) FROM subjects WHERE user_id=?");
$subjectCount->execute([$uid]); $subjects = $subjectCount->fetchColumn();

$taskCount = $pdo->prepare("SELECT COUNT(*) FROM tasks WHERE user_id=? AND status!='completed'");
$taskCount->execute([$uid]); $pendingTasks = $taskCount->fetchColumn();

// Streak
$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 $d) {
    if ($d === $check->format('Y-m-d')) { $streak++; $check->modify('-1 day'); }
    elseif ($d < $check->format('Y-m-d')) break;
}

// A/L countdown — per user year
$userAlYear = null; $showYearPopup = false;
try {
    $r = $pdo->prepare("SELECT al_year FROM users WHERE id=?");
    $r->execute([$uid]);
    $rec = $r->fetch();
    $userAlYear = !empty($rec['al_year']) ? (int)$rec['al_year'] : null;
    $showYearPopup = ($userAlYear === null);
} catch (Exception $e) { $showYearPopup = false; }

if ($userAlYear) {
    $examQ = $pdo->prepare("SELECT * FROM al_exam_dates WHERE is_active=1 AND YEAR(exam_date)=? ORDER BY exam_date ASC");
    $examQ->execute([$userAlYear]);
} else {
    $examQ = $pdo->query("SELECT * FROM al_exam_dates WHERE is_active=1 ORDER BY exam_date ASC");
}
$exams = $examQ->fetchAll();
$exam  = $exams[0] ?? null;

// Recent study sessions
$recentQ = $pdo->prepare("SELECT ss.*, s.name as subject_name, s.color FROM study_sessions ss JOIN subjects s ON ss.subject_id=s.id WHERE ss.user_id=? ORDER BY ss.date DESC, ss.created_at DESC LIMIT 5");
$recentQ->execute([$uid]); $recent = $recentQ->fetchAll();

// Weekly study data for chart
$weekData = [];
for ($i=6; $i>=0; $i--) {
    $d = 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,$d]);
    $weekData[] = ['date'=>date('D', strtotime($d)), 'minutes'=>(int)$q->fetchColumn()];
}

// Top subjects this month
$topSubQ = $pdo->prepare("SELECT s.name, s.color, SUM(ss.duration_minutes) as total FROM study_sessions ss JOIN subjects s ON ss.subject_id=s.id WHERE ss.user_id=? AND ss.date >= DATE_SUB(CURDATE(),INTERVAL 30 DAY) GROUP BY ss.subject_id ORDER BY total DESC LIMIT 5");
$topSubQ->execute([$uid]); $topSubs = $topSubQ->fetchAll();

// Announcements
$annQ = $pdo->query("SELECT * FROM announcements WHERE is_active=1 ORDER BY priority DESC, created_at DESC LIMIT 3");
$announcements = $annQ->fetchAll();

// Recent marks
$marksQ = $pdo->prepare("SELECT m.*, s.name as subject_name, s.color FROM marks m JOIN subjects s ON m.subject_id=s.id WHERE m.user_id=? ORDER BY m.exam_date DESC LIMIT 5");
$marksQ->execute([$uid]); $recentMarks = $marksQ->fetchAll();

// Weekly subject targets
$weekStartDash = date('Y-m-d', strtotime('monday this week'));
try { $pdo->exec("ALTER TABLE subjects ADD COLUMN weekly_target_hours DECIMAL(4,1) DEFAULT 0"); } catch(PDOException $e){}
$weekTargetsQ = $pdo->prepare("
    SELECT s.name, s.color, s.weekly_target_hours,
           COALESCE(SUM(CASE WHEN ss.date >= ? THEN ss.duration_minutes ELSE 0 END),0) AS week_mins
    FROM subjects s
    LEFT JOIN study_sessions ss ON s.id=ss.subject_id
    WHERE s.user_id=? AND s.weekly_target_hours > 0
    GROUP BY s.id ORDER BY s.name
");
$weekTargetsQ->execute([$weekStartDash, $uid]);
$weekTargets = $weekTargetsQ->fetchAll();

// Class Hours - weekly data for chart
$classWeekData = [];
for ($i=6; $i>=0; $i--) {
    $d = date('Y-m-d', strtotime("-$i days"));
    $cq = $pdo->prepare("SELECT COALESCE(SUM(duration_minutes),0) as total, COALESCE(SUM(CASE WHEN attended=1 THEN duration_minutes ELSE 0 END),0) as attended FROM class_hours WHERE user_id=? AND class_date=?");
    $cq->execute([$uid, $d]);
    $cr = $cq->fetch();
    $classWeekData[] = ['date'=>date('D', strtotime($d)), 'total'=>(int)$cr['total'], 'attended'=>(int)$cr['attended']];
}

// Class hours summary (this month)
$chSumQ = $pdo->prepare("SELECT COUNT(*) as total, SUM(attended) as attended, COALESCE(SUM(duration_minutes),0) as total_mins, COALESCE(SUM(CASE WHEN attended=1 THEN duration_minutes ELSE 0 END),0) as att_mins FROM class_hours WHERE user_id=? AND class_date >= DATE_SUB(CURDATE(), INTERVAL 30 DAY)");
$chSumQ->execute([$uid]); $chSum = $chSumQ->fetch();
$chTotal = (int)($chSum['total']??0); $chAtt = (int)($chSum['attended']??0);
$chRate = $chTotal > 0 ? round(($chAtt/$chTotal)*100) : 0;

// Top 3 performers this month
$top3Q = $pdo->query("SELECT u.name, u.avatar,
    COUNT(DISTINCT ss.id) as sessions,
    COALESCE(SUM(ss.duration_minutes),0) as total_mins,
    COALESCE(AVG(m.marks_obtained/m.total_marks*100),0) as avg_mark,
    (SELECT COUNT(*) FROM study_streaks WHERE user_id=u.id AND date>=DATE_SUB(CURDATE(),INTERVAL 30 DAY)) as streak_days
    FROM users u
    LEFT JOIN study_sessions ss ON u.id=ss.user_id AND ss.date>=DATE_SUB(CURDATE(),INTERVAL 30 DAY)
    LEFT JOIN marks m ON u.id=m.user_id
    WHERE u.is_verified=1 AND (u.is_disabled IS NULL OR u.is_disabled=0)
    GROUP BY u.id
    ORDER BY total_mins DESC
    LIMIT 3");
$top3 = $top3Q->fetchAll();

// ── Today's timetable slots (for end-of-class popup) ──────────────
$todaySlots = [];
try {
    $todayName = date('l');
    $tsQ = $pdo->prepare("
        SELECT t.id, t.start_time, t.end_time, t.label, t.color,
               s.name as subject_name, s.id as subject_id, s.color as subject_color
        FROM timetable t
        LEFT JOIN subjects s ON t.subject_id = s.id
        WHERE t.user_id = ? AND t.day_of_week = ? AND t.is_active = 1
        ORDER BY t.start_time
    ");
    $tsQ->execute([$uid, $todayName]);
    $todaySlots = $tsQ->fetchAll();

    // Mark which slots are already logged in DB today
    if (!empty($todaySlots)) {
        $logQ = $pdo->prepare("SELECT start_time, end_time FROM class_hours WHERE user_id=? AND class_date=CURDATE()");
        $logQ->execute([$uid]);
        $loggedKeys = [];
        foreach ($logQ->fetchAll() as $lr) {
            $loggedKeys[substr($lr['start_time'],0,5).'_'.substr($lr['end_time'],0,5)] = true;
        }
        foreach ($todaySlots as &$sl) {
            $k = substr($sl['start_time'],0,5).'_'.substr($sl['end_time'],0,5);
            $sl['already_logged'] = isset($loggedKeys[$k]) ? 1 : 0;
        }
        unset($sl);
    }
} catch (Exception $e) { $todaySlots = []; }

renderHeader('Dashboard', 'dashboard');
?>

<style>
@import url('https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;500;600;700;800;900&family=Plus+Jakarta+Sans:wght@300;400;500;600;700&display=swap');

:root {
  --df: 'Outfit', sans-serif;
  --db: 'Plus Jakarta Sans', sans-serif;
  --dr: 16px;
  --dlg: 22px;
  --dxl: 28px;
  --dg: 16px;
}

.dp { font-family: var(--db); padding-bottom: 48px; max-width: 1280px; }

/* ── Announcement ── */
.da { display:flex;align-items:center;gap:12px;padding:11px 16px;background:linear-gradient(100deg,rgba(99,102,241,.10),rgba(168,85,247,.06));border:1px solid rgba(99,102,241,.22);border-radius:var(--dr);margin-bottom:14px;animation:drise .4s ease both; }
.da-hi .da-t { color:#fbbf24; }
.da-t { font-size:13px;font-weight:700;color:var(--text-primary); }
.da-b { font-size:12px;color:var(--text-secondary);margin-left:8px; }

/* ── Hero ── */
.dh { display:grid;grid-template-columns:1fr auto;gap:var(--dg);margin-bottom:var(--dg);align-items:stretch; }
@media(max-width:720px){.dh{grid-template-columns:1fr;}}

.dclk {
  background:var(--bg-card);border:1px solid var(--border);border-radius:var(--dxl);
  padding:26px 30px;position:relative;overflow:hidden;animation:drise .5s .05s ease both;
}
.dclk::before {
  content:'';position:absolute;top:-60px;left:-60px;width:220px;height:220px;
  background:radial-gradient(circle,rgba(99,102,241,.16) 0%,transparent 70%);pointer-events:none;
}
.dclk-day  { font-family:var(--df);font-size:12px;font-weight:700;letter-spacing:3px;text-transform:uppercase;color:var(--accent);margin-bottom:4px; }
.dclk-date { font-family:var(--df);font-size:30px;font-weight:800;color:var(--text-primary);line-height:1.1;letter-spacing:-.5px; }
.dclk-tr   { display:flex;align-items:baseline;gap:8px;margin-top:14px; }
.dclk-time { font-family:var(--df);font-size:50px;font-weight:900;letter-spacing:-3px;line-height:1;background:linear-gradient(135deg,#818cf8 0%,#c084fc 50%,#38bdf8 100%);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text;font-variant-numeric:tabular-nums; }
.dclk-ap   { font-family:var(--df);font-size:13px;font-weight:700;color:var(--text-muted);letter-spacing:2px;text-transform:uppercase;padding-bottom:6px; }

/* ── Floating study icons ── */
.dclk-icons {
  position: absolute;
  inset: 0;
  pointer-events: none;
  overflow: hidden;
  border-radius: var(--dxl);
}
.sci {
  position: absolute;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 14px;
  font-size: 18px;
  backdrop-filter: blur(2px);
  animation: sci-float linear infinite;
  opacity: 0;
}
/* individual icons — position, size, timing */
.sci-1  { width:42px;height:42px; top:8%;  right:12%; background:rgba(99,102,241,.10); border:1px solid rgba(99,102,241,.18); animation-duration:7s;  animation-delay:0s;   font-size:20px; }
.sci-2  { width:36px;height:36px; top:55%; right:6%;  background:rgba(168,85,247,.09); border:1px solid rgba(168,85,247,.16); animation-duration:9s;  animation-delay:1.2s; font-size:17px; }
.sci-3  { width:38px;height:38px; top:22%; right:30%; background:rgba(6,182,212,.08);  border:1px solid rgba(6,182,212,.15);  animation-duration:8s;  animation-delay:2.5s; font-size:18px; }
.sci-4  { width:32px;height:32px; top:70%; right:22%; background:rgba(245,158,11,.08); border:1px solid rgba(245,158,11,.15); animation-duration:10s; animation-delay:0.8s; font-size:15px; }
.sci-5  { width:44px;height:44px; top:5%;  right:50%; background:rgba(16,185,129,.08); border:1px solid rgba(16,185,129,.15); animation-duration:11s; animation-delay:3.5s; font-size:21px; }
.sci-6  { width:34px;height:34px; top:78%; right:40%; background:rgba(239,68,68,.07);  border:1px solid rgba(239,68,68,.14);  animation-duration:8.5s;animation-delay:1.8s; font-size:16px; }
.sci-7  { width:38px;height:38px; top:40%; right:14%; background:rgba(99,102,241,.08); border:1px solid rgba(99,102,241,.14); animation-duration:9.5s;animation-delay:4.2s; font-size:18px; }
.sci-8  { width:30px;height:30px; top:15%; right:44%; background:rgba(168,85,247,.07); border:1px solid rgba(168,85,247,.13); animation-duration:7.5s;animation-delay:2.0s; font-size:14px; }

/* Light mode: more subtle */
[data-theme="light"] .sci { opacity: 0; }
[data-theme="light"] .sci-1  { background:rgba(99,102,241,.06);  border-color:rgba(99,102,241,.12);  }
[data-theme="light"] .sci-2  { background:rgba(168,85,247,.05);  border-color:rgba(168,85,247,.1);   }
[data-theme="light"] .sci-3  { background:rgba(6,182,212,.05);   border-color:rgba(6,182,212,.1);    }
[data-theme="light"] .sci-4  { background:rgba(245,158,11,.05);  border-color:rgba(245,158,11,.1);   }
[data-theme="light"] .sci-5  { background:rgba(16,185,129,.05);  border-color:rgba(16,185,129,.1);   }
[data-theme="light"] .sci-6  { background:rgba(239,68,68,.04);   border-color:rgba(239,68,68,.08);   }
[data-theme="light"] .sci-7  { background:rgba(99,102,241,.05);  border-color:rgba(99,102,241,.1);   }
[data-theme="light"] .sci-8  { background:rgba(168,85,247,.04);  border-color:rgba(168,85,247,.08);  }

@keyframes sci-float {
  0%   { transform: translateY(0px)   rotate(0deg)   scale(0.9);  opacity: 0;   }
  8%   { opacity: 0.75; }
  45%  { transform: translateY(-18px) rotate(6deg)   scale(1.06); opacity: 0.8; }
  55%  { transform: translateY(-22px) rotate(-4deg)  scale(1.04); opacity: 0.75;}
  92%  { opacity: 0.65; }
  100% { transform: translateY(-8px)  rotate(2deg)   scale(0.95); opacity: 0;   }
}
/* each icon gets a slightly different drift pattern */
.sci-1 { animation-name: sci-float-a; }
.sci-3 { animation-name: sci-float-b; }
.sci-5 { animation-name: sci-float-c; }
.sci-7 { animation-name: sci-float-b; }

@keyframes sci-float-a {
  0%   { transform: translateY(0px)   rotate(-3deg)  scale(0.88); opacity: 0;   }
  10%  { opacity: 0.8; }
  50%  { transform: translateY(-16px) rotate(8deg)   scale(1.08); opacity: 0.85;}
  90%  { opacity: 0.7; }
  100% { transform: translateY(-6px)  rotate(-2deg)  scale(0.92); opacity: 0;   }
}
@keyframes sci-float-b {
  0%   { transform: translate(0px, 0px)    scale(0.9);  opacity: 0;   }
  12%  { opacity: 0.7; }
  40%  { transform: translate(-8px,-20px)  scale(1.05); opacity: 0.78;}
  60%  { transform: translate(6px, -14px)  scale(1.02); opacity: 0.72;}
  88%  { opacity: 0.6; }
  100% { transform: translate(0px, -5px)   scale(0.94); opacity: 0;   }
}
@keyframes sci-float-c {
  0%   { transform: translateY(0)    rotate(0)      scale(1);    opacity: 0;   }
  6%   { opacity: 0.9; }
  35%  { transform: translateY(-24px) rotate(-10deg) scale(1.1);  opacity: 0.88;}
  65%  { transform: translateY(-12px) rotate(5deg)   scale(1.03); opacity: 0.8; }
  94%  { opacity: 0.6; }
  100% { transform: translateY(-4px)  rotate(-3deg)  scale(0.95); opacity: 0;   }
}

.dcd {
  background:var(--bg-card);border:1px solid rgba(99,102,241,.28);border-radius:var(--dxl);
  padding:26px 26px;min-width:220px;width:100%;flex:0 0 100%;position:relative;overflow:hidden;box-sizing:border-box;
  display:flex;flex-direction:column;justify-content:space-between;animation:drise .5s .1s ease both;
}
.dcd::after { content:'';position:absolute;bottom:-40px;right:-40px;width:160px;height:160px;background:radial-gradient(circle,rgba(168,85,247,.12),transparent 70%);pointer-events:none; }
.dcd-chip { display:inline-flex;align-items:center;gap:6px;background:rgba(99,102,241,.12);border:1px solid rgba(99,102,241,.2);border-radius:99px;padding:4px 12px;font-size:11px;font-weight:700;color:var(--accent);letter-spacing:.5px;text-transform:uppercase;width:fit-content;margin-bottom:12px; }
.dcd-nm { font-family:var(--df);font-size:15px;font-weight:700;color:var(--text-primary);line-height:1.3;margin-bottom:3px; }
.dcd-dt { font-size:12px;color:var(--text-muted);margin-bottom:16px; }
/* ── Countdown floating icons ── */
.dcd-icons { position:absolute;inset:0;pointer-events:none;overflow:hidden;border-radius:var(--dxl); }
.cdi {
  position:absolute;
  display:flex;align-items:center;justify-content:center;
  border-radius:11px;
  animation:cdi-drift linear infinite;
  opacity:0;
}
.cdi-1 { width:34px;height:34px; top:6%;  right:8%;  background:rgba(99,102,241,.1); border:1px solid rgba(99,102,241,.2);  font-size:16px; animation-duration:8s;  animation-delay:0s;   }
.cdi-2 { width:28px;height:28px; top:50%; right:5%;  background:rgba(168,85,247,.09);border:1px solid rgba(168,85,247,.18); font-size:13px; animation-duration:10s; animation-delay:1.5s; }
.cdi-3 { width:32px;height:32px; top:75%; right:14%; background:rgba(6,182,212,.08); border:1px solid rgba(6,182,212,.16);  font-size:15px; animation-duration:7.5s;animation-delay:3.2s; }
.cdi-4 { width:26px;height:26px; top:18%; right:38%; background:rgba(245,158,11,.08);border:1px solid rgba(245,158,11,.15); font-size:12px; animation-duration:9s;  animation-delay:0.6s; }
.cdi-5 { width:30px;height:30px; top:60%; right:30%; background:rgba(16,185,129,.08);border:1px solid rgba(16,185,129,.15); font-size:14px; animation-duration:11s; animation-delay:2.8s; }
[data-theme="light"] .cdi-1{background:rgba(99,102,241,.06);border-color:rgba(99,102,241,.12);}
[data-theme="light"] .cdi-2{background:rgba(168,85,247,.05);border-color:rgba(168,85,247,.1);}
[data-theme="light"] .cdi-3{background:rgba(6,182,212,.05);border-color:rgba(6,182,212,.1);}
[data-theme="light"] .cdi-4{background:rgba(245,158,11,.05);border-color:rgba(245,158,11,.1);}
[data-theme="light"] .cdi-5{background:rgba(16,185,129,.05);border-color:rgba(16,185,129,.1);}
@keyframes cdi-drift {
  0%   { transform:translate(0,0)        rotate(0deg)   scale(.88); opacity:0;    }
  10%  { opacity:.75; }
  40%  { transform:translate(-4px,-16px) rotate(-8deg)  scale(1.06); opacity:.82; }
  60%  { transform:translate(3px,-20px)  rotate(5deg)   scale(1.03); opacity:.75; }
  90%  { opacity:.55; }
  100% { transform:translate(-1px,-7px)  rotate(-2deg)  scale(.92); opacity:0;   }
}
.dcd-units { display:flex;gap:10px; }
.dcd-unit { flex:1;background:var(--bg-secondary);border:1px solid var(--border);border-radius:var(--dr);padding:12px 8px 8px;text-align:center; }
.dcd-n { font-family:var(--df);font-size:30px;font-weight:900;line-height:1;background:linear-gradient(135deg,#6366f1,#a855f7);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text;letter-spacing:-1px;display:block; }
.dcd-l { font-size:9px;font-weight:700;color:var(--text-muted);letter-spacing:1.5px;text-transform:uppercase;margin-top:4px;display:block; }
.dcd-wrap { display:flex;flex-direction:column;min-width:220px;max-width:100%;overflow:hidden; }
.dcd-track { display:flex;transition:transform .38s cubic-bezier(.4,0,.2,1);will-change:transform;cursor:grab;user-select:none; }
.dcd-track.dragging { cursor:grabbing;transition:none; }
.dcd-dots { display:flex;justify-content:center;gap:6px;padding:10px 0 2px; }
.dcd-dot { width:6px;height:6px;border-radius:99px;border:none;padding:0;cursor:pointer;background:var(--border);transition:all .25s ease; }
.dcd-dot.active { width:18px;background:var(--accent); }
/* ── Flip Card ── */
.dcd-flip-wrapper {
  position: relative;
  height: 90px;
  perspective: 800px;
  cursor: pointer;
  margin-top: 4px;
}
.dcd-face {
  position: absolute;
  inset: 0;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  transition: transform 0.55s cubic-bezier(0.34, 1.1, 0.64, 1);
  transform-style: preserve-3d;
}
.dcd-front {
  transform: rotateY(0deg);
}
.dcd-back {
  transform: rotateY(180deg);
}
.dcd-flip-wrapper.flipped .dcd-front {
  transform: rotateY(-180deg);
}
.dcd-flip-wrapper.flipped .dcd-back {
  transform: rotateY(0deg);
}
.dcd-units-detailed {
  gap: 6px !important;
}
.dcd-unit-sm {
  padding: 8px 4px 6px !important;
}
.dcd-unit-sm .dcd-n {
  font-size: 22px !important;
  letter-spacing: -0.5px !important;
}
.dcd-unit-sm .dcd-l {
  font-size: 8px !important;
}
.dcd-flip-hint {
  font-size: 10px;
  color: var(--text-muted);
  text-align: center;
  margin-top: 6px;
  opacity: 0.6;
  letter-spacing: 0.3px;
  transition: opacity 0.2s;
}
.dcd-flip-wrapper:hover .dcd-flip-hint {
  opacity: 1;
  color: var(--accent);
}

/* Flip number animation - digit slots */
.dcd-digit-slot {
  display: inline-block;
  position: relative;
  overflow: hidden;
  height: 1.15em;
  vertical-align: top;
}
.dcd-digit-slot span {
  display: block;
  transition: transform 0.22s cubic-bezier(0.34, 1.3, 0.64, 1), opacity 0.18s ease;
}
.dcd-digit-slot.tick span {
  animation: digit-tick 0.22s cubic-bezier(0.34, 1.2, 0.64, 1);
}
@keyframes digit-tick {
  0%   { transform: translateY(-60%) scale(0.85); opacity: 0.3; }
  60%  { transform: translateY(8%) scale(1.06);  opacity: 1; }
  100% { transform: translateY(0)  scale(1);     opacity: 1; }
}



/* ── Quick Actions ── */


/* ── Stats ── */
.dstats { display:grid;grid-template-columns:repeat(4,1fr);gap:var(--dg);margin-bottom:var(--dg); }
@media(max-width:900px){.dstats{grid-template-columns:repeat(2,1fr);}}

.dst { background:var(--bg-card);border:1px solid var(--border);border-radius:var(--dlg);padding:22px 22px 18px;position:relative;overflow:hidden;transition:transform .2s,box-shadow .2s,border-color .2s;animation:drise .5s ease both;cursor:default; }
.dst:nth-child(1){animation-delay:.12s} .dst:nth-child(2){animation-delay:.17s} .dst:nth-child(3){animation-delay:.22s} .dst:nth-child(4){animation-delay:.27s}
.dst:hover { transform:translateY(-4px);box-shadow:0 16px 40px rgba(0,0,0,.2);border-color:var(--border-light); }
.dst::before { content:'';position:absolute;width:120px;height:120px;border-radius:50%;top:-30px;right:-30px;pointer-events:none; }
.dst1::before{background:rgba(99,102,241,.16)} .dst2::before{background:rgba(6,182,212,.14)} .dst3::before{background:rgba(245,158,11,.14)} .dst4::before{background:rgba(16,185,129,.14)}
.dst::after { content:'';position:absolute;bottom:0;left:0;right:0;height:2px;opacity:0;transition:opacity .2s; }
.dst:hover::after{opacity:1}
.dst1::after{background:linear-gradient(90deg,#6366f1,#a855f7)} .dst2::after{background:linear-gradient(90deg,#06b6d4,#6366f1)} .dst3::after{background:linear-gradient(90deg,#f59e0b,#ef4444)} .dst4::after{background:linear-gradient(90deg,#10b981,#06b6d4)}

.dsth { display:flex;justify-content:space-between;align-items:flex-start;margin-bottom:16px; }
.dsti { width:42px;height:42px;border-radius:12px;display:flex;align-items:center;justify-content:center;font-size:19px; }
.dsttag { font-size:11px;font-weight:700;padding:3px 9px;border-radius:99px; }
.tg { background:rgba(16,185,129,.12);color:#10b981; } .ta { background:rgba(245,158,11,.12);color:#f59e0b; } .tr { background:rgba(239,68,68,.12);color:#ef4444; } .tc { background:rgba(6,182,212,.12);color:#06b6d4; }

.dstv { font-family:var(--df);font-size:30px;font-weight:800;color:var(--text-primary);line-height:1;letter-spacing:-.5px; }
.dstv .du { font-size:14px;color:var(--text-muted);font-weight:500;font-family:var(--db); }
.dstl { font-size:12px;color:var(--text-muted);margin-top:6px;font-weight:500; }

/* ── Main grid ── */
.dmg { display:grid;grid-template-columns:1fr 330px;gap:var(--dg);margin-bottom:var(--dg);align-items:start; }
@media(max-width:960px){.dmg{grid-template-columns:1fr;}}

/* ── Card ── */
.dc { background:var(--bg-card);border:1px solid var(--border);border-radius:var(--dlg);padding:22px;animation:drise .5s .3s ease both; }
.dch { display:flex;align-items:center;justify-content:space-between;margin-bottom:18px;gap:12px; }
.dct { font-family:var(--df);font-size:15px;font-weight:700;color:var(--text-primary);letter-spacing:-.2px; }
.dcl { font-size:12px;font-weight:600;color:var(--accent);text-decoration:none;padding:5px 12px;border-radius:8px;border:1px solid rgba(99,102,241,.25);transition:all .16s;flex-shrink:0;white-space:nowrap; }
.dcl:hover { background:rgba(99,102,241,.1);border-color:rgba(99,102,241,.4); }

.dptgl { display:flex;background:var(--bg-secondary);border-radius:9px;padding:3px;gap:2px; }
.dptb { padding:5px 13px;border-radius:7px;border:none;font-family:var(--db);font-size:12px;font-weight:600;cursor:pointer;background:transparent;color:var(--text-muted);transition:all .16s; }
.dptb.active { background:var(--bg-card);color:var(--text-primary);box-shadow:0 1px 4px rgba(0,0,0,.18); }
.dchw { height:210px; }

.dsr { margin-bottom:14px; }
.dsi { display:flex;justify-content:space-between;align-items:center;margin-bottom:7px; }
.dsn { font-size:13px;color:var(--text-primary);font-weight:500;display:flex;align-items:center;gap:8px; }
.dsdot { width:8px;height:8px;border-radius:50%;flex-shrink:0; }
.dst_ { font-size:12px;color:var(--text-muted);font-weight:600; }
.dpr { height:5px;background:var(--bg-secondary);border-radius:99px;overflow:hidden; }
.dprb { height:100%;border-radius:99px;transition:width 1s cubic-bezier(.4,0,.2,1); }

/* ── Table grid ── */
.dtg { display:grid;grid-template-columns:1fr 1fr;gap:var(--dg);margin-bottom:var(--dg); }
@media(max-width:860px){.dtg{grid-template-columns:1fr;}}

/* Shared dot + badge styles */
.dinl { display:inline-block;width:8px;height:8px;border-radius:50%;margin-right:7px;vertical-align:middle;flex-shrink:0; }
.dsc { padding:3px 10px;border-radius:99px;font-size:11px;font-weight:700;display:inline-block;white-space:nowrap; }
.dsca{background:rgba(16,185,129,.12);color:#10b981;} .dscb{background:rgba(245,158,11,.12);color:#f59e0b;} .dscc{background:rgba(239,68,68,.12);color:#ef4444;}
.ddur { font-weight:700;color:var(--accent);font-size:13px;white-space:nowrap; }

/* Desktop header row */
.drow-hd {
  display:grid;
  grid-template-columns:80px 1fr 80px;
  gap:8px;
  padding:0 0 10px;
  border-bottom:1px solid var(--border);
  font-size:11px;
  font-weight:700;
  color:var(--text-muted);
  text-transform:uppercase;
  letter-spacing:.8px;
}
/* Data row */
.drow {
  display:grid;
  grid-template-columns:80px 1fr 80px;
  gap:8px;
  padding:10px 0;
  border-bottom:1px solid var(--border);
  align-items:center;
}
.drow:last-child { border-bottom:none; }
.drow-date {
  font-size:12px;
  color:var(--text-muted);
  white-space:nowrap;
}
.drow-subj {
  font-size:13px;
  color:var(--text-primary);
  display:flex;
  align-items:center;
  overflow:hidden;
  white-space:nowrap;
  text-overflow:ellipsis;
}
.drow-val {
  text-align:right;
}

/* ── Mobile: card layout ── */
@media(max-width:600px){
  .drow-hd { display:none; }
  .drow {
    display:grid;
    grid-template-columns:1fr auto;
    grid-template-rows:auto auto;
    grid-template-areas:
      "date  val"
      "subj  val";
    gap:3px 12px;
    background:var(--bg-secondary);
    border:1px solid var(--border) !important;
    border-radius:12px;
    padding:12px 14px;
    margin-bottom:8px;
  }
  .drow:last-child { margin-bottom:0; border-bottom:1px solid var(--border) !important; }
  .drow-date {
    grid-area:date;
    font-size:11px;
    font-weight:700;
    color:var(--text-muted);
    letter-spacing:.5px;
    text-transform:uppercase;
    white-space:nowrap;
    overflow:hidden;
    text-overflow:ellipsis;
  }
  .drow-subj {
    grid-area:subj;
    font-size:14px;
    font-weight:600;
    color:var(--text-primary);
  }
  .drow-val {
    grid-area:val;
    display:flex;
    align-items:center;
    justify-content:flex-end;
    text-align:right;
  }
}

/* ── Targets ── */
.dtr_ { display:flex;justify-content:space-between;align-items:center;margin-bottom:7px; }
.dtnm { display:flex;align-items:center;gap:8px;font-size:13px;font-weight:600;color:var(--text-primary); }
.dtdc { background:rgba(16,185,129,.12);color:#10b981;font-size:10px;padding:2px 8px;border-radius:99px;font-weight:700; }
.dtt  { font-size:12px;color:var(--text-muted);font-weight:500; }
.dtt.done { color:#10b981;font-weight:700; }
.dti  { margin-bottom:16px; }
.dti:last-child{margin-bottom:0;}

/* ── Performers ── */
.dp3g { display:grid;grid-template-columns:repeat(3,1fr);gap:14px; }
@media(max-width:720px){.dp3g{grid-template-columns:1fr;}}

.dprf { background:var(--bg-secondary);border:1px solid var(--border);border-radius:var(--dlg);padding:20px 16px 16px;text-align:center;position:relative;overflow:hidden;transition:transform .2s,box-shadow .2s; }
.dprf:hover{transform:translateY(-5px);}
.dprf::before { content:'';position:absolute;inset:0;background:radial-gradient(ellipse at 50% -10%,var(--dpg,rgba(99,102,241,.08)) 0%,transparent 65%);pointer-events:none; }
.dmdl { position:absolute;top:10px;left:12px;font-size:20px; }
.dpav { width:54px;height:54px;border-radius:50%;border:2.5px solid var(--dpc,#6366f1);background:var(--dpb,rgba(99,102,241,.1));display:flex;align-items:center;justify-content:center;font-size:21px;font-weight:800;color:var(--dpc,#6366f1);margin:0 auto 12px;overflow:hidden; }
.dpav img { width:100%;height:100%;object-fit:cover; }
.dpnm { font-size:13px;font-weight:700;color:var(--text-primary);margin-bottom:12px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis; }
.dpst { background:var(--bg-card);border-radius:9px;padding:7px 10px;display:flex;justify-content:space-between;align-items:center;margin-bottom:6px; }
.dpst:last-child{margin-bottom:0;}
.dpsl{font-size:11px;color:var(--text-muted);} .dpsv{font-size:13px;font-weight:700;color:var(--text-primary);}

/* ── Empty ── */
.dempty { text-align:center;padding:28px 20px; }
.dei { font-size:34px;margin-bottom:10px; }
.dempty h3 { font-size:14px;font-weight:600;color:var(--text-secondary);margin-bottom:4px; }
.dempty p { font-size:12px;color:var(--text-muted); }

/* ── Animations ── */
@keyframes drise { from{opacity:0;transform:translateY(18px)} to{opacity:1;transform:translateY(0)} }

/* ══════════════════════════════════════════════
   TUTORIAL BANNER
══════════════════════════════════════════════ */
.tutorial-banner {
  display: flex; align-items: center; gap: 14px;
  padding: 14px 18px;
  background: linear-gradient(110deg, rgba(99,102,241,.13) 0%, rgba(139,92,246,.09) 50%, rgba(6,182,212,.07) 100%);
  border: 1px solid rgba(99,102,241,.3);
  border-radius: var(--dr);
  margin-bottom: 16px;
  animation: drise .45s ease both;
  position: relative;
  overflow: hidden;
}
.tutorial-banner::before {
  content: '';
  position: absolute; left: 0; top: 0; bottom: 0; width: 3px;
  background: linear-gradient(180deg, #6366f1, #8b5cf6, #06b6d4);
  border-radius: 3px 0 0 3px;
}
.tutorial-banner-icon {
  font-size: 26px; flex-shrink: 0;
  filter: drop-shadow(0 0 8px rgba(99,102,241,.5));
}
.tutorial-banner-body { flex: 1; min-width: 0; }
.tutorial-banner-title {
  font-size: 13px; font-weight: 700; color: var(--text-primary);
  display: flex; align-items: center; gap: 7px; margin-bottom: 3px;
}
.tutorial-banner-title .tut-badge {
  font-size: 10px; font-weight: 700; letter-spacing: .6px; text-transform: uppercase;
  padding: 2px 7px; border-radius: 20px;
  background: rgba(99,102,241,.2); color: #818cf8; border: 1px solid rgba(99,102,241,.3);
}
.tutorial-banner-sub {
  font-size: 12px; color: var(--text-secondary); line-height: 1.5;
}
.tutorial-banner-actions {
  display: flex; align-items: center; gap: 8px; flex-shrink: 0;
}
.tut-btn-go {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 7px 14px; border-radius: 8px;
  background: linear-gradient(135deg, #6366f1, #8b5cf6);
  color: #fff; font-size: 12px; font-weight: 700;
  text-decoration: none; border: none; cursor: pointer;
  transition: opacity .2s, transform .2s, box-shadow .2s;
  box-shadow: 0 4px 14px rgba(99,102,241,.35);
  white-space: nowrap;
}
.tut-btn-go:hover { opacity: .9; transform: translateY(-1px); box-shadow: 0 6px 20px rgba(99,102,241,.4); }
.tut-btn-close {
  width: 30px; height: 30px; border-radius: 8px; border: 1px solid rgba(255,255,255,.08);
  background: rgba(255,255,255,.04); color: var(--text-secondary);
  display: flex; align-items: center; justify-content: center;
  cursor: pointer; transition: background .2s, color .2s;
  flex-shrink: 0;
}
.tut-btn-close:hover { background: rgba(255,255,255,.1); color: var(--text-primary); }
@media (max-width: 600px) {
  .tutorial-banner { flex-wrap: wrap; gap: 10px; }
  .tutorial-banner-actions { width: 100%; justify-content: flex-end; }
}

/* ══════════════════════════════════════════════
   TELEGRAM CHANNEL BANNER
══════════════════════════════════════════════ */
.tg-banner {
  display: flex; align-items: center; gap: 14px;
  padding: 14px 18px;
  background: linear-gradient(110deg, rgba(38,165,228,.14) 0%, rgba(38,165,228,.07) 60%, rgba(99,102,241,.06) 100%);
  border: 1px solid rgba(38,165,228,.32);
  border-radius: var(--dr);
  margin-bottom: 16px;
  animation: drise .45s .03s ease both;
  position: relative;
  overflow: hidden;
}
.tg-banner::before {
  content: '';
  position: absolute; left: 0; top: 0; bottom: 0; width: 3px;
  background: linear-gradient(180deg, #29b6f6, #26A5E4, #1e88c7);
  border-radius: 3px 0 0 3px;
}
.tg-banner-icon {
  width: 34px; height: 34px; flex-shrink: 0;
  filter: drop-shadow(0 0 8px rgba(38,165,228,.5));
}
.tg-banner-body { flex: 1; min-width: 0; }
.tg-banner-title {
  font-size: 13px; font-weight: 700; color: var(--text-primary);
  display: flex; align-items: center; gap: 7px; margin-bottom: 3px;
}
.tg-banner-title .tg-badge {
  font-size: 10px; font-weight: 700; letter-spacing: .6px; text-transform: uppercase;
  padding: 2px 7px; border-radius: 20px;
  background: rgba(38,165,228,.18); color: #4fc3f7; border: 1px solid rgba(38,165,228,.35);
}
.tg-banner-sub {
  font-size: 12px; color: var(--text-secondary); line-height: 1.5;
}
.tg-banner-actions {
  display: flex; align-items: center; gap: 8px; flex-shrink: 0;
}
.tg-btn-go {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 7px 14px; border-radius: 8px;
  background: linear-gradient(135deg, #26A5E4, #1e88c7);
  color: #fff; font-size: 12px; font-weight: 700;
  text-decoration: none; border: none; cursor: pointer;
  transition: opacity .2s, transform .2s, box-shadow .2s;
  box-shadow: 0 4px 14px rgba(38,165,228,.35);
  white-space: nowrap;
}
.tg-btn-go:hover { opacity: .9; transform: translateY(-1px); box-shadow: 0 6px 20px rgba(38,165,228,.4); }
.tg-btn-close {
  width: 30px; height: 30px; border-radius: 8px; border: 1px solid rgba(255,255,255,.08);
  background: rgba(255,255,255,.04); color: var(--text-secondary);
  display: flex; align-items: center; justify-content: center;
  cursor: pointer; transition: background .2s, color .2s;
  flex-shrink: 0;
}
.tg-btn-close:hover { background: rgba(255,255,255,.1); color: var(--text-primary); }
@media (max-width: 600px) {
  .tg-banner { flex-wrap: wrap; gap: 10px; }
  .tg-banner-actions { width: 100%; justify-content: flex-end; }
}
</style>

<div class="dp">

<!-- ── TUTORIAL BANNER ─────────────────────────────── -->
<div class="tutorial-banner" id="tutorialBanner">
  <div class="tutorial-banner-icon">🎓</div>
  <div class="tutorial-banner-body">
    <div class="tutorial-banner-title">
      New to StudyTrack?
      <span class="tut-badge">Tutorial</span>
    </div>
    <div class="tutorial-banner-sub">Watch our step-by-step guide and get up and running in under 2 minutes.</div>
  </div>
  <div class="tutorial-banner-actions">
    <a href="tutorial.php" class="tut-btn-go">
      <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><polygon points="10 8 16 12 10 16 10 8"/></svg>
      Watch Tutorial
    </a>
    <button class="tut-btn-close" id="tutorialBannerClose" title="Dismiss">
      <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M18 6 6 18M6 6l12 12"/></svg>
    </button>
  </div>
</div>

<!-- ── TELEGRAM CHANNEL BANNER ─────────────────────────────── -->
<div class="tg-banner" id="telegramBanner">
  <svg class="tg-banner-icon" viewBox="0 0 240 240" xmlns="http://www.w3.org/2000/svg">
    <circle cx="120" cy="120" r="120" fill="#26A5E4"/>
    <path fill="#fff" d="M100.1 143.1l50.3 37.2c5.7 3.2 9.9 1.5 11.3-5.3l20.5-96.4c2-8.4-3.2-12.2-8.7-9.7l-120 46.3c-8.2 3.2-8.1 7.7-1.5 9.7l30.8 9.6 74.6-47.1c3.5-2.2 6.7-1 4.1 1.4l-60.6 54.7-2.5 33.6z"/>
  </svg>
  <div class="tg-banner-body">
    <div class="tg-banner-title">
      Join our Telegram Channel
      <span class="tg-badge">New</span>
    </div>
    <div class="tg-banner-sub">Get study tips, exam updates &amp; announcements — join the StudyTrack community.</div>
  </div>
  <div class="tg-banner-actions">
    <a href="https://t.me/studytrack_official" target="_blank" rel="noopener" class="tg-btn-go" id="telegramBannerJoin">
      <svg width="13" height="13" viewBox="0 0 240 240" xmlns="http://www.w3.org/2000/svg"><circle cx="120" cy="120" r="120" fill="#fff" fill-opacity=".2"/><path fill="#fff" d="M100.1 143.1l50.3 37.2c5.7 3.2 9.9 1.5 11.3-5.3l20.5-96.4c2-8.4-3.2-12.2-8.7-9.7l-120 46.3c-8.2 3.2-8.1 7.7-1.5 9.7l30.8 9.6 74.6-47.1c3.5-2.2 6.7-1 4.1 1.4l-60.6 54.7-2.5 33.6z"/></svg>
      Join Channel
    </a>
    <button class="tg-btn-close" id="telegramBannerClose" title="Dismiss">
      <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M18 6 6 18M6 6l12 12"/></svg>
    </button>
  </div>
</div>

<?php if (!empty($announcements)): foreach ($announcements as $ann): ?>
<div class="da <?= $ann['priority']==='high' ? 'da-hi' : '' ?>">
  <span style="font-size:17px;flex-shrink:0"><?= $ann['priority']==='high' ? '🔔' : '📌' ?></span>
  <div><span class="da-t"><?= htmlspecialchars($ann['title']) ?></span><span class="da-b"><?= htmlspecialchars($ann['content']) ?></span></div>
</div>
<?php endforeach; endif; ?>

<!-- HERO -->
<div class="dh">
  <div class="dclk">
    <!-- Floating study icons -->
    <div class="dclk-icons">
      <div class="sci sci-1"><svg width="18" height="18" fill="none" stroke="#818cf8" stroke-width="2" viewBox="0 0 24 24"><path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"/><path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z"/></svg></div>
      <div class="sci sci-2"><svg width="16" height="16" fill="none" stroke="#c084fc" stroke-width="2" viewBox="0 0 24 24"><path d="M12 20h9"/><path d="M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4L16.5 3.5z"/></svg></div>
      <div class="sci sci-3"><svg width="17" height="17" fill="none" stroke="#38bdf8" stroke-width="2" viewBox="0 0 24 24"><path d="M9 3H5a2 2 0 0 0-2 2v4m6-6h10a2 2 0 0 1 2 2v4M9 3v18m0 0h10a2 2 0 0 0 2-2v-4M9 21H5a2 2 0 0 1-2-2v-4m0 0h18"/></svg></div>
      <div class="sci sci-4"><svg width="15" height="15" fill="none" stroke="#fbbf24" stroke-width="2" viewBox="0 0 24 24"><line x1="19" y1="5" x2="5" y2="19"/><circle cx="6.5" cy="6.5" r="2.5"/><circle cx="17.5" cy="17.5" r="2.5"/></svg></div>
      <div class="sci sci-5"><svg width="19" height="19" fill="none" stroke="#34d399" stroke-width="2" viewBox="0 0 24 24"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg></div>
      <div class="sci sci-6"><svg width="15" height="15" fill="none" stroke="#f87171" stroke-width="2" viewBox="0 0 24 24"><polyline points="22 12 18 12 15 21 9 3 6 12 2 12"/></svg></div>
      <div class="sci sci-7"><svg width="17" height="17" fill="none" stroke="#818cf8" stroke-width="2" viewBox="0 0 24 24"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/><polyline points="10 9 9 9 8 9"/></svg></div>
      <div class="sci sci-8"><svg width="14" height="14" fill="none" stroke="#c084fc" stroke-width="2" viewBox="0 0 24 24"><polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"/></svg></div>
    </div>
    <div id="d-day" class="dclk-day">Wednesday</div>
    <div id="d-date" class="dclk-date">March 11, 2026</div>
    <div class="dclk-tr">
      <div id="d-time" class="dclk-time">12:00:00</div>
      <div id="d-ampm" class="dclk-ap">AM</div>
    </div>
  </div>
  <?php if (!empty($exams)): ?>
  <div class="dcd-wrap">
    <div class="dcd-track" id="dcdTrack">
      <?php foreach ($exams as $i => $ex): ?>
      <div class="dcd" data-exam-date="<?= htmlspecialchars($ex['exam_date']) ?>">
        <div class="dcd-icons">
          <div class="cdi cdi-1"><svg width="14" height="14" fill="none" stroke="#818cf8" stroke-width="2" viewBox="0 0 24 24"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg></div>
          <div class="cdi cdi-2"><svg width="12" height="12" fill="none" stroke="#c084fc" stroke-width="2" viewBox="0 0 24 24"><rect x="3" y="4" width="18" height="18" rx="2"/><line x1="16" y1="2" x2="16" y2="6"/><line x1="8" y1="2" x2="8" y2="6"/><line x1="3" y1="10" x2="21" y2="10"/></svg></div>
          <div class="cdi cdi-3"><svg width="13" height="13" fill="none" stroke="#38bdf8" stroke-width="2" viewBox="0 0 24 24"><path d="M22 10v6M2 10l10-5 10 5-10 5z"/><path d="M6 12v5c3 3 9 3 12 0v-5"/></svg></div>
          <div class="cdi cdi-4"><svg width="11" height="11" fill="none" stroke="#fbbf24" stroke-width="2" viewBox="0 0 24 24"><polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"/></svg></div>
          <div class="cdi cdi-5"><svg width="13" height="13" fill="none" stroke="#34d399" stroke-width="2" viewBox="0 0 24 24"><polyline points="23 6 13.5 15.5 8.5 10.5 1 18"/><polyline points="17 6 23 6 23 12"/></svg></div>
        </div>
        <div>
          <div class="dcd-chip">⏳ Countdown</div>
          <div class="dcd-nm"><?= htmlspecialchars($ex['exam_name']) ?></div>
          <div class="dcd-dt"><?= date('F j, Y', strtotime($ex['exam_date'])) ?></div>
        </div>
        <!-- FLIP CARD WRAPPER -->
        <div class="dcd-flip-wrapper" title="Click to see detailed countdown">
          <!-- FRONT: Months + Days -->
          <div class="dcd-face dcd-front">
            <div class="dcd-units">
              <div class="dcd-unit"><span class="dcd-n dcd-months">00</span><span class="dcd-l">Months</span></div>
              <div class="dcd-unit"><span class="dcd-n dcd-days">00</span><span class="dcd-l">Days</span></div>
            </div>
            <div class="dcd-flip-hint">tap for detailed view</div>
          </div>
          <!-- BACK: Days + Hours + Minutes + Seconds -->
          <div class="dcd-face dcd-back">
            <div class="dcd-units dcd-units-detailed">
              <div class="dcd-unit dcd-unit-sm"><span class="dcd-n dcd-b-days">00</span><span class="dcd-l">Days</span></div>
              <div class="dcd-unit dcd-unit-sm"><span class="dcd-n dcd-b-hours">00</span><span class="dcd-l">Hours</span></div>
              <div class="dcd-unit dcd-unit-sm"><span class="dcd-n dcd-b-mins">00</span><span class="dcd-l">Mins</span></div>
              <div class="dcd-unit dcd-unit-sm"><span class="dcd-n dcd-b-secs">00</span><span class="dcd-l">Secs</span></div>
            </div>
            <div class="dcd-flip-hint">tap to go back</div>
          </div>
        </div>
        <div class="dcd-today-lbl" style="display:none;margin-top:10px;font-size:13px;color:#22c55e;font-weight:700">🎉 Exam Day!</div>
      </div>
      <?php endforeach; ?>
    </div>
    <?php if (count($exams) > 1): ?>
    <div class="dcd-dots" id="dcdDots">
      <?php foreach ($exams as $i => $ex): ?>
      <button class="dcd-dot<?= $i===0?' active':'' ?>" data-idx="<?= $i ?>"></button>
      <?php endforeach; ?>
    </div>
    <?php endif; ?>
  </div>
  <?php endif; ?>
</div>

<script>
(function(){
  var M=['January','February','March','April','May','June','July','August','September','October','November','December'];
  var D=['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'];
  function tick(){
    var n=new Date(), el=document.getElementById('d-day');
    if(!el) return;
    el.textContent=D[n.getDay()];
    document.getElementById('d-date').textContent=M[n.getMonth()]+' '+n.getDate()+', '+n.getFullYear();
    var h=n.getHours(),m=n.getMinutes(),s=n.getSeconds();
    var ap=h>=12?'PM':'AM',h12=h%12||12;
    var p=function(x){return String(x).padStart(2,'0');};
    document.getElementById('d-time').textContent=p(h12)+':'+p(m)+':'+p(s);
    document.getElementById('d-ampm').textContent=ap;
  }
  tick(); setInterval(tick,1000);
})();
</script>


<!-- STATS -->
<div class="dstats">
  <div class="dst dst1">
    <div class="dsth"><div class="dsti" style="background:rgba(99,102,241,.12)">📅</div><span class="dsttag tc">30 days</span></div>
    <div class="dstv"><?= floor($monthMinutes/60) ?><span class="du">h <?= $monthMinutes%60 ?>m</span></div>
    <div class="dstl">Study Time This Month</div>
  </div>
  <div class="dst dst2">
    <div class="dsth"><div class="dsti" style="background:rgba(6,182,212,.12)">⏱️</div><span class="dsttag tg">Today</span></div>
    <div class="dstv"><?= floor($todayMinutes/60) ?><span class="du">h <?= $todayMinutes%60 ?>m</span></div>
    <div class="dstl">Today's Study Time</div>
  </div>
  <div class="dst dst3">
    <div class="dsth"><div class="dsti" style="background:rgba(245,158,11,.12)">🔥</div><span class="dsttag <?= $streak > 0 ? 'ta' : 'tr' ?>"><?= $streak > 0 ? 'Active' : 'Start!' ?></span></div>
    <div class="dstv"><?= $streak ?><span class="du"> days</span></div>
    <div class="dstl">Current Streak</div>
  </div>
  <div class="dst dst4">
    <div class="dsth"><div class="dsti" style="background:rgba(16,185,129,.12)">✅</div><span class="dsttag <?= $pendingTasks > 5 ? 'tr' : 'tg' ?>"><?= $pendingTasks > 0 ? 'Pending' : 'All done!' ?></span></div>
    <div class="dstv"><?= $pendingTasks ?></div>
    <div class="dstl">Pending Tasks</div>
  </div>
</div>



<!-- CHART + SUBJECTS -->
<div class="dmg">
  <div class="dc">
    <div class="dch">
      <div class="dct">📊 Study Hours</div>
      <div class="dptgl" data-chart="d-wchart">
        <button class="dptb active" data-period="week">Week</button>
        <button class="dptb" data-period="month">Month</button>
      </div>
    </div>
    <div class="dchw"><canvas id="d-wchart"></canvas></div>
  </div>
  <div class="dc">
    <div class="dch">
      <div class="dct">📖 Subjects</div>
      <a href="<?= SITE_URL ?>/subjects" class="dcl">Manage</a>
    </div>
    <?php if ($topSubs):
      $maxMin = max(array_column($topSubs,'total'));
      foreach ($topSubs as $sub):
        $pct = $maxMin > 0 ? round(($sub['total']/$maxMin)*100) : 0;
    ?>
    <div class="dsr">
      <div class="dsi">
        <span class="dsn"><span class="dsdot" style="background:<?= htmlspecialchars($sub['color']) ?>"></span><?= htmlspecialchars($sub['name']) ?></span>
        <span class="dst_"><?= floor($sub['total']/60) ?>h <?= $sub['total']%60 ?>m</span>
      </div>
      <div class="dpr"><div class="dprb" style="width:<?= $pct ?>%;background:<?= htmlspecialchars($sub['color']) ?>"></div></div>
    </div>
    <?php endforeach; else: ?>
    <div class="dempty"><div class="dei">📚</div><h3>No sessions yet</h3><p>Start logging to see breakdown</p></div>
    <?php endif; ?>
  </div>
</div>


<!-- CLASS HOURS CHART -->
<div class="dc" style="margin-bottom:var(--dg);animation:drise .5s .28s ease both">
  <div class="dch">
    <div class="dct">🏫 Class Hours This Week</div>
    <div style="display:flex;align-items:center;gap:16px">
      <?php if($chTotal > 0): ?>
      <span style="font-size:12px;font-weight:700;padding:4px 12px;border-radius:99px;background:rgba(16,185,129,.12);color:#10b981"><?= $chRate ?>% Attendance</span>
      <?php endif; ?>
      <a href="<?= SITE_URL ?>/class-hours" class="dcl">View All</a>
    </div>
  </div>
  <div style="display:grid;grid-template-columns:repeat(3,1fr);gap:12px;margin-bottom:18px">
    <div style="background:var(--bg-secondary);border:1px solid var(--border);border-radius:14px;padding:14px 16px">
      <div style="font-size:11px;font-weight:700;color:var(--text-muted);text-transform:uppercase;letter-spacing:.8px;margin-bottom:6px">Total Classes</div>
      <div style="font-family:'Outfit',sans-serif;font-size:26px;font-weight:800;color:var(--text-primary);line-height:1"><?= $chTotal ?></div>
      <div style="font-size:11px;color:var(--text-muted);margin-top:3px">This month</div>
    </div>
    <div style="background:var(--bg-secondary);border:1px solid rgba(16,185,129,.2);border-radius:14px;padding:14px 16px">
      <div style="font-size:11px;font-weight:700;color:var(--text-muted);text-transform:uppercase;letter-spacing:.8px;margin-bottom:6px">Attended</div>
      <div style="font-family:'Outfit',sans-serif;font-size:26px;font-weight:800;color:#10b981;line-height:1"><?= $chAtt ?></div>
      <div style="font-size:11px;color:var(--text-muted);margin-top:3px"><?= floor(($chSum['att_mins']??0)/60) ?>h <?= ($chSum['att_mins']??0)%60 ?>m</div>
    </div>
    <div style="background:var(--bg-secondary);border:1px solid rgba(239,68,68,.2);border-radius:14px;padding:14px 16px">
      <div style="font-size:11px;font-weight:700;color:var(--text-muted);text-transform:uppercase;letter-spacing:.8px;margin-bottom:6px">Missed</div>
      <div style="font-family:'Outfit',sans-serif;font-size:26px;font-weight:800;color:#ef4444;line-height:1"><?= $chTotal - $chAtt ?></div>
      <div style="font-size:11px;color:var(--text-muted);margin-top:3px"><?= floor((($chSum['total_mins']??0)-($chSum['att_mins']??0))/60) ?>h <?= (($chSum['total_mins']??0)-($chSum['att_mins']??0))%60 ?>m</div>
    </div>
  </div>
  <div style="height:180px"><canvas id="d-classchart"></canvas></div>
</div>


<!-- SPACED REPETITION -->
<div class="dc" style="margin-bottom:var(--dg);animation:drise .5s .3s ease both">
  <div class="dch">
    <div class="dct">🔁 Spaced Repetition</div>
    <?php if ($dueReviewCount > 0): ?>
      <span style="font-size:11px;font-weight:700;padding:4px 12px;border-radius:99px;background:rgba(239,68,68,.12);color:#ef4444;flex-shrink:0"><?= $dueReviewCount ?> due</span>
    <?php else: ?>
      <a href="<?= SITE_URL ?>/study-log" class="dcl">Study Log</a>
    <?php endif; ?>
  </div>

  <?php if ($dueReviews): ?>
    <div id="dashSrList">
    <?php foreach ($dueReviews as $r):
      $daysAgo = max(0, (int)((strtotime('today') - strtotime($r['last_studied_date'])) / 86400));
    ?>
    <div id="dashSrRow<?= $r['id'] ?>" style="background:var(--bg-secondary);border:1px solid var(--border);border-radius:14px;padding:12px 14px;margin-bottom:8px;display:flex;align-items:center;justify-content:space-between;gap:10px;flex-wrap:wrap">
      <div style="min-width:0;flex:1 1 180px">
        <div style="display:flex;align-items:center;gap:7px;font-size:13px;font-weight:600;color:var(--text-primary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap">
          <span class="dsdot" style="background:<?= htmlspecialchars($r['subject_color']) ?>"></span><?= htmlspecialchars($r['topic']) ?>
        </div>
        <div style="font-size:11px;color:var(--text-muted);margin-top:2px"><?= htmlspecialchars($r['subject_name']) ?> &bull; studied <?= $daysAgo === 0 ? 'today' : $daysAgo.'d ago' ?></div>
      </div>
      <div style="display:flex;gap:6px;flex-shrink:0">
        <button onclick="dashReviewAction('review_done',<?= $r['id'] ?>,this)" style="padding:7px 11px;border-radius:9px;border:none;background:rgba(99,102,241,.14);color:#818cf8;font-size:11px;font-weight:700;cursor:pointer;white-space:nowrap">✅ Reviewed</button>
        <button onclick="dashReviewAction('mastered',<?= $r['id'] ?>,this)" style="padding:7px 11px;border-radius:9px;border:none;background:rgba(16,185,129,.14);color:#10b981;font-size:11px;font-weight:700;cursor:pointer;white-space:nowrap">🎓 Mastered</button>
      </div>
    </div>
    <?php endforeach; ?>
    </div>
    <?php if ($dueReviewCount > count($dueReviews)): ?>
      <div style="text-align:center;margin-top:6px"><a href="<?= SITE_URL ?>/study-log" class="dcl" style="display:inline-block">+<?= $dueReviewCount - count($dueReviews) ?> more due</a></div>
    <?php endif; ?>
  <?php else: ?>
    <div class="dempty"><div class="dei">🎉</div><h3>Nothing due for review</h3><p>Log a topic in your Study Log and we'll remind you when it's time to revisit it.</p></div>
  <?php endif; ?>

  <?php if ($upcomingReviews): ?>
  <div style="margin-top:<?= $dueReviews ? '14px' : '2px' ?>;padding-top:12px;border-top:1px solid var(--border)">
    <div style="font-size:11px;font-weight:700;color:var(--text-muted);text-transform:uppercase;letter-spacing:.6px;margin-bottom:8px">Coming up</div>
    <?php foreach ($upcomingReviews as $u): ?>
    <div style="display:flex;align-items:center;justify-content:space-between;gap:10px;padding:5px 0;font-size:12px">
      <span style="display:flex;align-items:center;gap:7px;color:var(--text-secondary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0"><span class="dsdot" style="background:<?= htmlspecialchars($u['subject_color']) ?>;flex-shrink:0"></span><?= htmlspecialchars($u['topic']) ?></span>
      <span style="color:var(--text-muted);flex-shrink:0"><?= date('M j', strtotime($u['next_review_date'])) ?></span>
    </div>
    <?php endforeach; ?>
  </div>
  <?php endif; ?>
</div>


<!-- TABLES -->
<div class="dtg">
  <div class="dc" style="padding-bottom:16px;animation-delay:.35s">
    <div class="dch">
      <div class="dct">⏱️ Recent Sessions</div>
      <a href="<?= SITE_URL ?>/study-log" class="dcl">View All</a>
    </div>
    <?php if ($recent): ?>
    <!-- Desktop header -->
    <div class="drow-hd">
      <span>Date</span><span>Subject</span><span style="text-align:right">Duration</span>
    </div>
    <?php foreach ($recent as $s): ?>
    <div class="drow">
      <span class="drow-date"><?= date('M j', strtotime($s['date'])) ?></span>
      <span class="drow-subj">
        <span class="dinl" style="background:<?= htmlspecialchars($s['color']) ?>"></span><?= htmlspecialchars($s['subject_name']) ?>
      </span>
      <span class="drow-val"><span class="ddur"><?= floor($s['duration_minutes']/60) ?>h <?= $s['duration_minutes']%60 ?>m</span></span>
    </div>
    <?php endforeach; ?>
    <?php else: ?>
    <div class="dempty"><div class="dei">⏱️</div><h3>No sessions yet</h3><p>Start logging your study time</p></div>
    <?php endif; ?>
  </div>

  <div class="dc" style="padding-bottom:16px;animation-delay:.4s">
    <div class="dch">
      <div class="dct">📝 Recent Results</div>
      <a href="<?= SITE_URL ?>/marks" class="dcl">View All</a>
    </div>
    <?php if ($recentMarks): ?>
    <!-- Desktop header -->
    <div class="drow-hd">
      <span>Exam</span><span>Subject</span><span style="text-align:right">Score</span>
    </div>
    <?php foreach ($recentMarks as $m):
      $pct = round(($m['marks_obtained']/$m['total_marks'])*100);
      $sc  = $pct>=75?'dsca':($pct>=50?'dscb':'dscc');
    ?>
    <div class="drow">
      <span class="drow-date"><?= htmlspecialchars($m['exam_name']) ?></span>
      <span class="drow-subj">
        <span class="dinl" style="background:<?= htmlspecialchars($m['color']) ?>"></span><?= htmlspecialchars($m['subject_name']) ?>
      </span>
      <span class="drow-val"><span class="dsc <?= $sc ?>"><?= $pct ?>%</span></span>
    </div>
    <?php endforeach; ?>
    <?php else: ?>
    <div class="dempty"><div class="dei">📝</div><h3>No marks yet</h3><p>Add your exam results</p></div>
    <?php endif; ?>
  </div>
</div>

<!-- WEEKLY TARGETS -->
<div class="dc" style="margin-bottom:var(--dg);animation-delay:.44s">
  <div class="dch">
    <div class="dct">🎯 Weekly Study Targets</div>
    <a href="<?= SITE_URL ?>/subjects" class="dcl">Manage</a>
  </div>
  <?php if (!empty($weekTargets)):
    foreach ($weekTargets as $wt):
      $targetMins = (float)$wt['weekly_target_hours'] * 60;
      $wkMins     = (int)$wt['week_mins'];
      $pct        = $targetMins > 0 ? min(100, round(($wkMins/$targetMins)*100)) : 0;
      $wH = floor($wkMins/60); $wM = $wkMins%60;
      $tH = floor($targetMins/60); $tM = (int)$targetMins%60;
      $done = $wkMins >= $targetMins;
      $bc = $pct>=100?'#10b981':($pct>=60?'#f59e0b':htmlspecialchars($wt['color']));
  ?>
  <div class="dti">
    <div class="dtr_">
      <span class="dtnm">
        <span class="dsdot" style="background:<?= htmlspecialchars($wt['color']) ?>"></span>
        <?= htmlspecialchars($wt['name']) ?>
        <?php if ($done): ?><span class="dtdc">✓ Done</span><?php endif; ?>
      </span>
      <span class="dtt <?= $done?'done':'' ?>"><?= $wH ?>h <?= $wM ?>m / <?= $tH ?>h<?= $tM>0?' '.$tM.'m':'' ?></span>
    </div>
    <div class="dpr" style="height:7px"><div class="dprb" style="width:<?= $pct ?>%;background:<?= $bc ?>"></div></div>
  </div>
  <?php endforeach; else: ?>
  <div class="dempty" style="padding:20px">
    <div class="dei">🎯</div>
    <h3>No weekly targets set</h3>
    <p>Go to Subjects and set weekly hour targets to track your progress here.</p>
    <a href="<?= SITE_URL ?>/subjects" class="dqb dqp" style="margin-top:14px;display:inline-flex">Set Targets</a>
  </div>
  <?php endif; ?>
</div>

<!-- TOP PERFORMERS -->
<?php if (!empty($top3)): ?>
<div class="dc" style="animation-delay:.5s">
  <div class="dch">
    <div class="dct">🏆 Top Performers This Month</div>
    <a href="<?= SITE_URL ?>/leaderboard" class="dcl">Full Leaderboard</a>
  </div>
  <div class="dp3g">
  <?php
    $medals  = ['🥇','🥈','🥉'];
    $pColors = ['#f59e0b','#94a3b8','#cd7c2f'];
    $pBgs    = ['rgba(245,158,11,.10)','rgba(148,163,184,.08)','rgba(205,124,47,.08)'];
    foreach ($top3 as $i => $p):
      $hrs  = floor($p['total_mins']/60); $mins = $p['total_mins']%60;
      $avg  = round($p['avg_mark'],1); $init = strtoupper($p['name'][0]);
  ?>
  <div class="dprf" style="--dpc:<?= $pColors[$i] ?>;--dpb:<?= $pBgs[$i] ?>;--dpg:<?= $pBgs[$i] ?>;border-color:<?= $pColors[$i] ?>28"
       onmouseover="this.style.boxShadow='0 12px 32px <?= $pColors[$i] ?>22'"
       onmouseout="this.style.boxShadow=''">
    <div class="dmdl"><?= $medals[$i] ?></div>
    <div class="dpav">
      <?php if (!empty($p['avatar']) && file_exists(__DIR__.'/'.$p['avatar'])): ?>
        <img src="<?= SITE_URL ?>/<?= htmlspecialchars($p['avatar']) ?>">
      <?php else: ?><?= $init ?><?php endif; ?>
    </div>
    <div class="dpnm"><?= htmlspecialchars($p['name']) ?></div>
    <div class="dpst"><span class="dpsl">Study Time</span><span class="dpsv"><?= $hrs ?>h <?= $mins ?>m</span></div>
    <div class="dpst"><span class="dpsl">Sessions</span><span class="dpsv"><?= $p['sessions'] ?></span></div>
    <?php if ($avg > 0): ?>
    <div class="dpst">
      <span class="dpsl">Avg Mark</span>
      <span class="dpsv" style="color:<?= $avg>=75?'#10b981':($avg>=55?'#f59e0b':'#ef4444') ?>"><?= $avg ?>%</span>
    </div>
    <?php endif; ?>
  </div>
  <?php endforeach; ?>
  </div>
</div>
<?php endif; ?>

</div><!-- .dp -->

<script>
(function(){
  var labels = <?= json_encode(array_column($weekData,'date')) ?>;
  var mins   = <?= json_encode(array_column($weekData,'minutes')) ?>;
  var ctx    = document.getElementById('d-wchart').getContext('2d');

  var dChart = new Chart(ctx, {
    type: 'bar',
    data: {
      labels: labels,
      datasets:[{
        label: 'Study Time',
        data: mins,
        backgroundColor: mins.map(function(v,i){
          return i===mins.length-1 ? '#6366f1' : 'rgba(99,102,241,0.4)';
        }),
        hoverBackgroundColor: '#818cf8',
        borderRadius: 9,
        borderSkipped: false,
        borderWidth: 0,
      }]
    },
    options:{
      responsive:true, maintainAspectRatio:false,
      plugins:{
        legend:{display:false},
        tooltip:{
          backgroundColor:'rgba(16,16,24,.96)',borderColor:'rgba(99,102,241,.3)',borderWidth:1,
          cornerRadius:10,padding:12,
          titleFont:{family:"'Plus Jakarta Sans',sans-serif",size:12},
          bodyFont:{family:"'Plus Jakarta Sans',sans-serif",size:13,weight:'700'},
          callbacks:{ label:function(ctx){ var v=ctx.raw; return '  '+Math.floor(v/60)+'h '+(v%60)+'m'; } }
        }
      },
      scales:{
        x:{ grid:{display:false}, border:{display:false}, ticks:{color:'#64748b',font:{family:"'Plus Jakarta Sans',sans-serif",size:12}} },
        y:{ grid:{color:'rgba(42,42,61,.35)'}, border:{display:false}, ticks:{color:'#64748b',font:{family:"'Plus Jakarta Sans',sans-serif",size:11},callback:function(v){return Math.floor(v/60)+'h';}} }
      },
      animation:{duration:600,easing:'easeInOutCubic'}
    }
  });

  document.querySelectorAll('.dptb[data-period]').forEach(function(btn){
    btn.addEventListener('click', async function(){
      btn.closest('.dptgl').querySelectorAll('.dptb').forEach(function(b){b.classList.remove('active');});
      btn.classList.add('active');
      try {
        var res  = await fetch('<?= SITE_URL ?>/dashboard-chart.php?period='+btn.dataset.period, {headers:{'X-Requested-With':'XMLHttpRequest'}});
        var data = await res.json();
        if (data.success) {
          var l=data.data.map(function(d){return d.date;});
          var m=data.data.map(function(d){return d.minutes;});
          dChart.data.labels=l;
          dChart.data.datasets[0].data=m;
          dChart.data.datasets[0].backgroundColor=m.map(function(v,i){return i===m.length-1?'#6366f1':'rgba(99,102,241,0.4)';});
          dChart.update();
        }
      } catch(e){ console.error(e); }
    });
  });

  // ── Class Hours Chart ──
  (function(){
    var clCtx = document.getElementById('d-classchart');
    if (!clCtx) return;
    var clLabels = <?= json_encode(array_column($classWeekData,'date')) ?>;
    var clTotal  = <?= json_encode(array_column($classWeekData,'total')) ?>;
    var clAttend = <?= json_encode(array_column($classWeekData,'attended')) ?>;
    new Chart(clCtx.getContext('2d'), {
      type: 'bar',
      data: {
        labels: clLabels,
        datasets: [
          { label: 'Attended', data: clAttend, backgroundColor: 'rgba(16,185,129,0.75)', hoverBackgroundColor: '#34d399', borderRadius: 8, borderSkipped: false, borderWidth: 0 },
          { label: 'Scheduled', data: clTotal, backgroundColor: 'rgba(99,102,241,0.22)', hoverBackgroundColor: 'rgba(99,102,241,0.38)', borderRadius: 8, borderSkipped: false, borderWidth: 0 }
        ]
      },
      options: {
        responsive: true, maintainAspectRatio: false,
        plugins: {
          legend: { display: true, position: 'top', labels: { color: '#94a3b8', font: { family:"'Plus Jakarta Sans',sans-serif", size: 11 }, boxWidth: 10, boxHeight: 10, borderRadius: 4, padding: 14 } },
          tooltip: {
            backgroundColor: 'rgba(16,16,24,.96)', borderColor: 'rgba(99,102,241,.3)', borderWidth: 1,
            cornerRadius: 10, padding: 12,
            titleFont: { family:"'Plus Jakarta Sans',sans-serif", size: 12 },
            bodyFont: { family:"'Plus Jakarta Sans',sans-serif", size: 13, weight: '700' },
            callbacks: { label: function(ctx){ var v=ctx.raw; return '  '+Math.floor(v/60)+'h '+(v%60)+'m'; } }
          }
        },
        scales: {
          x: { grid: { display: false }, border: { display: false }, ticks: { color: '#64748b', font: { family:"'Plus Jakarta Sans',sans-serif", size: 12 } } },
          y: { grid: { color: 'rgba(42,42,61,.35)' }, border: { display: false }, ticks: { color: '#64748b', font: { family:"'Plus Jakarta Sans',sans-serif", size: 11 }, callback: function(v){ return Math.floor(v/60)+'h'; } } }
        },
        animation: { duration: 700, easing: 'easeInOutCubic' }
      }
    });
  })();

})();
</script>

<?php if (!empty($exams)): ?>
<script>
(function(){
  var cards=document.querySelectorAll('#dcdTrack .dcd');
  var track=document.getElementById('dcdTrack');
  var dots=document.querySelectorAll('.dcd-dot');
  var total=cards.length,cur=0;
  function pad(n){return String(n).padStart(2,'0');}
  function animateDigit(el, val) {
    var str = pad(val);
    if (el && el.textContent !== str) {
      el.textContent = str;
      el.classList.remove('tick');
      void el.offsetWidth; // reflow
      el.classList.add('tick');
    }
  }

  function tickCard(card){
    var target=new Date(card.getAttribute('data-exam-date')+' 08:00:00');
    var now=new Date(),diff=target-now;
    var mEl=card.querySelector('.dcd-months'),dEl=card.querySelector('.dcd-days'),lEl=card.querySelector('.dcd-today-lbl');
    var bDEl=card.querySelector('.dcd-b-days'),bHEl=card.querySelector('.dcd-b-hours'),bMEl=card.querySelector('.dcd-b-mins'),bSEl=card.querySelector('.dcd-b-secs');
    if(diff<=0){
      if(mEl)mEl.textContent='00';if(dEl)dEl.textContent='00';
      if(bDEl)bDEl.textContent='00';if(bHEl)bHEl.textContent='00';if(bMEl)bMEl.textContent='00';if(bSEl)bSEl.textContent='00';
      if(lEl)lEl.style.display='block';return;
    }
    // Front face: months + remaining days
    var y1=now.getFullYear(),mo1=now.getMonth(),d1=now.getDate();
    var y2=target.getFullYear(),mo2=target.getMonth(),d2=target.getDate();
    var months=(y2-y1)*12+(mo2-mo1);if(d2<d1)months--;if(months<0)months=0;
    var after=new Date(y1,mo1+months,d1);
    var frontDays=Math.floor((target-after)/86400000);
    if(mEl)mEl.textContent=pad(months);if(dEl)dEl.textContent=pad(frontDays);
    // Back face: total days, hours, minutes, seconds
    var totalSecs=Math.floor(diff/1000);
    var bSecs=totalSecs%60;
    var totalMins=Math.floor(totalSecs/60);
    var bMins=totalMins%60;
    var totalHrs=Math.floor(totalMins/60);
    var bHrs=totalHrs%24;
    var bDays=Math.floor(totalHrs/24);
    animateDigit(bDEl,bDays);
    animateDigit(bHEl,bHrs);
    animateDigit(bMEl,bMins);
    animateDigit(bSEl,bSecs);
  }
  function tickAll(){cards.forEach(tickCard);}
  tickAll();
  setInterval(function(){cards.forEach(function(c){ var fw=c.querySelector('.dcd-flip-wrapper'); if(fw&&fw.classList.contains('flipped'))tickCard(c); });},1000);
  setInterval(tickAll,60000);

  // Flip on click
  cards.forEach(function(card){
    var fw=card.querySelector('.dcd-flip-wrapper');
    if(!fw)return;
    fw.addEventListener('click',function(e){
      e.stopPropagation();
      fw.classList.toggle('flipped');
      if(fw.classList.contains('flipped'))tickCard(card);
    });
  });
  function goTo(idx){
    cur=(idx+total)%total;
    if(track)track.style.transform='translateX(-'+(cur*100)+'%)';
    dots.forEach(function(d,i){d.classList.toggle('active',i===cur);});
  }
  dots.forEach(function(d){d.addEventListener('click',function(){goTo(parseInt(d.getAttribute('data-idx')));});});
  if(total>1){setInterval(function(){goTo(cur+1);},5000);}
  var sx=0,moved=0,drag=false;
  if(track){
    track.addEventListener('mousedown',function(e){drag=true;sx=e.clientX;moved=0;track.classList.add('dragging');});
    track.addEventListener('mousemove',function(e){if(drag)moved=e.clientX-sx;});
    track.addEventListener('mouseup',function(){if(!drag)return;drag=false;track.classList.remove('dragging');if(Math.abs(moved)>40)goTo(moved<0?cur+1:cur-1);});
    track.addEventListener('mouseleave',function(){if(drag){drag=false;track.classList.remove('dragging');}});
    track.addEventListener('touchstart',function(e){sx=e.touches[0].clientX;moved=0;},{passive:true});
    track.addEventListener('touchmove',function(e){moved=e.touches[0].clientX-sx;},{passive:true});
    track.addEventListener('touchend',function(){if(Math.abs(moved)>40)goTo(moved<0?cur+1:cur-1);});
  }
})();
</script>
<?php endif; ?>

<?php if (!empty($todaySlots)): ?>
<!-- ══════════════════════════════════════════════════════
     CLASS ENDED ATTENDANCE POPUP
══════════════════════════════════════════════════════ -->
<div id="attPopupOverlay" style="
    display:none;position:fixed;inset:0;z-index:9999;
    background:rgba(0,0,0,0.55);backdrop-filter:blur(4px);
    align-items:center;justify-content:center;padding:16px">
    <div id="attPopupBox" style="
        background:var(--bg-card);border:1px solid rgba(99,102,241,.35);
        border-radius:20px;max-width:380px;width:100%;
        box-shadow:0 24px 60px rgba(0,0,0,.5);
        animation:attPop .3s cubic-bezier(.34,1.56,.64,1) both">

        <!-- Header -->
        <div style="padding:20px 22px 16px;border-bottom:1px solid var(--border)">
            <div style="display:flex;align-items:center;gap:10px">
                <div style="width:40px;height:40px;border-radius:12px;background:rgba(99,102,241,.15);display:flex;align-items:center;justify-content:center;font-size:20px">🏫</div>
                <div>
                    <div style="font-size:15px;font-weight:800;color:var(--text-primary)" id="attPopupTitle">Class Ended</div>
                    <div style="font-size:12px;color:var(--text-muted)" id="attPopupTime"></div>
                </div>
            </div>
        </div>

        <!-- Body -->
        <div style="padding:18px 22px">
            <div style="font-size:13px;color:var(--text-secondary);margin-bottom:18px">
                Did you attend this class?
            </div>

            <!-- Buttons -->
            <div style="display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-bottom:14px">
                <button onclick="markAttendance(1)"
                    style="padding:13px;border:2px solid rgba(34,197,94,.3);border-radius:12px;
                           background:rgba(34,197,94,.08);color:#22c55e;
                           font-size:14px;font-weight:700;cursor:pointer;transition:all .2s"
                    onmouseover="this.style.background='rgba(34,197,94,.18)'"
                    onmouseout="this.style.background='rgba(34,197,94,.08)'">
                    ✓ Yes, Attended
                </button>
                <button onclick="markAttendance(0)"
                    style="padding:13px;border:2px solid rgba(239,68,68,.3);border-radius:12px;
                           background:rgba(239,68,68,.08);color:#ef4444;
                           font-size:14px;font-weight:700;cursor:pointer;transition:all .2s"
                    onmouseover="this.style.background='rgba(239,68,68,.18)'"
                    onmouseout="this.style.background='rgba(239,68,68,.08)'">
                    ✗ No, Missed
                </button>
            </div>

            <!-- Success state (hidden initially) -->
            <div id="attPopupSuccess" style="display:none;text-align:center;padding:8px 0">
                <div style="font-size:28px;margin-bottom:6px" id="attSuccessIcon">✅</div>
                <div style="font-size:13px;font-weight:700;color:var(--text-primary)" id="attSuccessMsg">Logged!</div>
            </div>

            <div id="attPopupError" style="display:none;font-size:12px;color:#ef4444;text-align:center;margin-top:6px"></div>
        </div>
    </div>
</div>

<style>
@keyframes attPop {
    from { opacity:0; transform:scale(.88) translateY(16px); }
    to   { opacity:1; transform:scale(1) translateY(0); }
}
</style>

<script>
(function(){
    // Timetable slots — already_logged=1 means DB already has an entry today
    var todaySlots = <?= json_encode(array_map(fn($sl) => [
        'id'             => (int)$sl['id'],
        'start'          => substr($sl['start_time'], 0, 5),
        'end'            => substr($sl['end_time'], 0, 5),
        'label'          => $sl['label'] ?: ($sl['subject_name'] ?: 'Class'),
        'subject_id'     => (int)($sl['subject_id'] ?? 0),
        'subject_name'   => $sl['subject_name'] ?? '',
        'color'          => $sl['subject_color'] ?: $sl['color'] ?: '#6366f1',
        'already_logged' => (int)($sl['already_logged'] ?? 0),
    ], $todaySlots)) ?>;

    var TODAY = new Date().toISOString().split('T')[0];
    var SK    = 'att_done_' + TODAY + '_';

    var pending = [];
    var current = null;

    // Convert "HH:MM" to minutes since midnight
    function toMins(hhmm) {
        var p = hhmm.split(':');
        return parseInt(p[0]) * 60 + parseInt(p[1]);
    }

    // Slot is "done" if: DB already has a log OR user marked in this session
    function alreadyDone(sl) {
        return sl.already_logged === 1 || sessionStorage.getItem(SK + sl.id) !== null;
    }
    function markDone(slotId) {
        sessionStorage.setItem(SK + slotId, '1');
    }

    function checkSlots() {
        var d   = new Date();
        var now = d.getHours() * 60 + d.getMinutes();

        todaySlots.forEach(function(sl) {
            var endMins  = toMins(sl.end);

            // Show popup ONLY if:
            // 1. Class has already ended (now >= end time)
            // 2. Not more than 2 hours after end (not too stale)
            // 3. Not already logged in DB or this session
            if (now >= endMins && now < (endMins + 120) && !alreadyDone(sl)) {
                var inPending = pending.some(function(p){ return p.id === sl.id; });
                if (!inPending && (!current || current.id !== sl.id)) {
                    pending.push(sl);
                }
            }
        });

        if (!current && pending.length > 0) showPopup(pending.shift());
    }

    function showPopup(slot) {
        current = slot;
        document.getElementById('attPopupTitle').textContent = slot.label;
        document.getElementById('attPopupTime').textContent  = slot.start + ' – ' + slot.end;
        document.getElementById('attPopupSuccess').style.display = 'none';
        document.getElementById('attPopupError').style.display   = 'none';

        // Restore buttons
        document.getElementById('attPopupBox').querySelectorAll('button').forEach(function(b){
            b.style.display = '';
        });

        var ov = document.getElementById('attPopupOverlay');
        ov.style.display = 'flex';

        // Clicking backdrop does NOT close (must fill form)
        ov.onclick = function(e) {
            if (e.target === ov) {
                // Shake the box to indicate it must be filled
                var box = document.getElementById('attPopupBox');
                box.style.animation = 'none';
                box.offsetHeight; // reflow
                box.style.animation = 'attShake .4s ease';
            }
        };
    }

    function hidePopup() {
        document.getElementById('attPopupOverlay').style.display = 'none';
        current = null;
        // Show next pending after short delay
        setTimeout(function(){
            if (pending.length > 0) showPopup(pending.shift());
        }, 600);
    }

    window.markAttendance = async function(attended) {
        if (!current) return;

        var fd = new FormData();
        fd.append('action',     'add');
        fd.append('class_date', TODAY);
        fd.append('subject_id', current.subject_id || 0);
        fd.append('start_time', current.start);
        fd.append('end_time',   current.end);
        fd.append('class_type', 'regular');
        fd.append('attended',   attended);
        fd.append('notes',      '');

        var errEl  = document.getElementById('attPopupError');
        var sucEl  = document.getElementById('attPopupSuccess');
        errEl.style.display = 'none';

        try {
            var res  = await fetch('<?= SITE_URL ?>/class-hours', {
                method:'POST',
                headers:{'X-Requested-With':'XMLHttpRequest'},
                body: fd
            });
            var data = await res.json();

            if (data.success || data.message === 'Please fill in all required fields.') {
                // Mark done regardless (even if subject_id=0 we skip)
                markDone(current.id);
                // Also update the in-memory slot so interval won't re-queue it
                todaySlots.forEach(function(sl){ if(sl.id === current.id) sl.already_logged = 1; });

                // Show success
                document.getElementById('attPopupBox').querySelectorAll('button').forEach(function(b){
                    b.style.display = 'none';
                });
                document.getElementById('attSuccessIcon').textContent = attended ? '✅' : '😔';
                document.getElementById('attSuccessMsg').textContent  = attended ? 'Attendance marked!' : 'Marked as missed.';
                sucEl.style.display = 'block';
                setTimeout(hidePopup, 1200);
            } else {
                errEl.textContent    = data.message || 'Error saving.';
                errEl.style.display  = 'block';
            }
        } catch(e) {
            errEl.textContent   = 'Network error. Please try again.';
            errEl.style.display = 'block';
        }
    };

    // Add shake animation
    var st = document.createElement('style');
    st.textContent = '@keyframes attShake{0%,100%{transform:translateX(0)}20%,60%{transform:translateX(-8px)}40%,80%{transform:translateX(8px)}}';
    document.head.appendChild(st);

    // Check every 30 seconds + immediately
    checkSlots();
    checkInt = setInterval(checkSlots, 30000);
})();
</script>
<?php endif; ?>

<?php if ($showYearPopup): ?>
<div id="alYearOverlay" style="position:fixed;inset:0;z-index:9999;background:rgba(0,0,0,.65);backdrop-filter:blur(6px);display:flex;align-items:center;justify-content:center;">
<style>
@keyframes alyUp{from{opacity:0;transform:translateY(28px) scale(.96)}to{opacity:1;transform:none}}
#alYearModal{background:var(--bg-card);border:1px solid rgba(99,102,241,.35);border-radius:22px;padding:36px 32px 30px;width:min(94vw,400px);box-shadow:0 24px 80px rgba(0,0,0,.45);animation:alyUp .35s cubic-bezier(.34,1.56,.64,1);}
.aly-icon{width:52px;height:52px;border-radius:16px;background:linear-gradient(135deg,rgba(99,102,241,.2),rgba(168,85,247,.2));border:1px solid rgba(99,102,241,.3);display:flex;align-items:center;justify-content:center;margin:0 auto 18px;}
.aly-title{font-family:var(--df);font-size:20px;font-weight:800;color:var(--text-primary);text-align:center;margin-bottom:8px;}
.aly-sub{font-size:13px;color:var(--text-muted);text-align:center;line-height:1.5;margin-bottom:28px;}
.aly-opts{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-bottom:24px;}
.aly-opt{border:2px solid var(--border);border-radius:14px;padding:14px 10px;text-align:center;cursor:pointer;background:var(--bg-secondary);transition:all .18s ease;}
.aly-opt:hover{border-color:rgba(99,102,241,.5);background:rgba(99,102,241,.06);}
.aly-opt.selected{border-color:var(--accent);background:rgba(99,102,241,.12);box-shadow:0 0 0 3px rgba(99,102,241,.18);}
.aly-opt-yr{font-size:22px;font-weight:900;color:var(--text-primary);line-height:1;font-family:var(--df);}
.aly-opt-lbl{font-size:10px;font-weight:600;color:var(--text-muted);letter-spacing:1px;text-transform:uppercase;margin-top:4px;}
.aly-btn{width:100%;padding:13px;border:none;border-radius:12px;background:linear-gradient(135deg,#6366f1,#a855f7);color:#fff;font-family:var(--df);font-size:14px;font-weight:700;cursor:pointer;transition:opacity .18s,transform .18s;opacity:.4;pointer-events:none;}
.aly-btn.ready{opacity:1;pointer-events:auto;}
.aly-btn.ready:hover{transform:translateY(-1px);}
</style>
<div id="alYearModal">
  <div class="aly-icon"><svg width="26" height="26" fill="none" stroke="#818cf8" stroke-width="2" viewBox="0 0 24 24"><path d="M22 10v6M2 10l10-5 10 5-10 5z"/><path d="M6 12v5c3 3 9 3 12 0v-5"/></svg></div>
  <div class="aly-title">ඔබේ A/L Exam Year?</div>
  <div class="aly-sub">ඔබේ A/L examination year select කරන්න.<br>ඒ අනුව countdown show වේ.</div>
  <div class="aly-opts">
    <?php for($y=(int)date('Y'); $y<=(int)date('Y')+2; $y++): ?>
    <div class="aly-opt" data-year="<?= $y ?>" onclick="alySelect(this)">
      <div class="aly-opt-yr"><?= $y ?></div>
      <div class="aly-opt-lbl">A/L <?= $y ?></div>
    </div>
    <?php endfor; ?>
  </div>
  <button class="aly-btn" id="alyBtn" onclick="alySave()">Confirm &rarr;</button>
</div>
</div>
<script>
var _alySel=null;
function alySelect(el){
  document.querySelectorAll('.aly-opt').forEach(function(o){o.classList.remove('selected');});
  el.classList.add('selected');
  _alySel=el.getAttribute('data-year');
  var b=document.getElementById('alyBtn');
  b.classList.add('ready');
  b.textContent=_alySel+' A/L →';
}
function alySave(){
  if(!_alySel)return;
  var b=document.getElementById('alyBtn');
  b.textContent='Saving…';b.style.pointerEvents='none';
  var fd=new FormData();
  fd.append('action','save_al_year');
  fd.append('al_year',_alySel);
  fetch(window.location.href,{method:'POST',headers:{'X-Requested-With':'XMLHttpRequest'},body:fd})
  .then(function(r){return r.json();})
  .then(function(d){
    if(d.success){
      var o=document.getElementById('alYearOverlay');
      o.style.transition='opacity .3s';o.style.opacity='0';
      setTimeout(function(){o.remove();location.reload();},320);
    }
  });
}
</script>
<?php endif; ?>

<script>
/* ── Spaced repetition quick actions ── */
async function dashReviewAction(kind, id, btn) {
  var row = document.getElementById('dashSrRow'+id);
  var action = kind === 'mastered' ? 'sr_mastered' : 'sr_review_done';
  if (btn) { btn.disabled = true; btn.style.opacity = '0.6'; }
  try {
    var fd = new FormData(); fd.append('action', action); fd.append('id', id);
    var res  = await fetch(window.location.href, {method:'POST', headers:{'X-Requested-With':'XMLHttpRequest'}, body:fd});
    var data = await res.json();
    if (data.success && row) {
      row.style.transition = 'opacity .25s, transform .25s';
      row.style.opacity = '0'; row.style.transform = 'translateX(8px)';
      setTimeout(function(){ location.reload(); }, 350);
    } else if (btn) {
      btn.disabled = false; btn.style.opacity = '1';
    }
  } catch(e) {
    if (btn) { btn.disabled = false; btn.style.opacity = '1'; }
  }
}
</script>

<script>
/* ── Tutorial Banner ── */
(function(){
  var STORAGE_KEY = 'st_tutorial_banner_dismissed';
  var banner = document.getElementById('tutorialBanner');
  var closeBtn = document.getElementById('tutorialBannerClose');
  if (!banner) return;

  // Hide if already dismissed
  if (localStorage.getItem(STORAGE_KEY) === '1') {
    banner.style.display = 'none';
    return;
  }

  // Close button handler
  closeBtn.addEventListener('click', function(){
    banner.style.transition = 'opacity .3s, transform .3s, max-height .4s, margin .4s, padding .4s';
    banner.style.opacity = '0';
    banner.style.transform = 'translateY(-8px)';
    banner.style.maxHeight = banner.offsetHeight + 'px';
    // Collapse height smoothly
    requestAnimationFrame(function(){
      banner.style.maxHeight = '0';
      banner.style.marginBottom = '0';
      banner.style.paddingTop = '0';
      banner.style.paddingBottom = '0';
      banner.style.borderWidth = '0';
    });
    setTimeout(function(){
      banner.style.display = 'none';
      localStorage.setItem(STORAGE_KEY, '1');
    }, 420);
  });
})();
</script>

<script>
/* ── Telegram Channel Banner ── */
(function(){
  var STORAGE_KEY = 'st_telegram_banner_dismissed';
  var banner = document.getElementById('telegramBanner');
  var closeBtn = document.getElementById('telegramBannerClose');
  var joinBtn = document.getElementById('telegramBannerJoin');
  if (!banner) return;

  // Hide if already dismissed before
  if (localStorage.getItem(STORAGE_KEY) === '1') {
    banner.style.display = 'none';
    return;
  }

  function collapseAndDismiss() {
    banner.style.transition = 'opacity .3s, transform .3s, max-height .4s, margin .4s, padding .4s';
    banner.style.opacity = '0';
    banner.style.transform = 'translateY(-8px)';
    banner.style.maxHeight = banner.offsetHeight + 'px';
    requestAnimationFrame(function(){
      banner.style.maxHeight = '0';
      banner.style.marginBottom = '0';
      banner.style.paddingTop = '0';
      banner.style.paddingBottom = '0';
      banner.style.borderWidth = '0';
    });
    setTimeout(function(){
      banner.style.display = 'none';
      localStorage.setItem(STORAGE_KEY, '1');
    }, 420);
  }

  // Close button handler
  closeBtn.addEventListener('click', collapseAndDismiss);

  // Joining also dismisses the banner (link still opens in a new tab first)
  if (joinBtn) {
    joinBtn.addEventListener('click', function(){
      setTimeout(collapseAndDismiss, 150);
    });
  }
})();
</script>

<?php
require_once __DIR__ . '/includes/review-popup.php';
require_once 'includes/footer.php';
renderFooter();
?>