<!DOCTYPE html>

<html lang="en" data-theme="dark">

<head>

<meta charset="UTF-8"/>

<meta name="viewport" content="width=device-width, initial-scale=1.0"/>

<title>StudyBuddy</title>

<link rel="preconnect" href="https://fonts.googleapis.com"/>

<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin/>

<link href="https://fonts.googleapis.com/css2?family=DM+Sans:ital,wght@0,300;0,400;0,500;0,600;1,300&family=DM+Mono:wght@400;500&family=Playfair+Display:wght@400;500&display=swap" rel="stylesheet"/>

<style>

/* ══ THEME ══ */

:root {

  --bg:#0f1117; --bg2:#161820; --bg3:#1e2028; --bg4:#252730;

  --border:rgba(255,255,255,0.07); --border2:rgba(255,255,255,0.13);

  --text:#e8eaf0; --text2:#9095a8; --text3:#5a5f72;

  --shadow:0 2px 16px rgba(0,0,0,0.4);

  --accent:#6c8eff; --accent2:#4a6adb; --accent-bg:rgba(108,142,255,0.1);

  --green:#4ade80; --green-bg:rgba(74,222,128,0.1);

  --amber:#fbbf24; --amber-bg:rgba(251,191,36,0.1);

  --red:#f87171; --red-bg:rgba(248,113,113,0.1);

  --purple:#c084fc; --purple-bg:rgba(192,132,252,0.1);

  --teal:#2dd4bf; --teal-bg:rgba(45,212,191,0.1);

  --radius:12px; --radius-sm:8px;

  --sidebar:228px; --font:'DM Sans',sans-serif;

  --mono:'DM Mono',monospace; --display:'Playfair Display',serif;

  --tr:0.18s ease;

}

[data-theme="light"] {

  --bg:#eef0f5; --bg2:#ffffff; --bg3:#e8eaf0; --bg4:#d8dae6;

  --border:rgba(0,0,0,0.10); --border2:rgba(0,0,0,0.18);

  --text:#14172b; --text2:#404560; --text3:#7078a0;

  --shadow:0 2px 16px rgba(0,0,0,0.10);

  --accent-bg:rgba(108,142,255,0.10);

  --green-bg:rgba(22,160,60,0.10); --amber-bg:rgba(180,130,0,0.10);

  --red-bg:rgba(200,50,50,0.10); --purple-bg:rgba(140,60,200,0.10);

  --teal-bg:rgba(0,140,130,0.10);

}

[data-theme="light"] .stat-card,

[data-theme="light"] .card,

[data-theme="light"] .course-card,

[data-theme="light"] .course-full-card,

[data-theme="light"] .insight-card,

[data-theme="light"] .resource-card,

[data-theme="light"] .flag-card { box-shadow: 0 1px 4px rgba(0,0,0,0.07); }

[data-theme="light"] .asgn-table tr:hover td { background: var(--bg3); }

[data-theme="light"] .flag-card.alert { background:rgba(200,50,50,0.07); border-color:rgba(200,50,50,0.2); }

[data-theme="light"] .flag-card.warn  { background:rgba(180,130,0,0.07);  border-color:rgba(180,130,0,0.2); }

[data-theme="light"] .type-badge,

[data-theme="light"] .status-chip,

[data-theme="light"] .severity-badge,

[data-theme="light"] .resource-status { filter: saturate(1.3) brightness(0.75); }


*,*::before,*::after{box-sizing:border-box;margin:0;padding:0;}

body{font-family:var(--font);background:var(--bg);color:var(--text);min-height:100vh;display:flex;overflow:hidden;font-size:14px;line-height:1.5;transition:background var(--tr),color var(--tr);}

::-webkit-scrollbar{width:4px;} ::-webkit-scrollbar-track{background:transparent;} ::-webkit-scrollbar-thumb{background:var(--bg4);border-radius:4px;}


/* ══ SIDEBAR ══ */

.sidebar{width:var(--sidebar);min-height:100vh;background:var(--bg2);border-right:1px solid var(--border);display:flex;flex-direction:column;flex-shrink:0;transition:background var(--tr),border-color var(--tr);}

.sidebar-logo{padding:20px 16px 16px;border-bottom:1px solid var(--border);margin-bottom:6px;display:flex;align-items:center;gap:9px;}

.logo-icon{width:30px;height:30px;flex-shrink:0;}

.logo-text .wordmark{font-family:var(--display);font-size:16px;font-weight:500;letter-spacing:-0.02em;line-height:1;}

.logo-text .tagline{font-size:9px;color:var(--text3);letter-spacing:0.06em;text-transform:uppercase;margin-top:1px;}

.nav-section{padding:8px 12px 3px;font-size:9px;font-weight:700;letter-spacing:0.12em;text-transform:uppercase;color:var(--text3);}

.nav-item{display:flex;align-items:center;gap:9px;padding:8px 13px;margin:1px 7px;border-radius:var(--radius-sm);cursor:pointer;color:var(--text2);font-size:12.5px;font-weight:400;transition:background 0.15s,color 0.15s;}

.nav-item:hover{background:var(--bg3);color:var(--text);}

.nav-item.active{background:var(--accent-bg);color:var(--accent);font-weight:500;}

.nav-item .icon{width:14px;height:14px;flex-shrink:0;opacity:0.7;}

.nav-item.active .icon{opacity:1;}

.nav-badge{margin-left:auto;background:var(--red);color:#fff;font-size:9px;font-weight:700;padding:1px 5px;border-radius:20px;min-width:16px;text-align:center;}

.sidebar-bottom{margin-top:auto;padding:10px 7px 14px;border-top:1px solid var(--border);}

.user-pill{display:flex;align-items:center;gap:9px;padding:9px 10px;border-radius:var(--radius-sm);cursor:pointer;transition:background 0.15s;}

.user-pill:hover{background:var(--bg3);}

.avatar{width:28px;height:28px;border-radius:50%;background:linear-gradient(135deg,var(--accent),var(--accent2));display:flex;align-items:center;justify-content:center;font-size:11px;font-weight:600;color:#fff;flex-shrink:0;}

.user-info .name{font-size:12px;font-weight:500;}

.user-info .plan{font-size:10px;color:var(--text3);}

.user-pill-right{margin-left:auto;font-size:10px;color:var(--text3);}


/* ══ MAIN ══ */

.main{flex:1;overflow-y:auto;height:100vh;}

.page{display:none;}

.page.active{display:block;animation:pageIn 0.2s ease;}

@keyframes pageIn{from{opacity:0;transform:translateY(5px);}to{opacity:1;transform:translateY(0);}}

.page-header{padding:24px 28px 0;display:flex;align-items:flex-start;justify-content:space-between;gap:12px;flex-wrap:wrap;}

.page-title{font-family:var(--display);font-size:21px;font-weight:400;letter-spacing:-0.02em;}

.page-sub{font-size:12px;color:var(--text2);margin-top:2px;}

.page-body{padding:18px 28px 40px;}


/* ══ BUTTONS ══ */

.btn{display:inline-flex;align-items:center;gap:5px;padding:6px 13px;border-radius:var(--radius-sm);font-family:var(--font);font-size:12px;font-weight:500;cursor:pointer;border:none;transition:all 0.15s;white-space:nowrap;}

.btn-primary{background:var(--accent);color:#fff;} .btn-primary:hover{background:var(--accent2);transform:translateY(-1px);}

.btn-ghost{background:transparent;color:var(--text2);border:1px solid var(--border2);} .btn-ghost:hover{background:var(--bg3);color:var(--text);}

.btn-danger{background:var(--red-bg);color:var(--red);border:1px solid rgba(248,113,113,0.25);} .btn-danger:hover{background:rgba(248,113,113,0.2);}

.btn-success{background:var(--green-bg);color:var(--green);border:1px solid rgba(74,222,128,0.25);}

.btn-sm{padding:4px 10px;font-size:11px;}

.btn-icon{width:25px;height:25px;padding:0;justify-content:center;background:var(--bg3);color:var(--text2);border:1px solid var(--border);border-radius:6px;font-size:11px;}

.btn-icon:hover{background:var(--bg4);color:var(--text);}


/* ══ LAYOUT ══ */

.card{background:var(--bg2);border:1px solid var(--border);border-radius:var(--radius);padding:16px;transition:background var(--tr);}

.card-sm{padding:11px 13px;}

.grid-2{display:grid;grid-template-columns:1fr 1fr;gap:13px;}

.grid-3{display:grid;grid-template-columns:repeat(3,1fr);gap:13px;}

.grid-4{display:grid;grid-template-columns:repeat(4,1fr);gap:13px;}

.divider{height:1px;background:var(--border);margin:14px 0;}

.section-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:10px;}

.section-title{font-size:10px;font-weight:700;letter-spacing:0.1em;text-transform:uppercase;color:var(--text3);}

.empty-state{text-align:center;padding:32px 16px;color:var(--text3);}

.empty-state .ei{font-size:26px;margin-bottom:7px;}

.empty-state p{font-size:12px;}


/* ══ STAT CARDS ══ */

.stat-card{background:var(--bg2);border:1px solid var(--border);border-radius:var(--radius);padding:14px 16px;transition:border-color 0.15s,transform 0.15s,background var(--tr);}

.stat-card.clickable{cursor:pointer;} .stat-card.clickable:hover{border-color:var(--border2);transform:translateY(-2px);}

.stat-label{font-size:9px;font-weight:700;letter-spacing:0.09em;text-transform:uppercase;color:var(--text3);margin-bottom:5px;}

.stat-value{font-size:24px;font-weight:300;font-family:var(--display);letter-spacing:-0.03em;line-height:1;}

.stat-change{font-size:10px;color:var(--text3);margin-top:3px;}

.stat-change.up{color:var(--green);} .stat-change.down{color:var(--red);}

.stat-hint{font-size:9px;color:var(--accent);margin-top:4px;}


/* ══ COURSE CARDS ══ */

.course-card{background:var(--bg2);border:1px solid var(--border);border-radius:var(--radius);padding:13px 15px;transition:border-color 0.2s,transform 0.2s,background var(--tr);cursor:pointer;}

.course-card:hover{border-color:var(--border2);transform:translateY(-2px);}

.course-name{font-weight:500;font-size:13px;}

.course-code{font-size:9px;color:var(--text3);margin-top:1px;font-family:var(--mono);}

.course-grade{font-family:var(--display);font-size:19px;font-weight:400;letter-spacing:-0.03em;}

.progress-bar-wrap{height:3px;background:var(--bg4);border-radius:4px;overflow:hidden;margin:8px 0 6px;}

.progress-bar{height:100%;border-radius:4px;transition:width 0.5s ease;}

.course-meta{display:flex;justify-content:space-between;font-size:9px;color:var(--text3);}

.course-full-card{background:var(--bg2);border:1px solid var(--border);border-radius:var(--radius);overflow:hidden;transition:border-color 0.2s,background var(--tr);}

.course-full-card:hover{border-color:var(--border2);}

.course-full-header{padding:13px 15px 11px;border-bottom:1px solid var(--border);display:flex;align-items:center;gap:9px;}

.course-full-color{width:32px;height:32px;border-radius:var(--radius-sm);display:flex;align-items:center;justify-content:center;font-size:12px;font-weight:700;flex-shrink:0;}

.course-full-body{padding:11px 15px;}

.course-stat-row{display:flex;gap:14px;margin-bottom:10px;}

.course-stat-label{font-size:9px;color:var(--text3);text-transform:uppercase;letter-spacing:0.07em;margin-bottom:2px;}

.course-stat-val{font-size:15px;font-weight:300;font-family:var(--display);}

.grade-bar-wrap{height:4px;background:var(--bg4);border-radius:6px;overflow:hidden;margin:7px 0 5px;}


/* ══ ASSIGNMENT TABLE ══ */

.asgn-table{width:100%;border-collapse:collapse;}

.asgn-table th{text-align:left;padding:8px 11px;font-size:9px;font-weight:700;letter-spacing:0.09em;text-transform:uppercase;color:var(--text3);border-bottom:1px solid var(--border);}

.asgn-table td{padding:9px 11px;border-bottom:1px solid var(--border);font-size:12px;vertical-align:middle;}

.asgn-table tr:last-child td{border-bottom:none;}

.asgn-table tr:hover td{background:var(--bg3);}

.type-badge{display:inline-block;padding:2px 6px;border-radius:20px;font-size:8px;font-weight:700;letter-spacing:0.05em;text-transform:uppercase;}

.status-chip{display:inline-flex;align-items:center;gap:3px;padding:2px 6px;border-radius:20px;font-size:9px;font-weight:600;}

.row-actions{display:flex;gap:3px;opacity:0;transition:opacity 0.15s;}

.asgn-table tr:hover .row-actions{opacity:1;}


/* ══ FLAG CARDS ══ */

.flag-card{display:flex;gap:9px;padding:9px 11px;border-radius:var(--radius-sm);margin-bottom:6px;border:1px solid transparent;}

.flag-card.alert{background:var(--red-bg);border-color:rgba(248,113,113,0.2);}

.flag-card.warn{background:var(--amber-bg);border-color:rgba(251,191,36,0.2);}

.flag-card.info{background:var(--accent-bg);border-color:rgba(108,142,255,0.2);}

.flag-icon{font-size:12px;flex-shrink:0;margin-top:1px;}

.flag-text{font-size:11.5px;line-height:1.45;flex:1;color:var(--text);}

.flag-dismiss{background:none;border:none;color:var(--text3);cursor:pointer;font-size:14px;flex-shrink:0;padding:0 2px;line-height:1;transition:color 0.15s;}

.flag-dismiss:hover{color:var(--text);}


/* ══ TIMER ══ */

.timer-wrap{display:flex;flex-direction:column;align-items:center;padding:10px 14px 0;}

.timer-ring{position:relative;width:190px;height:190px;margin-bottom:18px;}

.timer-ring svg{transform:rotate(-90deg);}

.ring-bg{fill:none;stroke:var(--bg4);stroke-width:8;}

.ring-fg{fill:none;stroke:var(--accent);stroke-width:8;stroke-linecap:round;transition:stroke-dashoffset 1s linear;}

.timer-display{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;}

.timer-time{font-family:var(--mono);font-size:34px;font-weight:400;letter-spacing:-0.02em;line-height:1;}

.timer-label{font-size:10px;color:var(--text3);margin-top:2px;}

.timer-controls{display:flex;gap:9px;margin-bottom:13px;}

.timer-btn{width:42px;height:42px;border-radius:50%;border:none;cursor:pointer;display:flex;align-items:center;justify-content:center;font-size:15px;transition:transform 0.15s;}

.timer-btn:active{transform:scale(0.93);}

.timer-btn-primary{background:var(--accent);color:#fff;}

.timer-btn-ghost{background:var(--bg3);color:var(--text2);}

.timer-presets{display:flex;gap:5px;flex-wrap:wrap;justify-content:center;margin-bottom:7px;}

.custom-row{display:flex;align-items:center;gap:5px;margin-bottom:5px;}

.session-row{display:flex;align-items:center;gap:9px;padding:6px 0;border-bottom:1px solid var(--border);font-size:11px;}

.session-row:last-child{border-bottom:none;}

.session-dot{width:5px;height:5px;border-radius:50%;flex-shrink:0;}


/* ══ CHAT ══ */

.chat-layout{display:flex;height:100vh;flex-direction:column;}

.chat-header{padding:14px 24px 12px;border-bottom:1px solid var(--border);display:flex;align-items:center;gap:9px;flex-shrink:0;}

.chat-avatar-wrap{position:relative;}

.chat-avatar{width:36px;height:36px;border-radius:12px;background:linear-gradient(135deg,#6c8eff,#c084fc);display:flex;align-items:center;justify-content:center;font-size:18px;}

.chat-online-dot{position:absolute;bottom:-1px;right:-1px;width:9px;height:9px;background:var(--green);border-radius:50%;border:2px solid var(--bg2);}

.chat-info .name{font-weight:600;font-size:13px;}

.chat-info .status{font-size:10px;color:var(--green);}

.chat-messages{flex:1;overflow-y:auto;padding:14px 24px;display:flex;flex-direction:column;gap:11px;}

.msg{display:flex;gap:7px;max-width:80%;animation:msgIn 0.17s ease;}

@keyframes msgIn{from{opacity:0;transform:translateY(4px);}to{opacity:1;transform:translateY(0);}}

.msg.user{align-self:flex-end;flex-direction:row-reverse;}

.msg-avatar{width:24px;height:24px;border-radius:8px;flex-shrink:0;display:flex;align-items:center;justify-content:center;font-size:10px;font-weight:600;margin-top:2px;}

.msg-avatar.ai{background:linear-gradient(135deg,#6c8eff,#c084fc);color:#fff;font-size:12px;}

.msg-avatar.user-av{background:var(--accent2);color:#fff;}

.msg-bubble{padding:8px 12px;border-radius:12px;font-size:12.5px;line-height:1.6;}

.msg.ai .msg-bubble{background:var(--bg3);border:1px solid var(--border);border-top-left-radius:3px;}

.msg.user .msg-bubble{background:var(--accent2);color:#fff;border-top-right-radius:3px;}

.msg-bubble p{margin-bottom:4px;} .msg-bubble p:last-child{margin-bottom:0;}

.msg-bubble ul{padding-left:13px;} .msg-bubble li{margin-bottom:2px;}

.msg-bubble strong{font-weight:600;}

.msg-time{font-size:9px;color:var(--text3);margin-top:2px;text-align:right;}

.msg.ai .msg-time{text-align:left;}

.quick-prompts{padding:0 24px 7px;display:flex;gap:5px;flex-wrap:wrap;flex-shrink:0;}

.quick-chip{padding:4px 9px;background:var(--bg3);border:1px solid var(--border2);border-radius:20px;font-size:11px;color:var(--text2);cursor:pointer;transition:all 0.15s;white-space:nowrap;}

.quick-chip:hover{background:var(--bg4);color:var(--accent);border-color:rgba(108,142,255,0.3);}

.chat-input-wrap{padding:8px 24px 15px;border-top:1px solid var(--border);display:flex;gap:7px;align-items:flex-end;flex-shrink:0;}

.chat-input{flex:1;background:var(--bg3);border:1px solid var(--border2);border-radius:var(--radius);padding:9px 13px;color:var(--text);font-family:var(--font);font-size:12.5px;resize:none;outline:none;min-height:40px;max-height:100px;transition:border-color 0.2s,background var(--tr);}

.chat-input:focus{border-color:rgba(108,142,255,0.4);}

.chat-input::placeholder{color:var(--text3);}

.send-btn{width:36px;height:36px;border-radius:var(--radius-sm);background:var(--accent);border:none;color:#fff;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:background 0.15s,transform 0.1s;flex-shrink:0;}

.send-btn:hover{background:var(--accent2);} .send-btn:active{transform:scale(0.93);}

.typing-indicator{display:flex;gap:3px;padding:9px 11px;background:var(--bg3);border:1px solid var(--border);border-radius:12px;border-top-left-radius:3px;width:fit-content;}

.typing-dot{width:5px;height:5px;background:var(--text3);border-radius:50%;animation:tb 1.2s ease-in-out infinite;}

.typing-dot:nth-child(2){animation-delay:0.2s;} .typing-dot:nth-child(3){animation-delay:0.4s;}

@keyframes tb{0%,80%,100%{transform:translateY(0);opacity:.4;}40%{transform:translateY(-5px);opacity:1;}}


/* ══ INSIGHTS ══ */

.insight-card{background:var(--bg2);border:1px solid var(--border);border-radius:var(--radius);padding:13px 15px;margin-bottom:8px;display:flex;gap:11px;transition:border-color 0.2s,background var(--tr);}

.insight-card:hover{border-color:var(--border2);}

.insight-icon-wrap{width:34px;height:34px;border-radius:var(--radius-sm);display:flex;align-items:center;justify-content:center;font-size:15px;flex-shrink:0;}

.insight-title{font-weight:600;font-size:13px;margin-bottom:2px;}

.insight-desc{font-size:12px;color:var(--text2);line-height:1.5;}

.insight-meta{display:flex;align-items:center;gap:7px;margin-top:8px;font-size:10px;flex-wrap:wrap;}

.severity-badge{padding:2px 6px;border-radius:20px;font-size:8px;font-weight:700;letter-spacing:0.06em;text-transform:uppercase;}

.insight-dismiss{background:none;border:1px solid var(--border2);color:var(--text3);cursor:pointer;font-size:10px;padding:2px 8px;border-radius:20px;font-family:var(--font);transition:all 0.15s;}

.insight-dismiss:hover{background:var(--bg3);color:var(--text);}


/* ══ TASKS ══ */

.task-row{display:flex;align-items:center;gap:9px;padding:9px 13px;border-bottom:1px solid var(--border);transition:background 0.15s;}

.task-row:last-child{border-bottom:none;}

.task-row:hover{background:var(--bg3);}

.task-row.completed-row{opacity:0.6;}

.task-check{width:15px;height:15px;border-radius:50%;border:2px solid var(--border2);cursor:pointer;flex-shrink:0;display:flex;align-items:center;justify-content:center;transition:all 0.15s;}

.task-check.done{background:var(--green);border-color:var(--green);}

.task-check.done::after{content:'✓';font-size:8px;color:#fff;}

.task-info{flex:1;min-width:0;}

.task-title-txt{font-size:12.5px;font-weight:500;}

.task-done-txt{text-decoration:line-through;color:var(--text3);}

.task-sub{font-size:10px;color:var(--text3);margin-top:1px;}

.priority-dot{width:6px;height:6px;border-radius:50%;flex-shrink:0;}

.task-duration{font-size:9px;color:var(--teal);font-family:var(--mono);white-space:nowrap;}

.completed-section-header{padding:10px 13px 6px;background:var(--bg3);font-size:9px;font-weight:700;letter-spacing:0.1em;text-transform:uppercase;color:var(--text3);display:flex;justify-content:space-between;align-items:center;}


/* ══ RESOURCES ══ */

.resource-card{background:var(--bg2);border:1px solid var(--border);border-radius:var(--radius);padding:13px 15px;margin-bottom:8px;display:flex;align-items:flex-start;gap:11px;transition:border-color 0.2s,background var(--tr);}

.resource-card:hover{border-color:var(--border2);}

.resource-icon{width:34px;height:34px;border-radius:var(--radius-sm);display:flex;align-items:center;justify-content:center;font-size:15px;flex-shrink:0;}

.resource-body{flex:1;min-width:0;}

.resource-title{font-weight:600;font-size:13px;margin-bottom:2px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}

.resource-meta{font-size:11px;color:var(--text2);}

.resource-link{color:var(--accent);text-decoration:none;font-size:11px;}

.resource-link:hover{text-decoration:underline;}

.resource-status{padding:2px 7px;border-radius:20px;font-size:9px;font-weight:700;text-transform:uppercase;letter-spacing:0.05em;}

.obtained-divider{margin:18px 0 12px;padding:8px 0 6px;border-top:1px solid var(--border);display:flex;align-items:center;gap:8px;}

.obtained-divider-label{font-size:9px;font-weight:700;letter-spacing:0.1em;text-transform:uppercase;color:var(--green);white-space:nowrap;}

.obtained-divider-line{flex:1;height:1px;background:rgba(74,222,128,0.2);}


/* ══ PROGRAMS ══ */

.program-card{background:var(--bg2);border:1px solid var(--border);border-radius:var(--radius);overflow:hidden;transition:border-color 0.2s,background var(--tr);}

.program-card:hover{border-color:var(--border2);}

.program-header{padding:14px 16px 12px;display:flex;align-items:center;gap:10px;border-bottom:1px solid var(--border);}

.program-badge{width:38px;height:38px;border-radius:var(--radius-sm);display:flex;align-items:center;justify-content:center;font-size:16px;font-weight:700;flex-shrink:0;}

.program-body{padding:12px 16px;}

.program-stat-row{display:flex;gap:16px;margin-bottom:10px;}

.program-stat{flex:1;}


/* ══ CONTACTS PAGE ══ */

.contact-card{display:flex;align-items:center;gap:11px;padding:10px 13px;border-bottom:1px solid var(--border);}

.contact-card:hover{background:var(--bg3);}

.contact-card:last-child{border-bottom:none;}

.contact-avatar{width:32px;height:32px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:12px;font-weight:600;flex-shrink:0;}

.contact-info{flex:1;}

.contact-name{font-size:12.5px;font-weight:500;}

.contact-meta{font-size:10px;color:var(--text3);}

.contact-role-badge{padding:2px 7px;border-radius:20px;font-size:9px;font-weight:600;text-transform:uppercase;letter-spacing:0.05em;}


/* ══ SETTINGS PANEL ══ */

.settings-overlay{position:fixed;inset:0;z-index:200;display:none;}

.settings-overlay.open{display:flex;}

.settings-backdrop{position:absolute;inset:0;background:rgba(0,0,0,0.5);}

.settings-panel{position:absolute;right:0;top:0;bottom:0;width:320px;background:var(--bg2);border-left:1px solid var(--border2);display:flex;flex-direction:column;animation:slideIn 0.2s ease;}

@keyframes slideIn{from{transform:translateX(100%);}to{transform:translateX(0);}}

.settings-header{padding:18px 20px 14px;border-bottom:1px solid var(--border);display:flex;align-items:center;justify-content:space-between;}

.settings-title{font-family:var(--display);font-size:17px;font-weight:500;}

.settings-body{flex:1;overflow-y:auto;padding:16px 20px 24px;}

.settings-section{margin-bottom:20px;}

.settings-section-title{font-size:9px;font-weight:700;letter-spacing:0.12em;text-transform:uppercase;color:var(--text3);margin-bottom:10px;}

.settings-row{display:flex;align-items:center;justify-content:space-between;padding:8px 0;border-bottom:1px solid var(--border);}

.settings-row:last-child{border-bottom:none;}

.settings-row-label{font-size:12.5px;font-weight:500;}

.settings-row-sub{font-size:10px;color:var(--text3);margin-top:1px;}

.toggle-switch{position:relative;width:36px;height:20px;cursor:pointer;}

.toggle-switch input{opacity:0;width:0;height:0;}

.toggle-track{position:absolute;inset:0;background:var(--bg4);border-radius:20px;transition:background 0.2s;}

.toggle-track::after{content:'';position:absolute;width:14px;height:14px;left:3px;top:3px;background:#fff;border-radius:50%;transition:transform 0.2s;}

.toggle-switch input:checked ~ .toggle-track{background:var(--accent);}

.toggle-switch input:checked ~ .toggle-track::after{transform:translateX(16px);}

.widget-toggle{display:flex;align-items:center;gap:8px;padding:6px 10px;border-radius:var(--radius-sm);border:1px solid var(--border2);cursor:pointer;transition:all 0.15s;margin-bottom:5px;}

.widget-toggle.on{background:var(--accent-bg);border-color:rgba(108,142,255,0.3);color:var(--accent);}

.widget-toggle.off{color:var(--text3);}

.widget-toggle-label{font-size:12px;font-weight:500;}


/* ══ MODAL ══ */

.modal-overlay{position:fixed;inset:0;background:rgba(0,0,0,0.65);backdrop-filter:blur(4px);display:none;align-items:center;justify-content:center;z-index:150;}

.modal-overlay.open{display:flex;}

.modal{background:var(--bg2);border:1px solid var(--border2);border-radius:16px;padding:22px;width:460px;max-width:95vw;max-height:88vh;overflow-y:auto;animation:modalIn 0.2s cubic-bezier(.34,1.56,.64,1);}

.modal-sm{width:340px;}

.modal-lg{width:560px;}

@keyframes modalIn{from{opacity:0;transform:scale(0.94) translateY(8px);}to{opacity:1;transform:scale(1) translateY(0);}}

.modal-title{font-family:var(--display);font-size:16px;font-weight:500;margin-bottom:14px;}

.form-group{margin-bottom:11px;}

.form-label{font-size:11px;font-weight:600;color:var(--text2);margin-bottom:4px;display:block;letter-spacing:0.04em;}

.form-input,.form-select{width:100%;background:var(--bg3);border:1px solid var(--border2);color:var(--text);padding:7px 10px;border-radius:var(--radius-sm);font-family:var(--font);font-size:12px;outline:none;transition:border-color 0.2s,background var(--tr);}

.form-input:focus,.form-select:focus{border-color:rgba(108,142,255,0.5);}

.form-input::placeholder{color:var(--text3);}

.form-row{display:grid;grid-template-columns:1fr 1fr;gap:8px;}

.form-row-3{display:grid;grid-template-columns:1fr 1fr 1fr;gap:8px;}

.modal-actions{display:flex;gap:7px;justify-content:flex-end;margin-top:14px;flex-wrap:wrap;}

.modal-actions-split{display:flex;gap:7px;justify-content:space-between;margin-top:14px;flex-wrap:wrap;align-items:center;}

.color-picker{display:flex;gap:6px;flex-wrap:wrap;}

.color-swatch{width:19px;height:19px;border-radius:50%;cursor:pointer;border:2px solid transparent;transition:transform 0.15s;}

.color-swatch:hover{transform:scale(1.2);}

.color-swatch.selected{border-color:#fff;box-shadow:0 0 0 2px rgba(255,255,255,0.25);}

.confirm-modal{background:var(--bg2);border:1px solid var(--border2);border-radius:14px;padding:20px;width:320px;max-width:94vw;animation:modalIn 0.2s cubic-bezier(.34,1.56,.64,1);}

.confirm-title{font-weight:600;font-size:14px;margin-bottom:6px;}

.confirm-desc{font-size:12px;color:var(--text2);margin-bottom:16px;line-height:1.5;}

.tags-input-wrap{display:flex;flex-wrap:wrap;gap:4px;padding:5px 7px;background:var(--bg3);border:1px solid var(--border2);border-radius:var(--radius-sm);min-height:34px;cursor:text;}

.tags-input-wrap:focus-within{border-color:rgba(108,142,255,0.5);}

.tag{display:inline-flex;align-items:center;gap:3px;padding:2px 7px;background:var(--accent-bg);color:var(--accent);border-radius:20px;font-size:10px;font-weight:500;}

.tag-remove{cursor:pointer;opacity:0.6;} .tag-remove:hover{opacity:1;}

.tags-input{border:none;background:transparent;color:var(--text);font-family:var(--font);font-size:11.5px;outline:none;flex:1;min-width:70px;}

.autocomplete-wrap{position:relative;}

.autocomplete-list{position:absolute;background:var(--bg2);border:1px solid var(--border2);border-radius:var(--radius-sm);max-height:140px;overflow-y:auto;z-index:220;width:100%;top:calc(100% + 3px);left:0;box-shadow:var(--shadow);}

.autocomplete-item{padding:6px 10px;font-size:11.5px;cursor:pointer;}

.autocomplete-item:hover{background:var(--bg3);}

.dashboard-report-card{background:var(--bg2);border:1px solid var(--border);border-radius:var(--radius);padding:14px 16px;margin-bottom:10px;}

.report-row{display:flex;align-items:center;justify-content:space-between;padding:5px 0;border-bottom:1px solid var(--border);font-size:11.5px;}

.report-row:last-child{border-bottom:none;}

.report-label{color:var(--text2);}

.report-val{font-family:var(--mono);color:var(--text);font-weight:500;}


/* ══ RESPONSIVE ══ */

@media(max-width:760px){

  .sidebar{width:46px;}

  .sidebar-logo .logo-text,.nav-section,.user-info,.user-pill-right,.nav-item span{display:none;}

  .sidebar-logo{padding:12px 7px;justify-content:center;}

  .logo-icon{margin:0 auto;}

  .nav-item{padding:10px;justify-content:center;margin:1px 3px;}

  .page-body{padding:10px 10px 30px;}

  .page-header{padding:14px 10px 0;}

  .grid-4{grid-template-columns:1fr 1fr;}

  .grid-3{grid-template-columns:1fr 1fr;}

  .grid-2{grid-template-columns:1fr;}

}

</style>

</head>

<body>


<!-- ══ SIDEBAR ══ -->

<nav class="sidebar">

  <div class="sidebar-logo">

    <svg class="logo-icon" viewBox="0 0 30 30" xmlns="http://www.w3.org/2000/svg">

      <rect width="30" height="30" rx="8" fill="#6c8eff"/>

      <path d="M7 10h16M7 15h10M7 20h13" stroke="white" stroke-width="2" stroke-linecap="round"/>

      <circle cx="23" cy="20" r="4" fill="#4ade80"/>

      <path d="M21.5 20l1 1 2-2" stroke="white" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/>

    </svg>

    <div class="logo-text">

      <div class="wordmark">StudyBuddy</div>

      <div class="tagline">AI Academic Advisor</div>

    </div>

  </div>


  <div class="nav-section">Overview</div>

  <div class="nav-item active" onclick="nav('dashboard')"><svg class="icon" viewBox="0 0 16 16" fill="currentColor"><path d="M2 2h5v5H2V2zm7 0h5v5H9V2zm-7 7h5v5H2V9zm7 0h5v5H9V9z"/></svg><span>Dashboard</span></div>

  <div class="nav-item" onclick="nav('programs')"><svg class="icon" viewBox="0 0 16 16" fill="currentColor"><path d="M1 2a1 1 0 011-1h2a1 1 0 011 1v2a1 1 0 01-1 1H2a1 1 0 01-1-1V2zm5 0a1 1 0 011-1h2a1 1 0 011 1v2a1 1 0 01-1 1H7a1 1 0 01-1-1V2zm5 0a1 1 0 011-1h2a1 1 0 011 1v2a1 1 0 01-1 1h-2a1 1 0 01-1-1V2zM1 7a1 1 0 011-1h2a1 1 0 011 1v2a1 1 0 01-1 1H2a1 1 0 01-1-1V7zm5 0a1 1 0 011-1h2a1 1 0 011 1v2a1 1 0 01-1 1H7a1 1 0 01-1-1V7zm5 0a1 1 0 011-1h2a1 1 0 011 1v2a1 1 0 01-1 1h-2a1 1 0 01-1-1V7zM1 12a1 1 0 011-1h2a1 1 0 011 1v2a1 1 0 01-1 1H2a1 1 0 01-1-1v-2zm5 0a1 1 0 011-1h2a1 1 0 011 1v2a1 1 0 01-1 1H7a1 1 0 01-1-1v-2zm5 0a1 1 0 011-1h2a1 1 0 011 1v2a1 1 0 01-1 1h-2a1 1 0 01-1-1v-2z"/></svg><span>Programs</span></div>

  <div class="nav-item" onclick="nav('courses')"><svg class="icon" viewBox="0 0 16 16" fill="currentColor"><path d="M1 2.5A1.5 1.5 0 012.5 1h3A1.5 1.5 0 017 2.5v3A1.5 1.5 0 015.5 7h-3A1.5 1.5 0 011 5.5v-3zm8 0A1.5 1.5 0 0110.5 1h3A1.5 1.5 0 0115 2.5v3A1.5 1.5 0 0113.5 7h-3A1.5 1.5 0 019 5.5v-3zm-8 8A1.5 1.5 0 012.5 9h3A1.5 1.5 0 017 10.5v3A1.5 1.5 0 015.5 15h-3A1.5 1.5 0 011 13.5v-3zm8 0A1.5 1.5 0 0110.5 9h3a1.5 1.5 0 011.5 1.5v3a1.5 1.5 0 01-1.5 1.5h-3A1.5 1.5 0 019 13.5v-3z"/></svg><span>Courses</span></div>

  <div class="nav-item" onclick="nav('assignments')"><svg class="icon" viewBox="0 0 16 16" fill="currentColor"><path d="M3 0h10a2 2 0 012 2v12a2 2 0 01-2 2H3a2 2 0 01-2-2V2a2 2 0 012-2zm0 1a1 1 0 00-1 1v12a1 1 0 001 1h10a1 1 0 001-1V2a1 1 0 00-1-1H3z"/><path d="M5.5 5h5a.5.5 0 000-1h-5a.5.5 0 000 1zm0 3h5a.5.5 0 000-1h-5a.5.5 0 000 1zm0 3h3a.5.5 0 000-1h-3a.5.5 0 000 1z"/></svg><span>Assignments</span></div>


  <div class="nav-section">Tools</div>

  <div class="nav-item" onclick="nav('timer')"><svg class="icon" viewBox="0 0 16 16" fill="currentColor"><path d="M8 3.5a.5.5 0 00-1 0V9a.5.5 0 00.252.434l3.5 2a.5.5 0 00.496-.868L8 8.71V3.5z"/><path d="M8 16A8 8 0 108 0a8 8 0 000 16z"/></svg><span>Study Timer</span></div>

  <div class="nav-item" onclick="nav('tasks')"><svg class="icon" viewBox="0 0 16 16" fill="currentColor"><path d="M14 1a1 1 0 011 1v12a1 1 0 01-1 1H2a1 1 0 01-1-1V2a1 1 0 011-1h12zM2 0a2 2 0 00-2 2v12a2 2 0 002 2h12a2 2 0 002-2V2a2 2 0 00-2-2H2z"/><path d="M10.97 4.97a.75.75 0 010 1.06l-3.5 3.5a.75.75 0 01-1.06 0l-1.5-1.5a.75.75 0 011.06-1.06l.97.97 2.97-2.97a.75.75 0 011.06 0z"/></svg><span>Tasks</span></div>

  <div class="nav-item" onclick="nav('resources')"><svg class="icon" viewBox="0 0 16 16" fill="currentColor"><path d="M1 2.5A1.5 1.5 0 012.5 1h11A1.5 1.5 0 0115 2.5v1A1.5 1.5 0 0113.5 5h-11A1.5 1.5 0 011 3.5v-1zM1 7.5A1.5 1.5 0 012.5 6h11A1.5 1.5 0 0115 7.5v1A1.5 1.5 0 0113.5 10h-11A1.5 1.5 0 011 8.5v-1zm0 5A1.5 1.5 0 012.5 11h11a1.5 1.5 0 011.5 1.5v1a1.5 1.5 0 01-1.5 1.5h-11A1.5 1.5 0 011 13.5v-1z"/></svg><span>Resources</span></div>

  <div class="nav-item" onclick="nav('chat')"><svg class="icon" viewBox="0 0 16 16" fill="currentColor"><path d="M14 1a1 1 0 011 1v8a1 1 0 01-1 1H4.414A2 2 0 003 11.586l-2 2V2a1 1 0 011-1h12z"/></svg><span>Lyra AI</span></div>

  <div class="nav-item" onclick="nav('contacts')"><svg class="icon" viewBox="0 0 16 16" fill="currentColor"><path d="M7 14s-1 0-1-1 1-4 5-4 5 3 5 4-1 1-1 1H7zm4-6a3 3 0 100-6 3 3 0 000 6z"/><path fill-rule="evenodd" d="M5.216 14A2.238 2.238 0 015 13c0-1.355.68-2.75 1.936-3.72A6.325 6.325 0 005 9c-4 0-5 3-5 4s1 1 1 1h4.216z"/><path d="M4.5 8a2.5 2.5 0 100-5 2.5 2.5 0 000 5z"/></svg><span>Contacts</span></div>

  <div class="nav-item" onclick="nav('insights')"><svg class="icon" viewBox="0 0 16 16" fill="currentColor"><path d="M8 16a2 2 0 002-2H6a2 2 0 002 2zm.995-14.901a1 1 0 10-1.99 0A5.002 5.002 0 003 6c0 1.098-.5 6-2 7h14c-1.5-1-2-5.902-2-7 0-2.42-1.72-4.44-4.005-4.901z"/></svg><span>Insights</span><span class="nav-badge" id="insights-badge">3</span></div>


  <div class="sidebar-bottom">

    <div class="user-pill" onclick="openSettings()">

      <div class="avatar">JD</div>

      <div class="user-info"><div class="name">Jamie Davis</div><div class="plan">Free plan</div></div>

      <span class="user-pill-right">⚙</span>

    </div>

  </div>

</nav>


<!-- ══ MAIN ══ -->

<div class="main">


<!-- DASHBOARD -->

<div id="page-dashboard" class="page active">

  <div class="page-header">

    <div><div class="page-title" id="dash-greeting">Good evening, Jamie 👋</div><div class="page-sub">Spring 2026 · Week 9 of 16</div></div>

    <button class="btn btn-primary btn-sm" onclick="openCourseModal()">+ Add Course</button>

  </div>

  <div class="page-body">

    <div id="dash-stats-row" style="margin-bottom:16px"></div>

    <div class="grid-2" style="gap:16px" id="dash-main-grid">

      <div>

        <div class="section-header"><div class="section-title">Current Courses</div><button class="btn btn-ghost btn-sm" onclick="nav('courses')">View all</button></div>

        <div id="dash-courses"></div>

      </div>

      <div>

        <div class="section-header"><div class="section-title">⚡ Active Flags</div><button class="btn btn-ghost btn-sm" onclick="nav('insights')">All flags</button></div>

        <div id="dash-flags"></div>

        <div class="divider"></div>

        <div class="section-header"><div class="section-title">Upcoming Deadlines</div></div>

        <div class="card card-sm" id="dash-upcoming"></div>

      </div>

    </div>

    <!-- Reports row -->

    <div id="dash-reports" style="margin-top:16px"></div>

  </div>

</div>


<!-- PROGRAMS -->

<div id="page-programs" class="page">

  <div class="page-header">

    <div><div class="page-title">Programs</div><div class="page-sub">Degree programs, certificates, and short courses</div></div>

    <button class="btn btn-primary" onclick="openProgramModal()">+ Add Program</button>

  </div>

  <div class="page-body"><div class="grid-2" id="programs-grid"></div></div>

</div>


<!-- COURSES -->

<div id="page-courses" class="page">

  <div class="page-header">

    <div><div class="page-title">Courses</div><div class="page-sub" id="courses-sub">All courses</div></div>

    <button class="btn btn-primary" onclick="openCourseModal()">+ Add Course</button>

  </div>

  <div class="page-body"><div class="grid-2" id="courses-grid"></div></div>

</div>


<!-- ASSIGNMENTS -->

<div id="page-assignments" class="page">

  <div class="page-header">

    <div><div class="page-title">Assignments</div><div class="page-sub">All tasks across your courses</div></div>

    <button class="btn btn-primary" onclick="openAssignmentModal()">+ Add Assignment</button>

  </div>

  <div class="page-body">

    <div style="display:flex;gap:5px;margin-bottom:11px;flex-wrap:wrap" id="filter-bar">

      <button class="btn btn-ghost btn-sm filter-btn active" data-filter="all">All</button>

      <button class="btn btn-ghost btn-sm filter-btn" data-filter="pending">Pending</button>

      <button class="btn btn-ghost btn-sm filter-btn" data-filter="done">Completed</button>

      <button class="btn btn-ghost btn-sm filter-btn" data-filter="overdue">Overdue</button>

    </div>

    <div class="card" style="padding:0;overflow:hidden">

      <table class="asgn-table">

        <thead><tr><th>Assignment</th><th>Course</th><th>Type</th><th>Due</th><th>Weight</th><th>Score</th><th>Status</th><th>Time</th><th></th></tr></thead>

        <tbody id="asgn-tbody"></tbody>

      </table>

    </div>

  </div>

</div>


<!-- TIMER -->

<div id="page-timer" class="page">

  <div class="page-header"><div><div class="page-title">Study Timer</div><div class="page-sub">Track sessions and build habits</div></div></div>

  <div class="page-body">

    <div style="display:flex;gap:22px;flex-wrap:wrap;align-items:flex-start">

      <div class="timer-wrap" style="flex:0 0 auto">

        <div class="form-row" style="width:260px;margin-bottom:9px">

          <select class="form-select" id="timer-course-select" onchange="loadTimerAssignments()"><option value="">Select course...</option></select>

          <select class="form-select" id="timer-asgn-select"><option value="">Link assignment...</option></select>

        </div>

        <input class="form-input" id="timer-session-label" placeholder="Session label (optional)" style="width:260px;margin-bottom:9px"/>

        <div class="timer-ring">

          <svg width="190" height="190" viewBox="0 0 190 190"><circle class="ring-bg" cx="95" cy="95" r="83"/><circle class="ring-fg" id="timer-ring-fg" cx="95" cy="95" r="83" stroke-dasharray="521.5" stroke-dashoffset="0"/></svg>

          <div class="timer-display"><div class="timer-time" id="timer-display">25:00</div><div class="timer-label" id="timer-label">Focus session</div></div>

        </div>

        <div class="timer-controls">

          <button class="timer-btn timer-btn-ghost" title="Reset" onclick="resetTimer()">↺</button>

          <button class="timer-btn timer-btn-primary" id="timer-toggle" onclick="toggleTimer()">▶</button>

          <button class="timer-btn timer-btn-ghost" title="Skip" onclick="skipTimer()">⏭</button>

        </div>

        <div class="timer-presets">

          <button class="btn btn-ghost btn-sm" onclick="setTimer(25,'Focus session')">25 min</button>

          <button class="btn btn-ghost btn-sm" onclick="setTimer(50,'Deep work')">50 min</button>

          <button class="btn btn-ghost btn-sm" onclick="setTimer(5,'Short break')">5 min</button>

          <button class="btn btn-ghost btn-sm" onclick="setTimer(15,'Long break')">15 min</button>

        </div>

        <div class="custom-row">

          <input class="form-input" type="number" id="custom-mins" placeholder="45" min="1" max="360" style="width:54px;text-align:center"/>

          <span style="font-size:11px;color:var(--text3)">min</span>

          <input class="form-input" type="text" id="custom-label-inp" placeholder="label" style="width:90px"/>

          <button class="btn btn-ghost btn-sm" onclick="setCustomTimer()">Set</button>

        </div>

        <label style="font-size:11px;color:var(--text2);margin-top:8px;display:flex;align-items:center;gap:5px;cursor:pointer"><input type="checkbox" id="timer-sound-on" checked/> Sound on complete</label>

      </div>

      <div style="flex:1;min-width:220px;padding-top:2px">

        <div class="section-title" style="margin-bottom:9px">Recent Sessions</div>

        <div id="session-log-list" style="margin-bottom:12px"></div>

        <div class="divider"></div>

        <div class="section-title" style="margin-bottom:9px">This Week</div>

        <div class="grid-2" style="gap:7px" id="timer-stats"></div>

      </div>

    </div>

  </div>

</div>


<!-- TASKS -->

<div id="page-tasks" class="page">

  <div class="page-header">

    <div><div class="page-title">Task List</div><div class="page-sub">Personal to-dos and reminders</div></div>

    <div style="display:flex;gap:7px">

      <label style="display:flex;align-items:center;gap:5px;font-size:12px;color:var(--text2);cursor:pointer;padding:6px 10px;border:1px solid var(--border2);border-radius:var(--radius-sm)">

        <input type="checkbox" id="show-completed-toggle" onchange="renderTasks()"/> Show completed

      </label>

      <button class="btn btn-primary" onclick="openTaskModal()">+ Add Task</button>

    </div>

  </div>

  <div class="page-body">

    <div style="display:flex;gap:5px;margin-bottom:11px;flex-wrap:wrap" id="task-filter-bar">

      <button class="btn btn-ghost btn-sm task-filter-btn active" data-tf="all">All</button>

      <button class="btn btn-ghost btn-sm task-filter-btn" data-tf="pending">Pending</button>

      <button class="btn btn-ghost btn-sm task-filter-btn" data-tf="high">High Priority</button>

    </div>

    <div class="card" style="padding:0;overflow:hidden" id="task-list"></div>

  </div>

</div>


<!-- RESOURCES -->

<div id="page-resources" class="page">

  <div class="page-header">

    <div><div class="page-title">Resources</div><div class="page-sub">Textbooks, links, tools — linked to your courses</div></div>

    <button class="btn btn-primary" onclick="openResourceModal()">+ Add Resource</button>

  </div>

  <div class="page-body">

    <div style="display:flex;gap:5px;margin-bottom:11px;flex-wrap:wrap" id="res-filter-bar">

      <button class="btn btn-ghost btn-sm res-filter-btn active" data-rf="all">All</button>

      <button class="btn btn-ghost btn-sm res-filter-btn" data-rf="Book">Books</button>

      <button class="btn btn-ghost btn-sm res-filter-btn" data-rf="Link">Links</button>

      <button class="btn btn-ghost btn-sm res-filter-btn" data-rf="Tool">Tools</button>

      <button class="btn btn-ghost btn-sm res-filter-btn" data-rf="needed">Needed</button>

    </div>

    <div id="resources-needed-list"></div>

    <div id="resources-obtained-section" style="display:none">

      <div class="obtained-divider"><div class="obtained-divider-label">✓ Obtained</div><div class="obtained-divider-line"></div></div>

      <div id="resources-obtained-list"></div>

    </div>

  </div>

</div>


<!-- AI CHAT — Lyra -->

<div id="page-chat" class="page">

  <div class="chat-layout">

    <div class="chat-header">

      <div class="chat-avatar-wrap"><div class="chat-avatar">✦</div><div class="chat-online-dot"></div></div>

      <div class="chat-info"><div class="name">Lyra <span style="font-size:10px;color:var(--text3);font-weight:400">by StudyBuddy</span></div><div class="status">● Online · knows your academic profile</div></div>

      <button class="btn btn-ghost btn-sm" style="margin-left:auto" onclick="clearChat()">Clear</button>

    </div>

    <div class="chat-messages" id="chat-messages"></div>

    <div class="quick-prompts" id="quick-prompts">

      <div class="quick-chip" onclick="sendQuick(this)">What grade am I likely to get in Statistics?</div>

      <div class="quick-chip" onclick="sendQuick(this)">Which course needs most attention?</div>

      <div class="quick-chip" onclick="sendQuick(this)">Build me a study schedule for this week</div>

      <div class="quick-chip" onclick="sendQuick(this)">Am I on track for my GPA target?</div>

    </div>

    <div class="chat-input-wrap">

      <textarea class="chat-input" id="chat-input" rows="1" placeholder="Ask Lyra anything..." onkeydown="handleChatKey(event)"></textarea>

      <button class="send-btn" onclick="sendChat()"><svg width="13" height="13" viewBox="0 0 16 16" fill="currentColor"><path d="M15.854.146a.5.5 0 01.11.54l-5.819 14.547a.75.75 0 01-1.329.124l-3.178-4.995L.643 7.184a.75.75 0 01.124-1.33L15.314.037a.5.5 0 01.54.11z"/></svg></button>

    </div>

  </div>

</div>


<!-- CONTACTS -->

<div id="page-contacts" class="page">

  <div class="page-header">

    <div><div class="page-title">Contacts</div><div class="page-sub">Professors, TAs, and group members</div></div>

    <button class="btn btn-primary" onclick="openContactModal()">+ Add Contact</button>

  </div>

  <div class="page-body">

    <div style="display:flex;gap:5px;margin-bottom:11px;flex-wrap:wrap" id="contact-filter-bar">

      <button class="btn btn-ghost btn-sm contact-filter-btn active" data-cf="all">All</button>

      <button class="btn btn-ghost btn-sm contact-filter-btn" data-cf="professor">Professors</button>

      <button class="btn btn-ghost btn-sm contact-filter-btn" data-cf="ta">TAs</button>

      <button class="btn btn-ghost btn-sm contact-filter-btn" data-cf="member">Group Members</button>

    </div>

    <div class="card" style="padding:0;overflow:hidden" id="contacts-list"></div>

  </div>

</div>


<!-- INSIGHTS -->

<div id="page-insights" class="page">

  <div class="page-header"><div><div class="page-title">Insights & Flags</div><div class="page-sub">AI-generated alerts and academic intelligence</div></div></div>

  <div class="page-body" id="insights-body"></div>

</div>


</div><!-- /.main -->


<!-- ══ MODALS ══ -->


<!-- Program modal -->

<div class="modal-overlay" id="modal-program"><div class="modal">

  <div class="modal-title" id="prog-modal-title">Add Program</div>

  <input type="hidden" id="ep-id"/>

  <div class="form-group"><label class="form-label">Program Name</label><input class="form-input" id="fp-name" placeholder="e.g. BSc Computer Science"/></div>

  <div class="form-row">

    <div class="form-group"><label class="form-label">Institution</label><input class="form-input" id="fp-institution" placeholder="University name"/></div>

    <div class="form-group"><label class="form-label">Type</label><select class="form-select" id="fp-type"><option>Degree</option><option>Certificate</option><option>Short Course</option><option>Bootcamp</option><option>Self-study</option></select></div>

  </div>

  <div class="form-row">

    <div class="form-group"><label class="form-label">Start Year</label><select class="form-select" id="fp-start"></select></div>

    <div class="form-group"><label class="form-label">End Year (expected)</label><select class="form-select" id="fp-end"></select></div>

  </div>

  <div class="form-group"><label class="form-label">Color</label><div class="color-picker" id="prog-color-picker">

    <div class="color-swatch selected" data-color="#6c8eff" style="background:#6c8eff"></div>

    <div class="color-swatch" data-color="#4ade80" style="background:#4ade80"></div>

    <div class="color-swatch" data-color="#fbbf24" style="background:#fbbf24"></div>

    <div class="color-swatch" data-color="#f87171" style="background:#f87171"></div>

    <div class="color-swatch" data-color="#c084fc" style="background:#c084fc"></div>

    <div class="color-swatch" data-color="#2dd4bf" style="background:#2dd4bf"></div>

  </div></div>

  <div class="modal-actions-split">

    <button class="btn btn-danger btn-sm" id="del-prog-btn" onclick="confirmDeleteProgram()" style="display:none">🗑 Delete</button>

    <div style="display:flex;gap:7px;margin-left:auto">

      <button class="btn btn-ghost" onclick="closeModal('program')">Cancel</button>

      <button class="btn btn-primary" onclick="saveProgram()" id="prog-save-btn">Add Program</button>

    </div>

  </div>

</div></div>


<!-- Course modal -->

<div class="modal-overlay" id="modal-course"><div class="modal">

  <div class="modal-title" id="course-modal-title">Add Course</div>

  <input type="hidden" id="ec-id"/>

  <div class="form-group"><label class="form-label">Course Name</label><input class="form-input" id="fc-name" placeholder="e.g. Introduction to Statistics"/></div>

  <div class="form-row">

    <div class="form-group"><label class="form-label">Course Code</label><input class="form-input" id="fc-code" placeholder="STAT 301"/></div>

    <div class="form-group"><label class="form-label">Credits</label><input class="form-input" type="number" id="fc-credits" placeholder="3"/></div>

  </div>

  <div class="form-row">

    <div class="form-group"><label class="form-label">Target Grade %</label><input class="form-input" type="number" id="fc-target" placeholder="85"/></div>

    <div class="form-group"><label class="form-label">Difficulty (1–5)</label><select class="form-select" id="fc-difficulty"><option value="1">1 — Easy</option><option value="2">2</option><option value="3" selected>3 — Medium</option><option value="4">4</option><option value="5">5 — Hard</option></select></div>

  </div>

  <div class="form-row">

    <div class="form-group"><label class="form-label">Term</label><select class="form-select" id="fc-term"><option>Fall</option><option>Winter</option><option selected>Spring</option><option>Summer</option><option>Semester 1</option><option>Semester 2</option><option>Trimester 1</option><option>Trimester 2</option><option>Trimester 3</option></select></div>

    <div class="form-group"><label class="form-label">Year</label><select class="form-select" id="fc-year"></select></div>

  </div>

  <div class="form-group"><label class="form-label">Program (optional)</label><select class="form-select" id="fc-program"><option value="">— None —</option></select></div>

  <div class="form-group"><label class="form-label">Professor</label>

    <div class="autocomplete-wrap"><input class="form-input" id="fc-professor" placeholder="Prof. Smith" autocomplete="off" oninput="acFilter('professor',this.value)"/><div class="autocomplete-list" id="ac-professor" style="display:none"></div></div>

  </div>

  <div class="form-group"><label class="form-label">Teaching Assistant (optional)</label>

    <div class="autocomplete-wrap"><input class="form-input" id="fc-ta" placeholder="TA name" autocomplete="off" oninput="acFilter('ta',this.value)"/><div class="autocomplete-list" id="ac-ta" style="display:none"></div></div>

  </div>

  <div class="form-group"><label class="form-label">Color</label><div class="color-picker" id="color-picker">

    <div class="color-swatch selected" data-color="#6c8eff" style="background:#6c8eff"></div>

    <div class="color-swatch" data-color="#4ade80" style="background:#4ade80"></div>

    <div class="color-swatch" data-color="#fbbf24" style="background:#fbbf24"></div>

    <div class="color-swatch" data-color="#f87171" style="background:#f87171"></div>

    <div class="color-swatch" data-color="#c084fc" style="background:#c084fc"></div>

    <div class="color-swatch" data-color="#2dd4bf" style="background:#2dd4bf"></div>

    <div class="color-swatch" data-color="#fb923c" style="background:#fb923c"></div>

  </div></div>

  <div class="modal-actions-split">

    <button class="btn btn-danger btn-sm" id="del-course-btn" onclick="confirmDeleteCourse()" style="display:none">🗑 Delete</button>

    <div style="display:flex;gap:7px;margin-left:auto"><button class="btn btn-ghost" onclick="closeModal('course')">Cancel</button><button class="btn btn-primary" onclick="saveCourse()" id="course-save-btn">Add Course</button></div>

  </div>

</div></div>


<!-- Assignment modal -->

<div class="modal-overlay" id="modal-assignment"><div class="modal">

  <div class="modal-title" id="asgn-modal-title">Add Assignment</div>

  <input type="hidden" id="ea-id"/>

  <div class="form-group"><label class="form-label">Title</label><input class="form-input" id="fa-title" placeholder="e.g. Midterm Exam"/></div>

  <div class="form-row">

    <div class="form-group"><label class="form-label">Course</label><select class="form-select" id="fa-course" onchange="loadAsgnProgramTask()"></select></div>

    <div class="form-group"><label class="form-label">Type</label><select class="form-select" id="fa-type"><option>Exam</option><option>Essay</option><option>Homework</option><option>Quiz</option><option>Project</option><option>Lab</option></select></div>

  </div>

  <div class="form-group"><label class="form-label">Program Task (optional)</label><select class="form-select" id="fa-program-task"><option value="">— None —</option></select></div>

  <div class="form-row">

    <div class="form-group"><label class="form-label">Due Date <span style="color:var(--red)">*</span></label><input class="form-input" type="date" id="fa-due"/></div>

    <div class="form-group"><label class="form-label">Weight (%)</label><input class="form-input" type="number" id="fa-weight" placeholder="20"/></div>

  </div>

  <div class="form-row">

    <div class="form-group"><label class="form-label">Score Achieved</label><input class="form-input" type="number" id="fa-score" placeholder="Blank if not graded"/></div>

    <div class="form-group"><label class="form-label">Score Possible</label><input class="form-input" type="number" id="fa-possible" placeholder="100"/></div>

  </div>

  <div class="form-row">

    <div class="form-group"><label class="form-label">Status</label><select class="form-select" id="fa-status"><option value="pending">Pending</option><option value="done">Done</option></select></div>

    <div class="form-group"><label class="form-label">Assignment Type</label><select class="form-select" id="fa-group-type"><option value="individual">Individual</option><option value="group">Group</option></select></div>

  </div>

  <div class="form-group"><label class="form-label">Notes (optional)</label><input class="form-input" id="fa-notes" placeholder="Any notes..."/></div>

  <div class="modal-actions-split">

    <button class="btn btn-danger btn-sm" id="del-asgn-btn" onclick="confirmDeleteAssignmentById(null,true)" style="display:none">🗑 Delete</button>

    <div style="display:flex;gap:7px;margin-left:auto"><button class="btn btn-ghost" onclick="closeModal('assignment')">Cancel</button><button class="btn btn-primary" onclick="saveAssignment()" id="asgn-save-btn">Add Assignment</button></div>

  </div>

</div></div>


<!-- Extend due date -->

<div class="modal-overlay" id="modal-extend"><div class="modal modal-sm">

  <div class="modal-title">Extend Due Date</div>

  <input type="hidden" id="extend-id"/>

  <div class="form-group"><label class="form-label">Assignment</label><div id="extend-title-display" style="font-weight:500;font-size:12.5px;padding:5px 0"></div></div>

  <div class="form-group"><label class="form-label">New Due Date</label><input class="form-input" type="date" id="extend-date"/></div>

  <div class="form-group"><label class="form-label">Reason (optional)</label><input class="form-input" id="extend-reason" placeholder="e.g. Extension approved by professor"/></div>

  <div class="modal-actions"><button class="btn btn-ghost" onclick="closeModal('extend')">Cancel</button><button class="btn btn-primary" onclick="saveExtend()">Save</button></div>

</div></div>


<!-- Task modal -->

<div class="modal-overlay" id="modal-task"><div class="modal modal-sm">

  <div class="modal-title" id="task-modal-title">Add Task</div>

  <input type="hidden" id="et-id"/>

  <div class="form-group"><label class="form-label">Task</label><input class="form-input" id="ft-title" placeholder="e.g. Review lecture notes"/></div>

  <div class="form-row">

    <div class="form-group"><label class="form-label">Due Date</label><input class="form-input" type="date" id="ft-due"/></div>

    <div class="form-group"><label class="form-label">Priority</label><select class="form-select" id="ft-priority"><option value="low">Low</option><option value="medium" selected>Medium</option><option value="high">High</option></select></div>

  </div>

  <div class="form-group"><label class="form-label">Link to Course</label><select class="form-select" id="ft-course"><option value="">— None —</option></select></div>

  <div class="form-group"><label class="form-label">Notes</label><input class="form-input" id="ft-notes" placeholder="optional"/></div>

  <div class="modal-actions-split">

    <button class="btn btn-danger btn-sm" id="del-task-btn" onclick="confirmDeleteTask()" style="display:none">🗑 Delete</button>

    <div style="display:flex;gap:7px;margin-left:auto"><button class="btn btn-ghost" onclick="closeModal('task')">Cancel</button><button class="btn btn-primary" onclick="saveTask()" id="task-save-btn">Add Task</button></div>

  </div>

</div></div>


<!-- Resource modal -->

<div class="modal-overlay" id="modal-resource"><div class="modal">

  <div class="modal-title" id="res-modal-title">Add Resource</div>

  <input type="hidden" id="er-id"/>

  <div class="form-group"><label class="form-label">Title / Name</label><input class="form-input" id="fr-title" placeholder="e.g. Organic Chemistry by Clayden"/></div>

  <div class="form-row">

    <div class="form-group"><label class="form-label">Type</label><select class="form-select" id="fr-type"><option>Book</option><option>Link</option><option>Tool</option><option>Note</option><option>Video</option><option>Other</option></select></div>

    <div class="form-group"><label class="form-label">Status</label><select class="form-select" id="fr-status"><option value="needed">Needed</option><option value="pending">Ordered / Pending</option><option value="obtained">Obtained</option></select></div>

  </div>

  <div class="form-group"><label class="form-label">URL / Link</label><input class="form-input" id="fr-url" placeholder="https://..."/></div>

  <div class="form-row">

    <div class="form-group"><label class="form-label">Course</label><select class="form-select" id="fr-course" onchange="loadResAssignments()"><option value="">— None —</option></select></div>

    <div class="form-group"><label class="form-label">Assignment</label><select class="form-select" id="fr-assignment"><option value="">— None —</option></select></div>

  </div>

  <div class="form-group"><label class="form-label">Notes</label><input class="form-input" id="fr-notes" placeholder="ISBN, cost, notes..."/></div>

  <div class="modal-actions-split">

    <button class="btn btn-danger btn-sm" id="del-res-btn" onclick="confirmDeleteResource()" style="display:none">🗑 Delete</button>

    <div style="display:flex;gap:7px;margin-left:auto"><button class="btn btn-ghost" onclick="closeModal('resource')">Cancel</button><button class="btn btn-primary" onclick="saveResource()" id="res-save-btn">Add Resource</button></div>

  </div>

</div></div>


<!-- Contact modal -->

<div class="modal-overlay" id="modal-contact"><div class="modal modal-sm">

  <div class="modal-title" id="contact-modal-title">Add Contact</div>

  <input type="hidden" id="econ-id"/>

  <div class="form-group"><label class="form-label">Name</label><input class="form-input" id="fcon-name" placeholder="Full name"/></div>

  <div class="form-row">

    <div class="form-group"><label class="form-label">Role</label><select class="form-select" id="fcon-role"><option value="professor">Professor</option><option value="ta">Teaching Assistant</option><option value="member">Group Member</option><option value="other">Other</option></select></div>

    <div class="form-group"><label class="form-label">Email</label><input class="form-input" id="fcon-email" placeholder="email@uni.edu"/></div>

  </div>

  <div class="form-group"><label class="form-label">Department / Notes</label><input class="form-input" id="fcon-notes" placeholder="e.g. Statistics Dept."/></div>

  <div class="modal-actions-split">

    <button class="btn btn-danger btn-sm" id="del-contact-btn" onclick="confirmDeleteContact()" style="display:none">🗑 Delete</button>

    <div style="display:flex;gap:7px;margin-left:auto"><button class="btn btn-ghost" onclick="closeModal('contact')">Cancel</button><button class="btn btn-primary" onclick="saveContact()" id="contact-save-btn">Add Contact</button></div>

  </div>

</div></div>


<!-- Confirm modal -->

<div class="modal-overlay" id="modal-confirm"><div class="confirm-modal">

  <div class="confirm-title" id="confirm-title">Delete?</div>

  <div class="confirm-desc" id="confirm-desc">This cannot be undone.</div>

  <div style="display:flex;gap:7px;justify-content:flex-end"><button class="btn btn-ghost" onclick="closeModal('confirm')">Cancel</button><button class="btn btn-danger" id="confirm-ok">Delete</button></div>

</div></div>


<!-- Settings panel -->

<div class="settings-overlay" id="settings-overlay">

  <div class="settings-backdrop" onclick="closeSettings()"></div>

  <div class="settings-panel">

    <div class="settings-header">

      <div>

        <div class="settings-title">Settings</div>

        <div style="font-size:11px;color:var(--text3);margin-top:2px">Jamie Davis · Free plan</div>

      </div>

      <button class="btn-icon" onclick="closeSettings()">✕</button>

    </div>

    <div class="settings-body">

      <div class="settings-section">

        <div class="settings-section-title">Appearance</div>

        <div class="settings-row">

          <div><div class="settings-row-label">Dark Mode</div><div class="settings-row-sub">Switch between dark and light theme</div></div>

          <label class="toggle-switch"><input type="checkbox" id="settings-dark-toggle" onchange="toggleThemeFromSettings(this)"/><div class="toggle-track"></div></label>

        </div>

      </div>

      <div class="settings-section">

        <div class="settings-section-title">Study Goals</div>

        <div class="form-group">

          <label class="form-label">Weekly study goal (hours)</label>

          <input class="form-input" type="number" id="settings-study-goal" placeholder="18" min="1" max="100" onchange="saveStudyGoal(this.value)"/>

        </div>

        <div class="form-group">

          <label class="form-label">GPA target</label>

          <input class="form-input" type="number" id="settings-gpa-target" placeholder="3.7" min="0" max="4" step="0.1" onchange="saveGpaTarget(this.value)"/>

        </div>

      </div>

      <div class="settings-section">

        <div class="settings-section-title">Dashboard Widgets</div>

        <div style="font-size:11px;color:var(--text3);margin-bottom:9px">Toggle which cards appear on your dashboard</div>

        <div id="widget-toggles"></div>

      </div>

      <div class="settings-section">

        <div class="settings-section-title">Notifications</div>

        <div class="settings-row">

          <div><div class="settings-row-label">Timer sound alerts</div></div>

          <label class="toggle-switch"><input type="checkbox" id="settings-sound" checked onchange="document.getElementById('timer-sound-on').checked=this.checked"/><div class="toggle-track"></div></label>

        </div>

        <div class="settings-row">

          <div><div class="settings-row-label">Show completed tasks</div></div>

          <label class="toggle-switch"><input type="checkbox" id="settings-show-completed" onchange="syncShowCompleted(this)"/><div class="toggle-track"></div></label>

        </div>

      </div>

      <div class="settings-section">

        <div class="settings-section-title">Account</div>

        <div class="settings-row"><div><div class="settings-row-label">Name</div></div><input class="form-input" value="Jamie Davis" style="width:140px"/></div>

        <div class="settings-row"><div><div class="settings-row-label">Email</div></div><input class="form-input" value="jamie@uni.edu" style="width:160px"/></div>

      </div>

    </div>

  </div>

</div>

<script>

// ══════════════════════════════════════════════════════

//  SETTINGS & THEME

// ══════════════════════════════════════════════════════

const SETTINGS = {

  theme: localStorage.getItem('sb-theme')||'dark',

  studyGoal: parseFloat(localStorage.getItem('sb-study-goal'))||18,

  gpaTarget: parseFloat(localStorage.getItem('sb-gpa-target'))||3.7,

  showCompleted: localStorage.getItem('sb-show-completed')==='true',

  widgets: JSON.parse(localStorage.getItem('sb-widgets')||'null') || {gpa:true,studyhrs:true,assignments:true,flags:true,reports:true},

};

document.documentElement.dataset.theme = SETTINGS.theme;


function toggleTheme(){

  const isDark = document.documentElement.dataset.theme==='dark';

  document.documentElement.dataset.theme = isDark?'light':'dark';

  SETTINGS.theme = document.documentElement.dataset.theme;

  localStorage.setItem('sb-theme',SETTINGS.theme);

  const st=document.getElementById('settings-dark-toggle'); if(st) st.checked=!isDark;

}

function toggleThemeFromSettings(cb){ SETTINGS.theme=cb.checked?'dark':'light'; document.documentElement.dataset.theme=SETTINGS.theme; localStorage.setItem('sb-theme',SETTINGS.theme); }

function saveStudyGoal(v){ SETTINGS.studyGoal=parseFloat(v)||18; localStorage.setItem('sb-study-goal',SETTINGS.studyGoal); renderDashboard(); }

function saveGpaTarget(v){ SETTINGS.gpaTarget=parseFloat(v)||3.7; localStorage.setItem('sb-gpa-target',SETTINGS.gpaTarget); renderDashboard(); }

function syncShowCompleted(cb){ SETTINGS.showCompleted=cb.checked; localStorage.setItem('sb-show-completed',cb.checked); document.getElementById('show-completed-toggle').checked=cb.checked; renderTasks(); }


function openSettings(){

  document.getElementById('settings-overlay').classList.add('open');

  document.getElementById('settings-dark-toggle').checked = SETTINGS.theme==='dark';

  document.getElementById('settings-study-goal').value = SETTINGS.studyGoal;

  document.getElementById('settings-gpa-target').value = SETTINGS.gpaTarget;

  document.getElementById('settings-show-completed').checked = SETTINGS.showCompleted;

  // Widget toggles

  const wt=document.getElementById('widget-toggles');

  const widgets=[

    {key:'gpa',label:'Current GPA'},{key:'studyhrs',label:'Study Hours'},{key:'assignments',label:'Assignments Due'},

    {key:'flags',label:'Active Flags'},{key:'reports',label:'Activity Reports'},

  ];

  wt.innerHTML=widgets.map(w=>`<div class="widget-toggle ${SETTINGS.widgets[w.key]?'on':'off'}" onclick="toggleWidget('${w.key}',this)">

    <span style="font-size:12px">${SETTINGS.widgets[w.key]?'✓':'○'}</span>

    <span class="widget-toggle-label">${w.label}</span>

  </div>`).join('');

}

function closeSettings(){ document.getElementById('settings-overlay').classList.remove('open'); }

function toggleWidget(key,el){

  SETTINGS.widgets[key]=!SETTINGS.widgets[key];

  localStorage.setItem('sb-widgets',JSON.stringify(SETTINGS.widgets));

  el.className='widget-toggle '+(SETTINGS.widgets[key]?'on':'off');

  el.querySelector('span').textContent=SETTINGS.widgets[key]?'✓':'○';

  renderDashboard();

}


// ══════════════════════════════════════════════════════

//  DATA

// ══════════════════════════════════════════════════════

let selectedColor='#6c8eff', selectedProgColor='#6c8eff';

let timerInterval=null,timerRunning=false,timerSeconds=25*60,timerTotal=25*60,timerMode='Focus session',timerStartTime=null;

let activeFilter='all',activeTaskFilter='all',activeResFilter='all',activeContactFilter='all';

let editingCourseId=null,editingAssignmentId=null,editingTaskId=null,editingResourceId=null,editingContactId=null,editingProgramId=null;


const today=new Date();

const fmt=d=>{const x=new Date(d);return x.toISOString().split('T')[0];};

const addDays=n=>{const d=new Date(today);d.setDate(d.getDate()+n);return fmt(d);};

const fmtDuration=mins=>{if(!mins||mins<1)return null;if(mins<60)return `${Math.round(mins)}m`;return `${Math.floor(mins/60)}h ${Math.round(mins%60)}m`;};

const daysDiff=ms=>Math.round((new Date()-new Date(ms))/86400000);


let CONTACTS=[

  {id:1,name:'Prof. Martinez',role:'professor',email:'martinez@uni.edu',notes:'Statistics Dept.'},

  {id:2,name:'Prof. Chen',role:'professor',email:'chen@uni.edu',notes:'Chemistry Dept.'},

  {id:3,name:'Dr. Williams',role:'professor',email:'williams@uni.edu',notes:'History Dept.'},

  {id:4,name:'Alice Nguyen',role:'ta',email:'alice@uni.edu',notes:''},

  {id:5,name:'Bob Okafor',role:'ta',email:'bob@uni.edu',notes:''},

];


let PROGRAMS=[

  {id:1,name:'BSc Data Science',institution:'State University',type:'Degree',start:2023,end:2027,color:'#6c8eff'},

];


let PROGRAM_TASKS=[

  {id:1,programId:1,title:'Year 2 Statistics',done:false},

  {id:2,programId:1,title:'Year 2 Chemistry',done:false},

  {id:3,programId:1,title:'Core Writing Requirement',done:true},

];


let COURSES=[

  {id:1,name:'Introduction to Statistics',code:'STAT 301',credits:3,color:'#6c8eff',target:85,difficulty:4,term:'Spring',year:2026,professor:'Prof. Martinez',ta:'',programId:1},

  {id:2,name:'Organic Chemistry II',code:'CHEM 202',credits:4,color:'#f87171',target:80,difficulty:5,term:'Spring',year:2026,professor:'Prof. Chen',ta:'Alice Nguyen',programId:1},

  {id:3,name:'World History 1800–Present',code:'HIST 210',credits:3,color:'#4ade80',target:90,difficulty:2,term:'Spring',year:2026,professor:'Dr. Williams',ta:'',programId:null},

  {id:4,name:'Linear Algebra',code:'MATH 340',credits:3,color:'#fbbf24',target:82,difficulty:4,term:'Spring',year:2026,professor:'Prof. Martinez',ta:'Bob Okafor',programId:1},

  {id:5,name:'Technical Writing',code:'ENGL 215',credits:3,color:'#2dd4bf',target:88,difficulty:2,term:'Spring',year:2026,professor:'',ta:'',programId:null},

];


let ASSIGNMENTS=[

  {id:1,courseId:1,title:'Homework 3 – Probability',type:'Homework',due:addDays(-3),weight:10,status:'pending',score:null,possible:100,notes:'',groupType:'individual',createdAt:addDays(-14),completedAt:null},

  {id:2,courseId:1,title:'Midterm Exam',type:'Exam',due:addDays(-14),weight:30,status:'done',score:68,possible:100,notes:'',groupType:'individual',createdAt:addDays(-30),completedAt:addDays(-14),programTaskId:null},

  {id:3,courseId:1,title:'Final Exam',type:'Exam',due:addDays(42),weight:40,status:'pending',score:null,possible:100,notes:'',groupType:'individual',createdAt:addDays(-7),completedAt:null},

  {id:4,courseId:2,title:'Lab Report 4',type:'Lab',due:addDays(-1),weight:15,status:'pending',score:null,possible:100,notes:'',groupType:'group',createdAt:addDays(-10),completedAt:null},

  {id:5,courseId:2,title:'Reaction Mechanism Quiz',type:'Quiz',due:addDays(5),weight:10,status:'pending',score:null,possible:50,notes:'',groupType:'individual',createdAt:addDays(-5),completedAt:null},

  {id:6,courseId:2,title:'Final Exam',type:'Exam',due:addDays(44),weight:35,status:'pending',score:null,possible:100,notes:'',groupType:'individual',createdAt:addDays(-7),completedAt:null},

  {id:7,courseId:3,title:'Research Essay',type:'Essay',due:addDays(8),weight:25,status:'pending',score:null,possible:100,notes:'',groupType:'individual',createdAt:addDays(-5),completedAt:null},

  {id:8,courseId:3,title:'Midterm',type:'Exam',due:addDays(-21),weight:30,status:'done',score:91,possible:100,notes:'',groupType:'individual',createdAt:addDays(-40),completedAt:addDays(-21)},

  {id:9,courseId:4,title:'Problem Set 5',type:'Homework',due:addDays(3),weight:8,status:'pending',score:null,possible:40,notes:'',groupType:'individual',createdAt:addDays(-4),completedAt:null},

  {id:10,courseId:4,title:'Midterm',type:'Exam',due:addDays(-10),weight:30,status:'done',score:74,possible:100,notes:'',groupType:'individual',createdAt:addDays(-28),completedAt:addDays(-10)},

  {id:11,courseId:5,title:'Technical Report Draft',type:'Essay',due:addDays(6),weight:20,status:'pending',score:null,possible:100,notes:'',groupType:'individual',createdAt:addDays(-3),completedAt:null},

  {id:12,courseId:5,title:'Presentation',type:'Project',due:addDays(-5),weight:25,status:'done',score:95,possible:100,notes:'',groupType:'group',createdAt:addDays(-20),completedAt:addDays(-5)},

];


let SESSIONS=[

  {id:1,courseId:1,date:addDays(-1),planned:25,actual:25,label:'Focus session'},

  {id:2,courseId:2,date:addDays(-2),planned:50,actual:48,label:'Deep work'},

  {id:3,courseId:3,date:addDays(-2),planned:25,actual:25,label:'Focus session'},

  {id:4,courseId:4,date:addDays(-3),planned:25,actual:22,label:'Focus session'},

  {id:5,courseId:1,date:addDays(-4),planned:50,actual:50,label:'Deep work'},

  {id:6,courseId:2,date:addDays(-5),planned:50,actual:45,label:'Deep work'},

];


let INSIGHTS=[

  {id:1,type:'flag',severity:'alert',courseId:2,dismissed:false,title:'Grade at risk in Organic Chemistry',desc:'Projected grade 64.2% — below passing threshold. Final exam worth 35%, need 82%+ to pass.'},

  {id:2,type:'flag',severity:'alert',courseId:1,dismissed:false,title:'"Homework 3" is overdue',desc:'STAT 301 HW3 (10%) due 3 days ago. Submit ASAP — late credit beats zero.'},

  {id:3,type:'flag',severity:'warn',courseId:4,dismissed:false,title:'Statistics grade below target',desc:'13.6 points below 85% target in STAT 301. Need 93.2% average on remaining work.'},

  {id:4,type:'suggestion',severity:'info',courseId:2,dismissed:false,title:'Increase study time for Chemistry',desc:'Averaging 2.6 hrs/week for a difficulty-5 course. Aim for 4–5 hrs.'},

  {id:5,type:'prediction',severity:'info',courseId:5,dismissed:false,title:'On track to exceed target in Technical Writing',desc:'Current 91.3% vs 88% target. Maintain consistency.'},

];


let TASKS=[

  {id:1,title:'Email Prof. Martinez about HW3 extension',due:addDays(1),priority:'high',courseId:1,status:'pending',notes:'',createdAt:addDays(-1),completedAt:null},

  {id:2,title:'Order Organic Chemistry textbook',due:null,priority:'high',courseId:2,status:'pending',notes:'ISBN 978-0199270293',createdAt:addDays(-3),completedAt:null},

  {id:3,title:'Form study group for Linear Algebra',due:addDays(5),priority:'medium',courseId:4,status:'pending',notes:'',createdAt:addDays(-2),completedAt:null},

  {id:4,title:'Back up all class notes to cloud',due:null,priority:'low',courseId:null,status:'done',notes:'',createdAt:addDays(-10),completedAt:addDays(-2)},

];


let RESOURCES=[

  {id:1,title:'Organic Chemistry by Clayden',type:'Book',status:'needed',url:'',courseId:2,assignmentId:null,notes:'~$80 new'},

  {id:2,title:'Khan Academy – Statistics',type:'Link',status:'obtained',url:'https://khanacademy.org/statistics',courseId:1,assignmentId:null,notes:'Free'},

  {id:3,title:'Wolfram Alpha',type:'Tool',status:'obtained',url:'https://wolframalpha.com',courseId:4,assignmentId:null,notes:'Check algebra'},

  {id:4,title:'HIST 210 Course Reader',type:'Book',status:'obtained',url:'',courseId:3,assignmentId:null,notes:'Library reserve'},

];


// ══════════════════════════════════════════════════════

//  HELPERS

// ══════════════════════════════════════════════════════

const getCourse=id=>COURSES.find(c=>c.id===id);

const gradeColor=g=>!g&&g!==0?'var(--text2)':g>=90?'var(--green)':g>=80?'var(--teal)':g>=70?'var(--amber)':'var(--red)';

const isOverdue=a=>a.status!=='done'&&new Date(a.due)<today;


function computeGrade(courseId){

  const graded=ASSIGNMENTS.filter(a=>a.courseId===courseId&&a.score!==null&&a.status==='done');

  if(!graded.length)return null;

  const tw=graded.reduce((s,a)=>s+a.weight,0);

  const ws=graded.reduce((s,a)=>s+(a.score/a.possible)*a.weight,0);

  return tw>0?+(ws/tw*100).toFixed(1):null;

}


function dueDateLabel(dateStr){

  const d=new Date(dateStr),diff=Math.round((d-today)/86400000);

  if(diff<-1)return`<span style="color:var(--red)">${Math.abs(diff)}d overdue</span>`;

  if(diff===-1)return`<span style="color:var(--red)">Yesterday</span>`;

  if(diff===0)return`<span style="color:var(--amber)">Today</span>`;

  if(diff===1)return`<span style="color:var(--amber)">Tomorrow</span>`;

  if(diff<=7)return`<span style="color:var(--amber)">In ${diff}d</span>`;

  return`<span style="color:var(--text2)">${d.toLocaleDateString('en-US',{month:'short',day:'numeric'})}</span>`;

}


function typeBadgeStyle(t){return({Exam:'background:var(--red-bg);color:var(--red)',Essay:'background:var(--purple-bg);color:var(--purple)',Homework:'background:var(--accent-bg);color:var(--accent)',Quiz:'background:var(--amber-bg);color:var(--amber)',Project:'background:var(--teal-bg);color:var(--teal)',Lab:'background:var(--green-bg);color:var(--green)'})[t]||'background:var(--bg4);color:var(--text2)';}


function activeInsightCount(){return INSIGHTS.filter(i=>!i.dismissed).length;}

function updateBadge(){const n=activeInsightCount(),b=document.getElementById('insights-badge');b.textContent=n;b.style.display=n?'':'none';}


// ══════════════════════════════════════════════════════

//  NAV

// ══════════════════════════════════════════════════════

function nav(page,opts={}){

  document.querySelectorAll('.page').forEach(p=>p.classList.remove('active'));

  document.querySelectorAll('.nav-item').forEach(n=>n.classList.remove('active'));

  document.getElementById('page-'+page).classList.add('active');

  document.querySelectorAll('.nav-item').forEach(n=>{if(n.getAttribute('onclick')===`nav('${page}')`)n.classList.add('active');});

  if(opts.filter)activeFilter=opts.filter;

  ({dashboard:renderDashboard,programs:renderPrograms,courses:renderCourses,assignments:renderAssignments,timer:renderTimer,tasks:renderTasks,resources:renderResources,chat:initChat,contacts:renderContacts,insights:renderInsights})[page]?.();

}


// ══════════════════════════════════════════════════════

//  DASHBOARD

// ══════════════════════════════════════════════════════

function renderDashboard(){

  const overdueList=ASSIGNMENTS.filter(isOverdue);

  const dueSoon=ASSIGNMENTS.filter(a=>{const d=(new Date(a.due)-today)/86400000;return d>=0&&d<=7&&a.status!=='done';});

  const flags=activeInsightCount();

  const totalMins=SESSIONS.reduce((s,x)=>s+x.actual,0);

  const hrsThisWeek=(totalMins/60).toFixed(1);


  // Stat cards — only show enabled widgets

  const cards=[];

  if(SETTINGS.widgets.gpa)cards.push(`<div class="stat-card"><div class="stat-label">Current GPA</div><div class="stat-value" style="color:var(--green)">3.4</div><div class="stat-change up">↑ 0.2 · target ${SETTINGS.gpaTarget}</div></div>`);

  if(SETTINGS.widgets.studyhrs)cards.push(`<div class="stat-card"><div class="stat-label">Study Hrs / Week</div><div class="stat-value">${hrsThisWeek}</div><div class="stat-change">Goal: ${SETTINGS.studyGoal} hrs</div></div>`);

  if(SETTINGS.widgets.assignments)cards.push(`<div class="stat-card clickable" onclick="nav('assignments',{filter:'overdue'})" title="View overdue assignments"><div class="stat-label">Assignments Due</div><div class="stat-value" style="color:${overdueList.length>0?'var(--red)':dueSoon.length>0?'var(--amber)':'var(--green)'}">${overdueList.length+dueSoon.length}</div><div class="stat-change ${overdueList.length?'down':''}">${overdueList.length} overdue — click to view</div><div class="stat-hint">↗ Opens Assignments · Overdue tab</div></div>`);

  if(SETTINGS.widgets.flags)cards.push(`<div class="stat-card clickable" onclick="nav('insights')" title="View flags"><div class="stat-label">Active Flags</div><div class="stat-value" style="color:${flags>0?'var(--red)':'var(--green)'}">${flags}</div><div class="stat-change">${flags>0?'Click to view':'All clear 🎉'}</div><div class="stat-hint">${flags>0?'↗ Opens Insights':''}</div></div>`);


  const colCount=cards.length||1;

  const gridCols=colCount>=4?'grid-4':colCount===3?'grid-3':'grid-2';

  document.getElementById('dash-stats-row').innerHTML=`<div class="${gridCols}">${cards.join('')}</div>`;


  document.getElementById('dash-courses').innerHTML=COURSES.map(c=>{

    const g=computeGrade(c.id);

    return`<div class="course-card" onclick="nav('courses')" style="margin-bottom:8px">

      <div style="display:flex;align-items:flex-start;justify-content:space-between;margin-bottom:8px">

        <div><span style="display:inline-block;width:6px;height:6px;border-radius:50%;background:${c.color};margin-right:5px"></span><span class="course-name">${c.name}</span><div class="course-code">${c.code}</div></div>

        <div class="course-grade" style="color:${gradeColor(g)}">${g!==null?g+'%':'—'}</div>

      </div>

      <div class="progress-bar-wrap"><div class="progress-bar" style="width:${g||0}%;background:${c.color}"></div></div>

      <div class="course-meta"><span>Target: ${c.target}%</span><span>${g!==null?(g>=c.target?'✓ On track':`${(c.target-g).toFixed(1)}% below`):'No grades yet'}</span></div>

    </div>`;

  }).join('');


  document.getElementById('dash-flags').innerHTML=INSIGHTS.filter(i=>!i.dismissed&&i.severity!=='info').slice(0,3).map(i=>`

    <div class="flag-card ${i.severity}" id="dflag-${i.id}">

      <span class="flag-icon">${i.severity==='alert'?'🚨':'⚠️'}</span>

      <span class="flag-text">${i.desc}</span>

      <button class="flag-dismiss" onclick="dismissInsight(${i.id})" title="Dismiss alert only">×</button>

    </div>`).join('')||'<div style="font-size:11px;color:var(--text3);padding:4px 0">No active flags 🎉</div>';


  const up=[...ASSIGNMENTS].filter(a=>a.status!=='done').sort((a,b)=>new Date(a.due)-new Date(b.due)).slice(0,5);

  document.getElementById('dash-upcoming').innerHTML=up.length?up.map(a=>{

    const c=getCourse(a.courseId),urgency=(new Date(a.due)-today)/86400000;

    return`<div style="display:flex;align-items:center;gap:9px;padding:7px 0;border-bottom:1px solid var(--border)">

      <div style="width:6px;height:6px;border-radius:50%;flex-shrink:0;background:${isOverdue(a)?'var(--red)':urgency<=3?'var(--amber)':'var(--text3)'}"></div>

      <div style="flex:1;min-width:0"><div style="font-size:12px;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis">${a.title}</div><div style="font-size:9px;color:var(--text3)">${c?.code}</div></div>

      <div style="font-size:10px">${dueDateLabel(a.due)}</div>

      <span style="font-size:9px;color:var(--text3)">${a.weight}%</span>

    </div>`;

  }).join('')+'<div style="height:2px"></div>':'<div class="empty-state" style="padding:20px"><div class="ei">✅</div><p>Nothing due soon!</p></div>';


  // Reports widget

  if(SETTINGS.widgets.reports){

    const doneTasks=TASKS.filter(t=>t.status==='done'&&t.completedAt);

    const doneAsgn=ASSIGNMENTS.filter(a=>a.status==='done'&&a.completedAt);

    const avgTaskDays=doneTasks.length?Math.round(doneTasks.reduce((s,t)=>s+Math.max(0,(new Date(t.completedAt)-new Date(t.createdAt))/86400000),0)/doneTasks.length*10)/10:null;

    const avgAsgnDays=doneAsgn.length?Math.round(doneAsgn.reduce((s,a)=>s+Math.max(0,(new Date(a.completedAt)-new Date(a.createdAt))/86400000),0)/doneAsgn.length*10)/10:null;

    document.getElementById('dash-reports').innerHTML=`

      <div class="section-header"><div class="section-title">📊 Activity Reports</div></div>

      <div class="grid-3">

        <div class="dashboard-report-card">

          <div class="section-title" style="margin-bottom:8px">Assignments</div>

          <div class="report-row"><span class="report-label">Completed</span><span class="report-val">${doneAsgn.length}</span></div>

          <div class="report-row"><span class="report-label">Pending</span><span class="report-val">${ASSIGNMENTS.filter(a=>a.status==='pending'&&!isOverdue(a)).length}</span></div>

          <div class="report-row"><span class="report-label">Overdue</span><span class="report-val" style="color:var(--red)">${ASSIGNMENTS.filter(isOverdue).length}</span></div>

          ${avgAsgnDays!==null?`<div class="report-row"><span class="report-label">Avg completion</span><span class="report-val">${avgAsgnDays}d</span></div>`:''}

        </div>

        <div class="dashboard-report-card">

          <div class="section-title" style="margin-bottom:8px">Tasks</div>

          <div class="report-row"><span class="report-label">Completed</span><span class="report-val">${TASKS.filter(t=>t.status==='done').length}</span></div>

          <div class="report-row"><span class="report-label">Pending</span><span class="report-val">${TASKS.filter(t=>t.status==='pending').length}</span></div>

          <div class="report-row"><span class="report-label">High priority</span><span class="report-val" style="color:var(--red)">${TASKS.filter(t=>t.priority==='high'&&t.status==='pending').length}</span></div>

          ${avgTaskDays!==null?`<div class="report-row"><span class="report-label">Avg completion</span><span class="report-val">${avgTaskDays}d</span></div>`:''}

        </div>

        <div class="dashboard-report-card">

          <div class="section-title" style="margin-bottom:8px">Study Sessions</div>

          <div class="report-row"><span class="report-label">This week</span><span class="report-val">${SESSIONS.length}</span></div>

          <div class="report-row"><span class="report-label">Total mins</span><span class="report-val">${totalMins}</span></div>

          <div class="report-row"><span class="report-label">Goal progress</span><span class="report-val" style="color:${parseFloat(hrsThisWeek)>=SETTINGS.studyGoal?'var(--green)':'var(--amber)'}">${Math.round(parseFloat(hrsThisWeek)/SETTINGS.studyGoal*100)}%</span></div>

        </div>

      </div>`;

  } else { document.getElementById('dash-reports').innerHTML=''; }

}


// ══════════════════════════════════════════════════════

//  PROGRAMS

// ══════════════════════════════════════════════════════

function renderPrograms(){

  document.getElementById('programs-grid').innerHTML=PROGRAMS.length?PROGRAMS.map(p=>{

    const courses=COURSES.filter(c=>c.programId===p.id);

    const tasks=PROGRAM_TASKS.filter(t=>t.programId===p.id);

    const done=tasks.filter(t=>t.done).length;

    return`<div class="program-card">

      <div class="program-header">

        <div class="program-badge" style="background:${p.color}22;color:${p.color}">${p.name.split(' ').map(w=>w[0]).join('').slice(0,3).toUpperCase()}</div>

        <div style="flex:1"><div style="font-weight:600;font-size:13.5px">${p.name}</div><div style="font-size:10px;color:var(--text3)">${p.institution} · ${p.type} · ${p.start}–${p.end}</div></div>

        <button class="btn-icon" onclick="openEditProgram(${p.id})" title="Edit">✎</button>

      </div>

      <div class="program-body">

        <div class="program-stat-row">

          <div class="program-stat"><div class="course-stat-label">Courses</div><div class="course-stat-val">${courses.length}</div></div>

          <div class="program-stat"><div class="course-stat-label">Tasks</div><div class="course-stat-val">${done}/${tasks.length}</div></div>

        </div>

        <div style="margin-bottom:10px">

          <div style="font-size:10px;color:var(--text3);margin-bottom:6px;font-weight:600;letter-spacing:0.07em;text-transform:uppercase">Program Tasks</div>

          ${tasks.map(t=>`<div style="display:flex;align-items:center;gap:7px;padding:4px 0;font-size:12px;border-bottom:1px solid var(--border)">

            <div style="width:13px;height:13px;border-radius:50%;border:2px solid ${t.done?'var(--green)':'var(--border2)'};background:${t.done?'var(--green)':'transparent'};flex-shrink:0;display:flex;align-items:center;justify-content:center;font-size:7px;color:#fff">${t.done?'✓':''}</div>

            <span style="${t.done?'text-decoration:line-through;color:var(--text3)':''}">${t.title}</span>

          </div>`).join('')}

        </div>

        <div style="display:flex;gap:6px;flex-wrap:wrap">

          <button class="btn btn-ghost btn-sm" onclick="openCourseModal(null,${p.id})">+ Course</button>

          <button class="btn btn-ghost btn-sm" onclick="addProgramTask(${p.id})">+ Task</button>

        </div>

      </div>

    </div>`;

  }).join(''):`<div class="empty-state" style="grid-column:1/-1"><div class="ei">🎓</div><p>No programs yet. Add your degree, certificate, or short course.</p></div>`;

}


// ══════════════════════════════════════════════════════

//  COURSES

// ══════════════════════════════════════════════════════

function renderCourses(){

  const credits=COURSES.reduce((s,c)=>s+c.credits,0);

  document.getElementById('courses-sub').textContent=`${COURSES.length} courses · ${credits} credit hours`;

  document.getElementById('courses-grid').innerHTML=COURSES.map(c=>{

    const g=computeGrade(c.id),done=ASSIGNMENTS.filter(a=>a.courseId===c.id&&a.status==='done').length;

    const total=ASSIGNMENTS.filter(a=>a.courseId===c.id).length,overdue=ASSIGNMENTS.filter(a=>a.courseId===c.id&&isOverdue(a)).length;

    const sess=SESSIONS.filter(s=>s.courseId===c.id),avgMins=sess.length?Math.round(sess.reduce((s,x)=>s+x.actual,0)/sess.length):null;

    const abbr=c.name.split(' ').filter(w=>w.length>3).slice(0,2).map(w=>w[0]).join('').toUpperCase()||c.code.slice(0,2);

    const prog=PROGRAMS.find(p=>p.id===c.programId);

    return`<div class="course-full-card">

      <div class="course-full-header">

        <div class="course-full-color" style="background:${c.color}22;color:${c.color}">${abbr}</div>

        <div style="flex:1">

          <div style="font-weight:600;font-size:13px">${c.name}</div>

          <div style="font-size:9px;color:var(--text3);font-family:var(--mono)">${c.code} · ${c.credits}cr · ${c.term} ${c.year}${prog?` · <span style="color:${prog.color}">${prog.name}</span>`:''}</div>

          ${c.professor?`<div style="font-size:9px;color:var(--text3);margin-top:1px">👤 ${c.professor}${c.ta?' · TA: '+c.ta:''}</div>`:''}

        </div>

        <div style="display:flex;align-items:center;gap:6px">

          <div style="font-family:var(--display);font-size:19px;color:${gradeColor(g)}">${g!==null?g+'%':'—'}</div>

          <button class="btn-icon" onclick="openEditCourse(${c.id})" title="Edit">✎</button>

        </div>

      </div>

      <div class="course-full-body">

        <div class="grade-bar-wrap"><div class="progress-bar" style="width:${g||0}%;background:${c.color}"></div></div>

        <div style="display:flex;justify-content:space-between;font-size:9px;color:var(--text3);margin-bottom:10px"><span>Graded: ${g!==null?g+'%':'—'}</span><span>Target: ${c.target}%</span></div>

        <div class="course-stat-row">

          <div class="program-stat"><div class="course-stat-label">Tasks</div><div class="course-stat-val">${done}/${total}</div></div>

          <div class="program-stat"><div class="course-stat-label">Avg session</div><div class="course-stat-val">${avgMins?avgMins+'m':'—'}</div></div>

          <div class="program-stat"><div class="course-stat-label">Overdue</div><div class="course-stat-val" style="color:${overdue?'var(--red)':'var(--green)'}">${overdue}</div></div>

        </div>

        <div style="display:flex;gap:5px;flex-wrap:wrap">

          <button class="btn btn-ghost btn-sm" onclick="openAssignmentModal(${c.id})">+ Assignment</button>

          <button class="btn btn-ghost btn-sm" onclick="askLyraAbout('${c.name}')">Ask Lyra</button>

        </div>

      </div>

    </div>`;

  }).join('')||'<div class="empty-state" style="grid-column:1/-1"><div class="ei">📚</div><p>No courses yet!</p></div>';

}


// ══════════════════════════════════════════════════════

//  ASSIGNMENTS — overdue is purely computed

// ══════════════════════════════════════════════════════

function renderAssignments(){

  let list=[...ASSIGNMENTS];

  if(activeFilter==='pending')list=list.filter(a=>a.status==='pending'&&!isOverdue(a));

  if(activeFilter==='done')list=list.filter(a=>a.status==='done');

  if(activeFilter==='overdue')list=list.filter(a=>isOverdue(a));

  list.sort((a,b)=>new Date(a.due)-new Date(b.due));

  const statS={done:'background:var(--green-bg);color:var(--green)',pending:'background:var(--bg4);color:var(--text2)'};

  const statL={done:'✓ Done',pending:'● Pending'};

  document.getElementById('asgn-tbody').innerHTML=list.map(a=>{

    const c=getCourse(a.courseId),ov=isOverdue(a);

    const sStyle=ov?'background:var(--red-bg);color:var(--red)':statS[a.status]||'';

    const sLabel=ov?'⚠ Overdue':statL[a.status]||a.status;

    const scoreStr=a.score!==null?`<span style="color:${gradeColor(a.score/a.possible*100)}">${a.score}/${a.possible}</span>`:'<span style="color:var(--text3)">—</span>';

    const duration=a.completedAt&&a.createdAt?fmtDuration(Math.max(0,(new Date(a.completedAt)-new Date(a.createdAt))/60000)):null;

    const gtBadge=a.groupType==='group'?`<span style="font-size:8px;color:var(--teal);margin-left:4px">👥</span>`:'';

    return`<tr>

      <td><div style="font-weight:500">${a.title}${gtBadge}</div></td>

      <td><span style="display:inline-flex;align-items:center;gap:4px"><span style="width:5px;height:5px;border-radius:50%;background:${c?.color};display:inline-block"></span>${c?.code}</span></td>

      <td><span class="type-badge" style="${typeBadgeStyle(a.type)}">${a.type}</span></td>

      <td>${dueDateLabel(a.due)}</td>

      <td><span style="font-family:var(--mono);color:var(--text2)">${a.weight}%</span></td>

      <td>${scoreStr}</td>

      <td><span class="status-chip" style="${sStyle}">${sLabel}</span></td>

      <td>${duration?`<span class="task-duration">${duration}</span>`:'<span style="color:var(--text3);font-size:9px">—</span>'}</td>

      <td><div class="row-actions">

        ${a.status!=='done'?`<button class="btn-icon btn-success" onclick="markAsgnDone(${a.id})" title="Mark complete" style="color:var(--green);border-color:rgba(74,222,128,0.3)">✓</button>`:''}

        <button class="btn-icon" onclick="openExtendModal(${a.id})" title="Extend due date">📅</button>

        <button class="btn-icon" onclick="openEditAssignment(${a.id})" title="Edit">✎</button>

        <button class="btn-icon" onclick="confirmDeleteAssignmentById(${a.id})" title="Delete" style="color:var(--red)">✕</button>

      </div></td>

    </tr>`;

  }).join('')||`<tr><td colspan="9"><div class="empty-state"><div class="ei">📋</div><p>${activeFilter==='overdue'?'No overdue assignments 🎉':'No assignments found'}</p></div></td></tr>`;

  document.querySelectorAll('.filter-btn').forEach(b=>b.classList.toggle('active',b.dataset.filter===activeFilter));

}


document.getElementById('filter-bar').addEventListener('click',e=>{const b=e.target.closest('.filter-btn');if(b){activeFilter=b.dataset.filter;renderAssignments();}});


function markAsgnDone(id){

  const a=ASSIGNMENTS.find(x=>x.id===id);if(!a)return;

  a.status='done';a.completedAt=fmt(today);

  renderAssignments();renderDashboard();renderCourses();

}


function openExtendModal(id){

  const a=ASSIGNMENTS.find(x=>x.id===id);if(!a)return;

  document.getElementById('extend-id').value=id;

  document.getElementById('extend-title-display').textContent=a.title;

  document.getElementById('extend-date').value=a.due;

  document.getElementById('extend-reason').value='';

  openModal('extend');

}

function saveExtend(){

  const id=parseInt(document.getElementById('extend-id').value);

  const nd=document.getElementById('extend-date').value;if(!nd)return;

  const a=ASSIGNMENTS.find(x=>x.id===id);if(!a)return;

  a.due=nd;if(a.status!=='done')a.status='pending';

  closeModal('extend');renderAssignments();renderDashboard();

}


// ══════════════════════════════════════════════════════

//  TIMER

// ══════════════════════════════════════════════════════

function loadTimerAssignments(){

  const cid=parseInt(document.getElementById('timer-course-select').value)||null;

  const sel=document.getElementById('timer-asgn-select');

  const asgns=cid?ASSIGNMENTS.filter(a=>a.courseId===cid&&a.status!=='done'):[];

  sel.innerHTML='<option value="">Link assignment...</option>'+asgns.map(a=>`<option value="${a.id}">${a.title}</option>`).join('');

}


function renderTimer(){

  const sel=document.getElementById('timer-course-select');

  sel.innerHTML='<option value="">Select course...</option>'+COURSES.map(c=>`<option value="${c.id}">${c.name}</option>`).join('');

  loadTimerAssignments();

  renderSessionLog();

  const totalMins=SESSIONS.reduce((s,x)=>s+x.actual,0);

  document.getElementById('timer-stats').innerHTML=`

    <div class="stat-card"><div class="stat-label">Total This Week</div><div class="stat-value" style="font-size:19px">${(totalMins/60).toFixed(1)}h</div></div>

    <div class="stat-card"><div class="stat-label">Sessions</div><div class="stat-value" style="font-size:19px">${SESSIONS.length}</div></div>`;

  updateTimerDisplay();

}


function renderSessionLog(){

  document.getElementById('session-log-list').innerHTML=[...SESSIONS].reverse().slice(0,8).map(s=>{

    const c=getCourse(s.courseId);

    return`<div class="session-row"><div class="session-dot" style="background:${c?.color||'var(--text3)'}"></div><span style="flex:1;font-weight:500">${c?.code||'—'}</span><span style="color:var(--text2);font-family:var(--mono)">${s.actual}m</span><span style="color:var(--text3)">${s.label}</span><span style="color:var(--text3)">${new Date(s.date).toLocaleDateString('en-US',{month:'short',day:'numeric'})}</span></div>`;

  }).join('')||'<div style="font-size:11px;color:var(--text3);padding:6px 0">No sessions yet</div>';

}


function setTimer(mins,label){timerSeconds=mins*60;timerTotal=timerSeconds;timerMode=label;clearInterval(timerInterval);timerRunning=false;timerStartTime=null;document.getElementById('timer-toggle').textContent='▶';updateTimerDisplay();}

function setCustomTimer(){const m=parseInt(document.getElementById('custom-mins').value);const l=document.getElementById('custom-label-inp').value.trim()||'Custom session';if(!m||m<1)return;setTimer(m,l);}


function updateTimerDisplay(){

  const m=Math.floor(timerSeconds/60).toString().padStart(2,'0'),s=(timerSeconds%60).toString().padStart(2,'0');

  document.getElementById('timer-display').textContent=`${m}:${s}`;

  document.getElementById('timer-label').textContent=timerMode;

  const circ=2*Math.PI*83,offset=circ*(1-timerSeconds/timerTotal);

  const fg=document.getElementById('timer-ring-fg');

  if(fg){fg.style.strokeDashoffset=offset;fg.style.stroke=timerSeconds/timerTotal<0.25?'var(--amber)':'var(--accent)';}

}


function toggleTimer(){

  if(timerRunning){clearInterval(timerInterval);timerRunning=false;document.getElementById('timer-toggle').textContent='▶';}

  else{if(!timerStartTime)timerStartTime=Date.now();timerRunning=true;document.getElementById('timer-toggle').textContent='⏸';timerInterval=setInterval(()=>{if(timerSeconds>0){timerSeconds--;updateTimerDisplay();}else{onTimerComplete();}},1000);}

}


function onTimerComplete(){

  clearInterval(timerInterval);timerRunning=false;

  document.getElementById('timer-toggle').textContent='▶';

  document.getElementById('timer-label').textContent='Session complete! 🎉';

  if(document.getElementById('timer-sound-on').checked)playBeep();

  const courseId=parseInt(document.getElementById('timer-course-select').value)||null;

  const label=document.getElementById('timer-session-label').value.trim()||timerMode;

  SESSIONS.push({id:Date.now(),courseId,date:fmt(today),planned:Math.round(timerTotal/60),actual:Math.round(timerTotal/60),label});

  renderSessionLog();

  const totalMins=SESSIONS.reduce((s,x)=>s+x.actual,0);

  document.getElementById('timer-stats').innerHTML=`<div class="stat-card"><div class="stat-label">Total This Week</div><div class="stat-value" style="font-size:19px">${(totalMins/60).toFixed(1)}h</div></div><div class="stat-card"><div class="stat-label">Sessions</div><div class="stat-value" style="font-size:19px">${SESSIONS.length}</div></div>`;

  timerStartTime=null;

}


function playBeep(){

  try{const ctx=new(window.AudioContext||window.webkitAudioContext)();const pl=(f,t,d)=>{const o=ctx.createOscillator(),g=ctx.createGain();o.connect(g);g.connect(ctx.destination);o.type='sine';o.frequency.value=f;g.gain.setValueAtTime(0.35,t);g.gain.exponentialRampToValueAtTime(0.001,t+d);o.start(t);o.stop(t+d);};const t=ctx.currentTime;pl(880,t,.15);pl(1100,t+.18,.15);pl(1320,t+.36,.25);}catch(e){}

}


function resetTimer(){clearInterval(timerInterval);timerRunning=false;timerSeconds=timerTotal;timerStartTime=null;document.getElementById('timer-toggle').textContent='▶';updateTimerDisplay();}

function skipTimer(){if(!timerRunning&&timerSeconds===timerTotal)return;onTimerComplete();}


// ══════════════════════════════════════════════════════

//  TASKS — completed in separate section, with duration

// ══════════════════════════════════════════════════════

function renderTasks(){

  const showCompleted=document.getElementById('show-completed-toggle').checked;

  let pending=[...TASKS];

  if(activeTaskFilter==='pending')pending=pending.filter(t=>t.status==='pending');

  if(activeTaskFilter==='high')pending=pending.filter(t=>t.priority==='high'&&t.status==='pending');

  pending=pending.filter(t=>t.status!=='done');

  pending.sort((a,b)=>{const pd={high:0,medium:1,low:2};return pd[a.priority]-pd[b.priority];});

  const completed=TASKS.filter(t=>t.status==='done');

  const priorColor={high:'var(--red)',medium:'var(--amber)',low:'var(--text3)'};


  const taskRow=t=>{

    const c=getCourse(t.courseId);

    const duration=t.completedAt&&t.createdAt?fmtDuration(Math.max(0,(new Date(t.completedAt)-new Date(t.createdAt))/60000)):null;

    return`<div class="task-row ${t.status==='done'?'completed-row':''}">

      <div class="task-check ${t.status==='done'?'done':''}" onclick="toggleTask(${t.id})"></div>

      <div class="priority-dot" style="background:${priorColor[t.priority]}"></div>

      <div class="task-info">

        <div class="task-title-txt ${t.status==='done'?'task-done-txt':''}">${t.title}</div>

        <div class="task-sub">${c?`<span style="color:${c.color}">${c.code}</span> · `:''}${t.due?dueDateLabel(t.due):'No due date'}${t.notes?` · ${t.notes}`:''}</div>

      </div>

      ${duration?`<span class="task-duration">⏱ ${duration}</span>`:''}

      <div class="row-actions">

        <button class="btn-icon" onclick="openEditTask(${t.id})" title="Edit">✎</button>

        <button class="btn-icon" onclick="confirmDeleteTaskById(${t.id})" title="Delete" style="color:var(--red)">✕</button>

      </div>

    </div>`;

  };


  let html=pending.map(taskRow).join('');

  if(!pending.length)html='<div class="empty-state" style="padding:20px"><div class="ei">✅</div><p>No tasks here!</p></div>';


  if(showCompleted&&completed.length){

    html+=`<div class="completed-section-header"><span>✓ Completed (${completed.length})</span><button class="btn btn-ghost btn-sm" onclick="if(confirm('Clear all completed tasks?'))clearCompleted()">Clear all</button></div>`;

    html+=completed.map(taskRow).join('');

  }


  document.getElementById('task-list').innerHTML=html;

  document.querySelectorAll('.task-filter-btn').forEach(b=>b.classList.toggle('active',b.dataset.tf===activeTaskFilter));

}


function clearCompleted(){TASKS=TASKS.filter(t=>t.status!=='done');renderTasks();}


document.getElementById('task-filter-bar').addEventListener('click',e=>{const b=e.target.closest('.task-filter-btn');if(b){activeTaskFilter=b.dataset.tf;renderTasks();}});


function toggleTask(id){

  const t=TASKS.find(x=>x.id===id);if(!t)return;

  t.status=t.status==='done'?'pending':'done';

  if(t.status==='done')t.completedAt=fmt(today);

  else t.completedAt=null;

  renderTasks();renderDashboard();

}


// ══════════════════════════════════════════════════════

//  RESOURCES — obtained in separate section

//  Course→Assignment cascade

// ══════════════════════════════════════════════════════

const resTypeIcon={Book:'📚',Link:'🔗',Tool:'🛠️',Note:'📝',Video:'🎬',Other:'📦'};

const resStatusStyle={needed:'background:var(--red-bg);color:var(--red)',pending:'background:var(--amber-bg);color:var(--amber)',obtained:'background:var(--green-bg);color:var(--green)'};

const resStatusLabel={needed:'Needed',pending:'Ordered',obtained:'Obtained'};


function renderResources(){

  let list=[...RESOURCES];

  if(activeResFilter==='needed')list=list.filter(r=>r.status==='needed');

  else if(activeResFilter!=='all')list=list.filter(r=>r.type===activeResFilter);


  const notObtained=list.filter(r=>r.status!=='obtained');

  const obtained=list.filter(r=>r.status==='obtained');


  const resCard=r=>{

    const c=getCourse(r.courseId),a=r.assignmentId?ASSIGNMENTS.find(x=>x.id===r.assignmentId):null;

    return`<div class="resource-card">

      <div class="resource-icon" style="background:var(--bg3)">${resTypeIcon[r.type]||'📦'}</div>

      <div class="resource-body">

        <div class="resource-title">${r.title}</div>

        <div class="resource-meta">${c?`<span style="display:inline-flex;align-items:center;gap:3px;margin-right:7px"><span style="width:5px;height:5px;border-radius:50%;background:${c.color};display:inline-block"></span>${c.code}</span>`:''}${a?`<span style="color:var(--text3);margin-right:7px">→ ${a.title}</span>`:''}${r.url?`<a class="resource-link" href="${r.url}" target="_blank" rel="noopener">🔗 Open</a>`:''}</div>

        ${r.notes?`<div style="font-size:10px;color:var(--text3);margin-top:2px">${r.notes}</div>`:''}

        <div style="margin-top:7px;display:flex;align-items:center;gap:7px;flex-wrap:wrap">

          <span class="resource-status" style="${resStatusStyle[r.status]||''}">${resStatusLabel[r.status]||r.status}</span>

          <button class="btn btn-ghost btn-sm" onclick="cycleResourceStatus(${r.id})">Change status</button>

          <button class="btn-icon" onclick="openEditResource(${r.id})" title="Edit">✎</button>

          <button class="btn-icon" onclick="confirmDeleteResourceById(${r.id})" title="Delete" style="color:var(--red)">✕</button>

        </div>

      </div>

    </div>`;

  };


  document.getElementById('resources-needed-list').innerHTML=notObtained.length?notObtained.map(resCard).join(''):'<div class="empty-state"><div class="ei">📚</div><p>No resources here. Add a textbook, link, or tool!</p></div>';


  if(obtained.length){

    document.getElementById('resources-obtained-section').style.display='block';

    document.getElementById('resources-obtained-list').innerHTML=obtained.map(resCard).join('');

  } else { document.getElementById('resources-obtained-section').style.display='none'; }


  document.querySelectorAll('.res-filter-btn').forEach(b=>b.classList.toggle('active',b.dataset.rf===activeResFilter));

}


document.getElementById('res-filter-bar').addEventListener('click',e=>{const b=e.target.closest('.res-filter-btn');if(b){activeResFilter=b.dataset.rf;renderResources();}});


function cycleResourceStatus(id){const r=RESOURCES.find(x=>x.id===id);if(!r)return;r.status={needed:'pending',pending:'obtained',obtained:'needed'}[r.status]||'needed';renderResources();}


function loadResAssignments(){

  const cid=parseInt(document.getElementById('fr-course').value)||null;

  const sel=document.getElementById('fr-assignment');

  const asgns=cid?ASSIGNMENTS.filter(a=>a.courseId===cid):[];

  sel.innerHTML='<option value="">— None —</option>'+asgns.map(a=>`<option value="${a.id}">${a.title}</option>`).join('');

}


// ══════════════════════════════════════════════════════

//  CONTACTS

// ══════════════════════════════════════════════════════

const roleColors={professor:'background:var(--accent-bg);color:var(--accent)',ta:'background:var(--teal-bg);color:var(--teal)',member:'background:var(--amber-bg);color:var(--amber)',other:'background:var(--bg4);color:var(--text2)'};

const roleLabels={professor:'Professor',ta:'TA',member:'Group Member',other:'Other'};


function renderContacts(){

  let list=[...CONTACTS];

  if(activeContactFilter!=='all')list=list.filter(c=>c.role===activeContactFilter);

  document.getElementById('contacts-list').innerHTML=list.length?list.map(c=>{

    const initials=c.name.split(' ').slice(0,2).map(w=>w[0]).join('').toUpperCase();

    const hue={professor:240,ta:180,member:40,other:0}[c.role]||200;

    return`<div class="contact-card">

      <div class="contact-avatar" style="background:hsl(${hue},60%,${document.documentElement.dataset.theme==='dark'?'30%':'70%'});color:hsl(${hue},80%,${document.documentElement.dataset.theme==='dark'?'80%':'20%'})">${initials}</div>

      <div class="contact-info">

        <div class="contact-name">${c.name}</div>

        <div class="contact-meta">${c.email||''}${c.notes?' · '+c.notes:''}</div>

      </div>

      <span class="contact-role-badge" style="${roleColors[c.role]||''}">${roleLabels[c.role]||c.role}</span>

      <div class="row-actions" style="opacity:1">

        <button class="btn-icon" onclick="openEditContact(${c.id})" title="Edit">✎</button>

        <button class="btn-icon" onclick="confirmDeleteContactById(${c.id})" title="Delete" style="color:var(--red)">✕</button>

      </div>

    </div>`;

  }).join(''):'<div class="empty-state"><div class="ei">👥</div><p>No contacts yet</p></div>';

  document.querySelectorAll('.contact-filter-btn').forEach(b=>b.classList.toggle('active',b.dataset.cf===activeContactFilter));

}


document.getElementById('contact-filter-bar').addEventListener('click',e=>{const b=e.target.closest('.contact-filter-btn');if(b){activeContactFilter=b.dataset.cf;renderContacts();}});


// ══════════════════════════════════════════════════════

//  AI CHAT — Lyra

// ══════════════════════════════════════════════════════

function initChat(){

  const c=document.getElementById('chat-messages');

  if(c.children.length===0)appendMessage('ai',`Hi Jamie! I'm **Lyra** — your personal academic advisor. 👋


Here's your snapshot for this week:\n\n**📊 STAT 301** — 68% (midterm only). Big 40% final ahead.\n**⚗️ CHEM 202** — Most urgent. At-risk of failing.\n**✅ ENGL 215 & HIST 210** — Both on or above target.\n**🔢 MATH 340** — Small gap vs. target, closeable.\n\n**${ASSIGNMENTS.filter(isOverdue).length} overdue assignments** need attention. What would you like to work through?`);

}


function appendMessage(role,content){

  const c=document.getElementById('chat-messages');

  const div=document.createElement('div');div.className=`msg ${role==='user'?'user':'ai'}`;

  const fmtd=content.replace(/\*\*(.+?)\*\*/g,'<strong>$1</strong>').replace(/\n\n/g,'</p><p>').replace(/\n/g,'<br>');

  div.innerHTML=`<div class="msg-avatar ${role==='user'?'user-av':'ai'}">${role==='user'?'JD':'✦'}</div><div><div class="msg-bubble"><p>${fmtd}</p></div><div class="msg-time">${new Date().toLocaleTimeString('en-US',{hour:'2-digit',minute:'2-digit'})}</div></div>`;

  c.appendChild(div);c.scrollTop=c.scrollHeight;

}

function showTyping(){const c=document.getElementById('chat-messages');const d=document.createElement('div');d.className='msg ai';d.id='typing-msg';d.innerHTML=`<div class="msg-avatar ai">✦</div><div class="typing-indicator"><div class="typing-dot"></div><div class="typing-dot"></div><div class="typing-dot"></div></div>`;c.appendChild(d);c.scrollTop=c.scrollHeight;}

function hideTyping(){const e=document.getElementById('typing-msg');if(e)e.remove();}


const AI_R={

  stat:`Here's your **STAT 301** breakdown:\n\n**Graded:** Midterm (30%) scored 68% → contributes 20.4%\n**Remaining:** HW3 overdue (10%), Final Exam (40%)\n**Projected: ~68%** at current trajectory\n\nTo hit **85%**: need ~96% on Final + full HW3 credit — ambitious but possible.\nMore realistic: **74–78%**.\n\nShall I map out a study plan for the final?`,

  final:`**Grade math for STAT 301** (40% final remaining):\n\n| Goal | Final score needed |\n|---|---|\n| 90% (A) | ~99% — unlikely |\n| 85% (B) | ~87% — stretch |\n| 80% (B-) | ~74% — achievable |\n| 75% (C) | ~61% — within reach |\n\nFocus on probability distributions and hypothesis testing.`,

  attention:`Priority order right now:\n\n1. 🚨 **CHEM 202** — Below passing, 2 overdue, difficulty-5\n2. ⚠️ **STAT 301** — Below target, big final coming\n3. 📐 **MATH 340** — Minor gap, close with consistency\n4. ✅ **HIST 210 & ENGL 215** — Don't over-invest`,

  schedule:`**Suggested schedule this week:**\n\nMon–Tue: CHEM 202 (2h/day) — mechanisms + Lab Report 4\nWed: STAT 301 (2h) + MATH 340 (1h) — HW3 + Problem Set 5\nThu: CHEM quiz prep (1.5h) + ENGL draft (1.5h)\nFri–Weekend: HIST essay outline (2h) + STAT review (1.5h)\n\n**Total: ~16.5 hrs** ↑ from current pace`,

  gpa:`**Projected semester GPA at current trajectory:**\n\nSTAT 301 (C) + CHEM 202 (D) + HIST 210 (B+) + MATH 340 (C+) + ENGL 215 (A-)\n\n**Projected: ~2.37** — would pull your cumulative GPA down from 3.4.\n\nChemistry is make-or-break. Getting a C instead of D → ~2.64 semester GPA.`

};


async function sendChat(){

  const inp=document.getElementById('chat-input');const msg=inp.value.trim();if(!msg)return;

  inp.value='';appendMessage('user',msg);showTyping();

  document.getElementById('quick-prompts').style.display='none';

  await new Promise(r=>setTimeout(r,700+Math.random()*500));hideTyping();

  const l=msg.toLowerCase();

  const reply=l.includes('stat')||l.includes('likely')?AI_R.stat:l.includes('final')||l.includes('need')?AI_R.final:l.includes('attention')||l.includes('most')?AI_R.attention:l.includes('schedule')||l.includes('plan')||l.includes('week')?AI_R.schedule:l.includes('gpa')||l.includes('track')?AI_R.gpa:`I've reviewed your data. Most urgent: **CHEM 202** and **STAT 301**.\n\nTry: "Which course needs most attention?" or "Build a study schedule"`;

  appendMessage('ai',reply);

}

function sendQuick(el){document.getElementById('chat-input').value=el.textContent;sendChat();}

function handleChatKey(e){if(e.key==='Enter'&&!e.shiftKey){e.preventDefault();sendChat();}}

function clearChat(){document.getElementById('chat-messages').innerHTML='';document.getElementById('quick-prompts').style.display='flex';initChat();}

function askLyraAbout(name){nav('chat');setTimeout(()=>{document.getElementById('chat-input').value=`What's my projected grade in ${name} and how can I improve it?`;document.getElementById('chat-input').focus();},80);}


// ══════════════════════════════════════════════════════

//  INSIGHTS

// ══════════════════════════════════════════════════════

function dismissInsight(id){

  const i=INSIGHTS.find(x=>x.id===id);if(!i)return;i.dismissed=true;

  ['dflag-'+id,'insight-'+id].forEach(eid=>{const el=document.getElementById(eid);if(el){el.style.transition='opacity 0.25s';el.style.opacity='0';setTimeout(()=>el.remove(),260);}});

  updateBadge();

  setTimeout(()=>{renderDashboard();if(document.getElementById('page-insights').classList.contains('active'))renderInsights();},300);

}


function renderInsights(){

  const active=INSIGHTS.filter(i=>!i.dismissed);

  const sections=[

    {label:'🚨 Alerts',items:active.filter(i=>i.severity==='alert'),color:'var(--red)',bg:'var(--red-bg)'},

    {label:'⚠️ Warnings',items:active.filter(i=>i.severity==='warn'),color:'var(--amber)',bg:'var(--amber-bg)'},

    {label:'💡 Insights',items:active.filter(i=>i.severity==='info'),color:'var(--accent)',bg:'var(--accent-bg)'},

  ];

  document.getElementById('insights-body').innerHTML=sections.map(sec=>`

    <div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:9px"><div class="section-title">${sec.label}</div><span style="font-size:9px;color:var(--text3)">${sec.items.length} item${sec.items.length!==1?'s':''}</span></div>

    ${sec.items.length?sec.items.map(i=>{const c=getCourse(i.courseId);return`<div class="insight-card" id="insight-${i.id}">

      <div class="insight-icon-wrap" style="background:${sec.bg}"><span>${i.severity==='alert'?'🚨':i.severity==='warn'?'⚠️':i.type==='prediction'?'🔮':'💡'}</span></div>

      <div style="flex:1"><div class="insight-title">${i.title}</div><div class="insight-desc">${i.desc}</div>

        <div class="insight-meta">${c?`<span style="display:inline-flex;align-items:center;gap:3px"><span style="width:5px;height:5px;border-radius:50%;background:${c.color};display:inline-block"></span>${c.code}</span>`:''}<span class="severity-badge" style="background:${sec.bg};color:${sec.color}">${i.severity.toUpperCase()}</span><button class="btn btn-ghost btn-sm" onclick="askLyraAbout('${c?.name||''}')">Ask Lyra →</button><button class="insight-dismiss" onclick="dismissInsight(${i.id})">Dismiss ✕</button></div>

      </div>

    </div>`;}).join(''):`<div style="font-size:11px;color:var(--text3);padding:5px 0 12px">All clear ✅</div>`}

    <div style="height:4px"></div>`).join('');

}


// ══════════════════════════════════════════════════════

//  MODALS

// ══════════════════════════════════════════════════════

function openModal(n){document.getElementById('modal-'+n).classList.add('open');}

function closeModal(n){document.getElementById('modal-'+n).classList.remove('open');}

document.querySelectorAll('.modal-overlay').forEach(m=>{m.addEventListener('click',e=>{if(e.target===m)m.classList.remove('open');});});


// Color pickers

document.getElementById('color-picker').addEventListener('click',e=>{const sw=e.target.closest('.color-swatch');if(!sw)return;document.querySelectorAll('#color-picker .color-swatch').forEach(s=>s.classList.remove('selected'));sw.classList.add('selected');selectedColor=sw.dataset.color;});

document.getElementById('prog-color-picker').addEventListener('click',e=>{const sw=e.target.closest('.color-swatch');if(!sw)return;document.querySelectorAll('#prog-color-picker .color-swatch').forEach(s=>s.classList.remove('selected'));sw.classList.add('selected');selectedProgColor=sw.dataset.color;});


// Year dropdowns

(()=>{[['fc-year',2026],['fp-start',2023],['fp-end',2027]].forEach(([id,def])=>{const s=document.getElementById(id);for(let y=2018;y<=2035;y++){const o=document.createElement('option');o.value=y;o.textContent=y;if(y===def)o.selected=true;s.appendChild(o);}});})();


// Autocomplete

function acFilter(type,val){

  if(!val||val.length<1){document.getElementById('ac-'+type).style.display='none';return;}

  const roles={professor:['professor'],ta:['ta'],member:['professor','ta','member']};

  const matches=CONTACTS.filter(c=>(roles[type]||[]).includes(c.role)&&c.name.toLowerCase().includes(val.toLowerCase())).slice(0,6);

  const list=document.getElementById('ac-'+type);

  if(!matches.length){list.style.display='none';return;}

  list.innerHTML=matches.map(c=>`<div class="autocomplete-item" onclick="acSelect('${type}','${c.name}')">${c.name}${c.email?` <span style="color:var(--text3);font-size:9px">${c.email}</span>`:''}</div>`).join('');

  list.style.display='block';

}

function acSelect(type,val){if(type==='professor')document.getElementById('fc-professor').value=val;else if(type==='ta')document.getElementById('fc-ta').value=val;document.getElementById('ac-'+type).style.display='none';}

document.addEventListener('click',e=>{if(!e.target.closest('.autocomplete-wrap'))document.querySelectorAll('.autocomplete-list').forEach(l=>l.style.display='none');});


// ══ PROGRAM CRUD ══

function openProgramModal(){

  editingProgramId=null;selectedProgColor='#6c8eff';

  document.getElementById('prog-modal-title').textContent='Add Program';

  document.getElementById('prog-save-btn').textContent='Add Program';

  document.getElementById('del-prog-btn').style.display='none';

  document.getElementById('ep-id').value='';

  ['fp-name','fp-institution'].forEach(id=>document.getElementById(id).value='');

  document.getElementById('fp-type').value='Degree';

  document.getElementById('fp-start').value=2023; document.getElementById('fp-end').value=2027;

  document.querySelectorAll('#prog-color-picker .color-swatch').forEach(s=>s.classList.toggle('selected',s.dataset.color===selectedProgColor));

  openModal('program');

}

function openEditProgram(id){

  const p=PROGRAMS.find(x=>x.id===id);if(!p)return;

  editingProgramId=id;selectedProgColor=p.color;

  document.getElementById('prog-modal-title').textContent='Edit Program';

  document.getElementById('prog-save-btn').textContent='Save';

  document.getElementById('del-prog-btn').style.display='inline-flex';

  document.getElementById('ep-id').value=id;

  document.getElementById('fp-name').value=p.name;

  document.getElementById('fp-institution').value=p.institution;

  document.getElementById('fp-type').value=p.type;

  document.getElementById('fp-start').value=p.start; document.getElementById('fp-end').value=p.end;

  document.querySelectorAll('#prog-color-picker .color-swatch').forEach(s=>s.classList.toggle('selected',s.dataset.color===p.color));

  openModal('program');

}

function saveProgram(){

  const name=document.getElementById('fp-name').value.trim();if(!name)return;

  const data={name,institution:document.getElementById('fp-institution').value.trim(),type:document.getElementById('fp-type').value,start:parseInt(document.getElementById('fp-start').value),end:parseInt(document.getElementById('fp-end').value),color:selectedProgColor};

  if(editingProgramId)Object.assign(PROGRAMS.find(x=>x.id===editingProgramId),data);

  else PROGRAMS.push({id:Date.now(),...data});

  closeModal('program');renderPrograms();

}

function confirmDeleteProgram(){

  const p=PROGRAMS.find(x=>x.id===editingProgramId);if(!p)return;

  document.getElementById('confirm-title').textContent=`Delete "${p.name}"?`;

  document.getElementById('confirm-desc').textContent='Courses linked to this program will be unlinked.';

  document.getElementById('confirm-ok').onclick=()=>{PROGRAMS=PROGRAMS.filter(x=>x.id!==editingProgramId);COURSES.forEach(c=>{if(c.programId===editingProgramId)c.programId=null;});closeModal('program');closeModal('confirm');renderPrograms();};

  openModal('confirm');

}

function addProgramTask(programId){

  const title=prompt('Program task name:'); if(!title)return;

  PROGRAM_TASKS.push({id:Date.now(),programId,title,done:false});renderPrograms();

}


// ══ COURSE CRUD ══

function openCourseModal(preselectedId,preselectedProgramId){

  editingCourseId=null;selectedColor='#6c8eff';

  document.getElementById('course-modal-title').textContent='Add Course';

  document.getElementById('course-save-btn').textContent='Add Course';

  document.getElementById('del-course-btn').style.display='none';

  document.getElementById('ec-id').value='';

  ['fc-name','fc-code','fc-professor','fc-ta'].forEach(id=>document.getElementById(id).value='');

  document.getElementById('fc-credits').value=''; document.getElementById('fc-target').value='';

  document.getElementById('fc-difficulty').value='3';

  document.getElementById('fc-term').value='Spring'; document.getElementById('fc-year').value=2026;

  document.getElementById('fc-program').innerHTML='<option value="">— None —</option>'+PROGRAMS.map(p=>`<option value="${p.id}"${p.id===preselectedProgramId?' selected':''}>${p.name}</option>`).join('');

  document.querySelectorAll('#color-picker .color-swatch').forEach(s=>s.classList.toggle('selected',s.dataset.color===selectedColor));

  openModal('course');

}

function openEditCourse(id){

  const c=getCourse(id);if(!c)return;

  editingCourseId=id;selectedColor=c.color;

  document.getElementById('course-modal-title').textContent='Edit Course';

  document.getElementById('course-save-btn').textContent='Save';

  document.getElementById('del-course-btn').style.display='inline-flex';

  document.getElementById('ec-id').value=id;

  document.getElementById('fc-name').value=c.name; document.getElementById('fc-code').value=c.code;

  document.getElementById('fc-credits').value=c.credits; document.getElementById('fc-target').value=c.target;

  document.getElementById('fc-difficulty').value=c.difficulty; document.getElementById('fc-term').value=c.term||'Spring';

  document.getElementById('fc-year').value=c.year||2026; document.getElementById('fc-professor').value=c.professor||'';

  document.getElementById('fc-ta').value=c.ta||'';

  document.getElementById('fc-program').innerHTML='<option value="">— None —</option>'+PROGRAMS.map(p=>`<option value="${p.id}"${p.id===c.programId?' selected':''}>${p.name}</option>`).join('');

  document.querySelectorAll('#color-picker .color-swatch').forEach(s=>s.classList.toggle('selected',s.dataset.color===c.color));

  openModal('course');

}

function saveCourse(){

  const name=document.getElementById('fc-name').value.trim();if(!name)return;

  const prof=document.getElementById('fc-professor').value.trim();

  if(prof&&!CONTACTS.find(c=>c.name===prof))CONTACTS.push({id:Date.now(),name:prof,role:'professor',email:'',notes:''});

  const ta=document.getElementById('fc-ta').value.trim();

  if(ta&&!CONTACTS.find(c=>c.name===ta))CONTACTS.push({id:Date.now()+1,name:ta,role:'ta',email:'',notes:''});

  const data={name,code:document.getElementById('fc-code').value.trim(),credits:parseInt(document.getElementById('fc-credits').value)||3,target:parseInt(document.getElementById('fc-target').value)||85,difficulty:parseInt(document.getElementById('fc-difficulty').value)||3,term:document.getElementById('fc-term').value,year:parseInt(document.getElementById('fc-year').value)||2026,professor:prof,ta,color:selectedColor,programId:parseInt(document.getElementById('fc-program').value)||null};

  if(editingCourseId)Object.assign(getCourse(editingCourseId),data);

  else COURSES.push({id:Date.now(),...data});

  closeModal('course');renderDashboard();renderCourses();

}

function confirmDeleteCourse(){

  const c=getCourse(editingCourseId);if(!c)return;

  document.getElementById('confirm-title').textContent=`Delete "${c.name}"?`;

  document.getElementById('confirm-desc').textContent='All assignments for this course will also be removed.';

  document.getElementById('confirm-ok').onclick=()=>{COURSES=COURSES.filter(x=>x.id!==editingCourseId);ASSIGNMENTS=ASSIGNMENTS.filter(a=>a.courseId!==editingCourseId);closeModal('course');closeModal('confirm');renderDashboard();renderCourses();};

  openModal('confirm');

}


// ══ ASSIGNMENT CRUD ══

function loadAsgnProgramTask(){

  const cid=parseInt(document.getElementById('fa-course').value)||null;

  const c=getCourse(cid); const pid=c?.programId;

  const tasks=pid?PROGRAM_TASKS.filter(t=>t.programId===pid):[];

  document.getElementById('fa-program-task').innerHTML='<option value="">— None —</option>'+tasks.map(t=>`<option value="${t.id}">${t.title}</option>`).join('');

}

function openAssignmentModal(preselectedCourseId){

  editingAssignmentId=null;

  document.getElementById('asgn-modal-title').textContent='Add Assignment';

  document.getElementById('asgn-save-btn').textContent='Add Assignment';

  document.getElementById('del-asgn-btn').style.display='none';

  document.getElementById('ea-id').value='';

  document.getElementById('fa-title').value=''; document.getElementById('fa-due').value=fmt(today);

  document.getElementById('fa-weight').value=''; document.getElementById('fa-score').value='';

  document.getElementById('fa-possible').value='100'; document.getElementById('fa-status').value='pending';

  document.getElementById('fa-type').value='Exam'; document.getElementById('fa-notes').value='';

  document.getElementById('fa-group-type').value='individual';

  document.getElementById('fa-course').innerHTML=COURSES.map(c=>`<option value="${c.id}"${c.id===preselectedCourseId?' selected':''}>${c.name}</option>`).join('');

  loadAsgnProgramTask();

  openModal('assignment');

}

function openEditAssignment(id){

  const a=ASSIGNMENTS.find(x=>x.id===id);if(!a)return;

  editingAssignmentId=id;

  document.getElementById('asgn-modal-title').textContent='Edit Assignment';

  document.getElementById('asgn-save-btn').textContent='Save';

  document.getElementById('del-asgn-btn').style.display='inline-flex';

  document.getElementById('ea-id').value=id;

  document.getElementById('fa-title').value=a.title; document.getElementById('fa-due').value=a.due;

  document.getElementById('fa-weight').value=a.weight; document.getElementById('fa-score').value=a.score??'';

  document.getElementById('fa-possible').value=a.possible; document.getElementById('fa-status').value=a.status==='done'?'done':'pending';

  document.getElementById('fa-type').value=a.type; document.getElementById('fa-notes').value=a.notes||'';

  document.getElementById('fa-group-type').value=a.groupType||'individual';

  document.getElementById('fa-course').innerHTML=COURSES.map(c=>`<option value="${c.id}"${c.id===a.courseId?' selected':''}>${c.name}</option>`).join('');

  loadAsgnProgramTask();

  openModal('assignment');

}

function saveAssignment(){

  const title=document.getElementById('fa-title').value.trim();if(!title)return;

  const due=document.getElementById('fa-due').value;if(!due){alert('Due date is required — it\'s used to calculate overdue status automatically.');return;}

  const scoreVal=document.getElementById('fa-score').value;

  const status=document.getElementById('fa-status').value;

  const data={title,courseId:parseInt(document.getElementById('fa-course').value),type:document.getElementById('fa-type').value,due,weight:parseFloat(document.getElementById('fa-weight').value)||10,score:scoreVal!==''?parseFloat(scoreVal):null,possible:parseFloat(document.getElementById('fa-possible').value)||100,status,notes:document.getElementById('fa-notes').value.trim(),groupType:document.getElementById('fa-group-type').value,programTaskId:parseInt(document.getElementById('fa-program-task').value)||null,completedAt:status==='done'?fmt(today):null};

  if(editingAssignmentId)Object.assign(ASSIGNMENTS.find(x=>x.id===editingAssignmentId),data);

  else ASSIGNMENTS.push({id:Date.now(),createdAt:fmt(today),...data});

  closeModal('assignment');renderAssignments();renderDashboard();renderCourses();

}

function confirmDeleteAssignmentById(id,fromModal){

  const aid=id||(fromModal?parseInt(document.getElementById('ea-id').value):null);if(!aid)return;

  const a=ASSIGNMENTS.find(x=>x.id===aid);if(!a)return;

  document.getElementById('confirm-title').textContent=`Delete "${a.title}"?`;

  document.getElementById('confirm-desc').textContent='Grade data will be removed.';

  document.getElementById('confirm-ok').onclick=()=>{ASSIGNMENTS=ASSIGNMENTS.filter(x=>x.id!==aid);closeModal('assignment');closeModal('confirm');renderAssignments();renderDashboard();renderCourses();};

  openModal('confirm');

}


// ══ TASK CRUD ══

function openTaskModal(){

  editingTaskId=null;

  document.getElementById('task-modal-title').textContent='Add Task';

  document.getElementById('task-save-btn').textContent='Add Task';

  document.getElementById('del-task-btn').style.display='none';

  document.getElementById('et-id').value='';

  document.getElementById('ft-title').value=''; document.getElementById('ft-due').value='';

  document.getElementById('ft-priority').value='medium'; document.getElementById('ft-notes').value='';

  document.getElementById('ft-course').innerHTML='<option value="">— None —</option>'+COURSES.map(c=>`<option value="${c.id}">${c.name}</option>`).join('');

  openModal('task');

}

function openEditTask(id){

  const t=TASKS.find(x=>x.id===id);if(!t)return;

  editingTaskId=id;

  document.getElementById('task-modal-title').textContent='Edit Task';

  document.getElementById('task-save-btn').textContent='Save';

  document.getElementById('del-task-btn').style.display='inline-flex';

  document.getElementById('et-id').value=id;

  document.getElementById('ft-title').value=t.title; document.getElementById('ft-due').value=t.due||'';

  document.getElementById('ft-priority').value=t.priority; document.getElementById('ft-notes').value=t.notes||'';

  document.getElementById('ft-course').innerHTML='<option value="">— None —</option>'+COURSES.map(c=>`<option value="${c.id}"${c.id===t.courseId?' selected':''}>${c.name}</option>`).join('');

  openModal('task');

}

function saveTask(){

  const title=document.getElementById('ft-title').value.trim();if(!title)return;

  const data={title,due:document.getElementById('ft-due').value||null,priority:document.getElementById('ft-priority').value,courseId:parseInt(document.getElementById('ft-course').value)||null,notes:document.getElementById('ft-notes').value.trim(),status:'pending',completedAt:null};

  if(editingTaskId)Object.assign(TASKS.find(x=>x.id===editingTaskId),data);

  else TASKS.push({id:Date.now(),createdAt:fmt(today),...data});

  closeModal('task');renderTasks();renderDashboard();

}

function confirmDeleteTask(){confirmDeleteTaskById(editingTaskId,true);}

function confirmDeleteTaskById(id,fromModal){

  const tid=id||(fromModal?parseInt(document.getElementById('et-id').value):null);if(!tid)return;

  const t=TASKS.find(x=>x.id===tid);if(!t)return;

  document.getElementById('confirm-title').textContent=`Delete "${t.title}"?`;

  document.getElementById('confirm-desc').textContent='This task will be permanently removed.';

  document.getElementById('confirm-ok').onclick=()=>{TASKS=TASKS.filter(x=>x.id!==tid);closeModal('task');closeModal('confirm');renderTasks();renderDashboard();};

  openModal('confirm');

}


// ══ RESOURCE CRUD ══

function openResourceModal(){

  editingResourceId=null;

  document.getElementById('res-modal-title').textContent='Add Resource';

  document.getElementById('res-save-btn').textContent='Add Resource';

  document.getElementById('del-res-btn').style.display='none';

  document.getElementById('er-id').value='';

  ['fr-title','fr-url','fr-notes'].forEach(id=>document.getElementById(id).value='');

  document.getElementById('fr-type').value='Book'; document.getElementById('fr-status').value='needed';

  document.getElementById('fr-course').innerHTML='<option value="">— None —</option>'+COURSES.map(c=>`<option value="${c.id}">${c.name}</option>`).join('');

  document.getElementById('fr-assignment').innerHTML='<option value="">— None —</option>';

  openModal('resource');

}

function openEditResource(id){

  const r=RESOURCES.find(x=>x.id===id);if(!r)return;

  editingResourceId=id;

  document.getElementById('res-modal-title').textContent='Edit Resource';

  document.getElementById('res-save-btn').textContent='Save';

  document.getElementById('del-res-btn').style.display='inline-flex';

  document.getElementById('er-id').value=id;

  document.getElementById('fr-title').value=r.title; document.getElementById('fr-url').value=r.url||'';

  document.getElementById('fr-notes').value=r.notes||''; document.getElementById('fr-type').value=r.type;

  document.getElementById('fr-status').value=r.status;

  document.getElementById('fr-course').innerHTML='<option value="">— None —</option>'+COURSES.map(c=>`<option value="${c.id}"${c.id===r.courseId?' selected':''}>${c.name}</option>`).join('');

  const asgns=r.courseId?ASSIGNMENTS.filter(a=>a.courseId===r.courseId):[];

  document.getElementById('fr-assignment').innerHTML='<option value="">— None —</option>'+asgns.map(a=>`<option value="${a.id}"${a.id===r.assignmentId?' selected':''}>${a.title}</option>`).join('');

  openModal('resource');

}

function saveResource(){

  const title=document.getElementById('fr-title').value.trim();if(!title)return;

  const data={title,type:document.getElementById('fr-type').value,status:document.getElementById('fr-status').value,url:document.getElementById('fr-url').value.trim(),courseId:parseInt(document.getElementById('fr-course').value)||null,assignmentId:parseInt(document.getElementById('fr-assignment').value)||null,notes:document.getElementById('fr-notes').value.trim()};

  if(editingResourceId)Object.assign(RESOURCES.find(x=>x.id===editingResourceId),data);

  else RESOURCES.push({id:Date.now(),...data});

  closeModal('resource');renderResources();

}

function confirmDeleteResource(){confirmDeleteResourceById(editingResourceId,true);}

function confirmDeleteResourceById(id,fromModal){

  const rid=id||(fromModal?parseInt(document.getElementById('er-id').value):null);if(!rid)return;

  const r=RESOURCES.find(x=>x.id===rid);if(!r)return;

  document.getElementById('confirm-title').textContent=`Delete "${r.title}"?`;

  document.getElementById('confirm-desc').textContent='This resource will be permanently removed.';

  document.getElementById('confirm-ok').onclick=()=>{RESOURCES=RESOURCES.filter(x=>x.id!==rid);closeModal('resource');closeModal('confirm');renderResources();};

  openModal('confirm');

}


// ══ CONTACT CRUD ══

function openContactModal(){

  editingContactId=null;

  document.getElementById('contact-modal-title').textContent='Add Contact';

  document.getElementById('contact-save-btn').textContent='Add Contact';

  document.getElementById('del-contact-btn').style.display='none';

  document.getElementById('econ-id').value='';

  ['fcon-name','fcon-email','fcon-notes'].forEach(id=>document.getElementById(id).value='');

  document.getElementById('fcon-role').value='professor';

  openModal('contact');

}

function openEditContact(id){

  const c=CONTACTS.find(x=>x.id===id);if(!c)return;

  editingContactId=id;

  document.getElementById('contact-modal-title').textContent='Edit Contact';

  document.getElementById('contact-save-btn').textContent='Save';

  document.getElementById('del-contact-btn').style.display='inline-flex';

  document.getElementById('econ-id').value=id;

  document.getElementById('fcon-name').value=c.name; document.getElementById('fcon-email').value=c.email||'';

  document.getElementById('fcon-notes').value=c.notes||''; document.getElementById('fcon-role').value=c.role;

  openModal('contact');

}

function saveContact(){

  const name=document.getElementById('fcon-name').value.trim();if(!name)return;

  const data={name,role:document.getElementById('fcon-role').value,email:document.getElementById('fcon-email').value.trim(),notes:document.getElementById('fcon-notes').value.trim()};

  if(editingContactId)Object.assign(CONTACTS.find(x=>x.id===editingContactId),data);

  else CONTACTS.push({id:Date.now(),...data});

  closeModal('contact');renderContacts();

}

function confirmDeleteContact(){confirmDeleteContactById(editingContactId);}

function confirmDeleteContactById(id){

  const c=CONTACTS.find(x=>x.id===id);if(!c)return;

  document.getElementById('confirm-title').textContent=`Delete "${c.name}"?`;

  document.getElementById('confirm-desc').textContent='They will be removed from your contacts list.';

  document.getElementById('confirm-ok').onclick=()=>{CONTACTS=CONTACTS.filter(x=>x.id!==id);closeModal('contact');closeModal('confirm');renderContacts();};

  openModal('confirm');

}


// ══════════════════════════════════════════════════════

//  INIT

// ══════════════════════════════════════════════════════

document.getElementById('show-completed-toggle').checked=SETTINGS.showCompleted;

renderDashboard();

updateBadge();

updateTimerDisplay();

const h=new Date().getHours();

document.getElementById('dash-greeting').textContent=`${h<12?'Good morning':h<17?'Good afternoon':'Good evening'}, Jamie 👋`;

</script>

</body>

</html>