{"id":629,"date":"2026-09-15T02:55:54","date_gmt":"2026-09-15T02:55:54","guid":{"rendered":"https:\/\/kalhonaho.online\/?page_id=629"},"modified":"2026-09-16T12:05:04","modified_gmt":"2026-09-16T12:05:04","slug":"p3","status":"publish","type":"page","link":"https:\/\/kalhonaho.online\/?page_id=629","title":{"rendered":"P3"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"629\" class=\"elementor elementor-629\">\n\t\t\t\t<div class=\"elementor-element elementor-element-eca2d9b e-con e-atomic-element e-flexbox-base e-78532b0 \" data-id=\"eca2d9b\" data-element_type=\"e-flexbox\" data-e-type=\"e-flexbox\" data-interaction-id=\"eca2d9b\">\n    \t\t<div class=\"elementor-element elementor-element-e6cbc46 elementor-widget elementor-widget-html\" data-id=\"e6cbc46\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t\t<!DOCTYPE html>\r\n<html lang=\"en\">\r\n<head>\r\n<meta charset=\"UTF-8\">\r\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\r\n<title>Capstone Project 3 \u2014 Meta Ads + CRO + Automation + CRM + Analytics | Digital Nest<\/title>\r\n<link rel=\"preconnect\" href=\"https:\/\/fonts.googleapis.com\">\r\n<link href=\"https:\/\/fonts.googleapis.com\/css2?family=Poppins:wght@500;600;700;800&family=Inter:wght@400;500;600;700&display=swap\" rel=\"stylesheet\">\r\n<style>\r\n  :root{\r\n    --navy:#082A5E;\r\n    --blue:#0D4EA0;\r\n    --blue-light:#3E7BD6;\r\n    --blue-tint:#EAF1FB;\r\n    --blue-tint2:#F4F8FE;\r\n    --gold:#F2A900;\r\n    --gold-dark:#C98A00;\r\n    --green:#1E9E6D;\r\n    --green-tint:#E6F6EF;\r\n    --amber:#E2A03F;\r\n    --amber-tint:#FCF3E3;\r\n    --red:#D6455A;\r\n    --red-tint:#FBEAED;\r\n    --ink:#1C2B42;\r\n    --ink-soft:#5A6B85;\r\n    --line:#DCE6F5;\r\n    --white:#FFFFFF;\r\n    --radius:14px;\r\n    --shadow: 0 4px 18px rgba(8,42,94,0.08);\r\n  }\r\n  *{box-sizing:border-box;}\r\n  html,body{margin:0;padding:0;}\r\n  body{\r\n    font-family:'Inter',sans-serif;\r\n    background: var(--blue-tint2);\r\n    color:var(--ink);\r\n    -webkit-font-smoothing:antialiased;\r\n  }\r\n  h1,h2,h3,h4{font-family:'Poppins',sans-serif;margin:0;color:var(--navy);}\r\n  p{line-height:1.55;}\r\n  a{color:var(--blue);}\r\n  button{font-family:'Inter',sans-serif;cursor:pointer;}\r\n  ::-webkit-scrollbar{height:8px;width:8px;}\r\n  ::-webkit-scrollbar-thumb{background:#c7d6ef;border-radius:8px;}\r\n\r\n  \/* ---------- Header ---------- *\/\r\n  .topbar{\r\n    background: linear-gradient(135deg, var(--navy) 0%, var(--blue) 100%);\r\n    color:#fff;\r\n    padding:22px 28px 0 28px;\r\n    position:sticky; top:0; z-index:50;\r\n    box-shadow: 0 6px 24px rgba(8,42,94,0.18);\r\n  }\r\n  .topbar-inner{\r\n    max-width:1240px; margin:0 auto;\r\n    display:flex; align-items:flex-start; justify-content:space-between; gap:24px; flex-wrap:wrap;\r\n  }\r\n  .brandmark{display:flex; align-items:center; gap:14px;}\r\n  .logo-badge{\r\n    width:52px;height:52px;border-radius:14px;\r\n    background:#fff; display:flex; align-items:center; justify-content:center;\r\n    box-shadow: inset 0 0 0 3px var(--gold);\r\n    flex-shrink:0;\r\n  }\r\n  .logo-badge svg{width:30px;height:30px;}\r\n  .brand-text .name{font-family:'Poppins',sans-serif;font-weight:800;font-size:19px;letter-spacing:0.2px;line-height:1.1;}\r\n  .brand-text .sub{font-size:11.5px;color:#CFE0FA;letter-spacing:1.5px;margin-top:2px;}\r\n  .headline{max-width:640px;}\r\n  .headline h1{color:#fff;font-size:22px;font-weight:700;line-height:1.3;}\r\n  .headline .tagline{color:#CFE0FA;font-size:13.5px;margin-top:6px;}\r\n  .meta-pills{display:flex; gap:8px; flex-wrap:wrap; margin-top:12px;}\r\n  .pill{\r\n    background:rgba(255,255,255,0.12); border:1px solid rgba(255,255,255,0.22);\r\n    color:#fff; font-size:12.5px; font-weight:600; padding:5px 12px; border-radius:99px;\r\n  }\r\n  .pill.gold{background:var(--gold); color:#402D00; border-color:var(--gold);}\r\n  .countdown-box{\r\n    background:rgba(255,255,255,0.1); border:1px solid rgba(255,255,255,0.22);\r\n    border-radius:14px; padding:14px 18px; min-width:190px; text-align:center;\r\n  }\r\n  .countdown-box .num{font-family:'Poppins',sans-serif; font-size:30px; font-weight:800; color:var(--gold);}\r\n  .countdown-box .lbl{font-size:11.5px; color:#CFE0FA; letter-spacing:0.6px; margin-top:2px;}\r\n\r\n  \/* Group bar *\/\r\n  .groupbar{\r\n    max-width:1240px; margin:16px auto 0 auto;\r\n    background:rgba(255,255,255,0.08); border:1px solid rgba(255,255,255,0.2);\r\n    border-radius:14px 14px 0 0; padding:12px 18px;\r\n    display:flex; align-items:center; gap:12px; flex-wrap:wrap;\r\n  }\r\n  .groupbar label{font-size:12px; color:#CFE0FA; font-weight:600;}\r\n  .groupbar select, .groupbar input{\r\n    background:#fff; border:none; border-radius:8px; padding:8px 10px; font-size:13.5px; font-family:'Inter',sans-serif;\r\n    color:var(--ink); min-width:150px;\r\n  }\r\n  .groupbar button{\r\n    background:var(--gold); color:#402D00; border:none; border-radius:8px; padding:8px 14px; font-weight:700; font-size:13px;\r\n  }\r\n  .groupbar .status{font-size:12.5px; color:#CFE0FA;}\r\n  .groupbar .status b{color:#fff;}\r\n\r\n  .backend-banner{\r\n    max-width:1240px; margin:16px auto 0 auto; background:var(--red-tint); border:1px solid #F0BFC7;\r\n    color:#7A2233; font-size:12.8px; padding:12px 16px; border-radius:12px;\r\n  }\r\n  .backend-banner b{color:#7A2233;}\r\n  .backend-row{display:flex; gap:8px; margin-top:8px; flex-wrap:wrap;}\r\n  .backend-row input{flex:1; min-width:260px; border:1.5px solid #F0BFC7; border-radius:8px; padding:8px 10px; font-size:13px;}\r\n  .backend-row button{background:var(--navy); color:#fff; border:none; border-radius:8px; padding:8px 16px; font-weight:700; font-size:13px;}\r\n\r\n  .btn-create-team{background:var(--green); color:#fff;}\r\n\r\n  button[disabled]{opacity:0.6; cursor:not-allowed;}\r\n\r\n  \/* Modal *\/\r\n  .modal-overlay{\r\n    display:none; position:fixed; inset:0; background:rgba(8,20,40,0.55); z-index:200;\r\n    align-items:center; justify-content:center; padding:20px;\r\n  }\r\n  .modal-overlay.open{display:flex;}\r\n  .modal-box{\r\n    background:#fff; border-radius:16px; width:100%; max-width:640px; max-height:88vh; overflow-y:auto;\r\n    box-shadow:0 20px 60px rgba(0,0,0,0.3);\r\n  }\r\n  .modal-head{display:flex; align-items:center; justify-content:space-between; padding:18px 22px; border-bottom:1px solid var(--line);}\r\n  .modal-head h3{font-size:17px;}\r\n  .modal-close{background:none; border:none; font-size:16px; color:var(--ink-soft); padding:4px 8px;}\r\n  .modal-body{padding:20px 22px;}\r\n  .modal-foot{display:flex; justify-content:flex-end; gap:10px; padding:16px 22px; border-top:1px solid var(--line);}\r\n\r\n  .members-section{margin-top:18px;}\r\n  .members-section > label{font-size:12.5px; font-weight:700; color:var(--navy); display:block; margin-bottom:8px;}\r\n  .member-row{display:grid; grid-template-columns:1fr 1fr 34px; gap:8px; margin-bottom:8px;}\r\n  .member-row input{border:1.5px solid var(--line); border-radius:9px; padding:9px 11px; font-size:13.3px; font-family:'Inter',sans-serif;}\r\n  .member-remove{background:var(--red-tint); color:var(--red); border:none; border-radius:8px; font-weight:700; font-size:14px;}\r\n\r\n  .team-info-card{padding:20px 22px;}\r\n  .team-info-grid{display:grid; grid-template-columns:1fr 1fr; gap:16px; margin-top:10px;}\r\n  @media(max-width:800px){.team-info-grid{grid-template-columns:1fr;}}\r\n  .team-info-item .ti-label{font-size:11px; font-weight:700; color:var(--ink-soft); text-transform:uppercase; letter-spacing:0.4px;}\r\n  .team-info-item .ti-value{font-size:14px; color:var(--ink); margin-top:3px; font-weight:600;}\r\n  .member-chip{display:inline-block; background:var(--blue-tint); color:var(--blue); font-size:12px; font-weight:700; padding:4px 11px; border-radius:99px; margin:3px 6px 0 0;}\r\n\r\n  \/* Tabs *\/\r\n  .tabs{\r\n    max-width:1240px; margin:0 auto; display:flex; gap:4px; overflow-x:auto;\r\n    padding-top:12px; scrollbar-width:none;\r\n  }\r\n  .tabs::-webkit-scrollbar{display:none;}\r\n  .tab-btn{\r\n    background:transparent; border:none; color:#CFE0FA; padding:12px 16px; font-size:13.5px; font-weight:600;\r\n    border-bottom:3px solid transparent; white-space:nowrap;\r\n  }\r\n  .tab-btn.active{color:#fff; border-bottom-color:var(--gold);}\r\n  .tab-btn:hover{color:#fff;}\r\n\r\n  \/* ---------- Layout ---------- *\/\r\n  .wrap{max-width:1240px; margin:0 auto; padding:26px 28px 80px 28px;}\r\n  .view{display:none; animation:fadein .25s ease;}\r\n  .view.active{display:block;}\r\n  @keyframes fadein{from{opacity:0; transform:translateY(4px);} to{opacity:1; transform:translateY(0);}}\r\n\r\n  .card{\r\n    background:#fff; border:1px solid var(--line); border-radius:var(--radius); box-shadow:var(--shadow);\r\n  }\r\n  .section-title{display:flex; align-items:center; gap:10px; margin-bottom:6px;}\r\n  .section-title h2{font-size:19px;}\r\n  .section-desc{color:var(--ink-soft); font-size:13.5px; margin-bottom:18px; max-width:760px;}\r\n\r\n  \/* Dashboard *\/\r\n  .stat-grid{display:grid; grid-template-columns:repeat(4,1fr); gap:16px; margin-bottom:24px;}\r\n  @media(max-width:900px){.stat-grid{grid-template-columns:repeat(2,1fr);}}\r\n  .stat-card{padding:18px; }\r\n  .stat-card .stat-num{font-family:'Poppins',sans-serif; font-size:30px; font-weight:800; color:var(--blue);}\r\n  .stat-card .stat-lbl{font-size:12.5px; color:var(--ink-soft); font-weight:600; margin-top:2px;}\r\n  .stat-card.gold .stat-num{color:var(--gold-dark);}\r\n  .stat-card.green .stat-num{color:var(--green);}\r\n  .stat-card.navy .stat-num{color:var(--navy);}\r\n\r\n  .progress-outer{background:var(--blue-tint); border-radius:99px; height:10px; overflow:hidden; margin-top:8px;}\r\n  .progress-inner{background:linear-gradient(90deg, var(--blue), var(--gold)); height:100%; border-radius:99px; transition:width .4s ease;}\r\n\r\n  .phase-row{\r\n    display:grid; grid-template-columns: 40px 1fr 130px 90px; align-items:center; gap:14px;\r\n    padding:13px 16px; border-bottom:1px solid var(--line);\r\n  }\r\n  .phase-row:last-child{border-bottom:none;}\r\n  .phase-num-badge{\r\n    width:32px;height:32px;border-radius:9px; background:var(--blue-tint); color:var(--blue);\r\n    display:flex; align-items:center; justify-content:center; font-weight:800; font-size:13px; font-family:'Poppins',sans-serif;\r\n  }\r\n  .phase-row .ph-title{font-weight:700; font-size:13.8px; color:var(--ink);}\r\n  .phase-row .ph-dates{font-size:11.5px; color:var(--ink-soft); margin-top:2px;}\r\n  .status-chip{font-size:11px; font-weight:700; padding:4px 10px; border-radius:99px; text-align:center; white-space:nowrap;}\r\n  .status-chip.notstarted{background:#EEF1F6; color:#66748F;}\r\n  .status-chip.progress{background:var(--amber-tint); color:var(--amber);}\r\n  .status-chip.done{background:var(--green-tint); color:var(--green);}\r\n\r\n  .leaderboard-table{width:100%; border-collapse:collapse; font-size:13px;}\r\n  .leaderboard-table th{\r\n    text-align:left; padding:10px 12px; background:var(--blue-tint); color:var(--navy); font-size:11.5px;\r\n    text-transform:none; letter-spacing:0.2px; font-weight:700; position:sticky; top:0;\r\n  }\r\n  .leaderboard-table td{padding:10px 12px; border-bottom:1px solid var(--line); color:var(--ink);}\r\n  .leaderboard-table tr:hover td{background:var(--blue-tint2);}\r\n\r\n  \/* Roadmap \/ Phases *\/\r\n  .phase-card{margin-bottom:16px; overflow:hidden;}\r\n  .phase-head{\r\n    padding:18px 20px; display:flex; align-items:center; gap:16px; cursor:pointer; user-select:none;\r\n  }\r\n  .phase-head .num{\r\n    width:42px;height:42px;border-radius:11px; background:var(--navy); color:#fff; flex-shrink:0;\r\n    display:flex;align-items:center;justify-content:center; font-family:'Poppins',sans-serif; font-weight:800; font-size:15px;\r\n  }\r\n  .phase-head .titles{flex:1; min-width:0;}\r\n  .phase-head h3{font-size:15.5px;}\r\n  .phase-head .dates{font-size:12px; color:var(--ink-soft); margin-top:2px; font-weight:600;}\r\n  .phase-head .chev{font-size:14px; color:var(--ink-soft); transition:transform .2s ease;}\r\n  .phase-card.open .chev{transform:rotate(180deg);}\r\n  .phase-progress-mini{width:130px; flex-shrink:0;}\r\n  .phase-progress-mini .pct{font-size:11.5px; color:var(--ink-soft); text-align:right; margin-bottom:3px; font-weight:700;}\r\n  .phase-body{display:none; padding:0 20px 20px 20px; border-top:1px solid var(--line);}\r\n  .phase-card.open .phase-body{display:block;}\r\n  .concept-box{\r\n    background:var(--blue-tint2); border:1px dashed var(--blue-light); border-radius:10px; padding:14px 16px; margin:16px 0;\r\n  }\r\n  .concept-box .cb-title{font-size:12px; font-weight:800; color:var(--blue); letter-spacing:0.3px; margin-bottom:6px;}\r\n  .concept-box p{font-size:13.3px; color:var(--ink); margin:0;}\r\n  .concept-box p + p{margin-top:8px;}\r\n  .task-list{list-style:none; margin:0; padding:0;}\r\n  .task-item{\r\n    display:flex; gap:12px; padding:11px 4px; border-bottom:1px solid var(--line); align-items:flex-start;\r\n  }\r\n  .task-item:last-child{border-bottom:none;}\r\n  .task-check{\r\n    width:21px;height:21px; border-radius:6px; border:2px solid var(--blue-light); flex-shrink:0; margin-top:1px;\r\n    display:flex; align-items:center; justify-content:center; font-size:13px; color:#fff; font-weight:800; background:#fff;\r\n  }\r\n  .task-check.checked{background:var(--green); border-color:var(--green);}\r\n  .task-main{flex:1; min-width:0;}\r\n  .task-label{font-size:13.6px; font-weight:600; color:var(--ink); cursor:pointer;}\r\n  .task-item.done .task-label{color:var(--ink-soft); text-decoration:line-through;}\r\n  .task-detail{font-size:12.4px; color:var(--ink-soft); margin-top:3px;}\r\n  .task-proof{font-size:12px; margin-top:5px; color:var(--blue); word-break:break-all;}\r\n  .task-owner-badge{\r\n    font-size:10.5px; background:var(--blue-tint); color:var(--blue); padding:2px 8px; border-radius:99px; font-weight:700;\r\n    flex-shrink:0; margin-top:1px;\r\n  }\r\n\r\n  \/* Forms *\/\r\n  .form-grid{display:grid; grid-template-columns:1fr 1fr; gap:14px;}\r\n  @media(max-width:700px){.form-grid{grid-template-columns:1fr;}}\r\n  .field{display:flex; flex-direction:column; gap:6px;}\r\n  .field.full{grid-column:1\/-1;}\r\n  .field label{font-size:12.5px; font-weight:700; color:var(--navy);}\r\n  .field input, .field select, .field textarea{\r\n    border:1.5px solid var(--line); border-radius:9px; padding:10px 12px; font-size:13.5px; font-family:'Inter',sans-serif;\r\n    color:var(--ink); background:#fff;\r\n  }\r\n  .field textarea{resize:vertical; min-height:70px;}\r\n  .field input:focus, .field select:focus, .field textarea:focus{outline:none; border-color:var(--blue-light);}\r\n  .btn-primary{\r\n    background:var(--blue); color:#fff; border:none; padding:11px 22px; border-radius:9px; font-weight:700; font-size:13.7px;\r\n  }\r\n  .btn-primary:hover{background:var(--navy);}\r\n  .btn-gold{background:var(--gold); color:#402D00;}\r\n  .btn-gold:hover{background:var(--gold-dark); color:#fff;}\r\n  .btn-outline{background:#fff; border:1.5px solid var(--blue); color:var(--blue); padding:9px 16px; border-radius:9px; font-weight:700; font-size:13px;}\r\n\r\n  .eod-entry{border:1px solid var(--line); border-radius:12px; padding:14px 16px; margin-bottom:12px;}\r\n  .eod-entry .eod-head{display:flex; justify-content:space-between; align-items:center; margin-bottom:8px; flex-wrap:wrap; gap:6px;}\r\n  .eod-entry .eod-date{font-weight:800; color:var(--navy); font-size:13.5px;}\r\n  .eod-entry .eod-by{font-size:11.5px; color:var(--ink-soft);}\r\n  .eod-entry .eod-block{font-size:13px; margin-top:6px;}\r\n  .eod-entry .eod-block b{color:var(--navy); font-size:11.5px; text-transform:none; display:block; margin-bottom:2px;}\r\n\r\n  .empty-note{color:var(--ink-soft); font-size:13px; text-align:center; padding:26px 10px;}\r\n\r\n  .briefing-block{margin-bottom:20px;}\r\n  .briefing-block h4{font-size:14px; color:var(--navy); margin-bottom:6px;}\r\n  .briefing-block ul{margin:4px 0 0 18px; padding:0; font-size:13.3px; color:var(--ink); line-height:1.7;}\r\n  .toolchain{display:flex; flex-wrap:wrap; gap:8px; margin-top:8px;}\r\n  .toolchain span{\r\n    background:var(--blue-tint); color:var(--blue); font-size:12px; font-weight:700; padding:5px 11px; border-radius:99px;\r\n  }\r\n  .two-col{display:grid; grid-template-columns:1.4fr 1fr; gap:20px;}\r\n  @media(max-width:900px){.two-col{grid-template-columns:1fr;}}\r\n  .side-note{padding:16px 18px;}\r\n  .side-note h4{font-size:13px; margin-bottom:8px;}\r\n  .side-note ol, .side-note ul{margin:0; padding-left:18px; font-size:12.8px; color:var(--ink-soft); line-height:1.8;}\r\n\r\n  .grid-2{display:grid; grid-template-columns:1fr 1fr; gap:20px;}\r\n  @media(max-width:900px){.grid-2{grid-template-columns:1fr;}}\r\n  .pad{padding:22px 24px;}\r\n  .mb{margin-bottom:20px;}\r\n\r\n  .banner-note{\r\n    background:var(--amber-tint); border:1px solid #F0D9AC; color:#7A5A0F; font-size:12.7px; padding:10px 14px; border-radius:9px;\r\n    margin-bottom:16px;\r\n  }\r\n  select#groupSelect{max-width:200px;}\r\n  .footer-note{text-align:center; color:var(--ink-soft); font-size:12px; margin-top:30px;}\r\n<\/style>\r\n<\/head>\r\n<body>\r\n\r\n<div class=\"topbar\">\r\n  <div class=\"topbar-inner\">\r\n    <div class=\"brandmark\">\r\n      <div class=\"logo-badge\">\r\n        <svg viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M4 12c0-4.4 3.6-8 8-8s8 3.6 8 8-3.6 8-8 8\" stroke=\"#0D4EA0\" stroke-width=\"2.2\" stroke-linecap=\"round\"\/><circle cx=\"12\" cy=\"12\" r=\"2.6\" fill=\"#F2A900\"\/><\/svg>\r\n      <\/div>\r\n      <div class=\"brand-text\">\r\n        <div class=\"name\">DIGITAL NEST<\/div>\r\n        <div class=\"sub\">SCHOOL OF BUSINESS<\/div>\r\n      <\/div>\r\n    <\/div>\r\n    <div class=\"headline\">\r\n      <h1>Capstone Project 3 \u2014 Group Command Center<\/h1>\r\n      <div class=\"tagline\">Meta Ads + CRO + Automation + CRM + Analytics, end-to-end on your own brand microsite.<\/div>\r\n      <div class=\"meta-pills\">\r\n        <span class=\"pill gold\">PGP 14 &amp; PGP 15<\/span>\r\n        <span class=\"pill\">Group Task<\/span>\r\n        <span class=\"pill\">15 Sep \u2013 29 Sep<\/span>\r\n        <span class=\"pill\">Domain: PGPDN.online<\/span>\r\n      <\/div>\r\n    <\/div>\r\n    <div class=\"countdown-box\">\r\n      <div class=\"num\" id=\"countdownNum\">--<\/div>\r\n      <div class=\"lbl\" id=\"countdownLbl\">DAYS TO FINAL PRESENTATION<\/div>\r\n    <\/div>\r\n  <\/div>\r\n\r\n  <div id=\"backendBanner\" class=\"backend-banner\">\r\n    <b>\u26a0 Backend not connected.<\/b> This site needs a Google Apps Script Web App URL to save and sync data. Paste it below (ask your mentor for the shared URL, or deploy your own using the Apps Script code provided).\r\n    <div class=\"backend-row\">\r\n      <input id=\"backendUrlInput\" placeholder=\"https:\/\/script.google.com\/macros\/s\/XXXXXXXX\/exec\">\r\n      <button id=\"backendSaveBtn\">Connect<\/button>\r\n    <\/div>\r\n  <\/div>\r\n\r\n  <div class=\"groupbar\">\r\n    <label>Your Team<\/label>\r\n    <select id=\"groupSelect\"><option value=\"\">\u2014 Select team \u2014<\/option><\/select>\r\n    <button id=\"loadGroupBtn\">Load Team<\/button>\r\n    <button id=\"openCreateModalBtn\" class=\"btn-create-team\">+ Create New Team<\/button>\r\n    <span class=\"status\" id=\"groupStatus\">No team loaded \u2014 data is shared with your teammates &amp; mentor once you load a team.<\/span>\r\n    <span class=\"status\" id=\"backendDot\" style=\"margin-left:auto;cursor:pointer;\" title=\"Click to reconnect \/ change backend URL\">\ud83d\udd34 Backend not connected<\/span>\r\n  <\/div>\r\n\r\n  <div id=\"createTeamOverlay\" class=\"modal-overlay\">\r\n    <div class=\"modal-box\">\r\n      <div class=\"modal-head\">\r\n        <h3>Create Your Team<\/h3>\r\n        <button class=\"modal-close\" id=\"closeCreateModalBtn\">\u2715<\/button>\r\n      <\/div>\r\n      <div class=\"modal-body\">\r\n        <div class=\"form-grid\">\r\n          <div class=\"field\"><label>Team Name *<\/label><input id=\"ctTeamName\" placeholder=\"e.g. Group 4\"><\/div>\r\n          <div class=\"field\"><label>Batch *<\/label><select id=\"ctBatch\"><option>PGP 14<\/option><option>PGP 15<\/option><\/select><\/div>\r\n          <div class=\"field\"><label>Brand Name *<\/label><input id=\"ctBrandName\" placeholder=\"e.g. Everest Wellness\"><\/div>\r\n          <div class=\"field\"><label>Brand Website \/ Subdomain<\/label><input id=\"ctBrandWebsite\" placeholder=\"brandname.pgpdn.online\"><\/div>\r\n          <div class=\"field full\"><label>Brand Description<\/label><textarea id=\"ctBrandDesc\" placeholder=\"One or two lines on what the brand does and who it serves\"><\/textarea><\/div>\r\n        <\/div>\r\n\r\n        <div class=\"members-section\">\r\n          <label>Team Members *<\/label>\r\n          <div id=\"membersList\"><\/div>\r\n          <button type=\"button\" class=\"btn-outline\" id=\"addMemberBtn\">+ Add Member<\/button>\r\n        <\/div>\r\n      <\/div>\r\n      <div class=\"modal-foot\">\r\n        <button class=\"btn-outline\" id=\"cancelCreateBtn\">Cancel<\/button>\r\n        <button class=\"btn-primary btn-gold\" id=\"submitCreateTeamBtn\">Create Team<\/button>\r\n      <\/div>\r\n    <\/div>\r\n  <\/div>\r\n\r\n  <div class=\"tabs\" id=\"tabBar\">\r\n    <button class=\"tab-btn active\" data-tab=\"dashboard\">Track Dashboard<\/button>\r\n    <button class=\"tab-btn\" data-tab=\"roadmap\">Concepts &amp; Tasks<\/button>\r\n    <button class=\"tab-btn\" data-tab=\"eod\">Daily EOD Report<\/button>\r\n    <button class=\"tab-btn\" data-tab=\"submit\">Submit Tasks<\/button>\r\n    <button class=\"tab-btn\" data-tab=\"briefing\">Full Task Briefing<\/button>\r\n  <\/div>\r\n<\/div>\r\n\r\n<div class=\"wrap\">\r\n\r\n  <!-- ============ DASHBOARD ============ -->\r\n  <div class=\"view active\" id=\"view-dashboard\">\r\n    <div class=\"banner-note\" id=\"noGroupBanner\">Load or create your team above to start tracking \u2014 your checklist, EOD reports and submissions save automatically and sync for your whole team.<\/div>\r\n\r\n    <div class=\"card team-info-card mb\" id=\"teamInfoCard\" style=\"display:none;\">\r\n      <div class=\"section-title\"><h2 id=\"teamInfoName\">Team<\/h2><\/div>\r\n      <div class=\"team-info-grid\">\r\n        <div class=\"team-info-item\"><div class=\"ti-label\">Batch<\/div><div class=\"ti-value\" id=\"tiBatch\">\u2014<\/div><\/div>\r\n        <div class=\"team-info-item\"><div class=\"ti-label\">Brand<\/div><div class=\"ti-value\" id=\"tiBrand\">\u2014<\/div><\/div>\r\n        <div class=\"team-info-item\"><div class=\"ti-label\">Brand Website<\/div><div class=\"ti-value\" id=\"tiWebsite\">\u2014<\/div><\/div>\r\n        <div class=\"team-info-item\"><div class=\"ti-label\">Brand Description<\/div><div class=\"ti-value\" id=\"tiDesc\">\u2014<\/div><\/div>\r\n      <\/div>\r\n      <div class=\"team-info-item\" style=\"margin-top:14px;\">\r\n        <div class=\"ti-label\">Team Members<\/div>\r\n        <div id=\"tiMembers\" style=\"margin-top:6px;\">\u2014<\/div>\r\n      <\/div>\r\n    <\/div>\r\n\r\n    <div class=\"stat-grid\">\r\n      <div class=\"card stat-card\">\r\n        <div class=\"stat-num\" id=\"statPct\">0%<\/div>\r\n        <div class=\"stat-lbl\">Overall Task Completion<\/div>\r\n        <div class=\"progress-outer\"><div class=\"progress-inner\" id=\"statPctBar\" style=\"width:0%\"><\/div><\/div>\r\n      <\/div>\r\n      <div class=\"card stat-card gold\">\r\n        <div class=\"stat-num\" id=\"statTasksDone\">0 \/ 0<\/div>\r\n        <div class=\"stat-lbl\">Tasks Completed<\/div>\r\n      <\/div>\r\n      <div class=\"card stat-card green\">\r\n        <div class=\"stat-num\" id=\"statEodCount\">0<\/div>\r\n        <div class=\"stat-lbl\">EOD Reports Submitted<\/div>\r\n      <\/div>\r\n      <div class=\"card stat-card navy\">\r\n        <div class=\"stat-num\" id=\"statPhaseNow\">\u2013<\/div>\r\n        <div class=\"stat-lbl\">Current Phase<\/div>\r\n      <\/div>\r\n    <\/div>\r\n\r\n    <div class=\"card pad mb\">\r\n      <div class=\"section-title\"><h2>Phase-wise Progress<\/h2><\/div>\r\n      <div class=\"section-desc\">Live status of your group across all 12 phases of the capstone. Tick tasks in <b>Concepts &amp; Tasks<\/b> to update this automatically.<\/div>\r\n      <div id=\"phaseProgressList\"><\/div>\r\n    <\/div>\r\n\r\n    <div class=\"card pad\">\r\n      <div class=\"section-title\"><h2>Class Leaderboard \u2014 All Groups<\/h2><\/div>\r\n      <div class=\"section-desc\">Visible to everyone so mentors and groups can see overall class progress at a glance.<\/div>\r\n      <div style=\"overflow-x:auto;\">\r\n        <table class=\"leaderboard-table\">\r\n          <thead><tr><th>Group<\/th><th>Batch<\/th><th>Brand<\/th><th>Tasks Done<\/th><th>Progress<\/th><th>Last EOD<\/th><\/tr><\/thead>\r\n          <tbody id=\"leaderboardBody\"><tr><td colspan=\"6\" class=\"empty-note\">No groups have started yet.<\/td><\/tr><\/tbody>\r\n        <\/table>\r\n      <\/div>\r\n    <\/div>\r\n  <\/div>\r\n\r\n  <!-- ============ ROADMAP ============ -->\r\n  <div class=\"view\" id=\"view-roadmap\">\r\n    <div class=\"section-title\"><h2>Concepts &amp; Tasks \u2014 12 Phases<\/h2><\/div>\r\n    <div class=\"section-desc\">Each phase explains the <b>concept<\/b> you're applying, then lists the exact <b>tasks<\/b> to complete. Tick a task, attach the deliverable link, and it's saved for your group instantly.<\/div>\r\n    <div id=\"phaseContainer\"><\/div>\r\n  <\/div>\r\n\r\n  <!-- ============ EOD ============ -->\r\n  <div class=\"view\" id=\"view-eod\">\r\n    <div class=\"two-col\">\r\n      <div>\r\n        <div class=\"card pad mb\">\r\n          <div class=\"section-title\"><h2>Submit Today's EOD Report<\/h2><\/div>\r\n          <div class=\"section-desc\">Every group submits one End-of-Day report per working day of the sprint. Be specific \u2014 mentors review these to unblock you fast.<\/div>\r\n          <div class=\"form-grid\">\r\n            <div class=\"field\"><label>Date<\/label><input type=\"date\" id=\"eodDate\"><\/div>\r\n            <div class=\"field\"><label>Submitted by<\/label><input type=\"text\" id=\"eodBy\" placeholder=\"Your name\"><\/div>\r\n            <div class=\"field full\"><label>Current phase you worked on today<\/label>\r\n              <select id=\"eodPhase\"><\/select>\r\n            <\/div>\r\n            <div class=\"field full\"><label>What did you complete today?<\/label>\r\n              <textarea id=\"eodDone\" placeholder=\"e.g. Subdomain created, WordPress installed, GA4 property connected...\"><\/textarea>\r\n            <\/div>\r\n            <div class=\"field full\"><label>Blockers \/ help needed<\/label>\r\n              <textarea id=\"eodBlockers\" placeholder=\"e.g. Waiting on Hostinger access from Jayanth\"><\/textarea>\r\n            <\/div>\r\n            <div class=\"field full\"><label>Plan for tomorrow<\/label>\r\n              <textarea id=\"eodPlan\" placeholder=\"e.g. Start CRO audit of Competitor 1 using the template\"><\/textarea>\r\n            <\/div>\r\n          <\/div>\r\n          <div style=\"margin-top:14px;\"><button class=\"btn-primary\" id=\"submitEodBtn\">Submit EOD Report<\/button><\/div>\r\n        <\/div>\r\n      <\/div>\r\n      <div class=\"card side-note\">\r\n        <h4>What makes a good EOD report<\/h4>\r\n        <ul>\r\n          <li>Name the exact task, not just the phase (\"GA4 config tag fired on all pages\", not \"worked on analytics\").<\/li>\r\n          <li>Flag blockers the moment they happen \u2014 access, approvals, tool logins.<\/li>\r\n          <li>Tomorrow's plan should map to one or two tasks in the checklist, not the whole phase.<\/li>\r\n          <li>One report per day, per group \u2014 assign a rotating scribe if needed.<\/li>\r\n        <\/ul>\r\n      <\/div>\r\n    <\/div>\r\n\r\n    <div class=\"card pad\" style=\"margin-top:20px;\">\r\n      <div class=\"section-title\"><h2>EOD History<\/h2><\/div>\r\n      <div id=\"eodHistory\"><div class=\"empty-note\">No EOD reports yet.<\/div><\/div>\r\n    <\/div>\r\n  <\/div>\r\n\r\n  <!-- ============ SUBMIT TASKS ============ -->\r\n  <div class=\"view\" id=\"view-submit\">\r\n    <div class=\"two-col\">\r\n      <div class=\"card pad mb\">\r\n        <div class=\"section-title\"><h2>Submit a Deliverable<\/h2><\/div>\r\n        <div class=\"section-desc\">Attach proof of work \u2014 a link, doc, sheet, or short description \u2014 against the exact task it belongs to. This also marks the task complete on your dashboard.<\/div>\r\n        <div class=\"form-grid\">\r\n          <div class=\"field full\"><label>Phase<\/label><select id=\"submitPhase\"><\/select><\/div>\r\n          <div class=\"field full\"><label>Task<\/label><select id=\"submitTask\"><\/select><\/div>\r\n          <div class=\"field full\"><label>Link (Sheet \/ Doc \/ Drive \/ Live URL)<\/label><input type=\"text\" id=\"submitLink\" placeholder=\"https:\/\/...\"><\/div>\r\n          <div class=\"field full\"><label>Notes<\/label><textarea id=\"submitNotes\" placeholder=\"Short note on what was done \/ which model, template or tool used\"><\/textarea><\/div>\r\n          <div class=\"field\"><label>Submitted by<\/label><input type=\"text\" id=\"submitBy\" placeholder=\"Your name\"><\/div>\r\n        <\/div>\r\n        <div style=\"margin-top:14px;\"><button class=\"btn-primary btn-gold\" id=\"submitTaskBtn\">Mark Complete &amp; Submit<\/button><\/div>\r\n      <\/div>\r\n      <div class=\"card side-note\">\r\n        <h4>Submission checklist<\/h4>\r\n        <ul>\r\n          <li>Google Sheets \/ Docs: set sharing to \"Anyone with the link \u2013 Viewer\" before pasting.<\/li>\r\n          <li>Live pages: paste the actual subdomain URL, not the WordPress admin link.<\/li>\r\n          <li>Templates (Funnel, Media Plan, Persona, A\/B Plan, CRO Audit): submit the filled copy, not the blank template.<\/li>\r\n          <li>Screenshots of GTM\/GA4\/CRM setups can go in a shared Drive folder \u2014 paste that folder link.<\/li>\r\n        <\/ul>\r\n      <\/div>\r\n    <\/div>\r\n\r\n    <div class=\"card pad\" style=\"margin-top:20px;\">\r\n      <div class=\"section-title\"><h2>Submission Log<\/h2><\/div>\r\n      <div style=\"overflow-x:auto;\">\r\n        <table class=\"leaderboard-table\">\r\n          <thead><tr><th>Date<\/th><th>Phase<\/th><th>Task<\/th><th>Link<\/th><th>Notes<\/th><th>By<\/th><\/tr><\/thead>\r\n          <tbody id=\"submissionLog\"><tr><td colspan=\"6\" class=\"empty-note\">No submissions yet.<\/td><\/tr><\/tbody>\r\n        <\/table>\r\n      <\/div>\r\n    <\/div>\r\n  <\/div>\r\n\r\n  <!-- ============ BRIEFING ============ -->\r\n  <div class=\"view\" id=\"view-briefing\">\r\n    <div class=\"card pad\">\r\n      <div class=\"section-title\"><h2>Full Task Briefing<\/h2><\/div>\r\n      <div class=\"section-desc\">The complete brief for Capstone Project 3, organized in the order you'll execute it. This is the reference copy \u2014 the working checklist lives under <b>Concepts &amp; Tasks<\/b>.<\/div>\r\n\r\n      <div class=\"briefing-block\">\r\n        <h4>Project overview<\/h4>\r\n        <ul>\r\n          <li>Group capstone for PGP 14 and PGP 15, running <b>15 Sep \u2013 29 Sep<\/b>, ending in a final presentation.<\/li>\r\n          <li>Every group has already chosen a brand to build the entire funnel around.<\/li>\r\n          <li>Every group gets a subdomain under <b>PGPDN.online<\/b> (Hostinger access via Jayanth), named after the brand.<\/li>\r\n          <li>The deliverable is a working, tracked, automated lead-generation system for that brand \u2014 landing page, ads, tracking, and CRM \u2014 plus a live campaign run.<\/li>\r\n        <\/ul>\r\n      <\/div>\r\n\r\n      <div class=\"briefing-block\">\r\n        <h4>1. Domain, hosting &amp; base setup<\/h4>\r\n        <ul>\r\n          <li>Get Hostinger access from Jayanth and create your brand's subdomain on PGPDN.online.<\/li>\r\n          <li>Install WordPress on the subdomain.<\/li>\r\n          <li>Create a new dedicated email ID, new GTM container, new GA4 property, and new Microsoft Clarity project for this subdomain.<\/li>\r\n        <\/ul>\r\n      <\/div>\r\n\r\n      <div class=\"briefing-block\">\r\n        <h4>2. Competitor research &amp; CRO audit<\/h4>\r\n        <ul>\r\n          <li>Run a competitor analysis (template shared in WhatsApp group).<\/li>\r\n          <li>Conduct a CRO audit of a competitor's page using the shared template.<\/li>\r\n        <\/ul>\r\n      <\/div>\r\n\r\n      <div class=\"briefing-block\">\r\n        <h4>3. AI landing page &amp; conversion elements<\/h4>\r\n        <ul>\r\n          <li>Build one AI-assisted landing page (ChatGPT, Claude, or similar).<\/li>\r\n          <li>Write the copy applying Fogg's Behaviour Model, the LIFT Model, or a mix of both \u2014 state which you used.<\/li>\r\n          <li>Set up: Lead Form via Instant Form, Chatbot via Live Chatbot, Popup via Hello Bar, WhatsApp button via Wati.<\/li>\r\n          <li>Create an A\/B test variant of the landing page (template shared).<\/li>\r\n        <\/ul>\r\n      <\/div>\r\n\r\n      <div class=\"briefing-block\">\r\n        <h4>4. Meta Ads account<\/h4>\r\n        <ul>\r\n          <li>Set up a new Meta Ads account if required, or reuse an existing one if you already have access.<\/li>\r\n        <\/ul>\r\n      <\/div>\r\n\r\n      <div class=\"briefing-block\">\r\n        <h4>5. Tracking implementation<\/h4>\r\n        <ul>\r\n          <li>Install the new GTM container on the new WordPress site, firing on all pages and the Thank You page.<\/li>\r\n          <li>Set up GA4 tags for all pages, plus a Thank You page event named <b>\"Lead\"<\/b>.<\/li>\r\n          <li>Track: all button clicks, form starts, video engagement, scroll depth, element visibility, and the Meta pixel \u2014 across all pages and the Thank You page.<\/li>\r\n          <li>Deploy Microsoft Clarity, Hello Bar, and the Chatbot via GTM, and keep the GTM workspace organized into folders.<\/li>\r\n        <\/ul>\r\n      <\/div>\r\n\r\n      <div class=\"briefing-block\">\r\n        <h4>6. Campaign planning (templates shared)<\/h4>\r\n        <ul>\r\n          <li>Marketing funnel for the Meta ad<\/li>\r\n          <li>Media plan<\/li>\r\n          <li>Campaign structure<\/li>\r\n          <li>Buyer persona<\/li>\r\n          <li>A\/B testing plan<\/li>\r\n        <\/ul>\r\n      <\/div>\r\n\r\n      <div class=\"briefing-block\">\r\n        <h4>7. Creative production<\/h4>\r\n        <ul>\r\n          <li>Script, shoot, and edit a Reel ad.<\/li>\r\n          <li>Build the ad using Claude or manually.<\/li>\r\n          <li>Apply Ads Manager Rules and Value Rules where applicable.<\/li>\r\n        <\/ul>\r\n      <\/div>\r\n\r\n      <div class=\"briefing-block\">\r\n        <h4>8. Data pipeline &amp; CRM<\/h4>\r\n        <ul>\r\n          <li>Push KPI data into a Google Sheet via Apps Script.<\/li>\r\n          <li>Build one organized master sheet consolidating KPIs and leads from every source.<\/li>\r\n          <li>Set up Zoho CRM to manage all leads centrally.<\/li>\r\n          <li>Build Zapier workflows: Lead Form \u2192 Sheet \u2192 CRM; Chatbot \u2192 Sheet \u2192 CRM; Popup \u2192 Sheet \u2192 CRM; Meta Instant Form \u2192 Sheet \u2192 CRM.<\/li>\r\n          <li>Every new CRM lead should trigger an automated welcome email \u2014 write the email and wire the workflow.<\/li>\r\n          <li>Define a lead scoring &amp; qualification framework, and assign leads to a sales team you nominate from your group.<\/li>\r\n          <li>Build a CRM dashboard in Zoho.<\/li>\r\n        <\/ul>\r\n      <\/div>\r\n\r\n      <div class=\"briefing-block\">\r\n        <h4>9. Launch &amp; optimize<\/h4>\r\n        <ul>\r\n          <li>Launch the campaign and run it until you get a qualified lead within budget.<\/li>\r\n          <li>Follow a full optimization checklist (built into the \"Launch &amp; Optimize\" phase of this tracker) covering CTR, CPL, match rate, LP conversion, and budget issues.<\/li>\r\n        <\/ul>\r\n      <\/div>\r\n\r\n      <div class=\"briefing-block\">\r\n        <h4>10. Final presentation<\/h4>\r\n        <ul>\r\n          <li>Present the full journey: brand, funnel, creative, tracking, automation, CRM, results, and learnings.<\/li>\r\n        <\/ul>\r\n      <\/div>\r\n\r\n      <div class=\"briefing-block\">\r\n        <h4>Tool stack you'll touch<\/h4>\r\n        <div class=\"toolchain\">\r\n          <span>Hostinger<\/span><span>WordPress<\/span><span>Google Tag Manager<\/span><span>GA4<\/span><span>Microsoft Clarity<\/span>\r\n          <span>Meta Ads Manager<\/span><span>Meta Instant Form<\/span><span>Live Chatbot<\/span><span>Hello Bar<\/span><span>Wati<\/span>\r\n          <span>ChatGPT \/ Claude<\/span><span>Google Sheets + Apps Script<\/span><span>Zapier<\/span><span>Zoho CRM<\/span>\r\n        <\/div>\r\n      <\/div>\r\n    <\/div>\r\n  <\/div>\r\n\r\n<\/div>\r\n\r\n<div class=\"footer-note\">Digital Nest School of Business \u00b7 Capstone Project 3 Tracker \u00b7 Data syncs live for your group and mentors.<\/div>\r\n\r\n<script>\r\n\/* =============================================================\r\n   DATA MODEL \u2014 PHASES (concept + tasks, unchanged from before)\r\n   ============================================================= *\/\r\nconst PROJECT_END = new Date('2026-09-29T23:59:59');\r\n\r\nconst PHASES = [\r\n  {\r\n    id:'p1', title:'Domain, Hosting & Base Tracking Setup', dates:'15\u201316 Sep',\r\n    concept:`Every group's brand needs its own clean, isolated environment before any tracking or ads work starts. A subdomain on PGPDN.online keeps each brand's WordPress install, tracking IDs and traffic completely separate from other groups, so your GA4 and GTM data is never mixed with someone else's.`,\r\n    tasks:[\r\n      {id:'t1', label:'Request Hostinger access from Jayanth', detail:'Confirm access and note down login details securely.'},\r\n      {id:'t2', label:'Create your subdomain on PGPDN.online', detail:'Name the subdomain after your chosen brand.'},\r\n      {id:'t3', label:'Install WordPress on the subdomain', detail:'Complete the base WordPress setup and remove default demo content.'},\r\n      {id:'t4', label:'Create a new dedicated email ID for the brand', detail:'Used for CRM, Meta Business, GA4 and all tool sign-ups.'},\r\n      {id:'t5', label:'Create a new GTM container for the subdomain', detail:'One container per brand, not reused from a personal account.'},\r\n      {id:'t6', label:'Create a new GA4 property for the subdomain', detail:'Link it to the correct data stream (the new subdomain).'},\r\n      {id:'t7', label:'Set up a new Microsoft Clarity project for the subdomain', detail:'Used later for session recordings and heatmaps.'},\r\n    ]\r\n  },\r\n  {\r\n    id:'p2', title:'Competitor Research & CRO Audit', dates:'16\u201317 Sep',\r\n    concept:`Before you design your own page, study how competitors convert visitors. A CRO (Conversion Rate Optimization) audit looks at a page's clarity, friction points, trust signals and calls-to-action to find what's working and what's leaking conversions \u2014 insights you'll reuse in your own landing page.`,\r\n    tasks:[\r\n      {id:'t1', label:'Shortlist 3\u20135 direct competitors for your brand', detail:'Pick brands targeting a similar audience or offer.'},\r\n      {id:'t2', label:'Fill the Competitor Analysis template', detail:'Template shared in the WhatsApp group.'},\r\n      {id:'t3', label:'Conduct a CRO audit on one competitor landing page', detail:'Use the shared CRO audit template \u2014 note friction points and strengths.'},\r\n    ]\r\n  },\r\n  {\r\n    id:'p3', title:'AI Landing Page & Copywriting', dates:'17\u201319 Sep',\r\n    concept:`Fogg's Behaviour Model says a behaviour (like submitting a form) happens only when Motivation, Ability and a Prompt all line up at the same moment \u2014 so your page must build desire, remove friction, and give a clear trigger. The LIFT Model instead audits six conversion levers: Value proposition, relevance, Clarity, urgency, anxiety and distraction \u2014 reducing anxiety and distraction while raising clarity and relevance. You can build your copy using one model, or blend both.`,\r\n    tasks:[\r\n      {id:'t1', label:'Draft the landing page structure using ChatGPT or Claude', detail:'Sections, flow, and key messages before writing final copy.'},\r\n      {id:'t2', label:\"Write final LP copy using Fogg's Model, LIFT Model, or both\", detail:'Document which model(s) you applied and why.'},\r\n      {id:'t3', label:'Build the landing page on your WordPress subdomain', detail:'Mobile-responsive, fast-loading, on-brand.'},\r\n      {id:'t4', label:'Set up the Lead Form using Instant Form', detail:'On-page lead capture form.'},\r\n      {id:'t5', label:'Install a Live Chatbot on the page', detail:'Basic qualifying questions and handoff message.'},\r\n      {id:'t6', label:'Install a Popup using Hello Bar', detail:'Exit-intent or timed popup with a clear offer.'},\r\n      {id:'t7', label:'Add a WhatsApp button using Wati', detail:'Sticky button connected to your brand WhatsApp number.'},\r\n      {id:'t8', label:'Create an A\/B test variant of the landing page', detail:'Template shared \u2014 vary one meaningful element (headline, CTA, hero, form length).'},\r\n    ]\r\n  },\r\n  {\r\n    id:'p4', title:'Meta Ads Account Setup', dates:'19 Sep',\r\n    concept:`Every ad, pixel event and audience needs a clean Meta Business Manager and Ad Account tied to the right Page. If your group already has a usable ad account, you don't need a new one \u2014 just confirm access and Page ownership before spending any budget.`,\r\n    tasks:[\r\n      {id:'t1', label:'Set up a new Meta Ads account, or confirm access to an existing one', detail:'Note which option your group used and why.'},\r\n      {id:'t2', label:'Verify Business Manager, Page access, and Pixel placeholder', detail:'Make sure the right people on your team have admin access.'},\r\n    ]\r\n  },\r\n  {\r\n    id:'p5', title:'Tracking Implementation (GTM \u00b7 GA4 \u00b7 Clarity \u00b7 Pixel)', dates:'19\u201321 Sep',\r\n    concept:`A well-organized GTM container is the backbone of measurement \u2014 every button click, form start, scroll, and video play should fire a tag so GA4 and Meta know what happened. The Thank You page carries the most important signal: a \"Lead\" conversion event, since that's what tells Meta's algorithm who a good lead looks like.`,\r\n    tasks:[\r\n      {id:'t1', label:'Install the new GTM container on the new WordPress site', detail:'Base container snippet in the header and body.'},\r\n      {id:'t2', label:'Fire GTM base tag on all pages', detail:'Confirm via GTM Preview mode.'},\r\n      {id:'t3', label:'Fire GTM base tag on the Thank You page', detail:'Separate confirmation event.'},\r\n      {id:'t4', label:'Create a GA4 configuration tag firing on all pages', detail:'Single GA4 config tag, all pages trigger.'},\r\n      {id:'t5', label:'Create a GA4 event tag on the Thank You page named \"Lead\"', detail:'This is your primary conversion event.'},\r\n      {id:'t6', label:'Set up Button Click tracking for all key CTAs', detail:'Header CTA, hero CTA, sticky WhatsApp button, form submit button.'},\r\n      {id:'t7', label:'Set up Form Start tracking', detail:'Fires when a user interacts with the first form field.'},\r\n      {id:'t8', label:'Set up Video engagement tracking', detail:'Play, 25\/50\/75\/100% milestones if a video is used.'},\r\n      {id:'t9', label:'Set up Scroll Depth tracking', detail:'25\/50\/75\/90% thresholds.'},\r\n      {id:'t10', label:'Set up Element Visibility tracking', detail:'Track when key sections (offer, testimonials, form) enter the viewport.'},\r\n      {id:'t11', label:'Set up Meta Pixel base code + events on all pages and the Thank You page', detail:'PageView on all pages, Lead event on Thank You page.'},\r\n      {id:'t12', label:'Deploy Microsoft Clarity via GTM', detail:'Custom HTML tag firing on all pages.'},\r\n      {id:'t13', label:'Deploy Hello Bar tracking via GTM', detail:'Fire popup view \/ interaction as GTM events.'},\r\n      {id:'t14', label:'Deploy Chatbot tracking via GTM', detail:'Fire chatbot open \/ message-sent as GTM events.'},\r\n      {id:'t15', label:'Organize the GTM workspace into folders', detail:'e.g. Base Tags, GA4, Meta Pixel, Clarity\/Tools, Engagement Tracking.'},\r\n    ]\r\n  },\r\n  {\r\n    id:'p6', title:'Campaign Planning & Strategy', dates:'21\u201323 Sep',\r\n    concept:`Good ad performance is planned, not improvised. A funnel maps the journey from cold audience to lead; a media plan sets budget and timeline; a campaign structure defines how ad sets and audiences are organized; a buyer persona keeps targeting and messaging aligned to a real person; and an A\/B testing plan makes sure every test has a clear hypothesis and success metric.`,\r\n    tasks:[\r\n      {id:'t1', label:'Build the Meta Ads funnel', detail:'Template shared \u2014 awareness \u2192 consideration \u2192 conversion stages.'},\r\n      {id:'t2', label:'Build the Media Plan', detail:'Template shared \u2014 budget split, flight dates, placements.'},\r\n      {id:'t3', label:'Define the Campaign Structure', detail:'Template shared \u2014 campaigns, ad sets, audiences, ads.'},\r\n      {id:'t4', label:'Create the Buyer Persona', detail:'Template shared \u2014 demographics, pain points, motivations, objections.'},\r\n      {id:'t5', label:'Create the A\/B Testing Plan for ads', detail:'Template shared \u2014 variable tested, hypothesis, success metric.'},\r\n    ]\r\n  },\r\n  {\r\n    id:'p7', title:'Creative Production', dates:'23\u201324 Sep',\r\n    concept:`The Reel is usually the highest-impact creative in a Meta campaign \u2014 the first 2\u20133 seconds decide whether someone keeps watching. Script it around a hook, a problem, and a clear offer before you shoot, so editing is fast and focused.`,\r\n    tasks:[\r\n      {id:'t1', label:'Write the script for the Reel ad', detail:'Hook, problem, solution\/offer, CTA \u2014 timed to 15\u201330 seconds.'},\r\n      {id:'t2', label:'Shoot the Reel footage', detail:'Vertical 9:16, clean audio, good lighting.'},\r\n      {id:'t3', label:'Edit the Reel ad', detail:'Captions, music, brand elements, strong opening frame.'},\r\n    ]\r\n  },\r\n  {\r\n    id:'p8', title:'Ad Setup & Automation Rules', dates:'24 Sep',\r\n    concept:`Automated Rules pause or adjust ad sets when they cross a threshold (e.g. CPL too high, budget spent, low CTR), and Value Rules bid more for higher-value leads. Not every campaign needs them at this budget scale \u2014 decide deliberately and record your reasoning either way.`,\r\n    tasks:[\r\n      {id:'t1', label:'Build the ad creative and copy using Claude or manually', detail:'Primary text, headline, description, CTA button.'},\r\n      {id:'t2', label:'Set up Automated Rules and Value Rules if applicable', detail:'State clearly whether your group used these and why \/ why not.'},\r\n    ]\r\n  },\r\n  {\r\n    id:'p9', title:'Data Pipeline & CRM Setup', dates:'24\u201326 Sep',\r\n    concept:`A CRM only helps if leads actually land in it \u2014 automatically, from every source. Zapier connects your Lead Form, Chatbot, Popup and Meta Instant Form to a Google Sheet (for KPI reporting) and then to Zoho CRM (for sales follow-up), while lead scoring tells your sales team which leads to call first.`,\r\n    tasks:[\r\n      {id:'t1', label:'Set up Apps Script to push KPI data into a Google Sheet', detail:'Automate pulling ad\/LP KPIs on a schedule.'},\r\n      {id:'t2', label:'Build one organized master Google Sheet', detail:'Consolidate KPIs and leads from every source into one place.'},\r\n      {id:'t3', label:'Set up Zoho CRM for the brand', detail:'Pipeline stages, lead fields, and owners configured.'},\r\n      {id:'t4', label:'Zapier: Lead Form \u2192 Google Sheet \u2192 Zoho CRM', detail:'Test end-to-end with a sample submission.'},\r\n      {id:'t5', label:'Zapier: Chatbot \u2192 Google Sheet \u2192 Zoho CRM', detail:'Test end-to-end with a sample submission.'},\r\n      {id:'t6', label:'Zapier: Popup (Hello Bar) \u2192 Google Sheet \u2192 Zoho CRM', detail:'Test end-to-end with a sample submission.'},\r\n      {id:'t7', label:'Zapier: Meta Instant Form \u2192 Google Sheet \u2192 Zoho CRM', detail:'Test end-to-end with a sample submission.'},\r\n      {id:'t8', label:'Write and automate a \"new lead\" welcome email', detail:'Triggered automatically the moment a lead lands in Zoho CRM.'},\r\n      {id:'t9', label:'Define the Lead Scoring & Qualification Framework', detail:'Criteria that separate a Marketing Qualified Lead from a Sales Qualified Lead.'},\r\n      {id:'t10', label:'Set up Lead Assignment to your sales team', detail:'Nominate 1\u20132 members from your group as the \"sales team\".'},\r\n      {id:'t11', label:'Build a CRM Dashboard in Zoho', detail:'Lead volume, source, stage, and conversion rate at a glance.'},\r\n    ]\r\n  },\r\n  {\r\n    id:'p10', title:'Campaign Launch & Optimization', dates:'26\u201328 Sep',\r\n    concept:`Launching is the start of learning, not the end of the work. Track performance daily against budget and keep optimizing \u2014 creative, audience, or landing page \u2014 until you get at least one qualified lead within your budget. Use the optimization checklist below whenever a metric goes off track.`,\r\n    tasks:[\r\n      {id:'t1', label:'Launch the Meta ad campaign', detail:'Double-check pixel firing and budget before going live.'},\r\n      {id:'t2', label:'Monitor daily performance vs. budget', detail:'CPL, CTR, spend pace, and lead quality reviewed every day.'},\r\n      {id:'t3', label:'Run the campaign until a qualified lead is achieved within budget', detail:'Log every optimization change made along the way.'},\r\n      {id:'t4', label:'Complete the Optimization Checklist below', detail:'Work through each symptom and its fix as it applies to your campaign.'},\r\n    ],\r\n    checklist:[\r\n      {issue:'Low CTR on ads', fix:'Refresh creative\/thumbnail, tighten the hook in the first 2 seconds, test a new headline.'},\r\n      {issue:'High CPL (cost per lead)', fix:'Narrow or widen audience, check for audience overlap, test a lower-friction offer.'},\r\n      {issue:'Low form completion \/ high drop-off', fix:'Shorten the form, restate the value prop above the fold, reduce required fields.'},\r\n      {issue:'Low Instant Form match rate', fix:'Check field mapping in Meta, simplify qualifying questions.'},\r\n      {issue:'Ads disapproved or limited delivery', fix:'Review ad copy against Meta policy, remove flagged claims\/imagery, resubmit.'},\r\n      {issue:'Budget spent with no leads', fix:'Pause the weakest ad set, reallocate budget to the best-performing audience.'},\r\n      {issue:'High traffic but low landing page conversion', fix:'Re-check LIFT\/Fogg elements \u2014 clarity, anxiety, and CTA visibility on the LP.'},\r\n      {issue:'Leads coming in but not qualifying', fix:'Revisit the Lead Scoring framework and tighten targeting\/persona fit.'},\r\n    ]\r\n  },\r\n  {\r\n    id:'p11', title:'Final Presentation', dates:'29 Sep',\r\n    concept:`The presentation tells the whole story \u2014 brand, funnel, tracking, automation, and results \u2014 as one narrative. Judges will care less about the number of tools used and more about whether the system actually worked end-to-end and what you learned when it didn't.`,\r\n    tasks:[\r\n      {id:'t1', label:'Compile the results deck', detail:'Brand, funnel, creative, tracking setup, CRM\/automation, results, key learnings.'},\r\n      {id:'t2', label:'Assign speaking parts across the group', detail:'Every member presents at least one section.'},\r\n      {id:'t3', label:'Rehearse the presentation once as a full run-through', detail:'Time it and tighten any long sections.'},\r\n      {id:'t4', label:'Submit the final presentation file\/link', detail:'Paste the shared link in the Submit Tasks tab.'},\r\n    ]\r\n  },\r\n];\r\n\r\nfunction totalTaskCount(){ return PHASES.reduce((s,p)=>s+p.tasks.length,0); }\r\n\r\n\/* =============================================================\r\n   BACKEND CONNECTION \u2014 Google Apps Script Web App\r\n   ============================================================= *\/\r\nlet APPS_SCRIPT_URL = localStorage.getItem('capstone_gas_url') || 'https:\/\/script.google.com\/macros\/s\/AKfycbwY7XRKRhfY_fjT20n7DFlYbhi1YcA6Pz1a51XXcoo_KFHq4MVcVErgMaYUhyLqleTr\/exec';\r\n\r\nconst api = {\r\n  configured(){ return !!APPS_SCRIPT_URL; },\r\n  async call(params){\r\n    if(!APPS_SCRIPT_URL) throw new Error('Backend not connected');\r\n    const qs = new URLSearchParams(params).toString();\r\n    const res = await fetch(APPS_SCRIPT_URL + '?' + qs);\r\n    if(!res.ok) throw new Error('Backend request failed (HTTP '+res.status+')');\r\n    const data = await res.json();\r\n    if(data && data.error) throw new Error(data.error);\r\n    return data;\r\n  },\r\n  getTeams(){ return this.call({action:'getTeams'}); },\r\n  getTeamData(team){ return this.call({action:'getTeamData', team}); },\r\n  createTeam(payload){ return this.call(Object.assign({action:'createTeam'}, payload)); },\r\n  setTask(payload){ return this.call(Object.assign({action:'setTask'}, payload)); },\r\n  addEod(payload){ return this.call(Object.assign({action:'addEod'}, payload)); },\r\n  addSubmission(payload){ return this.call(Object.assign({action:'addSubmission'}, payload)); }\r\n};\r\n\r\nfunction updateBackendStatusUI(){\r\n  const banner = document.getElementById('backendBanner');\r\n  const dot = document.getElementById('backendDot');\r\n  if(api.configured()){\r\n    banner.style.display='none';\r\n    dot.textContent = '\ud83d\udfe2 Backend connected';\r\n  } else {\r\n    banner.style.display='block';\r\n    dot.textContent = '\ud83d\udd34 Backend not connected';\r\n  }\r\n}\r\n\r\ndocument.getElementById('backendDot').addEventListener('click', ()=>{\r\n  document.getElementById('backendBanner').style.display='block';\r\n});\r\n\r\ndocument.getElementById('backendSaveBtn').addEventListener('click', async ()=>{\r\n  const url = document.getElementById('backendUrlInput').value.trim();\r\n  if(!url){ alert('Paste your Apps Script Web App URL first.'); return; }\r\n  APPS_SCRIPT_URL = url;\r\n  localStorage.setItem('capstone_gas_url', url);\r\n  updateBackendStatusUI();\r\n  try{\r\n    await api.getTeams();\r\n    alert('Connected! You can now load or create a team.');\r\n    await loadTeamsList();\r\n  }catch(e){\r\n    alert('Could not reach that URL: ' + e.message);\r\n  }\r\n});\r\n\r\n\/* =============================================================\r\n   STATE\r\n   ============================================================= *\/\r\nlet currentTeamKey = null;\r\nlet currentTeam = null;          \/\/ {teamKey, teamName, batch, brandName, brandWebsite, brandDescription, members:[{name,role}]}\r\nlet currentTasksMap = {};        \/\/ \"phaseId_taskId\" -> {done, link, notes, by, updatedAt}\r\nlet currentEod = [];\r\nlet currentSubmissions = [];\r\nlet teamsIndex = [];             \/\/ list of team summary objects from the Teams sheet\r\n\r\nfunction slugify(name){ return name.trim().toLowerCase().replace(\/[^a-z0-9]+\/g,'_').replace(\/^_+|_+$\/g,'').slice(0,60); }\r\n\r\nasync function withButtonLoading(btn, label, fn){\r\n  const original = btn.textContent;\r\n  btn.disabled = true;\r\n  btn.textContent = label;\r\n  try{\r\n    await fn();\r\n  } finally {\r\n    btn.disabled = false;\r\n    btn.textContent = original;\r\n  }\r\n}\r\n\r\n\/* ---------- Load list of teams for dropdown + leaderboard ---------- *\/\r\nasync function loadTeamsList(){\r\n  if(!api.configured()){ teamsIndex = []; renderGroupSelect(); renderLeaderboard(); return; }\r\n  try{\r\n    const data = await api.getTeams();\r\n    teamsIndex = (data.teams || []).filter(t => t.teamKey);\r\n  }catch(e){ teamsIndex = []; }\r\n  renderGroupSelect();\r\n  renderLeaderboard();\r\n}\r\n\r\n\/* ---------- Load one team's full data ---------- *\/\r\nasync function loadTeam(teamKey){\r\n  if(!api.configured()){ alert('Connect the backend first (see the red banner at the top).'); return; }\r\n  try{\r\n    const data = await api.getTeamData(teamKey);\r\n    if(!data.team){ alert('That team was not found.'); return; }\r\n    currentTeamKey = teamKey;\r\n    currentTeam = data.team;\r\n    currentTeam.members = safeParseJson(currentTeam.members, []);\r\n    currentTasksMap = {};\r\n    (data.tasks || []).forEach(t=>{\r\n      currentTasksMap[t.phaseId+'_'+t.taskId] = t;\r\n    });\r\n    currentEod = data.eod || [];\r\n    currentSubmissions = data.submissions || [];\r\n  }catch(e){\r\n    alert('Could not reach the backend: ' + e.message);\r\n    return;\r\n  }\r\n  document.getElementById('noGroupBanner').style.display='none';\r\n  document.getElementById('groupStatus').innerHTML = `Loaded: <b>${currentTeam.teamName}<\/b> (${currentTeam.batch})`;\r\n  try{ localStorage.setItem('capstone_last_group', teamKey); }catch(e){}\r\n  renderAll();\r\n}\r\n\r\nfunction safeParseJson(str, fallback){\r\n  try{ return JSON.parse(str); }catch(e){ return fallback; }\r\n}\r\n\r\n\/* =============================================================\r\n   CREATE TEAM MODAL\r\n   ============================================================= *\/\r\nfunction openCreateModal(){\r\n  document.getElementById('createTeamOverlay').classList.add('open');\r\n  const list = document.getElementById('membersList');\r\n  if(!list.children.length){ addMemberRow(); addMemberRow(); }\r\n}\r\nfunction closeCreateModal(){\r\n  document.getElementById('createTeamOverlay').classList.remove('open');\r\n}\r\ndocument.getElementById('openCreateModalBtn').addEventListener('click', openCreateModal);\r\ndocument.getElementById('closeCreateModalBtn').addEventListener('click', closeCreateModal);\r\ndocument.getElementById('cancelCreateBtn').addEventListener('click', closeCreateModal);\r\n\r\nfunction addMemberRow(name, role){\r\n  const list = document.getElementById('membersList');\r\n  const row = document.createElement('div');\r\n  row.className = 'member-row';\r\n  row.innerHTML = `\r\n    <input class=\"member-name\" placeholder=\"Member name\" value=\"${name||''}\">\r\n    <input class=\"member-role\" placeholder=\"Role (e.g. Ad Ops, CRO, CRM)\" value=\"${role||''}\">\r\n    <button type=\"button\" class=\"member-remove\">\u2715<\/button>\r\n  `;\r\n  row.querySelector('.member-remove').addEventListener('click', ()=> row.remove());\r\n  list.appendChild(row);\r\n}\r\ndocument.getElementById('addMemberBtn').addEventListener('click', ()=> addMemberRow());\r\n\r\ndocument.getElementById('submitCreateTeamBtn').addEventListener('click', async (e)=>{\r\n  const btn = e.currentTarget;\r\n  if(!api.configured()){ alert('Connect the backend first (see the red banner at the top).'); return; }\r\n\r\n  const teamName = document.getElementById('ctTeamName').value.trim();\r\n  const batch = document.getElementById('ctBatch').value;\r\n  const brandName = document.getElementById('ctBrandName').value.trim();\r\n  const brandWebsite = document.getElementById('ctBrandWebsite').value.trim();\r\n  const brandDescription = document.getElementById('ctBrandDesc').value.trim();\r\n\r\n  const members = [];\r\n  document.querySelectorAll('#membersList .member-row').forEach(row=>{\r\n    const name = row.querySelector('.member-name').value.trim();\r\n    const role = row.querySelector('.member-role').value.trim();\r\n    if(name) members.push({name, role});\r\n  });\r\n\r\n  if(!teamName || !brandName){ alert('Team Name and Brand Name are required.'); return; }\r\n  if(!members.length){ alert('Add at least one team member.'); return; }\r\n\r\n  const teamKey = slugify(teamName);\r\n\r\n  await withButtonLoading(btn, 'Creating\u2026', async ()=>{\r\n    try{\r\n      await api.createTeam({\r\n        teamKey, teamName, batch, brandName, brandWebsite, brandDescription,\r\n        members: JSON.stringify(members)\r\n      });\r\n      closeCreateModal();\r\n      document.getElementById('ctTeamName').value='';\r\n      document.getElementById('ctBrandName').value='';\r\n      document.getElementById('ctBrandWebsite').value='';\r\n      document.getElementById('ctBrandDesc').value='';\r\n      document.getElementById('membersList').innerHTML='';\r\n      await loadTeamsList();\r\n      await loadTeam(teamKey);\r\n    }catch(err){\r\n      alert('Could not create the team: ' + err.message);\r\n    }\r\n  });\r\n});\r\n\r\n\/* =============================================================\r\n   LOAD EXISTING TEAM\r\n   ============================================================= *\/\r\nfunction renderGroupSelect(){\r\n  const sel = document.getElementById('groupSelect');\r\n  sel.innerHTML = '<option value=\"\">\u2014 Select team \u2014<\/option>' +\r\n    teamsIndex.map(t=>`<option value=\"${t.teamKey}\">${t.teamName} (${t.batch})<\/option>`).join('');\r\n  if(currentTeamKey) sel.value = currentTeamKey;\r\n}\r\n\r\ndocument.getElementById('loadGroupBtn').addEventListener('click', async (e)=>{\r\n  const sel = document.getElementById('groupSelect').value;\r\n  if(!sel){ alert('Select a team from the dropdown first, or click \"+ Create New Team\".'); return; }\r\n  await withButtonLoading(e.currentTarget, 'Loading\u2026', async ()=>{ await loadTeam(sel); });\r\n});\r\n\r\n\/* =============================================================\r\n   RENDER: everything\r\n   ============================================================= *\/\r\nfunction renderAll(){\r\n  renderDashboard();\r\n  renderTeamInfo();\r\n  renderPhases();\r\n  renderEodPhaseOptions();\r\n  renderSubmitOptions();\r\n  renderEodHistory();\r\n  renderSubmissionLog();\r\n  renderLeaderboard();\r\n}\r\n\r\nfunction renderTeamInfo(){\r\n  const card = document.getElementById('teamInfoCard');\r\n  if(!currentTeam){ card.style.display='none'; return; }\r\n  card.style.display='block';\r\n  document.getElementById('teamInfoName').textContent = currentTeam.teamName;\r\n  document.getElementById('tiBatch').textContent = currentTeam.batch || '\u2014';\r\n  document.getElementById('tiBrand').textContent = currentTeam.brandName || '\u2014';\r\n  document.getElementById('tiWebsite').textContent = currentTeam.brandWebsite || '\u2014';\r\n  document.getElementById('tiDesc').textContent = currentTeam.brandDescription || '\u2014';\r\n  const membersBox = document.getElementById('tiMembers');\r\n  const members = currentTeam.members || [];\r\n  membersBox.innerHTML = members.length\r\n    ? members.map(m=>`<span class=\"member-chip\">${m.name}${m.role?' \u00b7 '+m.role:''}<\/span>`).join('')\r\n    : '\u2014';\r\n}\r\n\r\nfunction isTaskDone(phaseId, taskId){\r\n  const rec = currentTasksMap[phaseId+'_'+taskId];\r\n  return rec && (rec.done === true || rec.done === 'TRUE' || rec.done === 'true');\r\n}\r\n\r\nfunction completionStats(){\r\n  const total = totalTaskCount();\r\n  let done = 0;\r\n  Object.values(currentTasksMap).forEach(t=>{ if(t.done===true || t.done==='TRUE' || t.done==='true') done++; });\r\n  return {done, total, pct: total? Math.round(done\/total*100):0};\r\n}\r\n\r\nfunction phaseStats(phase){\r\n  const total = phase.tasks.length;\r\n  let done=0;\r\n  phase.tasks.forEach(t=>{ if(isTaskDone(phase.id,t.id)) done++; });\r\n  return {done, total, pct: total? Math.round(done\/total*100):0};\r\n}\r\n\r\nfunction currentPhaseLabel(){\r\n  for(const p of PHASES){\r\n    const s = phaseStats(p);\r\n    if(s.done < s.total) return p.title;\r\n  }\r\n  return 'All phases complete \ud83c\udf89';\r\n}\r\n\r\n\/* ---------- Dashboard ---------- *\/\r\nfunction renderDashboard(){\r\n  document.getElementById('noGroupBanner').style.display = currentTeam ? 'none' : 'block';\r\n  const stats = completionStats();\r\n  document.getElementById('statPct').textContent = stats.pct+'%';\r\n  document.getElementById('statPctBar').style.width = stats.pct+'%';\r\n  document.getElementById('statTasksDone').textContent = stats.done+' \/ '+stats.total;\r\n  document.getElementById('statEodCount').textContent = currentTeam ? currentEod.length : 0;\r\n  document.getElementById('statPhaseNow').textContent = currentTeam ? currentPhaseLabel() : '\u2013';\r\n\r\n  const list = document.getElementById('phaseProgressList');\r\n  list.innerHTML = PHASES.map((p,i)=>{\r\n    const s = phaseStats(p);\r\n    let chip = 'notstarted', chipLabel='Not started';\r\n    if(s.done===s.total && s.total>0){ chip='done'; chipLabel='Complete'; }\r\n    else if(s.done>0){ chip='progress'; chipLabel='In progress'; }\r\n    return `<div class=\"phase-row\">\r\n      <div class=\"phase-num-badge\">${i+1}<\/div>\r\n      <div><div class=\"ph-title\">${p.title}<\/div><div class=\"ph-dates\">${p.dates}<\/div><\/div>\r\n      <div><div class=\"progress-outer\"><div class=\"progress-inner\" style=\"width:${s.pct}%\"><\/div><\/div><\/div>\r\n      <div class=\"status-chip ${chip}\">${chipLabel}<\/div>\r\n    <\/div>`;\r\n  }).join('');\r\n}\r\n\r\nasync function renderLeaderboard(){\r\n  const body = document.getElementById('leaderboardBody');\r\n  if(!api.configured() || !teamsIndex.length){ body.innerHTML = '<tr><td colspan=\"6\" class=\"empty-note\">No teams have started yet.<\/td><\/tr>'; return; }\r\n  const rows = [];\r\n  for(const t of teamsIndex){\r\n    let data = null;\r\n    try{ data = await api.getTeamData(t.teamKey); }catch(e){}\r\n    const total = totalTaskCount();\r\n    let done = 0;\r\n    (data && data.tasks ? data.tasks : []).forEach(x=>{ if(x.done===true || x.done==='TRUE' || x.done==='true') done++; });\r\n    const pct = total? Math.round(done\/total*100):0;\r\n    const eodArr = data && data.eod ? data.eod : [];\r\n    const lastEod = eodArr.length ? eodArr[eodArr.length-1].date : '\u2014';\r\n    rows.push({name:t.teamName, batch:t.batch, brand:t.brandName||'\u2014', done, total, pct, lastEod});\r\n  }\r\n  rows.sort((a,b)=>b.pct-a.pct);\r\n  body.innerHTML = rows.map(r=>`<tr>\r\n      <td><b>${r.name}<\/b><\/td><td>${r.batch}<\/td><td>${r.brand}<\/td>\r\n      <td>${r.done} \/ ${r.total}<\/td>\r\n      <td><div class=\"progress-outer\" style=\"width:100px;\"><div class=\"progress-inner\" style=\"width:${r.pct}%\"><\/div><\/div><\/td>\r\n      <td>${r.lastEod}<\/td>\r\n    <\/tr>`).join('');\r\n}\r\n\r\n\/* ---------- Roadmap ---------- *\/\r\nfunction renderPhases(){\r\n  const c = document.getElementById('phaseContainer');\r\n  c.innerHTML = PHASES.map((p,i)=>{\r\n    const s = phaseStats(p);\r\n    const tasksHtml = p.tasks.map(t=>{\r\n      const key = p.id+'_'+t.id;\r\n      const rec = currentTasksMap[key];\r\n      const done = isTaskDone(p.id, t.id);\r\n      return `<li class=\"task-item ${done?'done':''}\" data-key=\"${key}\">\r\n        <div class=\"task-check ${done?'checked':''}\" data-toggle=\"${key}\" data-phase=\"${p.id}\" data-task=\"${t.id}\" data-label=\"${t.label.replace(\/\"\/g,'&quot;')}\">${done?'\u2713':''}<\/div>\r\n        <div class=\"task-main\">\r\n          <div class=\"task-label\" data-toggle=\"${key}\" data-phase=\"${p.id}\" data-task=\"${t.id}\" data-label=\"${t.label.replace(\/\"\/g,'&quot;')}\">${t.label}<\/div>\r\n          <div class=\"task-detail\">${t.detail}<\/div>\r\n          ${rec && rec.link ? `<div class=\"task-proof\">\ud83d\udd17 <a href=\"${rec.link}\" target=\"_blank\" rel=\"noopener\">${rec.link}<\/a><\/div>` : ''}\r\n        <\/div>\r\n      <\/li>`;\r\n    }).join('');\r\n\r\n    let checklistHtml = '';\r\n    if(p.checklist){\r\n      checklistHtml = `<div class=\"concept-box\"><div class=\"cb-title\">OPTIMIZATION CHECKLIST<\/div>` +\r\n        p.checklist.map(c=>`<p><b>${c.issue}:<\/b> ${c.fix}<\/p>`).join('') + `<\/div>`;\r\n    }\r\n\r\n    return `<div class=\"card phase-card ${i===0?'open':''}\" id=\"card-${p.id}\">\r\n      <div class=\"phase-head\" data-toggle-phase=\"${p.id}\">\r\n        <div class=\"num\">${i+1}<\/div>\r\n        <div class=\"titles\">\r\n          <h3>${p.title}<\/h3>\r\n          <div class=\"dates\">${p.dates}<\/div>\r\n        <\/div>\r\n        <div class=\"phase-progress-mini\">\r\n          <div class=\"pct\">${s.done}\/${s.total} done<\/div>\r\n          <div class=\"progress-outer\"><div class=\"progress-inner\" style=\"width:${s.pct}%\"><\/div><\/div>\r\n        <\/div>\r\n        <div class=\"chev\">\u25be<\/div>\r\n      <\/div>\r\n      <div class=\"phase-body\">\r\n        <div class=\"concept-box\">\r\n          <div class=\"cb-title\">CONCEPT<\/div>\r\n          <p>${p.concept}<\/p>\r\n        <\/div>\r\n        <ul class=\"task-list\">${tasksHtml}<\/ul>\r\n        ${checklistHtml}\r\n      <\/div>\r\n    <\/div>`;\r\n  }).join('');\r\n\r\n  c.querySelectorAll('[data-toggle-phase]').forEach(el=>{\r\n    el.addEventListener('click', ()=>{\r\n      document.getElementById('card-'+el.dataset.togglePhase).classList.toggle('open');\r\n    });\r\n  });\r\n  c.querySelectorAll('[data-toggle]').forEach(el=>{\r\n    el.addEventListener('click', (e)=>{\r\n      e.stopPropagation();\r\n      toggleTask(el.dataset.phase, el.dataset.task, el.dataset.label);\r\n    });\r\n  });\r\n}\r\n\r\nasync function toggleTask(phaseId, taskId, label){\r\n  if(!currentTeam){ alert('Load or create your team first.'); return; }\r\n  const key = phaseId+'_'+taskId;\r\n  const existing = currentTasksMap[key] || {};\r\n  const newDone = !isTaskDone(phaseId, taskId);\r\n  let link = existing.link || '';\r\n  if(newDone && !link){\r\n    link = prompt('Optional: paste a link to the deliverable (or leave blank):','') || '';\r\n  }\r\n  const by = existing.by || currentTeam.teamName;\r\n  currentTasksMap[key] = { teamKey:currentTeamKey, phaseId, taskId, taskLabel:label, done:newDone, link, notes:existing.notes||'', by, updatedAt:new Date().toISOString() };\r\n  renderAll();\r\n  try{\r\n    await api.setTask({ team:currentTeamKey, phaseId, taskId, taskLabel:label, done:String(newDone), link, notes:existing.notes||'', by });\r\n  }catch(e){\r\n    alert('Could not save this task \u2014 check your internet connection. ('+e.message+')');\r\n  }\r\n}\r\n\r\n\/* ---------- EOD ---------- *\/\r\nfunction renderEodPhaseOptions(){\r\n  const sel = document.getElementById('eodPhase');\r\n  sel.innerHTML = PHASES.map(p=>`<option value=\"${p.id}\">${p.title}<\/option>`).join('');\r\n}\r\n\r\ndocument.getElementById('submitEodBtn').addEventListener('click', async (e)=>{\r\n  if(!currentTeam){ alert('Load or create your team first.'); return; }\r\n  const date = document.getElementById('eodDate').value || new Date().toISOString().slice(0,10);\r\n  const by = document.getElementById('eodBy').value.trim();\r\n  const phaseId = document.getElementById('eodPhase').value;\r\n  const done = document.getElementById('eodDone').value.trim();\r\n  const blockers = document.getElementById('eodBlockers').value.trim();\r\n  const plan = document.getElementById('eodPlan').value.trim();\r\n  if(!by || !done){ alert('Please fill in your name and what you completed today.'); return; }\r\n  const phase = PHASES.find(p=>p.id===phaseId);\r\n\r\n  await withButtonLoading(e.currentTarget, 'Submitting\u2026', async ()=>{\r\n    try{\r\n      await api.addEod({ team:currentTeamKey, date, by, phase: phase?phase.title:'', done, blockers, plan });\r\n      currentEod.push({date, by, phase: phase?phase.title:'', done, blockers, plan});\r\n      document.getElementById('eodBy').value='';\r\n      document.getElementById('eodDone').value='';\r\n      document.getElementById('eodBlockers').value='';\r\n      document.getElementById('eodPlan').value='';\r\n      renderAll();\r\n    }catch(err){\r\n      alert('Could not submit the EOD report: ' + err.message);\r\n    }\r\n  });\r\n});\r\n\r\nfunction renderEodHistory(){\r\n  const box = document.getElementById('eodHistory');\r\n  if(!currentTeam || !currentEod.length){ box.innerHTML='<div class=\"empty-note\">No EOD reports yet.<\/div>'; return; }\r\n  const items = [...currentEod].reverse();\r\n  box.innerHTML = items.map(e=>`\r\n    <div class=\"eod-entry\">\r\n      <div class=\"eod-head\"><span class=\"eod-date\">${e.date} \u2014 ${e.phase}<\/span><span class=\"eod-by\">by ${e.by}<\/span><\/div>\r\n      <div class=\"eod-block\"><b>COMPLETED TODAY<\/b>${e.done}<\/div>\r\n      ${e.blockers?`<div class=\"eod-block\"><b>BLOCKERS<\/b>${e.blockers}<\/div>`:''}\r\n      ${e.plan?`<div class=\"eod-block\"><b>TOMORROW'S PLAN<\/b>${e.plan}<\/div>`:''}\r\n    <\/div>`).join('');\r\n}\r\n\r\n\/* ---------- Submit Tasks ---------- *\/\r\nfunction renderSubmitOptions(){\r\n  const phaseSel = document.getElementById('submitPhase');\r\n  phaseSel.innerHTML = PHASES.map(p=>`<option value=\"${p.id}\">${p.title}<\/option>`).join('');\r\n  updateSubmitTaskOptions();\r\n  phaseSel.onchange = updateSubmitTaskOptions;\r\n}\r\nfunction updateSubmitTaskOptions(){\r\n  const phaseId = document.getElementById('submitPhase').value;\r\n  const phase = PHASES.find(p=>p.id===phaseId);\r\n  const taskSel = document.getElementById('submitTask');\r\n  taskSel.innerHTML = phase.tasks.map(t=>`<option value=\"${t.id}\">${t.label}<\/option>`).join('');\r\n}\r\n\r\ndocument.getElementById('submitTaskBtn').addEventListener('click', async (e)=>{\r\n  if(!currentTeam){ alert('Load or create your team first.'); return; }\r\n  const phaseId = document.getElementById('submitPhase').value;\r\n  const taskId = document.getElementById('submitTask').value;\r\n  const link = document.getElementById('submitLink').value.trim();\r\n  const notes = document.getElementById('submitNotes').value.trim();\r\n  const by = document.getElementById('submitBy').value.trim();\r\n  if(!by){ alert('Please add your name.'); return; }\r\n  const phase = PHASES.find(p=>p.id===phaseId);\r\n  const task = phase.tasks.find(t=>t.id===taskId);\r\n  const key = phaseId+'_'+taskId;\r\n  const date = new Date().toISOString().slice(0,10);\r\n\r\n  await withButtonLoading(e.currentTarget, 'Submitting\u2026', async ()=>{\r\n    try{\r\n      await api.setTask({ team:currentTeamKey, phaseId, taskId, taskLabel:task.label, done:'true', link, notes, by });\r\n      await api.addSubmission({ team:currentTeamKey, date, phase:phase.title, task:task.label, link, notes, by });\r\n      currentTasksMap[key] = { teamKey:currentTeamKey, phaseId, taskId, taskLabel:task.label, done:true, link, notes, by, updatedAt:new Date().toISOString() };\r\n      currentSubmissions.push({date, phase:phase.title, task:task.label, link, notes, by});\r\n      document.getElementById('submitLink').value='';\r\n      document.getElementById('submitNotes').value='';\r\n      renderAll();\r\n    }catch(err){\r\n      alert('Could not submit: ' + err.message);\r\n    }\r\n  });\r\n});\r\n\r\nfunction renderSubmissionLog(){\r\n  const body = document.getElementById('submissionLog');\r\n  if(!currentTeam || !currentSubmissions.length){ body.innerHTML='<tr><td colspan=\"6\" class=\"empty-note\">No submissions yet.<\/td><\/tr>'; return; }\r\n  const items = [...currentSubmissions].reverse();\r\n  body.innerHTML = items.map(s=>`<tr>\r\n      <td>${s.date}<\/td><td>${s.phase}<\/td><td>${s.task}<\/td>\r\n      <td>${s.link?`<a href=\"${s.link}\" target=\"_blank\" rel=\"noopener\">link<\/a>`:'\u2014'}<\/td>\r\n      <td>${s.notes||'\u2014'}<\/td><td>${s.by}<\/td>\r\n    <\/tr>`).join('');\r\n}\r\n\r\n\/* =============================================================\r\n   TABS\r\n   ============================================================= *\/\r\ndocument.getElementById('tabBar').addEventListener('click', (e)=>{\r\n  const btn = e.target.closest('.tab-btn');\r\n  if(!btn) return;\r\n  document.querySelectorAll('.tab-btn').forEach(b=>b.classList.remove('active'));\r\n  btn.classList.add('active');\r\n  document.querySelectorAll('.view').forEach(v=>v.classList.remove('active'));\r\n  document.getElementById('view-'+btn.dataset.tab).classList.add('active');\r\n});\r\n\r\n\/* =============================================================\r\n   COUNTDOWN\r\n   ============================================================= *\/\r\nfunction updateCountdown(){\r\n  const now = new Date();\r\n  const diff = PROJECT_END - now;\r\n  const days = Math.max(0, Math.ceil(diff \/ (1000*60*60*24)));\r\n  document.getElementById('countdownNum').textContent = days;\r\n  document.getElementById('countdownLbl').textContent = days>0 ? 'DAYS TO FINAL PRESENTATION' : 'PRESENTATION DAY';\r\n}\r\nupdateCountdown();\r\nsetInterval(updateCountdown, 60*60*1000);\r\n\r\n\/* default EOD date = today *\/\r\ndocument.getElementById('eodDate').value = new Date().toISOString().slice(0,10);\r\n\r\n\/* =============================================================\r\n   INIT\r\n   ============================================================= *\/\r\n(async function init(){\r\n  document.getElementById('backendUrlInput').value = APPS_SCRIPT_URL;\r\n  updateBackendStatusUI();\r\n  await loadTeamsList();\r\n  try{\r\n    const last = localStorage.getItem('capstone_last_group');\r\n    if(last && teamsIndex.find(t=>t.teamKey===last)){\r\n      await loadTeam(last);\r\n    } else {\r\n      renderAll();\r\n    }\r\n  }catch(e){ renderAll(); }\r\n})();\r\n<\/script>\r\n<\/body>\r\n<\/html>\t\t\t\t<\/div>\n\t\t\n<\/div>\n\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>Capstone Project 3 \u2014 Meta Ads + CRO + Automation + CRM + Analytics | Digital Nest DIGITAL NEST SCHOOL OF BUSINESS Capstone Project 3 \u2014 Group Command Center Meta Ads + CRO + Automation + CRM + Analytics, end-to-end on your own brand microsite. PGP 14 &amp; PGP 15 Group Task 15 Sep \u2013 [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"elementor_canvas","meta":{"footnotes":"","_yoast_wpseo_title":"","_yoast_wpseo_metadesc":"","_yoast_wpseo_focuskw":"","rank_math_title":"","rank_math_description":"","rank_math_focus_keyword":""},"class_list":["post-629","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/kalhonaho.online\/index.php?rest_route=\/wp\/v2\/pages\/629","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/kalhonaho.online\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/kalhonaho.online\/index.php?rest_route=\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/kalhonaho.online\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/kalhonaho.online\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=629"}],"version-history":[{"count":25,"href":"https:\/\/kalhonaho.online\/index.php?rest_route=\/wp\/v2\/pages\/629\/revisions"}],"predecessor-version":[{"id":683,"href":"https:\/\/kalhonaho.online\/index.php?rest_route=\/wp\/v2\/pages\/629\/revisions\/683"}],"wp:attachment":[{"href":"https:\/\/kalhonaho.online\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=629"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}