<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="UTF-8" />

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

<title>Prism Digital — Lead Tracker</title>

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

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

<style>

/* ── CONFIG ── fill these in after Google Cloud setup ── */

/* See: PRISM_API_KEY and PRISM_SHEET_ID in the <script> below */


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


:root {

  --bg: #0d0f12;

  --surface: #13161b;

  --surface2: #1a1e25;

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

  --border-hover: rgba(255,255,255,0.14);

  --text: #e8eaf0;

  --text-muted: #6b7280;

  --text-dim: #3d4452;

  --accent: #3b82f6;

  --accent-glow: rgba(59,130,246,0.15);

  --accent-dim: rgba(59,130,246,0.25);

  --green: #10b981;

  --green-dim: rgba(16,185,129,0.15);

  --amber: #f59e0b;

  --amber-dim: rgba(245,158,11,0.15);

  --red: #ef4444;

  --red-dim: rgba(239,68,68,0.15);

  --teal: #14b8a6;

  --teal-dim: rgba(20,184,166,0.15);

  --font: 'DM Sans', sans-serif;

  --mono: 'DM Mono', monospace;

  --radius: 10px;

  --radius-lg: 16px;

}


html, body {

  background: var(--bg);

  color: var(--text);

  font-family: var(--font);

  font-size: 14px;

  min-height: 100vh;

  line-height: 1.6;

}


/* ── PASSWORD GATE ── */

#gate {

  min-height: 100vh;

  display: flex;

  align-items: center;

  justify-content: center;

  padding: 2rem;

}


.gate-card {

  width: 100%;

  max-width: 360px;

  background: var(--surface);

  border: 1px solid var(--border);

  border-radius: var(--radius-lg);

  padding: 2.5rem 2rem;

  text-align: center;

}


.gate-logo {

  display: flex;

  align-items: center;

  justify-content: center;

  gap: 10px;

  margin-bottom: 2rem;

}


.gate-prism {

  width: 32px;

  height: 32px;

}


.gate-brand {

  font-size: 18px;

  font-weight: 500;

  letter-spacing: -0.02em;

}


.gate-sub {

  font-size: 12px;

  color: var(--text-muted);

  margin-bottom: 1.75rem;

}


.gate-label {

  font-size: 12px;

  color: var(--text-muted);

  text-align: left;

  margin-bottom: 6px;

  display: block;

}


.gate-input {

  width: 100%;

  background: var(--bg);

  border: 1px solid var(--border);

  border-radius: var(--radius);

  color: var(--text);

  font-family: var(--mono);

  font-size: 14px;

  padding: 10px 14px;

  outline: none;

  margin-bottom: 12px;

  transition: border-color 0.15s;

}


.gate-input:focus { border-color: var(--accent); }

.gate-input.error { border-color: var(--red); }


.gate-btn {

  width: 100%;

  background: var(--accent);

  color: #fff;

  border: none;

  border-radius: var(--radius);

  font-family: var(--font);

  font-size: 14px;

  font-weight: 500;

  padding: 10px;

  cursor: pointer;

  transition: opacity 0.15s, transform 0.1s;

}


.gate-btn:hover { opacity: 0.9; }

.gate-btn:active { transform: scale(0.98); }


.gate-error {

  font-size: 12px;

  color: var(--red);

  margin-top: 8px;

  min-height: 18px;

}


/* ── MAIN APP ── */

#app { display: none; min-height: 100vh; }


header {

  background: var(--surface);

  border-bottom: 1px solid var(--border);

  padding: 0 2rem;

  height: 56px;

  display: flex;

  align-items: center;

  justify-content: space-between;

  position: sticky;

  top: 0;

  z-index: 10;

}


.header-left {

  display: flex;

  align-items: center;

  gap: 10px;

}


.header-brand { font-size: 15px; font-weight: 500; letter-spacing: -0.02em; }

.header-sep { color: var(--text-dim); }

.header-page { font-size: 14px; color: var(--text-muted); }


.header-right {

  display: flex;

  align-items: center;

  gap: 10px;

}


.sync-indicator {

  font-size: 11px;

  color: var(--text-muted);

  display: flex;

  align-items: center;

  gap: 5px;

}


.sync-dot {

  width: 6px; height: 6px;

  border-radius: 50%;

  background: var(--green);

}


.sync-dot.syncing { background: var(--amber); animation: pulse 1s infinite; }

.sync-dot.error { background: var(--red); }


@keyframes pulse { 0%,100%{opacity:1} 50%{opacity:0.4} }


.logout-btn {

  background: none;

  border: 1px solid var(--border);

  border-radius: var(--radius);

  color: var(--text-muted);

  font-family: var(--font);

  font-size: 12px;

  padding: 5px 12px;

  cursor: pointer;

  transition: all 0.15s;

}

.logout-btn:hover { border-color: var(--border-hover); color: var(--text); }


main { padding: 2rem; max-width: 1100px; margin: 0 auto; }


/* stats */

.stats-grid {

  display: grid;

  grid-template-columns: repeat(4, 1fr);

  gap: 12px;

  margin-bottom: 1.75rem;

}


.stat {

  background: var(--surface);

  border: 1px solid var(--border);

  border-radius: var(--radius);

  padding: 1rem 1.25rem;

}


.stat-val {

  font-size: 28px;

  font-weight: 300;

  letter-spacing: -0.03em;

  line-height: 1;

  margin-bottom: 4px;

}


.stat-key {

  font-size: 11px;

  color: var(--text-muted);

  text-transform: uppercase;

  letter-spacing: 0.06em;

}


/* toolbar */

.toolbar {

  display: flex;

  gap: 8px;

  margin-bottom: 1.25rem;

  flex-wrap: wrap;

  align-items: center;

}


.tb-input {

  flex: 1;

  min-width: 180px;

  background: var(--surface);

  border: 1px solid var(--border);

  border-radius: var(--radius);

  color: var(--text);

  font-family: var(--font);

  font-size: 13px;

  padding: 8px 12px;

  outline: none;

  transition: border-color 0.15s;

}

.tb-input:focus { border-color: var(--accent); }

.tb-input::placeholder { color: var(--text-dim); }


.tb-select {

  background: var(--surface);

  border: 1px solid var(--border);

  border-radius: var(--radius);

  color: var(--text);

  font-family: var(--font);

  font-size: 13px;

  padding: 8px 12px;

  outline: none;

  cursor: pointer;

}

.tb-select:focus { border-color: var(--accent); }


.btn {

  background: var(--surface);

  border: 1px solid var(--border);

  border-radius: var(--radius);

  color: var(--text);

  font-family: var(--font);

  font-size: 13px;

  font-weight: 500;

  padding: 8px 16px;

  cursor: pointer;

  display: inline-flex;

  align-items: center;

  gap: 6px;

  white-space: nowrap;

  transition: all 0.15s;

}

.btn:hover { border-color: var(--border-hover); background: var(--surface2); }

.btn:active { transform: scale(0.98); }


.btn-accent {

  background: var(--accent);

  border-color: var(--accent);

  color: #fff;

}

.btn-accent:hover { background: #2563eb; border-color: #2563eb; }


/* table */

.table-wrap {

  background: var(--surface);

  border: 1px solid var(--border);

  border-radius: var(--radius-lg);

  overflow: hidden;

}


table {

  width: 100%;

  border-collapse: collapse;

  table-layout: fixed;

}


thead th {

  padding: 10px 14px;

  font-size: 11px;

  font-weight: 500;

  color: var(--text-muted);

  text-transform: uppercase;

  letter-spacing: 0.06em;

  text-align: left;

  border-bottom: 1px solid var(--border);

  cursor: pointer;

  user-select: none;

  white-space: nowrap;

}

thead th:hover { color: var(--text); }


tbody td {

  padding: 11px 14px;

  border-bottom: 1px solid var(--border);

  font-size: 13px;

  color: var(--text);

  overflow: hidden;

  text-overflow: ellipsis;

  white-space: nowrap;

}

tbody tr:last-child td { border-bottom: none; }

tbody tr:hover { background: var(--surface2); }


.badge {

  display: inline-block;

  padding: 2px 9px;

  border-radius: 99px;

  font-size: 11px;

  font-weight: 500;

}


.badge-discovery { background: var(--accent-dim); color: #93c5fd; }

.badge-proposal  { background: var(--amber-dim);  color: #fcd34d; }

.badge-progress  { background: var(--teal-dim);   color: #5eead4; }

.badge-launched  { background: var(--green-dim);  color: #6ee7b7; }

.badge-lost      { background: rgba(255,255,255,0.05); color: var(--text-muted); }


.act-btn {

  background: none;

  border: none;

  color: var(--text-dim);

  cursor: pointer;

  padding: 3px 5px;

  border-radius: 6px;

  font-size: 14px;

  line-height: 1;

  transition: all 0.12s;

}

.act-btn:hover { background: var(--surface2); color: var(--text); }


.empty {

  text-align: center;

  padding: 3rem 1rem;

  color: var(--text-muted);

  font-size: 13px;

}


/* modal */

.overlay {

  display: none;

  position: fixed; inset: 0;

  background: rgba(0,0,0,0.6);

  z-index: 50;

  align-items: center;

  justify-content: center;

  padding: 1rem;

  backdrop-filter: blur(3px);

}

.overlay.open { display: flex; }


.modal {

  background: var(--surface);

  border: 1px solid var(--border-hover);

  border-radius: var(--radius-lg);

  padding: 1.5rem;

  width: 100%;

  max-width: 440px;

  max-height: 90vh;

  overflow-y: auto;

}


.modal-head {

  font-size: 15px;

  font-weight: 500;

  margin-bottom: 1.25rem;

  letter-spacing: -0.02em;

}


.fg { margin-bottom: 12px; }


.fg label {

  display: block;

  font-size: 11px;

  color: var(--text-muted);

  text-transform: uppercase;

  letter-spacing: 0.06em;

  margin-bottom: 5px;

}


.fg input, .fg select, .fg textarea {

  width: 100%;

  background: var(--bg);

  border: 1px solid var(--border);

  border-radius: var(--radius);

  color: var(--text);

  font-family: var(--font);

  font-size: 13px;

  padding: 8px 12px;

  outline: none;

  transition: border-color 0.15s;

}

.fg input:focus, .fg select:focus, .fg textarea:focus { border-color: var(--accent); }

.fg textarea { height: 80px; resize: vertical; }


.fg-row { display: flex; gap: 10px; }

.fg-row .fg { flex: 1; }


.modal-foot {

  display: flex;

  justify-content: flex-end;

  gap: 8px;

  margin-top: 1.25rem;

}


.note-item {

  background: var(--bg);

  border: 1px solid var(--border);

  border-radius: var(--radius);

  padding: 10px 12px;

  margin-bottom: 8px;

}

.note-date { font-size: 11px; color: var(--text-muted); margin-bottom: 3px; font-family: var(--mono); }

.note-text { font-size: 13px; }


.spinner {

  display: inline-block;

  width: 14px; height: 14px;

  border: 2px solid var(--border);

  border-top-color: var(--accent);

  border-radius: 50%;

  animation: spin 0.6s linear infinite;

  vertical-align: middle;

}

@keyframes spin { to { transform: rotate(360deg); } }


.toast {

  position: fixed;

  bottom: 1.5rem;

  right: 1.5rem;

  background: var(--surface2);

  border: 1px solid var(--border-hover);

  border-radius: var(--radius);

  padding: 10px 16px;

  font-size: 13px;

  color: var(--text);

  z-index: 200;

  opacity: 0;

  transform: translateY(8px);

  transition: all 0.2s;

  pointer-events: none;

}

.toast.show { opacity: 1; transform: translateY(0); }


@media (max-width: 640px) {

  .stats-grid { grid-template-columns: repeat(2, 1fr); }

  .col-contact, .col-service, .col-date { display: none; }

  main { padding: 1rem; }

  header { padding: 0 1rem; }

}

</style>

</head>

<body>


<!-- ── PASSWORD GATE ── -->

<div id="gate">

  <div class="gate-card">

    <div class="gate-logo">

      <svg class="gate-prism" viewBox="0 0 32 32" fill="none">

        <polygon points="16,2 30,28 2,28" fill="none" stroke="#3b82f6" stroke-width="1.5"/>

        <line x1="16" y1="2" x2="16" y2="28" stroke="#3b82f6" stroke-width="0.75" stroke-opacity="0.5"/>

        <line x1="16" y1="2" x2="2" y2="28" stroke="#3b82f6" stroke-width="0.75" stroke-opacity="0.3"/>

        <line x1="9" y1="15" x2="30" y2="28" stroke="#3b82f6" stroke-width="0.75" stroke-opacity="0.3"/>

      </svg>

      <span class="gate-brand">Prism Digital</span>

    </div>

    <div class="gate-sub">Lead Tracker — private dashboard</div>

    <label class="gate-label">Password</label>

    <input class="gate-input" id="gate-pw" type="password" placeholder="Enter password" onkeydown="if(event.key==='Enter')unlock()" />

    <button class="gate-btn" onclick="unlock()">Unlock dashboard</button>

    <div class="gate-error" id="gate-err"></div>

  </div>

</div>


<!-- ── MAIN APP ── -->

<div id="app">

  <header>

    <div class="header-left">

      <svg width="22" height="22" viewBox="0 0 32 32" fill="none">

        <polygon points="16,2 30,28 2,28" fill="none" stroke="#3b82f6" stroke-width="1.5"/>

        <line x1="16" y1="2" x2="16" y2="28" stroke="#3b82f6" stroke-width="0.75" stroke-opacity="0.5"/>

      </svg>

      <span class="header-brand">Prism Digital</span>

      <span class="header-sep">/</span>

      <span class="header-page">Lead Tracker</span>

    </div>

    <div class="header-right">

      <div class="sync-indicator">

        <div class="sync-dot" id="sync-dot"></div>

        <span id="sync-label">Connected</span>

      </div>

      <button class="logout-btn" onclick="logout()">Lock</button>

    </div>

  </header>


  <main>

    <div class="stats-grid" id="stats-grid"></div>


    <div class="toolbar">

      <input class="tb-input" type="text" id="search" placeholder="Search leads…" oninput="renderTable()" />

      <select class="tb-select" id="filter-stage" onchange="renderTable()">

        <option value="">All stages</option>

        <option>Discovery</option><option>Proposal</option>

        <option>In Progress</option><option>Launched</option><option>Lost</option>

      </select>

      <select class="tb-select" id="filter-service" onchange="renderTable()">

        <option value="">All services</option>

        <option>Website Design</option><option>Content Development</option>

        <option>SEO</option><option>Hosting</option>

        <option>Project Management</option><option>Other</option>

      </select>

      <button class="btn btn-accent" onclick="openAdd()">+ Add lead</button>

    </div>


    <div class="table-wrap">

      <div id="loading" style="text-align:center;padding:2.5rem;color:var(--text-muted);font-size:13px;">

        <span class="spinner"></span>&nbsp; Loading from Google Sheets…

      </div>

      <table id="leads-table" style="display:none;">

        <thead>

          <tr>

            <th style="width:22%" onclick="sort('name')">Name <span id="s-name"></span></th>

            <th class="col-contact" style="width:19%" onclick="sort('contact')">Contact <span id="s-contact"></span></th>

            <th class="col-service" style="width:16%" onclick="sort('service')">Service <span id="s-service"></span></th>

            <th style="width:15%" onclick="sort('stage')">Stage <span id="s-stage"></span></th>

            <th class="col-date" style="width:13%" onclick="sort('added')">Added <span id="s-added"></span></th>

            <th style="width:15%"></th>

          </tr>

        </thead>

        <tbody id="tbody"></tbody>

      </table>

      <div id="empty" class="empty" style="display:none;">No leads found.</div>

    </div>

  </main>

</div>


<!-- Add / Edit modal -->

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

  <div class="modal">

    <div class="modal-head" id="modal-title">Add new lead</div>

    <div class="fg">

      <label>Client / Business name *</label>

      <input type="text" id="f-name" placeholder="Acme Studio" />

    </div>

    <div class="fg-row">

      <div class="fg">

        <label>Contact name</label>

        <input type="text" id="f-contact" placeholder="Jane Smith" />

      </div>

      <div class="fg">

        <label>Email</label>

        <input type="text" id="f-email" placeholder="jane@acme.com" />

      </div>

    </div>

    <div class="fg-row">

      <div class="fg">

        <label>Service interest</label>

        <select id="f-service">

          <option value="">— select —</option>

          <option>Website Design</option><option>Content Development</option>

          <option>SEO</option><option>Hosting</option>

          <option>Project Management</option><option>Other</option>

        </select>

      </div>

      <div class="fg">

        <label>Pipeline stage</label>

        <select id="f-stage">

          <option>Discovery</option><option>Proposal</option>

          <option>In Progress</option><option>Launched</option><option>Lost</option>

        </select>

      </div>

    </div>

    <div class="fg">

      <label>Notes</label>

      <textarea id="f-notes" placeholder="Any context about this lead…"></textarea>

    </div>

    <div class="modal-foot">

      <button class="btn" onclick="closeModal('lead-modal')">Cancel</button>

      <button class="btn btn-accent" id="save-btn" onclick="saveLead()">Save lead</button>

    </div>

  </div>

</div>


<!-- Notes modal -->

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

  <div class="modal">

    <div class="modal-head" id="notes-title">Notes</div>

    <div id="notes-list"></div>

    <div class="fg" style="margin-top:10px;">

      <label>Add a note</label>

      <textarea id="new-note" placeholder="Log an update, call, or follow-up…"></textarea>

    </div>

    <div class="modal-foot">

      <button class="btn" onclick="closeModal('notes-modal')">Close</button>

      <button class="btn btn-accent" onclick="addNote()">Add note</button>

    </div>

  </div>

</div>


<div class="toast" id="toast"></div>


<script>

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

//  CONFIGURATION — fill these in

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

const CONFIG = {

  PASSWORD:   'prism2024',          // ← change this to your password

  API_KEY:    'AIzaSyCHhE3vwo85ED7TLWrrKoODsFS0sjYK_iA', // ← paste your Google API key

  SHEET_ID:   '1IyXLl_Pw_0wM1bv9qrIzYT1zoeaHd9AW4GwTYaAw6Rs',       // ← paste your Google Sheet ID

  SHEET_NAME: 'Leads',               // ← sheet tab name (keep as "Leads")

};

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


const BASE = `https://sheets.googleapis.com/v4/spreadsheets/${CONFIG.SHEET_ID}/values`;

const HEADERS = ['ID','Name','Contact','Email','Service','Stage','Added','Notes'];


let leads = [];

let editRow = null;   // 1-based sheet row of lead being edited

let notesRow = null;

let sortCol = 'added';

let sortDir = 'desc';

let authenticated = false;


// ── AUTH ──────────────────────────────────────

function unlock() {

  const pw = document.getElementById('gate-pw').value;

  const err = document.getElementById('gate-err');

  if (pw === CONFIG.PASSWORD) {

    authenticated = true;

    document.getElementById('gate').style.display = 'none';

    document.getElementById('app').style.display = 'block';

    loadLeads();

  } else {

    err.textContent = 'Incorrect password.';

    document.getElementById('gate-pw').classList.add('error');

    setTimeout(() => {

      err.textContent = '';

      document.getElementById('gate-pw').classList.remove('error');

    }, 2000);

  }

}


function logout() {

  authenticated = false;

  document.getElementById('app').style.display = 'none';

  document.getElementById('gate').style.display = 'flex';

  document.getElementById('gate-pw').value = '';

}


// ── SYNC STATUS ───────────────────────────────

function setSyncState(state) {

  const dot = document.getElementById('sync-dot');

  const lbl = document.getElementById('sync-label');

  dot.className = 'sync-dot' + (state === 'syncing' ? ' syncing' : state === 'error' ? ' error' : '');

  lbl.textContent = state === 'syncing' ? 'Saving…' : state === 'error' ? 'Sync error' : 'Synced';

}


// ── GOOGLE SHEETS API ─────────────────────────

async function sheetsGet(range) {

  const url = `${BASE}/${encodeURIComponent(range)}?key=${CONFIG.API_KEY}`;

  const r = await fetch(url);

  if (!r.ok) throw new Error('Sheets read failed: ' + r.status);

  return r.json();

}


async function sheetsAppend(values) {

  const url = `${BASE}/${encodeURIComponent(CONFIG.SHEET_NAME)}:append?valueInputOption=RAW&insertDataOption=INSERT_ROWS&key=${CONFIG.API_KEY}`;

  const r = await fetch(url, {

    method: 'POST',

    headers: { 'Content-Type': 'application/json' },

    body: JSON.stringify({ values })

  });

  if (!r.ok) throw new Error('Sheets append failed: ' + r.status);

  return r.json();

}


async function sheetsUpdate(range, values) {

  const url = `${BASE}/${encodeURIComponent(range)}?valueInputOption=RAW&key=${CONFIG.API_KEY}`;

  const r = await fetch(url, {

    method: 'PUT',

    headers: { 'Content-Type': 'application/json' },

    body: JSON.stringify({ values })

  });

  if (!r.ok) throw new Error('Sheets update failed: ' + r.status);

  return r.json();

}


async function sheetsClear(range) {

  const url = `${BASE}/${encodeURIComponent(range)}:clear?key=${CONFIG.API_KEY}`;

  const r = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json' } });

  if (!r.ok) throw new Error('Sheets clear failed: ' + r.status);

  return r.json();

}


// ── LOAD ──────────────────────────────────────

async function loadLeads() {

  setSyncState('syncing');

  try {

    const data = await sheetsGet(`${CONFIG.SHEET_NAME}!A:H`);

    const rows = data.values || [];

    // ensure header row

    if (rows.length === 0 || rows[0][0] !== 'ID') {

      await sheetsAppend([HEADERS]);

      leads = [];

    } else {

      leads = rows.slice(1).map((r, i) => ({

        id: r[0] || '',

        name: r[1] || '',

        contact: r[2] || '',

        email: r[3] || '',

        service: r[4] || '',

        stage: r[5] || 'Discovery',

        added: r[6] || '',

        notes: r[7] || '',

        _row: i + 2   // 1-based sheet row (row 1 = headers)

      })).filter(l => l.id);

    }

    setSyncState('ok');

  } catch(e) {

    setSyncState('error');

    showToast('Could not load from Google Sheets. Check your API key and Sheet ID.');

    leads = [];

  }

  document.getElementById('loading').style.display = 'none';

  document.getElementById('leads-table').style.display = '';

  renderAll();

}


// ── SAVE LEAD ─────────────────────────────────

async function saveLead() {

  const name = document.getElementById('f-name').value.trim();

  if (!name) { document.getElementById('f-name').focus(); return; }


  const row = [

    editRow ? leads.find(l => l._row === editRow)?.id || uid() : uid(),

    name,

    document.getElementById('f-contact').value.trim(),

    document.getElementById('f-email').value.trim(),

    document.getElementById('f-service').value,

    document.getElementById('f-stage').value,

    editRow ? leads.find(l => l._row === editRow)?.added || today() : today(),

    document.getElementById('f-notes').value.trim()

  ];


  setSyncState('syncing');

  try {

    if (editRow) {

      await sheetsUpdate(`${CONFIG.SHEET_NAME}!A${editRow}:H${editRow}`, [row]);

      showToast('Lead updated.');

    } else {

      await sheetsAppend([row]);

      showToast('Lead added.');

    }

    await loadLeads();

  } catch(e) {

    setSyncState('error');

    showToast('Save failed — check console.');

  }

  closeModal('lead-modal');

}


// ── DELETE ────────────────────────────────────

async function deleteLead(row) {

  if (!confirm('Delete this lead?')) return;

  setSyncState('syncing');

  try {

    await sheetsClear(`${CONFIG.SHEET_NAME}!A${row}:H${row}`);

    showToast('Lead removed.');

    await loadLeads();

  } catch(e) {

    setSyncState('error');

    showToast('Delete failed.');

  }

}


// ── NOTES ─────────────────────────────────────

function openNotes(row) {

  notesRow = row;

  const lead = leads.find(l => l._row === row);

  document.getElementById('notes-title').textContent = (lead?.name || 'Lead') + ' — notes';

  document.getElementById('new-note').value = '';

  renderNotesList(lead?.notes || '');

  document.getElementById('notes-modal').classList.add('open');

}


function renderNotesList(raw) {

  const el = document.getElementById('notes-list');

  const entries = raw ? raw.split('|||').filter(Boolean) : [];

  if (!entries.length) {

    el.innerHTML = '<div style="color:var(--text-muted);font-size:12px;padding:4px 0 8px;">No notes yet.</div>';

    return;

  }

  el.innerHTML = [...entries].reverse().map(e => {

    const sep = e.indexOf(': ');

    const date = sep > -1 ? e.slice(0, sep) : '';

    const text = sep > -1 ? e.slice(sep + 2) : e;

    return `<div class="note-item"><div class="note-date">${date}</div><div class="note-text">${text}</div></div>`;

  }).join('');

}


async function addNote() {

  const text = document.getElementById('new-note').value.trim();

  if (!text) return;

  const lead = leads.find(l => l._row === notesRow);

  if (!lead) return;

  const existing = lead.notes || '';

  const entry = `${today()}: ${text}`;

  const updated = existing ? existing + '|||' + entry : entry;


  setSyncState('syncing');

  try {

    await sheetsUpdate(`${CONFIG.SHEET_NAME}!H${notesRow}`, [[updated]]);

    document.getElementById('new-note').value = '';

    await loadLeads();

    const refreshed = leads.find(l => l.id === lead.id);

    renderNotesList(refreshed?.notes || '');

    showToast('Note added.');

  } catch(e) {

    setSyncState('error');

    showToast('Note save failed.');

  }

}


// ── MODALS ────────────────────────────────────

function openAdd() {

  editRow = null;

  document.getElementById('modal-title').textContent = 'Add new lead';

  document.getElementById('save-btn').textContent = 'Save lead';

  ['f-name','f-contact','f-email','f-notes'].forEach(id => document.getElementById(id).value = '');

  document.getElementById('f-service').value = '';

  document.getElementById('f-stage').value = 'Discovery';

  document.getElementById('lead-modal').classList.add('open');

}


function openEdit(row) {

  const lead = leads.find(l => l._row === row);

  if (!lead) return;

  editRow = row;

  document.getElementById('modal-title').textContent = 'Edit lead';

  document.getElementById('save-btn').textContent = 'Save changes';

  document.getElementById('f-name').value = lead.name;

  document.getElementById('f-contact').value = lead.contact;

  document.getElementById('f-email').value = lead.email;

  document.getElementById('f-service').value = lead.service;

  document.getElementById('f-stage').value = lead.stage;

  document.getElementById('f-notes').value = '';

  document.getElementById('lead-modal').classList.add('open');

}


function closeModal(id) {

  document.getElementById(id).classList.remove('open');

}


// ── RENDER ────────────────────────────────────

function renderStats() {

  const total = leads.length;

  const active = leads.filter(l => !['Launched','Lost'].includes(l.stage)).length;

  const proposals = leads.filter(l => l.stage === 'Proposal').length;

  const launched = leads.filter(l => l.stage === 'Launched').length;

  document.getElementById('stats-grid').innerHTML = [

    [total, 'Total leads'],

    [active, 'Active'],

    [proposals, 'Proposals'],

    [launched, 'Launched']

  ].map(([v,k]) => `<div class="stat"><div class="stat-val">${v}</div><div class="stat-key">${k}</div></div>`).join('');

}


function getFiltered() {

  const q = document.getElementById('search').value.toLowerCase();

  const st = document.getElementById('filter-stage').value;

  const sv = document.getElementById('filter-service').value;

  return leads.filter(l => {

    const mq = !q || [l.name,l.contact,l.email,l.service].some(v => v?.toLowerCase().includes(q));

    return mq && (!st || l.stage === st) && (!sv || l.service === sv);

  }).sort((a, b) => {

    let av = a[sortCol] || '', bv = b[sortCol] || '';

    const cmp = av < bv ? -1 : av > bv ? 1 : 0;

    return sortDir === 'asc' ? cmp : -cmp;

  });

}


function sort(col) {

  if (sortCol === col) sortDir = sortDir === 'asc' ? 'desc' : 'asc';

  else { sortCol = col; sortDir = 'asc'; }

  ['name','contact','service','stage','added'].forEach(c => {

    const el = document.getElementById('s-' + c);

    if (el) el.textContent = '';

  });

  const el = document.getElementById('s-' + col);

  if (el) el.textContent = sortDir === 'asc' ? ' ↑' : ' ↓';

  renderTable();

}


function badgeClass(stage) {

  return { Discovery:'badge-discovery', Proposal:'badge-proposal',

    'In Progress':'badge-progress', Launched:'badge-launched', Lost:'badge-lost' }[stage] || 'badge-discovery';

}


function renderTable() {

  const rows = getFiltered();

  const tbody = document.getElementById('tbody');

  const empty = document.getElementById('empty');

  if (!rows.length) {

    tbody.innerHTML = '';

    empty.style.display = '';

    return;

  }

  empty.style.display = 'none';

  tbody.innerHTML = rows.map(l => `

    <tr>

      <td title="${l.name}">${l.name || '—'}</td>

      <td class="col-contact" title="${l.contact}">${l.contact || l.email || '—'}</td>

      <td class="col-service" title="${l.service}">${l.service || '—'}</td>

      <td><span class="badge ${badgeClass(l.stage)}">${l.stage}</span></td>

      <td class="col-date">${l.added || '—'}</td>

      <td style="text-align:right;white-space:nowrap;">

        <button class="act-btn" title="Notes" onclick="openNotes(${l._row})">📝</button>

        <button class="act-btn" title="Edit" onclick="openEdit(${l._row})">✏️</button>

        <button class="act-btn" title="Delete" onclick="deleteLead(${l._row})">🗑</button>

      </td>

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

}


function renderAll() { renderStats(); renderTable(); }


// ── UTILS ─────────────────────────────────────

function uid() { return Date.now().toString(36) + Math.random().toString(36).slice(2); }

function today() { return new Date().toLocaleDateString('en-US',{year:'numeric',month:'short',day:'numeric'}); }


let toastTimer;

function showToast(msg) {

  const t = document.getElementById('toast');

  t.textContent = msg;

  t.classList.add('show');

  clearTimeout(toastTimer);

  toastTimer = setTimeout(() => t.classList.remove('show'), 3000);

}


// close modals on overlay click

document.querySelectorAll('.overlay').forEach(el => {

  el.addEventListener('click', e => { if (e.target === el) el.classList.remove('open'); });

});

</script>

</body>

</html>