<?php
require_once __DIR__ . '/includes/config.php';
requireLogin();
$user        = currentUser();
$currentPage = 'tasks';
$pageTitle   = 'Tasks';

// ── Load all tasks ─────────────────────────────────────────────────
$stmt = db()->prepare('
    SELECT * FROM tasks
    WHERE user_id = ?
    ORDER BY
        FIELD(priority,"urgent","high","medium","low"),
        CASE WHEN due_date IS NULL THEN 1 ELSE 0 END,
        due_date ASC, created_at DESC
');
$stmt->execute([$user['id']]);
$allTasks = $stmt->fetchAll();

$columns = ['todo' => [], 'in_progress' => [], 'done' => []];
foreach ($allTasks as $t) { $columns[$t['status']][] = $t; }

$total    = count($allTasks);
$done     = count($columns['done']);
$today    = date('Y-m-d');
$overdue  = 0; $dueToday = 0;
foreach ($allTasks as $t) {
    if ($t['due_date'] && $t['status'] !== 'done') {
        if ($t['due_date'] < $today)  $overdue++;
        if ($t['due_date'] === $today) $dueToday++;
    }
}
$pct = $total > 0 ? round($done / $total * 100) : 0;
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>Tasks – SPACE</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=Poppins:wght@300;400;500;600;700;800&display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/boxicons@2.1.4/css/boxicons.min.css">
<link rel="stylesheet" href="assets/css/main.css">
<meta name="csrf-token" content="<?= e(csrfToken()) ?>">
<style>
/* ══════════════════════════════════════════════════
   ROOT OVERRIDES
 ══════════════════════════════════════════════════ */
:root {
  --indigo: #6366f1; --amber: #f59e0b;
  --green: #22c55e;  --red: #ef4444;
}

/* Base button styles - no tap highlight */
button, .f-btn, .col-plus, .tc-check, .tc-mini, .sb, .pb, .mv-btn, .sfb, .sh-close, .f-btn, .btn {
  -webkit-tap-highlight-color: transparent;
}

.main-content {
  padding: 0; display: flex; flex-direction: column;
  height: 100vh; overflow: hidden;
}
@media (max-width: 768px) {
  .main-content { height: calc(100dvh - 72px); }
}

/* ══════════════════════════════════════════════════
   TOP BAR
══════════════════════════════════════════════════ */
.tasks-topbar {
  flex-shrink: 0; padding: 22px 24px 0;
  background: var(--bg); z-index: 20;
}
@media (max-width: 768px) { .tasks-topbar { padding: 14px 16px 0; } }

.tasks-heading-row {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 12px;
}
.tasks-heading-row h1 { font-size: clamp(20px, 2.8vw, 26px); font-weight: 800; line-height: 1.1; }
.tasks-heading-row .sub { font-size: 12px; color: var(--muted); margin-top: 3px; }

/* Stats chips */
.stats-row {
  display: flex; gap: 10px; margin: 14px 0 12px;
  overflow-x: auto; -ms-overflow-style: none; scrollbar-width: none;
}
.stats-row::-webkit-scrollbar { display: none; }
.s-chip {
  flex-shrink: 0; display: flex; align-items: center; gap: 7px;
  background: #fff; border: 1px solid #e5e5e5;
  border-radius: 50px; padding: 8px 14px;
  font-size: 11px; font-weight: 600; white-space: nowrap;
}
.s-chip i { font-size: 15px; }
.s-chip .n { font-size: 15px; font-weight: 800; }
.s-chip.prog { padding: 6px 14px 6px 8px; gap: 10px; }
.ring-wrap { position: relative; width: 32px; height: 32px; flex-shrink: 0; }
.ring-wrap svg { transform: rotate(-90deg); }
.ring-bg   { fill: none; stroke: var(--dark); stroke-width: 4; }
.ring-fill { fill: none; stroke: var(--indigo); stroke-width: 4; stroke-linecap: round; transition: stroke-dashoffset .6s; }
.ring-pct  {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  font-size: 8px; font-weight: 800;
}

/* Filter bar */
.filter-bar {
  display: flex; align-items: center; gap: 8px; padding-bottom: 12px;
  overflow-x: auto; -ms-overflow-style: none; scrollbar-width: none;
}
.filter-bar::-webkit-scrollbar { display: none; }
.f-search {
  flex-shrink: 0; display: flex; align-items: center; gap: 6px;
  background: var(--bg); box-shadow: var(--neu-in); border-radius: 50px;
  padding: 7px 14px; min-width: 120px; max-width: 170px;
}
.f-search input {
  background: none; border: none; outline: none;
  font-family: 'Poppins', sans-serif; font-size: 11px; color: var(--text); width: 100%;
}
.f-search input::placeholder { color: #bbb; }
.f-search i { font-size: 13px; color: #bbb; flex-shrink: 0; }
.f-btn {
  flex-shrink: 0; padding: 7px 14px; border-radius: 50px;
  background: #fff; border: 1px solid #e5e5e5;
  font-size: 11px; font-weight: 600; color: #888; border: none; cursor: pointer;
  font-family: 'Poppins', sans-serif; transition: .15s;
  display: flex; align-items: center; gap: 5px;
}
.f-btn:active { background: #f0f0f0; }
.f-btn.on { background: var(--text); color: var(--bg); border-color: var(--text); }
.f-btn i { font-size: 13px; }

/* ══════════════════════════════════════════════════
   KANBAN BOARD
══════════════════════════════════════════════════ */
.board {
  flex: 1; min-height: 0; display: flex; gap: 14px;
  overflow-x: auto; overflow-y: hidden;
  padding: 0 24px 16px; align-items: stretch;
  scroll-snap-type: x mandatory; -webkit-overflow-scrolling: touch;
}
.board::-webkit-scrollbar { display: none; }
@media (max-width: 768px) { .board { padding: 0 16px 12px; gap: 12px; } }
@media (min-width: 900px) {
  .board { overflow-x: hidden; }
  .t-col { width: calc((100% - 28px) / 3) !important; }
}

.t-col {
  flex-shrink: 0; width: clamp(242px, 72vw, 300px); scroll-snap-align: start;
  background: #f5f5f5; border-radius: 18px;
  box-shadow: 0 2px 8px rgba(0,0,0,0.06);
  display: flex; flex-direction: column; overflow: hidden;
}
.col-head {
  padding: 16px 16px 10px; flex-shrink: 0;
  display: flex; align-items: center; justify-content: space-between;
  border-bottom: 1px solid rgba(0,0,0,.04);
}
.col-head-l { display: flex; align-items: center; gap: 8px; }
.col-dot  { width: 10px; height: 10px; border-radius: 50%; flex-shrink: 0; }
.col-name { font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: .07em; }
.col-head-r { display: flex; align-items: center; gap: 6px; }
.col-count {
  min-width: 22px; height: 22px; border-radius: 11px; padding: 0 6px;
  background: var(--bg); box-shadow: var(--neu-in);
  display: flex; align-items: center; justify-content: center;
  font-size: 10px; font-weight: 800;
}
.col-plus {
  width: 28px; height: 28px; border-radius: 50%;
  background: var(--indigo); color: #fff;
  display: flex; align-items: center; justify-content: center;
  font-size: 17px; border: none; cursor: pointer; transition: .15s;
}
.col-plus:active { background: var(--dark); }

.col-body {
  flex: 1; overflow-y: auto; padding: 10px 12px 14px;
  -ms-overflow-style: none; scrollbar-width: none;
}
.col-body::-webkit-scrollbar { display: none; }

/* ── Task card ── */
.tc {
  background: #fff; border-radius: 14px;
  margin-bottom: 8px; padding: 12px 13px; cursor: pointer;
  border: 1px solid #e5e5e5; position: relative;
}
.tc:active { background: #f9f9f9; }
.tc:hover { border-color: var(--indigo); }
.tc.p-urgent { border-left: 3px solid #ec4899; }
.tc.p-high   { border-left: 3px solid var(--red); }
.tc.p-medium { border-left: 3px solid var(--amber); }
.tc.p-low    { border-left: 3px solid var(--green); }
.tc.is-done  { opacity: .6; }

.tc-top { display: flex; align-items: flex-start; gap: 8px; margin-bottom: 7px; }
.tc-check {
  width: 18px; height: 18px; border-radius: 50%; flex-shrink: 0; margin-top: 1px;
  background: var(--bg); box-shadow: var(--neu-in);
  display: flex; align-items: center; justify-content: center;
  font-size: 10px; border: none; cursor: pointer; transition: .18s;
}
.tc-check.checked { background: var(--green); box-shadow: none; color: #fff; }
.tc-title {
  font-size: 13px; font-weight: 600; line-height: 1.35; flex: 1;
}
.tc-title.strike { text-decoration: line-through; color: var(--muted); }

.tc-meta { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.pri-tag {
  font-size: 9px; font-weight: 700; padding: 2px 7px;
  border-radius: 20px; text-transform: uppercase; letter-spacing: .05em;
}
.p-l { background: #d1fae5; color: #065f46; }
.p-m { background: #fef3c7; color: #92400e; }
.p-h { background: #fee2e2; color: #991b1b; }
.p-u { background: #fce7f3; color: #9d174d; }
.due-chip {
  font-size: 9px; font-weight: 600; color: var(--muted);
  display: flex; align-items: center; gap: 3px;
}
.due-chip.od { color: var(--red); }
.due-chip.td { color: var(--amber); }
.subj-chip { font-size: 9px; color: #aaa; font-style: italic; max-width: 80px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.tc-foot {
  display: flex; align-items: center; justify-content: space-between;
  margin-top: 8px; padding-top: 7px; border-top: 1px solid rgba(0,0,0,.05);
}
.tc-actions { display: flex; gap: 5px; }
.tc-mini {
  width: 24px; height: 24px; border-radius: 50%;
  background: var(--bg); box-shadow: 2px 2px 4px var(--dark), -2px -2px 4px var(--light);
  display: flex; align-items: center; justify-content: center;
  font-size: 12px; color: var(--muted); border: none; cursor: pointer; transition: .15s;
}
.tc-mini:active { box-shadow: var(--neu-in); }
.tc-mini:hover  { color: var(--text); }

.col-empty {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  padding: 28px 12px; gap: 8px; color: var(--muted); text-align: center;
}
.col-empty i { font-size: 30px; opacity: .3; }
.col-empty p { font-size: 11px; line-height: 1.5; }

/* ══════════════════════════════════════════════════
   BOTTOM-SHEET SYSTEM
══════════════════════════════════════════════════ */
.sh-back {
  position: fixed; inset: 0;
  background: rgba(228,228,228,.65);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  z-index: 400; opacity: 0; pointer-events: none; transition: opacity .25s;
}
.sh-back.on { opacity: 1; pointer-events: all; }

.sh {
  position: fixed; bottom: 0; left: 50%;
  transform: translate(-50%, 100%);
  width: 100%; max-width: 520px;
  background: var(--bg); border-radius: 28px 28px 0 0;
  box-shadow: 0 -8px 40px rgba(0,0,0,.13);
  z-index: 401;
  transition: transform .32s cubic-bezier(.25,.8,.25,1);
  max-height: 93dvh; overflow-y: auto;
  padding-bottom: max(20px, env(safe-area-inset-bottom));
  -ms-overflow-style: none; scrollbar-width: none;
}
.sh::-webkit-scrollbar { display: none; }
.sh.on { transform: translate(-50%, 0); }

@media (min-width: 769px) {
  .sh {
    bottom: unset; top: 50%; border-radius: 28px; max-height: 86vh;
    opacity: 0; transition: transform .28s cubic-bezier(.25,.8,.25,1), opacity .28s;
    left: calc(var(--sidebar-w, 220px) / 2 + 50%);
  }
  .sh.on { transform: translate(-50%, -50%); opacity: 1; }
}

.sh-handle { width: 36px; height: 4px; border-radius: 2px; background: var(--dark); margin: 13px auto 0; }
.sh-title-row {
  display: flex; align-items: center; justify-content: space-between;
  padding: 16px 20px 0;
}
.sh-title { font-size: 17px; font-weight: 800; }
.sh-close {
  width: 36px; height: 36px; border-radius: 50%;
  background: var(--bg); box-shadow: var(--neu-sm);
  display: flex; align-items: center; justify-content: center;
  font-size: 18px; color: var(--muted); border: none; cursor: pointer;
}
.sh-close:active { box-shadow: var(--neu-in); }
.sh-body { padding: 16px 20px 6px; }

/* Form */
.sg { margin-bottom: 14px; }
.sl {
  display: block; font-size: 10px; font-weight: 700;
  text-transform: uppercase; letter-spacing: .08em; color: var(--muted); margin-bottom: 6px;
}
.si {
  width: 100%; padding: 12px 15px; border-radius: 13px;
  background: var(--bg); border: none; outline: none;
  box-shadow: var(--neu-in); font-family: 'Poppins', sans-serif;
  font-size: 13px; color: var(--text); transition: box-shadow .2s; resize: none;
}
.si:focus { box-shadow: inset 5px 5px 10px var(--dark), inset -5px -5px 10px var(--light); }
.si::placeholder { color: #aaa; }
.s2 { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }

/* Priority picker */
.pp { display: flex; gap: 7px; }
.pb {
  flex: 1; padding: 9px 4px; border-radius: 12px;
  background: var(--bg); box-shadow: var(--neu-sm);
  border: 2px solid transparent; font-size: 10px; font-weight: 700; color: var(--muted);
  cursor: pointer; font-family: 'Poppins', sans-serif; transition: .15s;
  display: flex; flex-direction: column; align-items: center; gap: 3px;
}
.pb i { font-size: 15px; }
.pb:active { transform: scale(.96); }
.pb[data-p="low"].on    { box-shadow: var(--neu-in); color: #065f46; border-color: #22c55e; }
.pb[data-p="medium"].on { box-shadow: var(--neu-in); color: #92400e; border-color: #f59e0b; }
.pb[data-p="high"].on   { box-shadow: var(--neu-in); color: #991b1b; border-color: #ef4444; }
.pb[data-p="urgent"].on { box-shadow: var(--neu-in); color: #9d174d; border-color: #ec4899; }

/* Status picker */
.sp { display: flex; gap: 7px; }
.sb {
  flex: 1; padding: 9px 4px; border-radius: 12px;
  background: #fff; border: 2px solid #e5e5e5;
  border: 2px solid transparent; font-size: 10px; font-weight: 700; color: #888;
  cursor: pointer; font-family: 'Poppins', sans-serif; transition: .15s;
  display: flex; flex-direction: column; align-items: center; gap: 3px;
}
.sb i { font-size: 16px; }
.sb[data-s="todo"].on        { border-color: var(--indigo); color: var(--indigo); }
.sb[data-s="in_progress"].on { border-color: var(--amber);  color: var(--amber); }
.sb[data-s="done"].on        { border-color: var(--green);  color: var(--green); }

/* Footer */
.sh-foot { display: flex; gap: 10px; padding: 12px 20px 0; }
.sfb {
  flex: 1; padding: 13px; border-radius: 50px; border: none; cursor: pointer;
  font-family: 'Poppins', sans-serif; font-size: 13px; font-weight: 700;
  background: var(--bg); box-shadow: var(--neu-sm); color: var(--text); transition: .15s;
  display: flex; align-items: center; justify-content: center; gap: 6px;
}
.sfb:active { box-shadow: var(--neu-in); transform: scale(.99); }
.sfb.prim { background: var(--text); color: var(--bg); box-shadow: none; flex: 2; }
.sfb.del  { color: var(--red); }
.sfb i { font-size: 15px; }
.go { display: none !important; }

/* Detail */
.det-row {
  display: flex; align-items: flex-start; gap: 10px;
  padding: 10px 0; border-bottom: 1px solid rgba(0,0,0,.05); font-size: 12px;
}
.det-row:last-child { border-bottom: none; }
.det-row i { font-size: 16px; color: var(--muted); width: 20px; flex-shrink: 0; margin-top: 1px; }
.det-lbl { color: var(--muted); font-weight: 600; min-width: 60px; font-size: 11px; }
.det-val { flex: 1; font-weight: 500; }

/* Quick move */
.mv-row { display: flex; gap: 8px; margin: 4px 0 0; }
.mv-btn {
  flex: 1; padding: 9px 6px; border-radius: 12px; border: none; cursor: pointer;
  background: var(--bg); box-shadow: var(--neu-sm);
  font-size: 10px; font-weight: 700; color: var(--muted);
  font-family: 'Poppins', sans-serif; transition: .15s;
  display: flex; flex-direction: column; align-items: center; gap: 3px;
}
.mv-btn i { font-size: 15px; }
.mv-btn:active { box-shadow: var(--neu-in); }
.mv-btn.mv-cur { box-shadow: var(--neu-in); font-weight: 800; }
.mv-todo { color: var(--indigo); }
.mv-prog { color: var(--amber); }
.mv-done { color: var(--green); }

/* Confirm delete */
.conf-body { padding: 10px 20px 0; text-align: center; }
.conf-ico { font-size: 44px; margin-bottom: 8px; }
.conf-msg { font-size: 13px; color: var(--muted); line-height: 1.6; }

/* ══════════════════════════════════════════════════
   TOASTS
══════════════════════════════════════════════════ */
.toast-tray {
  position: fixed; top: 16px; left: 50%; transform: translateX(-50%);
  z-index: 9999; display: flex; flex-direction: column; align-items: center;
  gap: 6px; pointer-events: none;
}
.tst {
  background: var(--text); color: var(--bg);
  padding: 9px 18px; border-radius: 50px; font-size: 12px; font-weight: 600;
  box-shadow: 4px 4px 12px rgba(0,0,0,.2); white-space: nowrap;
  animation: tIn .22s ease both;
}
.tst.ok  { background: #065f46; }
.tst.err { background: #991b1b; }
@keyframes tIn { from { opacity:0; transform:translateY(-6px); } to { opacity:1; transform:none; } }

/* Mobile nav overrides */
.mobile-bottom-nav .mob-nav-btn { font-size: 22px; display: flex; align-items: center; justify-content: center; }
</style>
</head>
<body>
<div class="app-layout">
  <?php include __DIR__ . '/includes/sidebar.php'; ?>

  <main class="main-content">

    <!-- Mobile top header -->
    <div class="mobile-header">
      <button type="button" id="menu-open-btn" style="background:#fff;box-shadow:0 2px 6px rgba(0,0,0,0.1);width:40px;height:40px;border-radius:50%;border:none;display:flex;align-items:center;justify-content:center;cursor:pointer;font-size:20px;">
        <i class='bx bx-menu'></i>
      </button>
      <div class="logo-circle-sm"><img src="space/assets/img/logo.svg" alt="SPACE" width="26"></div>
      <button type="button" onclick="openAdd()" style="background:var(--indigo);width:36px;height:36px;border-radius:50%;border:none;display:flex;align-items:center;justify-content:center;cursor:pointer;font-size:19px;color:#fff;">
        <i class='bx bx-plus'></i>
      </button>
    </div>

    <!-- TOP BAR -->
    <div class="tasks-topbar">
      <div class="tasks-heading-row">
        <div>
          <h1>Tasks</h1>
          <p class="sub" id="sub-line">
            <?= $total ?> total &bull; <?= $done ?> done<?= $overdue > 0 ? ' &bull; <span style="color:var(--red);font-weight:600">' . $overdue . ' overdue</span>' : '' ?>
          </p>
        </div>
        <button onclick="openAdd()" class="btn btn-primary" style="flex-shrink:0;" id="desk-add">
          <i class='bx bx-plus' style="font-size:16px"></i> New Task
        </button>
      </div>

      <!-- Stats -->
      <div class="stats-row">
        <div class="s-chip prog">
          <div class="ring-wrap">
            <svg width="32" height="32" viewBox="0 0 32 32">
              <circle class="ring-bg" cx="16" cy="16" r="12"/>
              <circle class="ring-fill" id="prog-ring" cx="16" cy="16" r="12"
                      stroke-dasharray="75.4"
                      stroke-dashoffset="<?= round(75.4 * (1 - $pct/100), 2) ?>"/>
            </svg>
            <div class="ring-pct" id="pct-txt"><?= $pct ?>%</div>
          </div>
          <div>
            <div style="font-size:13px;font-weight:700;line-height:1" id="done-tot"><?= $done ?>/<?= $total ?></div>
            <div style="font-size:9px;color:var(--muted)">Completed</div>
          </div>
        </div>
        <?php if ($dueToday): ?>
        <div class="s-chip" style="color:var(--amber)">
          <i class='bx bx-time-five'></i><span class="n" id="chip-today"><?= $dueToday ?></span><span>Due Today</span>
        </div>
        <?php endif; ?>
        <?php if ($overdue): ?>
        <div class="s-chip" style="color:var(--red)">
          <i class='bx bx-error-circle'></i><span class="n" id="chip-od"><?= $overdue ?></span><span>Overdue</span>
        </div>
        <?php endif; ?>
        <div class="s-chip" style="color:var(--indigo)">
          <i class='bx bx-loader-circle'></i><span class="n" id="chip-prog"><?= count($columns['in_progress']) ?></span><span>Doing</span>
        </div>
      </div>

      <!-- Filters -->
      <div class="filter-bar">
        <div class="f-search">
          <i class='bx bx-search'></i>
          <input type="text" placeholder="Search…" id="srch" oninput="applyFilters()">
        </div>
        <button class="f-btn on" data-f="all"         onclick="setF('all',this)"><i class='bx bx-grid-alt'></i>All</button>
        <button class="f-btn" data-f="todo"           onclick="setF('todo',this)"><i class='bx bx-circle'></i>To Do</button>
        <button class="f-btn" data-f="in_progress"    onclick="setF('in_progress',this)"><i class='bx bx-loader-circle'></i>Doing</button>
        <button class="f-btn" data-f="done"           onclick="setF('done',this)"><i class='bx bx-check-circle'></i>Done</button>
        <button class="f-btn" data-f="overdue"        onclick="setF('overdue',this)"><i class='bx bx-error'></i>Overdue</button>
        <button class="f-btn" data-f="today"          onclick="setF('today',this)"><i class='bx bx-calendar-event'></i>Today</button>
      </div>
    </div>

    <!-- BOARD -->
    <div class="board" id="board">
      <?php
      $coldefs = [
        'todo'        => ['label'=>'To Do',      'color'=>'#6366f1','dot'=>'#6366f1'],
        'in_progress' => ['label'=>'In Progress','color'=>'#f59e0b','dot'=>'#f59e0b'],
        'done'        => ['label'=>'Done',       'color'=>'#22c55e','dot'=>'#22c55e'],
      ];
      foreach ($columns as $status => $tasks):
        $cd = $coldefs[$status];
      ?>
      <div class="t-col" id="col-<?= $status ?>" data-status="<?= $status ?>">
        <div class="col-head">
          <div class="col-head-l">
            <span class="col-dot" style="background:<?= $cd['dot'] ?>"></span>
            <span class="col-name" style="color:<?= $cd['color'] ?>"><?= $cd['label'] ?></span>
          </div>
          <div class="col-head-r">
            <span class="col-count" id="cnt-<?= $status ?>"><?= count($tasks) ?></span>
            <button class="col-plus" onclick="openAdd(null,'<?= $status ?>')" title="Add"><i class='bx bx-plus'></i></button>
          </div>
        </div>
        <div class="col-body" id="cb-<?= $status ?>">
          <?php if (empty($tasks)): ?>
            <div class="col-empty"><i class='bx bx-task'></i><p>No tasks.<br>Click + to add.</p></div>
          <?php else: foreach ($tasks as $t):
            $isDone = $t['status'] === 'done';
            $due    = $t['due_date'] ? new DateTime($t['due_date']) : null;
            $od     = $due && $due->format('Y-m-d') < $today && !$isDone;
            $td     = $due && $due->format('Y-m-d') === $today && !$isDone;
            $priMap = ['low'=>'l','medium'=>'m','high'=>'h','urgent'=>'u'];
          ?>
            <div class="tc p-<?= $t['priority'] ?> <?= $isDone?'is-done':'' ?>"
                 id="tc-<?= $t['id'] ?>"
                 data-id="<?= $t['id'] ?>"
                 data-status="<?= $t['status'] ?>"
                 data-due="<?= $t['due_date'] ?? '' ?>"
                 data-title="<?= e($t['title']) ?>"
                 data-subj="<?= e($t['subject'] ?? '') ?>">

              <div class="tc-top">
                <button class="tc-check <?= $isDone?'checked':'' ?>"
                        onclick="qComplete(event,<?= $t['id'] ?>,<?= $isDone?'true':'false' ?>)">
                  <?= $isDone ? "<i class='bx bx-check'></i>" : '' ?>
                </button>
                <div class="tc-title <?= $isDone?'strike':'' ?>"
                     onclick="openDetail(<?= htmlspecialchars(json_encode($t),ENT_QUOTES) ?>)">
                  <?= e($t['title']) ?>
                </div>
              </div>

              <div class="tc-meta">
                <span class="pri-tag p-<?= $priMap[$t['priority']] ?>"><?= ucfirst($t['priority']) ?></span>
                <?php if ($due): ?>
                  <span class="due-chip <?= $od?'od':($td?'td':'') ?>">
                    <i class='bx bx-calendar' style="font-size:10px"></i>
                    <?= $od?'⚠ ':($td?'⏰ ':'') ?><?= $due->format('M j') ?>
                  </span>
                <?php endif; ?>
                <?php if ($t['subject']): ?>
                  <span class="subj-chip"><?= e($t['subject']) ?></span>
                <?php endif; ?>
              </div>

              <div class="tc-foot">
                <span style="font-size:9px;color:#bbb"><?= date('M j', strtotime($t['created_at'])) ?></span>
                <div class="tc-actions">
                  <button class="tc-mini" onclick="openEdit(<?= htmlspecialchars(json_encode($t),ENT_QUOTES) ?>)" title="Edit"><i class='bx bx-edit-alt'></i></button>
                  <button class="tc-mini" onclick="openConfirm(<?= $t['id'] ?>,'<?= e(addslashes($t['title'])) ?>')" title="Delete" style="color:#d0d0d0"><i class='bx bx-trash'></i></button>
                </div>
              </div>
            </div>
          <?php endforeach; endif; ?>
        </div>
      </div>
      <?php endforeach; ?>
    </div>

  </main>

  <nav class="mobile-bottom-nav">
    <a href="notes.php" class="mob-nav-btn"><i class='bx bxs-file-blank' style="font-size:22px"></i></a>
    <button class="mob-nav-fab" onclick="openAdd()"><i class='bx bx-plus' style="font-size:26px;color:var(--bg)"></i></button>
    <a href="ai.php" class="mob-nav-btn"><i class='bx bx-bot' style="font-size:22px;color:#ec4899"></i></a>
  </nav>
</div>

<!-- ════════════════════════════════════════
     ADD / EDIT SHEET
════════════════════════════════════════ -->
<div class="sh-back" id="form-back" onclick="closeForm()"></div>
<div class="sh" id="form-sh">
  <div class="sh-handle"></div>
  <div class="sh-title-row">
    <div class="sh-title" id="form-title">New Task</div>
    <button class="sh-close" onclick="closeForm()"><i class='bx bx-x'></i></button>
  </div>
  <div class="sh-body">
    <div class="sg">
      <label class="sl">Task Title *</label>
      <input type="text" class="si" id="f-title" placeholder="What needs to be done?" autocomplete="off">
    </div>
    <div class="sg">
      <label class="sl">Description</label>
      <textarea class="si" id="f-desc" rows="2" placeholder="Optional notes…"></textarea>
    </div>
    <div class="s2">
      <div class="sg">
        <label class="sl">Subject</label>
        <input type="text" class="si" id="f-subj" placeholder="e.g. CC101">
      </div>
      <div class="sg">
        <label class="sl">Due Date</label>
        <input type="date" class="si" id="f-due">
      </div>
    </div>
    <div class="sg">
      <label class="sl">Priority</label>
      <div class="pp">
        <button type="button" class="pb" data-p="low"    onclick="selP(this)"><i class='bx bx-down-arrow-circle'></i>Low</button>
        <button type="button" class="pb on" data-p="medium" onclick="selP(this)"><i class='bx bx-minus-circle'></i>Med</button>
        <button type="button" class="pb" data-p="high"   onclick="selP(this)"><i class='bx bx-up-arrow-circle'></i>High</button>
        <button type="button" class="pb" data-p="urgent" onclick="selP(this)"><i class='bx bxs-bell-ring'></i>Urgent</button>
      </div>
    </div>
    <div class="sg">
      <label class="sl">Status</label>
      <div class="sp">
        <button type="button" class="sb on" data-s="todo"        onclick="selS(this)"><i class='bx bx-circle'></i>To Do</button>
        <button type="button" class="sb"    data-s="in_progress" onclick="selS(this)"><i class='bx bx-loader-circle'></i>Doing</button>
        <button type="button" class="sb"    data-s="done"        onclick="selS(this)"><i class='bx bx-check-circle'></i>Done</button>
      </div>
    </div>
    <div id="ferr" style="color:var(--red);font-size:12px;margin-bottom:8px;display:none;"></div>
  </div>
  <div class="sh-foot">
    <button class="sfb" onclick="closeForm()">Cancel</button>
    <button class="sfb del go" id="del-btn" onclick="delFromForm()"><i class='bx bx-trash'></i>Delete</button>
    <button class="sfb prim" onclick="saveTask()"><i class='bx bx-save'></i><span id="save-lbl">Save</span></button>
  </div>
  <input type="hidden" id="f-id">
</div>

<!-- ════════════════════════════════════════
     DETAIL SHEET
════════════════════════════════════════ -->
<div class="sh-back" id="det-back" onclick="closeDet()"></div>
<div class="sh" id="det-sh">
  <div class="sh-handle"></div>
  <div class="sh-title-row">
    <div class="sh-title" id="det-title" style="font-size:15px;max-width:calc(100% - 60px);line-height:1.3"></div>
    <button class="sh-close" onclick="closeDet()"><i class='bx bx-x'></i></button>
  </div>
  <div style="padding:10px 20px 0;">
    <label class="sl">Move to</label>
    <div class="mv-row">
      <button class="mv-btn mv-todo" id="mv-todo"        onclick="qMove('todo')"><i class='bx bx-circle'></i>To Do</button>
      <button class="mv-btn mv-prog" id="mv-in_progress" onclick="qMove('in_progress')"><i class='bx bx-loader-circle'></i>Doing</button>
      <button class="mv-btn mv-done" id="mv-done"        onclick="qMove('done')"><i class='bx bx-check-circle'></i>Done</button>
    </div>
  </div>
  <div id="det-body" style="padding:4px 20px 8px;"></div>
  <div class="sh-foot">
    <button class="sfb del" onclick="delFromDet()"><i class='bx bx-trash'></i>Delete</button>
    <button class="sfb prim" onclick="editFromDet()"><i class='bx bx-edit'></i>Edit Task</button>
  </div>
</div>

<!-- ════════════════════════════════════════
     CONFIRM DELETE SHEET
════════════════════════════════════════ -->
<div class="sh-back" id="conf-back" onclick="closeConf()"></div>
<div class="sh" id="conf-sh" style="max-height:unset;">
  <div class="sh-handle"></div>
  <div class="conf-body">
    <div class="conf-ico">🗑️</div>
    <div class="sh-title" style="margin-bottom:8px">Delete Task?</div>
    <div class="conf-msg" id="conf-msg">This cannot be undone.</div>
  </div>
  <div class="sh-foot" style="padding-top:20px;">
    <button class="sfb" onclick="closeConf()">Cancel</button>
    <button class="sfb del prim" id="conf-ok"><i class='bx bx-trash'></i>Delete</button>
  </div>
</div>

<div class="toast-tray" id="toasts"></div>

<script src="assets/js/app.js"></script>
<script>
// Use CSRF from app.js
let curFilter = 'all', curDet = null, pendDelId = null, saving = false;

// ── Toast ─────────────────────────────────────────
function tt(msg, cls='', dur=2600) {
  const tray = document.getElementById('toasts');
  const el = document.createElement('div');
  el.className = 'tst ' + cls;
  el.textContent = msg;
  tray.appendChild(el);
  setTimeout(() => { el.style.transition='opacity .3s'; el.style.opacity=0; setTimeout(()=>el.remove(),300); }, dur);
}

// ── API ───────────────────────────────────────────
async function api(action, payload) {
  const r = await fetch('space/api/tasks.php?action=' + action, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ ...payload, csrf_token: window.CSRF }),
  });
  return r.json();
}

// ── Sheets ────────────────────────────────────────
function openSh(sh, bk)  { document.getElementById(bk).classList.add('on'); document.getElementById(sh).classList.add('on'); document.body.style.overflow='hidden'; }
function closeSh(sh, bk) { document.getElementById(bk).classList.remove('on'); document.getElementById(sh).classList.remove('on'); document.body.style.overflow=''; }

// ── Priority / Status pickers ─────────────────────
function selP(btn) { document.querySelectorAll('.pb').forEach(b=>b.classList.remove('on')); btn.classList.add('on'); }
function selS(btn) { document.querySelectorAll('.sb').forEach(b=>b.classList.remove('on')); btn.classList.add('on'); }

// ══════════════════════════════════════════════════
// FORM SHEET
// ══════════════════════════════════════════════════
function openAdd(defaultSt='todo') {
  resetForm(null, defaultSt);
  openSh('form-sh','form-back');
  setTimeout(()=>document.getElementById('f-title').focus(), 320);
}
function openEdit(task) {
  resetForm(task);
  openSh('form-sh','form-back');
  setTimeout(()=>document.getElementById('f-title').focus(), 320);
}
function closeForm() { closeSh('form-sh','form-back'); }

function resetForm(task, defSt='todo') {
  const isEdit = !!task;
  document.getElementById('form-title').textContent = isEdit ? 'Edit Task' : 'New Task';
  document.getElementById('save-lbl').textContent   = isEdit ? 'Update' : 'Save';
  document.getElementById('del-btn').classList.toggle('go', !isEdit);
  document.getElementById('ferr').style.display = 'none';
  document.getElementById('f-id').value    = isEdit ? task.id : '';
  document.getElementById('f-title').value = isEdit ? task.title : '';
  document.getElementById('f-desc').value  = isEdit ? (task.description||'') : '';
  document.getElementById('f-subj').value  = isEdit ? (task.subject||'') : '';
  document.getElementById('f-due').value   = isEdit ? (task.due_date||'') : '';
  const p = isEdit ? task.priority : 'medium';
  document.querySelectorAll('.pb').forEach(b => b.classList.toggle('on', b.dataset.p===p));
  const s = isEdit ? task.status : defSt;
  document.querySelectorAll('.sb').forEach(b => b.classList.toggle('on', b.dataset.s===s));
}

document.getElementById('f-title').addEventListener('keydown', e => { if (e.key==='Enter') { e.preventDefault(); saveTask(); } });

async function saveTask() {
  if (saving) return;
  const title = document.getElementById('f-title').value.trim();
  if (!title) {
    const e = document.getElementById('ferr');
    e.textContent = 'Task title is required.';
    e.style.display = 'block';
    document.getElementById('f-title').focus();
    return;
  }
  document.getElementById('ferr').style.display = 'none';
  saving = true;
  const saveBtn = document.querySelector('#form-sh .sfb.prim');
  if (saveBtn) saveBtn.style.opacity = '.5';

  const id  = document.getElementById('f-id').value;
  const pri = document.querySelector('.pb.on')?.dataset.p || 'medium';
  const st  = document.querySelector('.sb.on')?.dataset.s || 'todo';
  const pay = {
    title,
    description: document.getElementById('f-desc').value.trim(),
    subject:     document.getElementById('f-subj').value.trim(),
    due_date:    document.getElementById('f-due').value,
    priority: pri, status: st,
  };
  if (id) pay.id = id;

  const res = await api(id ? 'update' : 'create', pay);
  saving = false;
  if (saveBtn) saveBtn.style.opacity = '1';

  if (res.success) {
    tt(id ? '✅ Task updated!' : '✅ Task created!', 'ok');
    closeForm();
    await refresh();
  } else {
    const e = document.getElementById('ferr');
    e.textContent = res.message || 'Error saving task.';
    e.style.display = 'block';
  }
}

function delFromForm() {
  const id    = document.getElementById('f-id').value;
  const title = document.getElementById('f-title').value;
  if (!id) return;
  closeForm();
  setTimeout(() => openConfirm(id, title), 200);
}

// ══════════════════════════════════════════════════
// DETAIL SHEET
// ══════════════════════════════════════════════════
function openDetail(task) {
  curDet = task;
  document.getElementById('det-title').textContent = task.title;
  const todayStr = new Date().toISOString().split('T')[0];
  const due = task.due_date ? new Date(task.due_date + 'T12:00:00') : null;
  const od  = due && task.due_date < todayStr && task.status !== 'done';
  const td  = due && task.due_date === todayStr && task.status !== 'done';
  const pri = { low:'#22c55e', medium:'#f59e0b', high:'#ef4444', urgent:'#ec4899' };
  const stLbl = { todo:'To Do', in_progress:'In Progress', done:'Done' };
  const stIco = { todo:'bx-circle', in_progress:'bx-loader-circle', done:'bx-check-circle' };

  // Move buttons highlight
  ['todo','in_progress','done'].forEach(s => {
    document.getElementById('mv-'+s)?.classList.toggle('mv-cur', s===task.status);
  });

  document.getElementById('det-body').innerHTML = `
    <div class="det-row">
      <i class='bx bx-tag-alt'></i>
      <span class="det-lbl">Priority</span>
      <span class="det-val" style="color:${pri[task.priority]||'#888'};font-weight:700">${task.priority.charAt(0).toUpperCase()+task.priority.slice(1)}</span>
    </div>
    <div class="det-row">
      <i class='bx ${stIco[task.status]}'></i>
      <span class="det-lbl">Status</span>
      <span class="det-val">${stLbl[task.status]}</span>
    </div>
    ${task.due_date ? `<div class="det-row">
      <i class='bx bx-calendar' style="${od?'color:var(--red)':td?'color:var(--amber)':''}"></i>
      <span class="det-lbl">Due</span>
      <span class="det-val" style="${od?'color:var(--red);font-weight:600':td?'color:var(--amber);font-weight:600':''}">
        ${od?'⚠ Overdue · ':td?'⏰ Today · '    :''}${due.toLocaleDateString('en-US',{weekday:'short',month:'long',day:'numeric'})}
      </span>
    </div>` : ''}
    ${task.subject ? `<div class="det-row">
      <i class='bx bx-book-open'></i>
      <span class="det-lbl">Subject</span>
      <span class="det-val">${task.subject}</span>
    </div>` : ''}
    ${task.description ? `<div class="det-row" style="align-items:flex-start">
      <i class='bx bx-note'></i>
      <span class="det-lbl">Notes</span>
      <span class="det-val" style="line-height:1.65;white-space:pre-line">${task.description}</span>
    </div>` : ''}
    <div class="det-row">
      <i class='bx bx-time'></i>
      <span class="det-lbl">Created</span>
      <span class="det-val">${new Date(task.created_at).toLocaleDateString('en-US',{month:'short',day:'numeric',year:'numeric'})}</span>
    </div>
  `;

  openSh('det-sh','det-back');
}
function closeDet() { closeSh('det-sh','det-back'); }

async function qMove(st) {
  if (!curDet) return;
  const res = await api('status', { id: curDet.id, status: st });
  if (res.success) {
    const lbl = { todo:'To Do', in_progress:'In Progress', done:'Done' };
    tt('Moved to ' + lbl[st], 'ok');
    curDet.status = st;
    ['todo','in_progress','done'].forEach(s => document.getElementById('mv-'+s)?.classList.toggle('mv-cur', s===st));
    closeDet();
    await refresh();
  } else tt('Failed to move', 'err');
}

function editFromDet() { closeDet(); setTimeout(()=>openEdit(curDet),200); }
function delFromDet()  { closeDet(); setTimeout(()=>openConfirm(curDet.id, curDet.title),200); }

// ══════════════════════════════════════════════════
// QUICK COMPLETE (card checkbox)
// ══════════════════════════════════════════════════
async function qComplete(e, id, isDone) {
  e.stopPropagation();
  const res = await api('status', { id, status: isDone ? 'todo' : 'done' });
  if (res.success) { tt(isDone ? '↩ Marked incomplete' : '✅ Done!', isDone ? '' : 'ok'); await refresh(); }
  else tt('Update failed', 'err');
}

// ══════════════════════════════════════════════════
// CONFIRM DELETE SHEET
// ══════════════════════════════════════════════════
function openConfirm(id, title) {
  pendDelId = id;
  document.getElementById('conf-msg').textContent = '"' + title + '" will be permanently deleted.';
  document.getElementById('conf-ok').onclick = doDelete;
  openSh('conf-sh','conf-back');
}
function closeConf() { closeSh('conf-sh','conf-back'); pendDelId = null; }

async function doDelete() {
  if (!pendDelId) return;
  const res = await api('delete', { id: pendDelId });
  if (res.success) { tt('🗑 Task deleted'); closeConf(); await refresh(); }
  else tt('Delete failed', 'err');
}

// ══════════════════════════════════════════════════
// FILTER
// ══════════════════════════════════════════════════
function setF(f, btn) {
  curFilter = f;
  document.querySelectorAll('.f-btn').forEach(b => b.classList.remove('on'));
  btn.classList.add('on');
  applyFilters();
}
function applyFilters() {
  const q = (document.getElementById('srch').value||'').toLowerCase();
  const todayS = new Date().toISOString().split('T')[0];
  document.querySelectorAll('.tc').forEach(card => {
    const st  = card.dataset.status;
    const due = card.dataset.due;
    const ttl = (card.dataset.title||'').toLowerCase();
    const sbj = (card.dataset.subj||'').toLowerCase();
    const isDone = st==='done';
    const mF =
      curFilter==='all'      ? true :
      curFilter==='overdue'  ? (due && due < todayS && !isDone) :
      curFilter==='today'    ? (due && due===todayS && !isDone) :
      st===curFilter;
    const mS = !q || ttl.includes(q) || sbj.includes(q);
    card.style.display = mF && mS ? '' : 'none';
  });
  // Empty state per col
  document.querySelectorAll('.t-col').forEach(col => {
    const vis = [...col.querySelectorAll('.tc')].filter(c=>c.style.display!=='none');
    let fe = col.querySelector('.filter-empty');
    const cb = col.querySelector('.col-body');
    if (vis.length===0 && !fe) {
      const d = document.createElement('div');
      d.className='col-empty filter-empty';
      d.innerHTML="<i class='bx bx-search-alt'></i><p>No matching tasks</p>";
      cb.appendChild(d);
    } else if (vis.length>0 && fe) fe.remove();
  });
}

// ══════════════════════════════════════════════════
// REFRESH FROM API
// ══════════════════════════════════════════════════
async function refresh() {
  const r    = await fetch('space/api/tasks.php?action=list');
  const data = await r.json();
  if (!data.success) return;
  const tasks   = data.tasks;
  const todayS  = new Date().toISOString().split('T')[0];
  const priMap  = { low:'l', medium:'m', high:'h', urgent:'u' };
  const priLbl  = { low:'Low', medium:'Medium', high:'High', urgent:'Urgent' };
  const priC    = { low:'#22c55e', medium:'#f59e0b', high:'#ef4444', urgent:'#ec4899' };
  const stIco   = { todo:'bx-circle', in_progress:'bx-loader-circle', done:'bx-check-circle' };
  const stLbl   = { todo:'To Do', in_progress:'In Progress', done:'Done' };

  ['todo','in_progress','done'].forEach(st => {
    const cb  = document.getElementById('cb-' + st);
    const cnt = document.getElementById('cnt-' + st);
    const col = tasks.filter(t=>t.status===st);
    if (cnt) cnt.textContent = col.length;
    if (!cb)  return;
    cb.innerHTML = '';
    if (col.length===0) {
      cb.innerHTML = "<div class='col-empty'><i class='bx bx-task'></i><p>No tasks.<br>Click + to add.</p></div>";
      return;
    }
    col.forEach(t => {
      const isDone = t.status==='done';
      const od  = t.due_date && t.due_date < todayS && !isDone;
      const td2 = t.due_date && t.due_date===todayS && !isDone;
      const dueLabel = t.due_date
        ? new Date(t.due_date+'T12:00:00').toLocaleDateString('en-US',{month:'short',day:'numeric'})
        : '';
      const card = document.createElement('div');
      card.className = `tc p-${t.priority} ${isDone?'is-done':''}`;
      card.id = 'tc-'+t.id;
      Object.assign(card.dataset,{id:t.id,status:t.status,due:t.due_date||'',title:t.title,subj:t.subject||''});
      const esc = s => String(s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;');
      const tj  = s => JSON.stringify(s).replace(/'/g,"\\'");
      card.innerHTML = `
        <div class="tc-top">
          <button class="tc-check ${isDone?'checked':''}" onclick="qComplete(event,${t.id},${isDone})">
            ${isDone?"<i class='bx bx-check'></i>":''}
          </button>
          <div class="tc-title ${isDone?'strike':''}" onclick='openDetail(${tj(t)})'>${esc(t.title)}</div>
        </div>
        <div class="tc-meta">
          <span class="pri-tag p-${priMap[t.priority]}">${priLbl[t.priority]}</span>
          ${dueLabel?`<span class="due-chip ${od?'od':td2?'td':''}">
            <i class='bx bx-calendar' style="font-size:10px"></i>
            ${od?'⚠ ':td2?'⏰ ':''}${dueLabel}</span>`:''}
          ${t.subject?`<span class="subj-chip">${esc(t.subject)}</span>`:''}
        </div>
        <div class="tc-foot">
          <span style="font-size:9px;color:#bbb">${new Date(t.created_at).toLocaleDateString('en-US',{month:'short',day:'numeric'})}</span>
          <div class="tc-actions">
            <button class="tc-mini" onclick='openEdit(${tj(t)})' title="Edit"><i class='bx bx-edit-alt'></i></button>
            <button class="tc-mini" onclick="openConfirm(${t.id},'${esc(t.title).replace(/'/g,"\\'")}')"><i class='bx bx-trash'></i></button>
          </div>
        </div>
      `;
      cb.appendChild(card);
    });
  });

  // Stats update
  const total   = tasks.length;
  const done    = tasks.filter(t=>t.status==='done').length;
  const od2     = tasks.filter(t=>t.due_date && t.due_date<todayS && t.status!=='done').length;
  const dueT    = tasks.filter(t=>t.due_date && t.due_date===todayS && t.status!=='done').length;
  const pct     = total>0 ? Math.round(done/total*100) : 0;
  const circ    = 75.4;
  const ring    = document.getElementById('prog-ring');
  const pctTxt  = document.getElementById('pct-txt');
  const doneTot = document.getElementById('done-tot');
  const subLine = document.getElementById('sub-line');
  if (ring)    ring.style.strokeDashoffset = circ*(1-pct/100);
  if (pctTxt)  pctTxt.textContent = pct+'%';
  if (doneTot) doneTot.textContent = done+'/'+total;
  if (subLine) subLine.innerHTML  = `${total} total &bull; ${done} done${od2>0?` &bull; <span style="color:var(--red);font-weight:600">${od2} overdue</span>`:''}`;

  applyFilters();
}

// Escape key closes sheets
document.addEventListener('keydown', e => {
  if (e.key==='Escape') { closeForm(); closeDet(); closeConf(); }
});

// Mobile menu button
document.getElementById('menu-open-btn')?.addEventListener('click', () => {
  document.getElementById('side-menu')?.classList.add('active');
  document.getElementById('menu-overlay')?.classList.add('active');
});

// Close menu button
document.getElementById('menu-close-btn')?.addEventListener('click', () => {
  document.getElementById('side-menu')?.classList.remove('active');
  document.getElementById('menu-overlay')?.classList.remove('active');
});

// Close menu when clicking overlay
document.getElementById('menu-overlay')?.addEventListener('click', () => {
  document.getElementById('side-menu')?.classList.remove('active');
  document.getElementById('menu-overlay')?.classList.remove('active');
});
</script>
</body>
</html>