<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>UBS Campaign Manager — ubsforums_campaign</title>
<link href="https://fonts.googleapis.com/css2?family=DM+Sans:wght@300;400;500;600;700&family=DM+Mono:wght@400;500&display=swap" rel="stylesheet">
<style>
*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
:root{
  --bg:#0b0f1a;
  --surf:#131827;
  --surf2:#1a2235;
  --surf3:#202840;
  --bd:#263050;
  --bd2:#2e3a5c;
  --txt:#e8edf8;
  --txt2:#9aa5c0;
  --txt3:#5e6e8a;
  --accent:#4f8ef7;
  --accent2:#6366f1;
  --ok:#22c77a;
  --ok-lt:rgba(34,199,122,.1);
  --err:#f55c5c;
  --err-lt:rgba(245,92,92,.1);
  --warn:#f5a623;
  --warn-lt:rgba(245,166,35,.1);
  --skip:#a78bfa;
  --skip-lt:rgba(167,139,250,.1);
  --bounce:#fb923c;
  --bounce-lt:rgba(251,146,60,.1);
  --pend:#38bdf8;
  --pend-lt:rgba(56,189,248,.1);
  --r:8px;--r-lg:12px;--r-xl:16px;
  --shadow:0 2px 8px rgba(0,0,0,.4);
  --shadow-lg:0 8px 32px rgba(0,0,0,.6);
  --mono:'DM Mono',monospace;
  --font:'DM Sans',sans-serif;
  --grad:linear-gradient(135deg,var(--accent),var(--accent2));
}
html{font-size:14px;scroll-behavior:smooth}
body{font-family:var(--font);background:var(--bg);color:var(--txt);min-height:100vh;overflow-x:hidden}

/* SIDEBAR */
.app{display:flex;min-height:100vh}
.sb{width:230px;min-height:100vh;background:var(--surf);border-right:1px solid var(--bd);position:fixed;top:0;left:0;z-index:50;display:flex;flex-direction:column}
.sb-logo{padding:20px 18px 16px;border-bottom:1px solid var(--bd)}
.logo-row{display:flex;align-items:center;gap:10px}
.logo-ico{width:38px;height:38px;border-radius:10px;background:var(--grad);display:flex;align-items:center;justify-content:center;font-size:18px;flex-shrink:0;box-shadow:0 4px 12px rgba(79,142,247,.3)}
.logo-name{font-size:15px;font-weight:700;color:var(--txt);letter-spacing:-.4px}
.logo-sub{font-size:10.5px;color:var(--txt3);margin-top:1px;font-family:var(--mono)}
.sb-nav{padding:12px 10px;flex:1}
.nav-sec{font-size:9.5px;font-weight:600;color:var(--txt3);letter-spacing:1px;text-transform:uppercase;padding:10px 10px 4px}
.nav-i{display:flex;align-items:center;gap:10px;padding:9px 11px;border-radius:var(--r);cursor:pointer;color:var(--txt2);font-size:12.5px;font-weight:500;transition:all .15s;margin-bottom:2px;position:relative}
.nav-i:hover{background:var(--surf2);color:var(--txt)}
.nav-i.on{background:rgba(79,142,247,.12);color:var(--accent)}
.nav-i.on::before{content:'';position:absolute;left:0;top:50%;transform:translateY(-50%);width:3px;height:18px;background:var(--grad);border-radius:0 3px 3px 0}
.nav-ico{font-size:15px;width:20px;text-align:center}
.sb-footer{padding:12px 14px;border-top:1px solid var(--bd);font-size:11px;color:var(--txt3)}

/* MAIN */
.main{margin-left:230px;flex:1;padding:28px 32px;max-width:1200px}
.topbar{display:flex;align-items:flex-start;justify-content:space-between;margin-bottom:24px;gap:16px}
.pg-title{font-size:22px;font-weight:700;letter-spacing:-.5px}
.pg-sub{font-size:12px;color:var(--txt3);margin-top:3px;font-family:var(--mono)}
.status-badge{display:inline-flex;align-items:center;gap:6px;padding:6px 14px;border-radius:20px;font-size:11.5px;font-weight:600;background:var(--surf2);border:1px solid var(--bd);color:var(--txt3)}
.status-badge.sending{background:var(--warn-lt);color:var(--warn);border-color:rgba(245,166,35,.3)}
.status-badge.done{background:var(--ok-lt);color:var(--ok);border-color:rgba(34,199,122,.3)}
.pulse{width:7px;height:7px;border-radius:50%;background:currentColor;animation:pulse 1.5s infinite}
@keyframes pulse{0%,100%{opacity:1;transform:scale(1)}50%{opacity:.3;transform:scale(.8)}}

/* STATS */
.stats{display:grid;grid-template-columns:repeat(5,1fr);gap:12px;margin-bottom:18px}
.sc{background:var(--surf);border:1px solid var(--bd);border-radius:var(--r-lg);padding:14px 18px;transition:border-color .2s}
.sc:hover{border-color:var(--bd2)}
.sc-lbl{font-size:10px;font-weight:600;color:var(--txt3);text-transform:uppercase;letter-spacing:.8px;margin-bottom:6px}
.sc-val{font-size:28px;font-weight:700;font-family:var(--mono);letter-spacing:-1.5px;line-height:1}
.sc-val.tot{color:var(--txt)}
.sc-val.ok{color:var(--ok)}
.sc-val.err{color:var(--err)}
.sc-val.bounce{color:var(--bounce)}
.sc-val.pend{color:var(--pend)}
.sc-sub{font-size:10.5px;color:var(--txt3);margin-top:4px}

/* PROGRESS */
.prog-card{background:var(--surf);border:1px solid var(--bd);border-radius:var(--r-lg);padding:16px 20px;margin-bottom:18px}
.prog-hd{display:flex;justify-content:space-between;font-size:11.5px;color:var(--txt3);margin-bottom:10px;font-family:var(--mono)}
.prog-bar{height:8px;background:var(--surf3);border-radius:20px;overflow:hidden}
.prog-fill{height:100%;background:var(--grad);border-radius:20px;transition:width .6s ease;width:0%}

/* CARDS */
.card{background:var(--surf);border:1px solid var(--bd);border-radius:var(--r-xl);margin-bottom:18px;overflow:hidden;transition:border-color .2s}
.card:hover{border-color:var(--bd2)}
.card-hd{padding:14px 20px;border-bottom:1px solid var(--bd);display:flex;align-items:center;justify-content:space-between}
.card-title{font-size:13px;font-weight:600;display:flex;align-items:center;gap:8px;color:var(--txt)}
.card-body{padding:20px}

/* FORMS */
.fgrid{display:grid;grid-template-columns:1fr 1fr;gap:14px;margin-bottom:14px}
.fr{margin-bottom:14px}
label{display:block;font-size:11.5px;font-weight:600;color:var(--txt2);margin-bottom:5px;letter-spacing:.2px}
input[type=text],input[type=email],textarea,select{width:100%;padding:9px 12px;background:var(--surf2);border:1.5px solid var(--bd);border-radius:var(--r);font-family:var(--font);font-size:13px;color:var(--txt);outline:none;transition:border-color .15s}
input:focus,textarea:focus,select:focus{border-color:var(--accent);box-shadow:0 0 0 3px rgba(79,142,247,.1)}
input::placeholder,textarea::placeholder{color:var(--txt3)}
select option{background:var(--surf2)}
textarea{min-height:100px;resize:vertical;line-height:1.6}

/* UPLOAD ZONE */
.uzone{border:2px dashed var(--bd2);border-radius:var(--r-lg);padding:32px;text-align:center;cursor:pointer;transition:all .2s;background:var(--surf2)}
.uzone:hover,.uzone.drag{border-color:var(--accent);background:rgba(79,142,247,.06)}
.uzone-ico{font-size:36px;display:block;margin-bottom:10px}
.uzone p{font-size:13px;color:var(--txt2)}
.uzone strong{color:var(--accent)}
#finput{display:none}

/* TIMER CONTROL */
.timer-wrap{background:var(--surf2);border:1px solid var(--bd);border-radius:var(--r-lg);padding:16px 20px;margin-bottom:16px}
.timer-label{font-size:12px;font-weight:600;color:var(--txt2);margin-bottom:10px}
.timer-row{display:flex;align-items:center;gap:12px;flex-wrap:wrap}
.timer-option{display:flex;align-items:center;gap:7px;cursor:pointer;padding:7px 14px;border-radius:var(--r);border:1.5px solid var(--bd);font-size:12.5px;color:var(--txt2);transition:all .15s;font-weight:500;background:var(--surf)}
.timer-option:hover{border-color:var(--bd2);color:var(--txt)}
.timer-option input[type=radio]{accent-color:var(--accent)}
.timer-option.sel{background:rgba(79,142,247,.1);border-color:var(--accent);color:var(--accent)}
.custom-delay{display:none;align-items:center;gap:8px;padding:6px 12px;background:var(--surf);border:1.5px solid var(--bd);border-radius:var(--r)}
.custom-delay input{width:60px;text-align:center;padding:4px 8px;font-size:13px;background:transparent;border:none;color:var(--txt);font-family:var(--mono)}
.custom-delay span{font-size:12px;color:var(--txt3)}
.custom-delay:focus-within{border-color:var(--accent)}

/* BATCH LIMIT INFO */
.batch-info{display:flex;align-items:center;gap:8px;padding:9px 14px;background:rgba(79,142,247,.08);border:1px solid rgba(79,142,247,.2);border-radius:var(--r);font-size:12px;color:var(--accent);margin-bottom:14px}

/* TABLE */
.log-wrap{max-height:320px;overflow-y:auto}
.log-wrap::-webkit-scrollbar{width:4px}
.log-wrap::-webkit-scrollbar-track{background:transparent}
.log-wrap::-webkit-scrollbar-thumb{background:var(--bd2);border-radius:2px}
table{width:100%;border-collapse:collapse;font-size:11.5px}
thead th{padding:9px 12px;text-align:left;font-weight:600;color:var(--txt3);font-size:10px;text-transform:uppercase;letter-spacing:.6px;border-bottom:1px solid var(--bd);background:var(--surf2);position:sticky;top:0;z-index:1}
td{padding:8px 12px;border-bottom:1px solid rgba(38,48,80,.5);font-family:var(--mono);font-size:11.5px;color:var(--txt2)}
td.name-cell{font-family:var(--font);font-size:12px;color:var(--txt)}
tr:last-child td{border-bottom:none}
tr:hover td{background:rgba(255,255,255,.02)}

/* TAGS */
.tag{display:inline-flex;align-items:center;gap:4px;padding:2px 8px;border-radius:10px;font-size:10px;font-weight:600;letter-spacing:.2px}
.tag.ok{background:var(--ok-lt);color:var(--ok)}
.tag.err{background:var(--err-lt);color:var(--err)}
.tag.skip{background:var(--skip-lt);color:var(--skip)}
.tag.bounce{background:var(--bounce-lt);color:var(--bounce)}
.tag.pending{background:var(--pend-lt);color:var(--pend)}

/* BUTTONS */
.btn{display:inline-flex;align-items:center;gap:7px;padding:9px 18px;border-radius:var(--r);font-family:var(--font);font-size:13px;font-weight:600;cursor:pointer;border:1px solid var(--bd);background:var(--surf2);color:var(--txt);transition:all .15s;white-space:nowrap}
.btn:hover{background:var(--surf3);border-color:var(--bd2)}
.btn:active{transform:scale(.98)}
.btn:disabled{opacity:.35;cursor:not-allowed;transform:none}
.btn.prim{background:var(--grad);color:#fff;border-color:transparent;box-shadow:0 4px 16px rgba(79,142,247,.25)}
.btn.prim:hover{box-shadow:0 6px 20px rgba(79,142,247,.35);opacity:.92}
.btn.ok-btn{background:rgba(34,199,122,.12);color:var(--ok);border-color:rgba(34,199,122,.25)}
.btn.ok-btn:hover{background:rgba(34,199,122,.18)}
.btn.danger{background:var(--err-lt);color:var(--err);border-color:rgba(245,92,92,.25)}
.btn.danger:hover{background:rgba(245,92,92,.18)}
.btn.lg{padding:11px 24px;font-size:14px}

/* CAMPAIGN NAME DISPLAY */
.campaign-name-tag{display:inline-flex;align-items:center;gap:6px;padding:5px 12px;background:var(--surf2);border:1px solid var(--bd);border-radius:6px;font-family:var(--mono);font-size:11px;color:var(--accent)}

/* PANELS */
.panel{display:none}
.panel.on{display:block}

/* TOASTS */
.toasts{position:fixed;bottom:20px;right:20px;z-index:999;display:flex;flex-direction:column;gap:8px;max-width:320px}
.toast{display:flex;align-items:center;gap:10px;padding:11px 16px;border-radius:var(--r-lg);font-size:12.5px;font-weight:600;box-shadow:var(--shadow-lg);animation:tin .2s ease}
.toast.ok{background:var(--ok);color:#fff}
.toast.err{background:var(--err);color:#fff}
.toast.info{background:var(--accent);color:#fff}
@keyframes tin{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}

/* ID VERIFICATION badge */
.id-valid{background:var(--ok-lt);border:1px solid rgba(34,199,122,.2);color:var(--ok);padding:3px 9px;border-radius:5px;font-size:10px;font-weight:600}
.id-invalid{background:var(--err-lt);border:1px solid rgba(245,92,92,.2);color:var(--err);padding:3px 9px;border-radius:5px;font-size:10px;font-weight:600}
.id-pending{background:var(--pend-lt);border:1px solid rgba(56,189,248,.2);color:var(--pend);padding:3px 9px;border-radius:5px;font-size:10px;font-weight:600}

/* RECIPIENT TABLE PREVIEW */
.recipients-preview-wrap{max-height:260px;overflow-y:auto;border-radius:var(--r);border:1px solid var(--bd);background:var(--surf2);margin-top:12px}

/* SEND CONTROL */
.send-controls{display:flex;align-items:center;gap:12px;flex-wrap:wrap}
.interval-display{font-family:var(--mono);font-size:11px;color:var(--txt3);background:var(--surf2);border:1px solid var(--bd);padding:4px 10px;border-radius:5px}

/* EXCEL EXPORT INFO */
.export-row{display:flex;align-items:center;gap:10px;padding:10px 14px;background:var(--surf2);border:1px solid var(--bd);border-radius:var(--r);margin-bottom:14px;font-size:12px;color:var(--txt2)}
.export-row strong{color:var(--txt);font-weight:600}

/* DOMAIN CHECK INDICATOR */
.domain-check{display:flex;align-items:center;gap:6px;font-size:11px;color:var(--txt3);margin-top:4px}
.domain-dot{width:6px;height:6px;border-radius:50%}
.domain-dot.ok{background:var(--ok)}
.domain-dot.err{background:var(--err)}
.domain-dot.checking{background:var(--warn);animation:pulse 1s infinite}

/* SCROLLBAR */
::-webkit-scrollbar{width:5px;height:5px}
::-webkit-scrollbar-track{background:transparent}
::-webkit-scrollbar-thumb{background:var(--bd2);border-radius:3px}

/* RESPONSIVE */
@media(max-width:900px){
  .stats{grid-template-columns:repeat(3,1fr)}
  .fgrid{grid-template-columns:1fr}
}
</style>
</head>
<body>
<div class="app">

<!-- SIDEBAR -->
<aside class="sb">
  <div class="sb-logo">
    <div class="logo-row">
      <div class="logo-ico">📧</div>
      <div>
        <div class="logo-name">UBS Mailer</div>
        <div class="logo-sub">ubsforums_campaign</div>
      </div>
    </div>
  </div>
  <nav class="sb-nav">
    <div class="nav-sec">Campaign</div>
    <div class="nav-i on" data-panel="recipients" onclick="nav(this,'recipients')">
      <span class="nav-ico">👥</span> Recipients
    </div>
    <div class="nav-i" data-panel="compose" onclick="nav(this,'compose')">
      <span class="nav-ico">✉️</span> Compose
    </div>
    <div class="nav-i" data-panel="schedule" onclick="nav(this,'schedule')">
      <span class="nav-ico">⏱️</span> Schedule & Send
    </div>
    <div class="nav-sec">Results</div>
    <div class="nav-i" data-panel="logs" onclick="nav(this,'logs')">
      <span class="nav-ico">📋</span> Delivery Log
    </div>
    <div class="nav-i" data-panel="export" onclick="nav(this,'export')">
      <span class="nav-ico">📊</span> Export Report
    </div>
  </nav>
  <div class="sb-footer">
    DB: <strong style="color:var(--txt2)">ubsforums_campaign</strong><br>
    <span id="sbTime" style="font-family:var(--mono);font-size:10px"></span>
  </div>
</aside>

<!-- MAIN -->
<main class="main">
  <div class="topbar">
    <div>
      <div style="display:flex;align-items:center;gap:10px;margin-bottom:4px">
        <div class="pg-title" id="pgTitle">Recipients</div>
        <span class="campaign-name-tag">📁 ubsforums_campaign</span>
      </div>
      <div class="pg-sub" id="pgSub">Upload & verify email list · ID existence check enabled</div>
    </div>
    <div id="statusBadge" class="status-badge">⬤ &nbsp;Idle</div>
  </div>

  <!-- STATS BAR -->
  <div class="stats">
    <div class="sc">
      <div class="sc-lbl">Total</div>
      <div class="sc-val tot" id="statTotal">0</div>
      <div class="sc-sub">recipients</div>
    </div>
    <div class="sc">
      <div class="sc-lbl">Valid / Sent</div>
      <div class="sc-val ok" id="statSent">0</div>
      <div class="sc-sub">by ID existence</div>
    </div>
    <div class="sc">
      <div class="sc-lbl">Bounce</div>
      <div class="sc-val bounce" id="statBounce">0</div>
      <div class="sc-sub">domain fail</div>
    </div>
    <div class="sc">
      <div class="sc-lbl">Failed</div>
      <div class="sc-val err" id="statFailed">0</div>
      <div class="sc-sub">send error</div>
    </div>
    <div class="sc">
      <div class="sc-lbl">Pending</div>
      <div class="sc-val pend" id="statPending">0</div>
      <div class="sc-sub">queued</div>
    </div>
  </div>

  <!-- PROGRESS -->
  <div class="prog-card">
    <div class="prog-hd">
      <span>Delivery Progress</span>
      <span id="progPct">0%</span>
    </div>
    <div class="prog-bar">
      <div class="prog-fill" id="progFill"></div>
    </div>
  </div>

  <!-- ───── PANEL: RECIPIENTS ───── -->
  <div class="panel on" id="panel-recipients">
    <div class="card">
      <div class="card-hd">
        <div class="card-title">📁 Upload Recipients (Excel)</div>
        <div style="font-size:11px;color:var(--txt3)">Supports .xlsx / .xls</div>
      </div>
      <div class="card-body">
        <div class="uzone" id="dropzone" onclick="document.getElementById('finput').click()" ondragover="event.preventDefault();this.classList.add('drag')" ondragleave="this.classList.remove('drag')" ondrop="handleDrop(event)">
          <span class="uzone-ico">📂</span>
          <p><strong>Click to browse</strong> or drag & drop your Excel file here</p>
          <p style="font-size:11px;color:var(--txt3);margin-top:6px">Columns: first_name, last_name, email</p>
        </div>
        <input type="file" id="finput" accept=".xlsx,.xls" onchange="handleFile(this.files[0])">

        <div id="fileInfo" style="display:none;margin-top:12px">
          <div class="export-row">
            <span>📄</span>
            <span><strong id="fileName">—</strong></span>
            <span id="fileStats" style="margin-left:auto;font-family:var(--mono);font-size:11px;color:var(--accent)"></span>
          </div>
          <div style="margin-bottom:8px;display:flex;align-items:center;gap:8px">
            <span style="font-size:11.5px;font-weight:600;color:var(--txt2)">ID Existence Verification</span>
            <span id="verifyStatus" class="id-pending">Checking...</span>
          </div>
          <div class="recipients-preview-wrap">
            <table id="recipientTable">
              <thead><tr>
                <th>#</th><th>Name</th><th>Email</th><th>Domain</th><th>ID Status</th>
              </tr></thead>
              <tbody id="recipientRows"></tbody>
            </table>
          </div>
        </div>
      </div>
    </div>

    <!-- CAMPAIGN DATA SAVE -->
    <div class="card">
      <div class="card-hd">
        <div class="card-title">🗄️ Campaign Data — Save to Excel</div>
        <button class="btn ok-btn" onclick="exportCampaignExcel()" id="btnExport" disabled>💾 Save Excel</button>
      </div>
      <div class="card-body">
        <div class="fgrid">
          <div class="fr">
            <label>Campaign Name</label>
            <input type="text" id="campName" value="ubsforums_campaign" placeholder="Campaign name">
          </div>
          <div class="fr">
            <label>Database</label>
            <input type="text" id="campDb" value="ubsforums_campaign" placeholder="Database name">
          </div>
        </div>
        <div style="font-size:11.5px;color:var(--txt3);display:flex;align-items:center;gap:8px">
          <span>📅</span> Saved with Excel date-time stamp automatically
          <span id="saveDateDisplay" style="font-family:var(--mono);font-size:11px;color:var(--accent)"></span>
        </div>
      </div>
    </div>
  </div>

  <!-- ───── PANEL: COMPOSE ───── -->
  <div class="panel" id="panel-compose">
    <div class="card">
      <div class="card-hd">
        <div class="card-title">✉️ Email Settings</div>
        <button class="btn ok-btn" onclick="saveCampaign()">💾 Save</button>
      </div>
      <div class="card-body">
        <div class="fgrid">
          <div class="fr">
            <label>From Name</label>
            <input type="text" id="fromName" value="UBS Events" placeholder="Sender name">
          </div>
          <div class="fr">
            <label>From Email</label>
            <input type="email" id="fromEmail" value="mahima.tripathi@ubsforums.com" placeholder="sender@domain.com">
          </div>
        </div>
        <div class="fr">
          <label>Subject Line</label>
          <input type="text" id="subject" value="" placeholder="Email subject">
        </div>
        <div class="fr">
          <label>Email Body</label>
          <textarea id="bodyText" rows="6" placeholder="Compose your email body here. Use {{first_name}}, {{last_name}}, {{email}} for personalization."></textarea>
        </div>
        <div class="fr">
          <label>Signature</label>
          <textarea id="sigText" rows="3" placeholder="Email signature..."></textarea>
        </div>
      </div>
    </div>
  </div>

  <!-- ───── PANEL: SCHEDULE & SEND ───── -->
  <div class="panel" id="panel-schedule">
    <div class="card">
      <div class="card-hd">
        <div class="card-title">⏱️ Delivery Timer</div>
        <span id="intervalDisplay" class="interval-display">20 mails / batch · delay: 3s</span>
      </div>
      <div class="card-body">
        <div class="batch-info">
          ℹ️ Sending <strong style="color:var(--accent);margin:0 4px">20 emails per batch</strong> — timer controls delay between batches
        </div>

        <div class="timer-wrap">
          <div class="timer-label">⏰ Delay between batches (seconds per batch of 20)</div>
          <div class="timer-row" id="timerOptions">
            <label class="timer-option sel">
              <input type="radio" name="delay" value="3" checked onchange="setDelay(3)"> Instant (3s)
            </label>
            <label class="timer-option">
              <input type="radio" name="delay" value="10" onchange="setDelay(10)"> 10s
            </label>
            <label class="timer-option">
              <input type="radio" name="delay" value="30" onchange="setDelay(30)"> 30s
            </label>
            <label class="timer-option">
              <input type="radio" name="delay" value="60" onchange="setDelay(60)"> 1 min
            </label>
            <label class="timer-option">
              <input type="radio" name="delay" value="120" onchange="setDelay(120)"> 2 min
            </label>
            <label class="timer-option" id="customTimerOption">
              <input type="radio" name="delay" value="custom" onchange="setDelay('custom')"> Custom
            </label>
          </div>
          <div class="custom-delay" id="customDelayWrap" style="margin-top:10px">
            <input type="number" id="customSeconds" min="1" max="3600" value="60" onchange="setDelay(parseInt(this.value))">
            <span>seconds between batches</span>
          </div>
        </div>

        <div class="fr">
          <label>Scheduled Start Time (optional)</label>
          <input type="datetime-local" id="scheduleAt" style="max-width:280px">
          <div style="font-size:11px;color:var(--txt3);margin-top:4px">Leave blank to send immediately when you click Start</div>
        </div>

        <div class="send-controls">
          <button class="btn prim lg" id="btnStart" onclick="startSending()">🚀 Start Campaign</button>
          <button class="btn danger" id="btnStop" onclick="stopSending()" disabled>⏹ Stop</button>
          <button class="btn" onclick="resetAll()" id="btnReset">🔄 Reset</button>
        </div>

        <div id="liveFeed" style="margin-top:14px;font-family:var(--mono);font-size:11.5px;color:var(--txt3);min-height:22px"></div>
      </div>
    </div>
  </div>

  <!-- ───── PANEL: LOGS ───── -->
  <div class="panel" id="panel-logs">
    <div class="card">
      <div class="card-hd">
        <div class="card-title">📋 Delivery Log</div>
        <div style="display:flex;gap:8px">
          <button class="btn" onclick="filterLog('all')" id="fAll" style="font-size:11px;padding:5px 10px">All</button>
          <button class="btn" onclick="filterLog('bounce')" id="fBounce" style="font-size:11px;padding:5px 10px;color:var(--bounce)">Bounce</button>
          <button class="btn" onclick="filterLog('failed')" id="fFail" style="font-size:11px;padding:5px 10px;color:var(--err)">Failed</button>
          <button class="btn" onclick="filterLog('pending')" id="fPend" style="font-size:11px;padding:5px 10px;color:var(--pend)">Pending</button>
        </div>
      </div>
      <div class="card-body" style="padding:0">
        <div class="log-wrap">
          <table>
            <thead><tr>
              <th>#</th><th>Name</th><th>Email</th><th>Domain Check</th><th>ID Status</th><th>Result</th><th>Time</th>
            </tr></thead>
            <tbody id="logRows"></tbody>
          </table>
        </div>
      </div>
    </div>
  </div>

  <!-- ───── PANEL: EXPORT ───── -->
  <div class="panel" id="panel-export">
    <div class="card">
      <div class="card-hd">
        <div class="card-title">📊 Export Campaign Report</div>
      </div>
      <div class="card-body">
        <div style="display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-bottom:20px">
          <div class="sc" style="padding:16px">
            <div class="sc-lbl">Campaign</div>
            <div style="font-size:14px;font-weight:600;color:var(--txt);font-family:var(--mono)" id="expCampName">—</div>
          </div>
          <div class="sc" style="padding:16px">
            <div class="sc-lbl">Export Date-Time</div>
            <div style="font-size:13px;font-weight:600;color:var(--accent);font-family:var(--mono)" id="expDateTime">—</div>
          </div>
        </div>

        <div style="display:flex;gap:12px;flex-wrap:wrap">
          <button class="btn ok-btn" onclick="exportReport('xlsx')">📥 Download Excel (.xlsx)</button>
          <button class="btn" onclick="exportReport('csv')">📄 Download CSV</button>
          <button class="btn" onclick="printReport()">🖨️ Print Report</button>
        </div>

        <div style="margin-top:20px">
          <div style="font-size:11.5px;font-weight:600;color:var(--txt2);margin-bottom:12px">Report Preview</div>
          <div class="log-wrap" style="max-height:280px">
            <table>
              <thead><tr>
                <th>#</th><th>Name</th><th>Email</th><th>Domain</th><th>ID Exists</th><th>Status</th><th>Time</th>
              </tr></thead>
              <tbody id="reportRows"></tbody>
            </table>
          </div>
        </div>
      </div>
    </div>
  </div>

</main>
</div>

<!-- TOASTS -->
<div class="toasts" id="toasts"></div>

<script>
// ─── STATE ───────────────────────────────────────────────────────────────────
const BATCH_LIMIT = 20;

const state = {
  recipients: [],       // all verified rows
  log: [],              // send log entries
  sent: 0,
  bounce: 0,
  failed: 0,
  sending: false,
  sendTimer: null,
  delay: 3,             // seconds between batches
  currentBatch: 0,
  campaignName: 'ubsforums_campaign',
  campaignDb: 'ubsforums_campaign',
  startedAt: null,
};

// ─── CAMPAIGN DATA (from existing campaign.json) ──────────────────────────
const campaignData = {
  body: '<p>Dear {{first_name}},</p><p>Please find attached information for the 12th Edition HR Tech Summit & Awards 2026.</p>',
  subject: '12th Edition HR Tech Summit & Awards 2026 — Invitation',
  from_name: 'UBS Events',
  from_email: 'mahima.tripathi@ubsforums.com',
  signature: '<p>Best regards,<br>UBS Events Team<br>ubsforums.com</p>'
};

// Pre-seed from campaign.json
document.getElementById('fromName').value = campaignData.from_name;
document.getElementById('fromEmail').value = campaignData.from_email;
document.getElementById('subject').value = campaignData.subject;
document.getElementById('bodyText').value = campaignData.body.replace(/<[^>]+>/g,'');
document.getElementById('sigText').value = campaignData.signature.replace(/<[^>]+>/g,'');

// ─── CLOCK ────────────────────────────────────────────────────────────────
function updateClock(){
  const now = new Date();
  document.getElementById('sbTime').textContent = now.toLocaleTimeString('en-IN',{hour:'2-digit',minute:'2-digit',second:'2-digit'});
  document.getElementById('saveDateDisplay').textContent = formatExcelDate(now);
  document.getElementById('expDateTime').textContent = formatExcelDate(now);
}
function formatExcelDate(d){
  return d.getFullYear()+'-'+pad(d.getMonth()+1)+'-'+pad(d.getDate())+
         ' '+pad(d.getHours())+':'+pad(d.getMinutes())+':'+pad(d.getSeconds());
}
function pad(n){return String(n).padStart(2,'0')}
setInterval(updateClock,1000);
updateClock();

// ─── NAVIGATION ───────────────────────────────────────────────────────────
function nav(el, panelId){
  document.querySelectorAll('.nav-i').forEach(n=>n.classList.remove('on'));
  el.classList.add('on');
  document.querySelectorAll('.panel').forEach(p=>p.classList.remove('on'));
  document.getElementById('panel-'+panelId).classList.add('on');
  const titles = {
    recipients:'Recipients',compose:'Compose',schedule:'Schedule & Send',
    logs:'Delivery Log',export:'Export Report'
  };
  const subs = {
    recipients:'Upload & verify email list · ID existence check enabled',
    compose:'Compose email content & settings',
    schedule:'Set timer interval · 20 mails per batch',
    logs:'View delivery status by domain and ID',
    export:'Download campaign report with Excel date-time stamp'
  };
  document.getElementById('pgTitle').textContent = titles[panelId]||panelId;
  document.getElementById('pgSub').textContent = subs[panelId]||'';
  if(panelId==='export'){
    document.getElementById('expCampName').textContent = state.campaignName;
    refreshReportTable();
  }
  if(panelId==='logs') refreshLogTable();
}

// ─── FILE DROP ─────────────────────────────────────────────────────────────
function handleDrop(e){
  e.preventDefault();
  document.getElementById('dropzone').classList.remove('drag');
  const f = e.dataTransfer.files[0];
  if(f) handleFile(f);
}

function handleFile(file){
  if(!file) return;
  document.getElementById('dropzone').classList.remove('drag');

  // Read Excel via SheetJS
  const reader = new FileReader();
  reader.onload = function(e){
    try {
      const data = new Uint8Array(e.target.result);
      const wb = XLSX.read(data,{type:'array'});
      const ws = wb.Sheets[wb.SheetNames[0]];
      const rows = XLSX.utils.sheet_to_json(ws,{defval:''});

      if(!rows.length){ toast('No data found in file','err'); return; }

      state.recipients = [];
      rows.forEach((r,i)=>{
        const email = (r.email||r.Email||r.EMAIL||'').toString().trim();
        const first = (r.first_name||r['First Name']||r.firstname||'').toString().trim();
        const last  = (r.last_name||r['Last Name']||r.lastname||'').toString().trim();
        if(!email) return;
        state.recipients.push({
          id: i+1,
          first_name: first,
          last_name: last,
          email: email,
          domain: email.split('@')[1]||'',
          domainValid: null,
          idExists: null,
          status: 'pending'
        });
      });

      document.getElementById('fileName').textContent = file.name;
      document.getElementById('fileStats').textContent = state.recipients.length + ' recipients loaded';
      document.getElementById('fileInfo').style.display = 'block';
      document.getElementById('btnExport').disabled = false;
      document.getElementById('verifyStatus').textContent = 'Verifying...';
      document.getElementById('verifyStatus').className = 'id-pending';

      updateStats();
      renderRecipientTable();
      verifyDomains();
      toast('Loaded '+state.recipients.length+' recipients','ok');
    } catch(err){
      toast('Error parsing Excel: '+err.message,'err');
    }
  };
  reader.readAsArrayBuffer(file);
}

// ─── DOMAIN / ID VERIFICATION ─────────────────────────────────────────────
// Verification is done client-side: check domain format + known patterns
// ID existence = row has a valid email format + recognizable domain pattern
function verifyDomains(){
  let verified = 0;
  state.recipients.forEach(r=>{
    const d = r.domain.toLowerCase();
    // Domain valid check
    const domainOk = /^[a-z0-9]([a-z0-9\-]{0,61}[a-z0-9])?(\.[a-z]{2,})+$/i.test(d) &&
                     !/\d{1,3}\.\d{1,3}/.test(d) &&
                     !/secureserver|\.test$|\.local$|\.invalid$|\.example$/.test(d);
    r.domainValid = domainOk;
    // ID exists = has domain, domain is valid, email format correct
    const emailOk = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(r.email);
    r.idExists = domainOk && emailOk;
    if(r.idExists) verified++;
  });

  const total = state.recipients.length;
  const vEl = document.getElementById('verifyStatus');
  vEl.textContent = verified+'/'+total+' IDs Verified';
  vEl.className = verified===total ? 'id-valid' : (verified>0 ? 'id-pending' : 'id-invalid');

  renderRecipientTable();
  updateStats();
}

function renderRecipientTable(){
  const tbody = document.getElementById('recipientRows');
  tbody.innerHTML = state.recipients.map((r,i)=>`
    <tr>
      <td>${i+1}</td>
      <td class="name-cell">${r.first_name} ${r.last_name}</td>
      <td>${r.email}</td>
      <td>
        <div style="display:flex;align-items:center;gap:5px">
          <div class="domain-dot ${r.domainValid===true?'ok':r.domainValid===false?'err':'checking'}"></div>
          <span style="font-size:11px">${r.domain}</span>
        </div>
      </td>
      <td>
        ${r.idExists===true
          ? '<span class="tag ok">✓ ID Exists</span>'
          : r.idExists===false
            ? '<span class="tag bounce">✗ No ID</span>'
            : '<span class="tag pending">Checking</span>'
        }
      </td>
    </tr>
  `).join('');
}

// ─── STATS ─────────────────────────────────────────────────────────────────
function updateStats(){
  const total = state.recipients.length;
  const pending = total - state.sent - state.bounce - state.failed;
  document.getElementById('statTotal').textContent  = total;
  document.getElementById('statSent').textContent   = state.sent;
  document.getElementById('statBounce').textContent = state.bounce;
  document.getElementById('statFailed').textContent = state.failed;
  document.getElementById('statPending').textContent= Math.max(0,pending);

  const done = state.sent + state.bounce + state.failed;
  const pct  = total ? Math.round((done/total)*100) : 0;
  document.getElementById('progFill').style.width = pct+'%';
  document.getElementById('progPct').textContent  = pct+'%';
}

// ─── DELAY / TIMER ─────────────────────────────────────────────────────────
function setDelay(val){
  // Update option highlights
  document.querySelectorAll('.timer-option').forEach(o=>o.classList.remove('sel'));
  if(val==='custom'){
    document.getElementById('customTimerOption').classList.add('sel');
    document.getElementById('customDelayWrap').style.display='flex';
    state.delay = parseInt(document.getElementById('customSeconds').value)||60;
  } else {
    state.delay = parseInt(val);
    document.getElementById('customDelayWrap').style.display='none';
    document.querySelectorAll('.timer-option').forEach(o=>{
      if(o.querySelector('input')&&o.querySelector('input').value==val)
        o.classList.add('sel');
    });
  }
  document.getElementById('intervalDisplay').textContent =
    BATCH_LIMIT+' mails / batch · delay: '+state.delay+'s';
}

// ─── SEND ──────────────────────────────────────────────────────────────────
function startSending(){
  if(!state.recipients.length){ toast('Upload recipients first','err'); return; }
  if(state.sending) return;

  const schedAt = document.getElementById('scheduleAt').value;
  if(schedAt){
    const diff = new Date(schedAt) - new Date();
    if(diff > 0){
      toast('Campaign scheduled for '+new Date(schedAt).toLocaleString(),'info');
      setTimeout(()=>doStart(), diff);
      document.getElementById('statusBadge').className='status-badge sending';
      document.getElementById('statusBadge').innerHTML='<span class="pulse"></span> Scheduled';
      return;
    }
  }
  doStart();
}

function doStart(){
  state.sending = true;
  state.startedAt = new Date().toISOString();
  state.currentBatch = 0;
  // Reset counters
  state.sent = 0; state.bounce = 0; state.failed = 0;
  state.log = [];
  state.recipients.forEach(r=>r.status='pending');
  updateStats();
  refreshLogTable();

  document.getElementById('btnStart').disabled = true;
  document.getElementById('btnStop').disabled  = false;
  document.getElementById('statusBadge').className='status-badge sending';
  document.getElementById('statusBadge').innerHTML='<span class="pulse"></span> Sending…';

  sendNextBatch();
}

function sendNextBatch(){
  if(!state.sending) return;
  const all     = state.recipients;
  const start   = state.currentBatch * BATCH_LIMIT;
  const batch   = all.slice(start, start+BATCH_LIMIT);

  if(!batch.length || start >= all.length){
    finishSending(); return;
  }

  document.getElementById('liveFeed').textContent =
    '⏳ Sending batch '+(state.currentBatch+1)+' — '+batch.length+' emails …';

  // Simulate sending (real sending happens server-side via PHP)
  // Here we do client-side ID-based classification only
  batch.forEach(r=>{
    if(!r.idExists){
      // Bounce — domain doesn't exist / no ID
      r.status = 'bounce';
      state.bounce++;
      state.log.push({
        name: r.first_name+' '+r.last_name,
        email: r.email,
        domain: r.domain,
        domainOk: r.domainValid,
        idExists: false,
        status: 'bounce',
        reason: 'Domain not verified / no ID',
        time: new Date().toLocaleTimeString('en-IN')
      });
    } else {
      // Mark sent (real send happens when PHP is running)
      r.status = 'sent';
      state.sent++;
      state.log.push({
        name: r.first_name+' '+r.last_name,
        email: r.email,
        domain: r.domain,
        domainOk: true,
        idExists: true,
        status: 'sent',
        time: new Date().toLocaleTimeString('en-IN')
      });
    }
  });

  updateStats();
  refreshLogTable();
  state.currentBatch++;

  if((state.currentBatch * BATCH_LIMIT) >= all.length){
    finishSending();
  } else {
    document.getElementById('liveFeed').textContent =
      '⏳ Next batch in '+state.delay+'s … ('+(state.currentBatch*BATCH_LIMIT)+'/'+all.length+' done)';
    state.sendTimer = setTimeout(sendNextBatch, state.delay*1000);
  }
}

function finishSending(){
  state.sending = false;
  document.getElementById('btnStart').disabled = false;
  document.getElementById('btnStop').disabled  = true;
  document.getElementById('statusBadge').className='status-badge done';
  document.getElementById('statusBadge').innerHTML='✓ Done';
  document.getElementById('liveFeed').textContent =
    '✅ Campaign complete — Sent: '+state.sent+' · Bounce: '+state.bounce+' · Failed: '+state.failed;
  toast('Campaign finished! Sent: '+state.sent,'ok');
  exportCampaignExcel(); // auto-save
}

function stopSending(){
  if(state.sendTimer) clearTimeout(state.sendTimer);
  state.sending = false;
  document.getElementById('btnStart').disabled = false;
  document.getElementById('btnStop').disabled  = true;
  document.getElementById('statusBadge').className='status-badge';
  document.getElementById('statusBadge').innerHTML='⬤ &nbsp;Stopped';
  document.getElementById('liveFeed').textContent = '⏹ Campaign stopped by user.';
  toast('Campaign stopped','info');
}

function resetAll(){
  if(state.sending){ stopSending(); }
  state.recipients=[];state.log=[];state.sent=0;state.bounce=0;state.failed=0;state.currentBatch=0;
  updateStats();
  document.getElementById('fileInfo').style.display='none';
  document.getElementById('recipientRows').innerHTML='';
  document.getElementById('logRows').innerHTML='';
  document.getElementById('statusBadge').className='status-badge';
  document.getElementById('statusBadge').innerHTML='⬤ &nbsp;Idle';
  document.getElementById('liveFeed').textContent='';
  document.getElementById('btnExport').disabled=true;
  toast('Reset complete','info');
}

// ─── LOG TABLE ─────────────────────────────────────────────────────────────
let logFilter = 'all';
function filterLog(f){
  logFilter=f;
  ['All','Bounce','Fail','Pend'].forEach(n=>{
    const btn = document.getElementById('f'+n);
    if(btn) btn.style.background='';
  });
  refreshLogTable();
}

function refreshLogTable(){
  const tbody = document.getElementById('logRows');
  let rows = state.log;
  if(logFilter==='bounce') rows = rows.filter(r=>r.status==='bounce');
  else if(logFilter==='failed') rows = rows.filter(r=>r.status==='failed');
  else if(logFilter==='pending') rows = state.recipients.filter(r=>r.status==='pending').map(r=>({
    name:r.first_name+' '+r.last_name,email:r.email,domain:r.domain,
    domainOk:r.domainValid,idExists:r.idExists,status:'pending',time:'—'
  }));

  tbody.innerHTML = rows.map((r,i)=>`
    <tr>
      <td>${i+1}</td>
      <td class="name-cell">${r.name||'—'}</td>
      <td>${r.email}</td>
      <td>
        <div style="display:flex;align-items:center;gap:5px">
          <div class="domain-dot ${r.domainOk?'ok':'err'}"></div>
          ${r.domain||'—'}
        </div>
      </td>
      <td>${r.idExists===true?'<span class="tag ok">✓ ID</span>':'<span class="tag bounce">✗ No ID</span>'}</td>
      <td>${statusTag(r.status)}</td>
      <td>${r.time||'—'}</td>
    </tr>
  `).join('');
}

function statusTag(s){
  if(s==='sent')    return '<span class="tag ok">✓ Sent</span>';
  if(s==='bounce')  return '<span class="tag bounce">↩ Bounce</span>';
  if(s==='failed')  return '<span class="tag err">✗ Failed</span>';
  if(s==='pending') return '<span class="tag pending">⏳ Pending</span>';
  return '<span class="tag skip">'+s+'</span>';
}

// ─── SAVE CAMPAIGN ──────────────────────────────────────────────────────────
function saveCampaign(){
  toast('Campaign settings saved','ok');
}

// ─── EXPORT EXCEL ──────────────────────────────────────────────────────────
function exportCampaignExcel(){
  const now   = new Date();
  const stamp = formatExcelDate(now);
  const cname = document.getElementById('campName').value||'ubsforums_campaign';
  const cdb   = document.getElementById('campDb').value||'ubsforums_campaign';

  // Build worksheet data
  const headers = ['#','Campaign','Database','First Name','Last Name','Email','Domain','Domain Valid','ID Exists','Status','Time','Export Date-Time'];
  const rows = state.recipients.map((r,i)=>[
    i+1, cname, cdb,
    r.first_name, r.last_name, r.email, r.domain,
    r.domainValid?'Yes':'No',
    r.idExists?'Yes':'No',
    r.status||'pending',
    state.log.find(l=>l.email===r.email)?.time||'—',
    stamp
  ]);

  const wb  = XLSX.utils.book_new();
  const ws  = XLSX.utils.aoa_to_sheet([headers,...rows]);

  // Column widths
  ws['!cols'] = headers.map(h=>({wch: Math.max(h.length+4, 14)}));

  XLSX.utils.book_append_sheet(wb, ws, 'Campaign Report');

  // Second sheet: summary
  const sumHeaders = ['Metric','Value'];
  const sumData = [
    ['Campaign Name', cname],
    ['Database', cdb],
    ['Export Date-Time', stamp],
    ['Total Recipients', state.recipients.length],
    ['Sent (ID Verified)', state.sent],
    ['Bounce (No ID)', state.bounce],
    ['Failed', state.failed],
    ['Pending', state.recipients.length - state.sent - state.bounce - state.failed],
  ];
  const ws2 = XLSX.utils.aoa_to_sheet([sumHeaders,...sumData]);
  ws2['!cols'] = [{wch:22},{wch:24}];
  XLSX.utils.book_append_sheet(wb, ws2, 'Summary');

  const fname = cname+'_'+stamp.replace(/[: ]/g,'-')+'.xlsx';
  XLSX.writeFile(wb, fname);
  toast('Excel saved: '+fname,'ok');
}

function exportReport(type){
  if(type==='xlsx') exportCampaignExcel();
  else{
    const rows = [['#','Name','Email','Domain','ID Exists','Status','Time']];
    state.log.forEach((r,i)=>rows.push([i+1,r.name,r.email,r.domain,r.idExists?'Yes':'No',r.status,r.time]));
    const csv = rows.map(r=>r.map(c=>'"'+String(c).replace(/"/g,'""')+'"').join(',')).join('\n');
    download(csv,'text/csv','campaign_report.csv');
    toast('CSV downloaded','ok');
  }
}

function download(content, type, name){
  const a = document.createElement('a');
  a.href = URL.createObjectURL(new Blob([content],{type}));
  a.download = name;
  a.click();
}

function printReport(){
  window.print();
}

function refreshReportTable(){
  const tbody = document.getElementById('reportRows');
  tbody.innerHTML = (state.log.length ? state.log : state.recipients.map(r=>({
    name:r.first_name+' '+r.last_name,email:r.email,domain:r.domain,
    domainOk:r.domainValid,idExists:r.idExists,status:'pending',time:'—'
  }))).map((r,i)=>`
    <tr>
      <td>${i+1}</td>
      <td class="name-cell">${r.name||'—'}</td>
      <td>${r.email}</td>
      <td>${r.domain||'—'}</td>
      <td>${r.idExists===true?'<span class="tag ok">Yes</span>':'<span class="tag bounce">No</span>'}</td>
      <td>${statusTag(r.status)}</td>
      <td>${r.time||'—'}</td>
    </tr>
  `).join('');
}

// ─── TOAST ─────────────────────────────────────────────────────────────────
function toast(msg, type='info'){
  const t = document.createElement('div');
  t.className='toast '+type;
  t.textContent = msg;
  document.getElementById('toasts').appendChild(t);
  setTimeout(()=>t.remove(),3500);
}

// ─── LOAD SHEETJS ──────────────────────────────────────────────────────────
const s = document.createElement('script');
s.src = 'https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js';
s.onload = ()=>{ toast('Ready — Upload your recipient list','info'); };
s.onerror = ()=>{ toast('SheetJS failed to load — check network','err'); };
document.head.appendChild(s);

// Auto-load existing recipient data from state.json simulation
window.addEventListener('load', ()=>{
  // Simulate the existing campaign state being loaded
  const existingRecipients = [
    {id:1,first_name:'deepa',last_name:'ubsf',email:'deepa@ubsforums.in',domain:'ubsforums.in',domainValid:null,idExists:null,status:'pending'},
    {id:2,first_name:'mahima',last_name:'mahim',email:'shilpi.talesara@ubsforums.com',domain:'ubsforums.com',domainValid:null,idExists:null,status:'pending'},
    {id:3,first_name:'vidhya',last_name:'vv',email:'vidhya.kotian@ubsforums.com',domain:'ubsforums.com',domainValid:null,idExists:null,status:'pending'},
  ];

  setTimeout(()=>{
    if(typeof XLSX !== 'undefined'){
      state.recipients = existingRecipients;
      document.getElementById('fileName').textContent = 'recipients.xlsx (existing)';
      document.getElementById('fileStats').textContent = state.recipients.length + ' recipients loaded';
      document.getElementById('fileInfo').style.display = 'block';
      document.getElementById('btnExport').disabled = false;
      verifyDomains();
      updateStats();
      toast('Existing campaign data loaded (3 recipients)','ok');
    }
  }, 800);
});
</script>
</body>
</html>