<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Coarca — Invoice Generator</title>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
<style>
* { box-sizing: border-box; margin: 0; padding: 0; }
body { font-family: 'Inter', sans-serif; background: #f1f5f9; color: #1a1a1a; min-height: 100vh; }

.header {
  background: #1e293b;
  color: #fff;
  padding: 14px 28px;
  display: flex;
  align-items: center;
  gap: 14px;
  position: sticky;
  top: 0;
  z-index: 100;
  box-shadow: 0 2px 8px rgba(0,0,0,.25);
}
.header-logo { font-size: 1.4rem; font-weight: 800; color: #e8640a; letter-spacing: -0.5px; }
.header-sub  { font-size: .75rem; color: #94a3b8; margin-top: 1px; }
.header-right { margin-left: auto; }

.container { max-width: 960px; margin: 28px auto; padding: 0 16px 60px; }

.section-title {
  font-size: .7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .08em;
  color: #e8640a;
  margin: 28px 0 12px;
  display: flex;
  align-items: center;
  gap: 8px;
}
.section-title::after {
  content: '';
  flex: 1;
  height: 1px;
  background: #e2e8f0;
}

.card {
  background: #fff;
  border-radius: 12px;
  padding: 24px;
  box-shadow: 0 1px 3px rgba(0,0,0,.07);
  margin-bottom: 4px;
}

.grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.grid-3 { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 14px; }
.span-2 { grid-column: 1 / -1; }

.field { display: flex; flex-direction: column; gap: 5px; }
label { font-size: .78rem; font-weight: 600; color: #475569; }
input, select, textarea {
  border: 1.5px solid #e2e8f0;
  border-radius: 8px;
  padding: 9px 12px;
  font-size: .88rem;
  font-family: inherit;
  color: #1e293b;
  background: #f8fafc;
  transition: border-color .15s, background .15s;
}
input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: #e8640a;
  background: #fff;
}
input::placeholder, textarea::placeholder { color: #b0bec5; }

/* Services table */
.services-table { width: 100%; border-collapse: collapse; margin-top: 4px; }
.services-table thead th {
  background: #e8640a;
  color: #fff;
  font-size: .75rem;
  font-weight: 700;
  padding: 9px 10px;
  text-align: left;
  text-transform: uppercase;
  letter-spacing: .05em;
}
.services-table thead th:last-child { width: 44px; }
.services-table tbody tr { border-bottom: 1px solid #f1f5f9; }
.services-table tbody td { padding: 6px 4px; vertical-align: middle; }
.services-table tbody td:first-child { padding-left: 0; }
.services-table input {
  border-radius: 6px;
  padding: 7px 10px;
  font-size: .85rem;
  width: 100%;
}
.td-desc  { width: 60%; }
.td-qty   { width: 12%; }
.td-amt   { width: 18%; }
.td-del   { width: 44px; text-align: center; }

.btn-del-row {
  background: none;
  border: none;
  cursor: pointer;
  color: #94a3b8;
  padding: 4px;
  border-radius: 4px;
  transition: color .15s;
  font-size: 1.1rem;
  line-height: 1;
}
.btn-del-row:hover { color: #ef4444; }

.btn-add-row {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-top: 10px;
  background: none;
  border: 1.5px dashed #cbd5e1;
  border-radius: 8px;
  padding: 7px 14px;
  font-size: .82rem;
  font-weight: 500;
  color: #64748b;
  cursor: pointer;
  font-family: inherit;
  transition: all .15s;
}
.btn-add-row:hover { border-color: #e8640a; color: #e8640a; background: #fff5ee; }

/* Total preview */
.total-preview {
  background: #e8640a;
  color: #fff;
  border-radius: 10px;
  padding: 16px 24px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-top: 16px;
}
.total-preview .label { font-size: .8rem; font-weight: 600; opacity: .85; }
.total-preview .amount { font-size: 1.6rem; font-weight: 800; }

/* Submit */
.submit-bar {
  position: fixed;
  bottom: 0; left: 0; right: 0;
  background: #fff;
  border-top: 1px solid #e2e8f0;
  padding: 14px 24px;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 12px;
  z-index: 50;
  box-shadow: 0 -2px 12px rgba(0,0,0,.08);
}
.btn-generate {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: #e8640a;
  color: #fff;
  border: none;
  border-radius: 9px;
  padding: 12px 28px;
  font-size: .92rem;
  font-weight: 700;
  font-family: inherit;
  cursor: pointer;
  transition: background .15s;
}
.btn-generate:hover { background: #cc5508; }
.btn-generate:disabled { background: #f0b07a; cursor: not-allowed; }
.btn-reset {
  background: none;
  border: 1.5px solid #e2e8f0;
  border-radius: 9px;
  padding: 11px 20px;
  font-size: .88rem;
  font-weight: 500;
  color: #64748b;
  cursor: pointer;
  font-family: inherit;
  transition: all .15s;
}
.btn-reset:hover { border-color: #94a3b8; color: #334155; }

.spinner {
  width: 16px; height: 16px;
  border: 2px solid rgba(255,255,255,.4);
  border-top-color: #fff;
  border-radius: 50%;
  animation: spin .7s linear infinite;
  display: none;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* ── Tabs ── */
.tab-bar {
  display: flex;
  gap: 0;
  background: #fff;
  border-radius: 12px 12px 0 0;
  border-bottom: 2px solid #f1f5f9;
  overflow: hidden;
  margin-bottom: 0;
}
.tab-btn {
  flex: 1;
  padding: 14px 20px;
  border: none;
  background: none;
  font-family: inherit;
  font-size: .88rem;
  font-weight: 600;
  color: #94a3b8;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  transition: all .15s;
  border-bottom: 3px solid transparent;
  margin-bottom: -2px;
}
.tab-btn:hover { color: #e8640a; background: #fff8f4; }
.tab-btn.active { color: #e8640a; border-bottom-color: #e8640a; background: #fff; }
.tab-pane { display: none; }
.tab-pane.active { display: block; }

/* ── Quick Paste ── */
.paste-area {
  width: 100%;
  min-height: 220px;
  border: 2px dashed #cbd5e1;
  border-radius: 10px;
  padding: 16px;
  font-size: .88rem;
  font-family: 'Inter', monospace;
  color: #334155;
  background: #f8fafc;
  resize: vertical;
  transition: border-color .15s;
  line-height: 1.6;
}
.paste-area:focus { outline: none; border-color: #e8640a; background: #fff; }

.parse-status {
  display: none;
  margin-top: 12px;
  padding: 10px 14px;
  border-radius: 8px;
  font-size: .83rem;
  align-items: center;
  gap: 8px;
}
.parse-status.ok    { display:flex; background:#f0fdf4; color:#15803d; border:1px solid #bbf7d0; }
.parse-status.error { display:flex; background:#fef2f2; color:#dc2626; border:1px solid #fecaca; }
.parse-status.loading { display:flex; background:#eff6ff; color:#1d4ed8; border:1px solid #bfdbfe; }

.hint-box {
  background: #fff8f4;
  border: 1px solid #fed7aa;
  border-radius: 8px;
  padding: 12px 14px;
  font-size: .8rem;
  color: #92400e;
  margin-bottom: 16px;
  line-height: 1.7;
}
.hint-box strong { color: #c2410c; }

.btn-parse {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: #e8640a;
  color: #fff;
  border: none;
  border-radius: 9px;
  padding: 12px 24px;
  font-size: .9rem;
  font-weight: 700;
  font-family: inherit;
  cursor: pointer;
  transition: background .15s;
  margin-top: 14px;
}
.btn-parse:hover { background: #cc5508; }
.btn-parse:disabled { background: #f0b07a; cursor: not-allowed; }

.spin-sm {
  width:15px;height:15px;
  border:2px solid rgba(255,255,255,.4);
  border-top-color:#fff;
  border-radius:50%;
  animation:spin .7s linear infinite;
  display:none;
}

@media (max-width: 640px) {
  .grid-2, .grid-3 { grid-template-columns: 1fr; }
}
</style>
</head>
<body>

<div class="header">
  <img src="assets/logo.png" height="32" alt="Coarca" style="display:block">
  <div>
    <div style="font-size:.9rem;font-weight:700;">Invoice Generator</div>
    <div class="header-sub">Fill in the fields → Generate PDF</div>
  </div>
</div>

<div class="container">

<!-- TAB BAR -->
<div class="tab-bar">
  <button class="tab-btn active" onclick="switchTab('paste',this)" type="button">
    <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2"><path d="M9 12h6M9 16h6M9 8h6M5 3h14a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z"/></svg>
    Quick Paste
  </button>
  <button class="tab-btn" onclick="switchTab('form',this)" type="button" id="formTabBtn">
    <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2"><rect x="3" y="3" width="18" height="18" rx="2"/><path d="M8 12h8M8 8h8M8 16h5"/></svg>
    Manual Form
  </button>
</div>

<!-- ── TAB 1: QUICK PASTE ── -->
<div id="tab-paste" class="tab-pane active" style="background:#fff;border-radius:0 0 12px 12px;padding:24px;box-shadow:0 1px 3px rgba(0,0,0,.07);margin-bottom:4px;">

  <div class="hint-box">
    <strong>Paste your invoice info in any format.</strong> You can copy from an email, a PDF, a WhatsApp message, or just type it freely.<br>
    Examples: <em>"Invoice 2422, date 04/29/2026, container MRSU6971972, Bill to ILS Cargo..."</em><br>
    For services paste one per line: <em>"Freight + Fuel + 2 Day Chassis  1  $400"</em>
  </div>

  <textarea class="paste-area" id="pasteInput" placeholder="Paste or type invoice info here...
Example:
Invoice #: 2422
Invoice Date: 04/29/2026
Due Date: 05/28/2026
Container #: MRSU6971972
Booking #: 269760392
Reference #: SS0043893
Bill To: ILS CARGO
11459 NW 122nd Street
Miami, FL 33178
Phone: (305) 718-3799
Origin: Florida International Terminal (FIT)
4100 McIntosh Rd., Port Everglades FL 33316
Destination: ILS Cargo, 11459 NW 122nd Street, Miami FL 33178
BOL: 6792-6624  Pickup: 04/28/2026  Delivery: 04/28/2026  Return: 04/29/2026
Size: 40  Type: NOR

Services:
Freight + Fuel + 2 Day Chassis  1  400
Chassis  2  80
Storage  1  50
Missed Trip  1  150
Other  1  50"></textarea>

  <div class="parse-status" id="parseStatus"></div>

  <button type="button" class="btn-parse" id="parseBtn" onclick="parseAndFill()">
    <div class="spin-sm" id="parseSpin"></div>
    <svg id="parseIcon" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><polyline points="13 17 18 12 13 7"/><polyline points="6 17 11 12 6 7"/></svg>
    Auto-fill Form →
  </button>
</div>

<!-- ── TAB 2: MANUAL FORM ── -->
<div id="tab-form" class="tab-pane">
<form id="invoiceForm" action="generate.php" method="post" onsubmit="return false;">

  <!-- INVOICE INFORMATION -->
  <div class="section-title">Invoice Information</div>
  <div class="card">
    <div class="grid-3">
      <div class="field">
        <label>Invoice #</label>
        <input type="text" name="invoice_number" placeholder="2422" required>
      </div>
      <div class="field">
        <label>Invoice Date</label>
        <input type="text" name="invoice_date" placeholder="04/29/2026" required>
      </div>
      <div class="field">
        <label>Due Date</label>
        <input type="text" name="due_date" placeholder="05/28/2026">
      </div>
      <div class="field">
        <label>Container #</label>
        <input type="text" name="container_number" placeholder="MRSU6971972">
      </div>
      <div class="field">
        <label>Booking #</label>
        <input type="text" name="booking_number" placeholder="269760392">
      </div>
      <div class="field">
        <label>Reference #</label>
        <input type="text" name="reference_number" placeholder="SS0043893">
      </div>
    </div>
  </div>

  <!-- BILL TO -->
  <div class="section-title">Bill To</div>
  <div class="card">
    <div class="grid-2">
      <div class="field span-2">
        <label>Company Name</label>
        <input type="text" name="bill_to_name" placeholder="ILS CARGO" required>
      </div>
      <div class="field">
        <label>Address Line 1</label>
        <input type="text" name="bill_to_addr1" placeholder="11459 NW 122nd Street">
      </div>
      <div class="field">
        <label>Address Line 2</label>
        <input type="text" name="bill_to_addr2" placeholder="Miami, FL 33178">
      </div>
      <div class="field">
        <label>Phone</label>
        <input type="text" name="bill_to_phone" placeholder="(305) 718-3799">
      </div>
    </div>
  </div>

  <!-- SHIPMENT + MOVEMENT -->
  <div class="section-title">Shipment &amp; Movement</div>
  <div class="card">
    <div class="grid-3">
      <div class="field">
        <label>Container</label>
        <input type="text" name="container" placeholder="MRSU6971972">
      </div>
      <div class="field">
        <label>Size</label>
        <input type="text" name="size" placeholder="40">
      </div>
      <div class="field">
        <label>Type</label>
        <input type="text" name="type" placeholder="NOR">
      </div>
      <div class="field">
        <label>BOL</label>
        <input type="text" name="bol" placeholder="6792-6624">
      </div>
      <div class="field">
        <label>Pickup Date</label>
        <input type="text" name="pickup_date" placeholder="04/28/2026">
      </div>
      <div class="field">
        <label>Delivery Date</label>
        <input type="text" name="delivery_date" placeholder="04/28/2026">
      </div>
      <div class="field">
        <label>Return Date</label>
        <input type="text" name="return_date" placeholder="04/29/2026">
      </div>
    </div>
  </div>

  <!-- ORIGIN + DESTINATION -->
  <div class="section-title">Origin &amp; Destination</div>
  <div class="card">
    <div class="grid-2">
      <div>
        <div style="font-size:.78rem;font-weight:700;color:#64748b;margin-bottom:10px;text-transform:uppercase;letter-spacing:.05em">Origin</div>
        <div style="display:flex;flex-direction:column;gap:10px;">
          <div class="field"><label>Name / Terminal</label><input type="text" name="origin_name" placeholder="Florida International Terminal (FIT)"></div>
          <div class="field"><label>Address Line 1</label><input type="text" name="origin_addr1" placeholder="4100 McIntosh Rd."></div>
          <div class="field"><label>Address Line 2</label><input type="text" name="origin_addr2" placeholder="Port Everglades, FL 33316"></div>
        </div>
      </div>
      <div>
        <div style="font-size:.78rem;font-weight:700;color:#64748b;margin-bottom:10px;text-transform:uppercase;letter-spacing:.05em">Destination</div>
        <div style="display:flex;flex-direction:column;gap:10px;">
          <div class="field"><label>Name / Company</label><input type="text" name="dest_name" placeholder="ILS Cargo"></div>
          <div class="field"><label>Address Line 1</label><input type="text" name="dest_addr1" placeholder="11459 NW 122nd Street"></div>
          <div class="field"><label>Address Line 2</label><input type="text" name="dest_addr2" placeholder="Miami, FL 33178"></div>
        </div>
      </div>
    </div>
  </div>

  <!-- SERVICE DETAILS -->
  <div class="section-title">Service Details</div>
  <div class="card">
    <table class="services-table">
      <thead>
        <tr>
          <th class="td-desc">Description</th>
          <th class="td-qty">QTY</th>
          <th class="td-amt">Amount ($)</th>
          <th class="td-del"></th>
        </tr>
      </thead>
      <tbody id="servicesBody">
        <!-- rows injected by JS -->
      </tbody>
    </table>

    <button type="button" class="btn-add-row" onclick="addServiceRow()">
      <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>
      Add row
    </button>

    <div class="total-preview">
      <div class="label">TOTAL DUE</div>
      <div class="amount" id="totalPreview">$0.00</div>
    </div>
  </div>

  <!-- NOTES -->
  <div class="section-title">Notes <span style="font-weight:400;color:#94a3b8;text-transform:none;letter-spacing:0">(optional)</span></div>
  <div class="card">
    <textarea name="notes" rows="3" placeholder="Additional comments or instructions..."></textarea>
  </div>

</form>
</div><!-- /tab-form -->

</div><!-- /container -->

<!-- STICKY SUBMIT BAR -->
<div class="submit-bar" id="submitBar" style="display:none;">
  <button type="button" class="btn-reset" onclick="if(confirm('Clear all fields?')) document.getElementById('invoiceForm').reset(); updateTotal();">
    Clear
  </button>
  <button type="button" class="btn-generate" id="submitBtn">
    <div class="spinner" id="spinner"></div>
    <svg id="btnIcon" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/></svg>
    Generate PDF
  </button>
</div>

<script>
// ─── Tab switching ────────────────────────────────────────────────────────────

function switchTab(name, btn) {
  document.querySelectorAll('.tab-pane').forEach(p => p.classList.remove('active'));
  document.querySelectorAll('.tab-btn').forEach(b => b.classList.remove('active'));
  document.getElementById('tab-' + name).classList.add('active');
  btn.classList.add('active');
  // Show submit bar only on form tab
  document.getElementById('submitBar').style.display = name === 'form' ? 'flex' : 'none';
}

// ─── Quick Paste parser ───────────────────────────────────────────────────────

async function parseAndFill() {
  const text = document.getElementById('pasteInput').value.trim();
  if (!text) return;

  const btn  = document.getElementById('parseBtn');
  const spin = document.getElementById('parseSpin');
  const icon = document.getElementById('parseIcon');
  const stat = document.getElementById('parseStatus');

  btn.disabled = true;
  spin.style.display = 'block';
  icon.style.display = 'none';
  stat.className = 'parse-status loading';
  stat.innerHTML = '<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg> Analyzing text...';

  try {
    const fd = new FormData();
    fd.append('text', text);
    const res  = await fetch('api/parse.php', { method: 'POST', body: fd });
    const raw  = await res.text();

    let data;
    try { data = JSON.parse(raw); }
    catch(e) { throw new Error('Server response: ' + raw.substring(0, 200)); }

    if (data.error) throw new Error(data.error);

    fillForm(data);

    stat.className = 'parse-status ok';
    const filled = Object.keys(data).filter(k => k !== 'services' && data[k]).length;
    const svcs   = (data.services || []).length;
    stat.innerHTML = `<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><polyline points="20 6 9 17 4 12"/></svg> ${filled} fields + ${svcs} service rows filled — switching to form...`;

    setTimeout(() => {
      document.getElementById('formTabBtn').click();
      window.scrollTo({ top: 0, behavior: 'smooth' });
    }, 900);

  } catch (err) {
    stat.className = 'parse-status error';
    stat.innerHTML = '⚠ Error: ' + err.message;
  } finally {
    btn.disabled = false;
    spin.style.display = 'none';
    icon.style.display = 'block';
  }
}

function fillForm(data) {
  const set = (name, val) => {
    const el = document.querySelector(`[name="${name}"]`);
    if (el && val) el.value = val;
  };

  set('invoice_number',   data.invoice_number);
  set('invoice_date',     data.invoice_date);
  set('due_date',         data.due_date);
  set('container_number', data.container_number);
  set('booking_number',   data.booking_number);
  set('reference_number', data.reference_number);
  set('bill_to_name',     data.bill_to_name);
  set('bill_to_addr1',    data.bill_to_addr1);
  set('bill_to_addr2',    data.bill_to_addr2);
  set('bill_to_phone',    data.bill_to_phone);
  set('container',        data.container);
  set('size',             data.size);
  set('type',             data.type);
  set('bol',              data.bol);
  set('pickup_date',      data.pickup_date);
  set('delivery_date',    data.delivery_date);
  set('return_date',      data.return_date);
  set('origin_name',      data.origin_name);
  set('origin_addr1',     data.origin_addr1);
  set('origin_addr2',     data.origin_addr2);
  set('dest_name',        data.dest_name);
  set('dest_addr1',       data.dest_addr1);
  set('dest_addr2',       data.dest_addr2);
  set('notes',            data.notes);

  // Services
  if (data.services && data.services.length) {
    document.getElementById('servicesBody').innerHTML = '';
    rowCount = 0;
    data.services.forEach(s => addServiceRow(s.description, s.qty, s.amount));
  }
  updateTotal();
}

// ─── Service rows ─────────────────────────────────────────────────────────────

let rowCount = 0;

function addServiceRow(desc = '', qty = '1', amt = '') {
  const tbody = document.getElementById('servicesBody');
  const id = ++rowCount;
  const tr = document.createElement('tr');
  tr.dataset.row = id;
  tr.innerHTML = `
    <td class="td-desc">
      <input type="text" name="svc_desc[]" value="${esc(desc)}" placeholder="Service description">
    </td>
    <td class="td-qty">
      <input type="number" name="svc_qty[]" value="${esc(qty)}" min="0" step="1" style="text-align:center" oninput="updateTotal()">
    </td>
    <td class="td-amt">
      <input type="number" name="svc_amt[]" value="${esc(amt)}" min="0" step="0.01" placeholder="0.00" oninput="updateTotal()">
    </td>
    <td class="td-del">
      <button type="button" class="btn-del-row" onclick="removeRow(${id})" title="Remove">×</button>
    </td>`;
  tbody.appendChild(tr);
  updateTotal();
}

function removeRow(id) {
  const tr = document.querySelector(`[data-row="${id}"]`);
  if (tr) { tr.remove(); updateTotal(); }
}

function esc(s) {
  return String(s).replace(/"/g, '&quot;').replace(/</g, '&lt;');
}

function updateTotal() {
  let total = 0;
  const rows = document.getElementById('servicesBody').querySelectorAll('tr');
  rows.forEach(tr => {
    const qty = parseFloat(tr.querySelector('[name="svc_qty[]"]')?.value) || 1;
    const amt = parseFloat(tr.querySelector('[name="svc_amt[]"]')?.value) || 0;
    total += qty * amt;
  });
  document.getElementById('totalPreview').textContent =
    '$' + total.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
}

// Default 5 rows
['Freight + Fuel + 2 Day Chassis,1,400',
 'Chassis,2,80',
 'Storage,1,50',
 'Missed Trip,1,150',
 'Other,1,50'].forEach(r => {
  const [d, q, a] = r.split(',');
  addServiceRow(d, q, a);
});

// ─── Generate PDF — Blob download via button click (100% filename control) ───

document.getElementById('submitBtn').addEventListener('click', async function(e) {
  e.preventDefault();
  e.stopPropagation();

  const btn  = this;
  const form = document.getElementById('invoiceForm');
  const spin = document.getElementById('spinner');
  const icon = document.getElementById('btnIcon');

  // Native browser validation
  if (!form.checkValidity()) { form.reportValidity(); return; }

  btn.disabled = true;
  spin.style.display = 'block';
  icon.style.display = 'none';

  try {
    const fd  = new FormData(form);
    const res = await fetch('generate.php', { method: 'POST', body: fd });

    const ct = res.headers.get('content-type') || '';

    if (!ct.includes('application/pdf')) {
      const text = await res.text();
      const msg  = text.match(/<p[^>]*>([^<]+)<\/p>/i)?.[1]
                || text.match(/<h[1-6][^>]*>([^<]+)<\/h[1-6]>/i)?.[1]
                || ('Server error ' + res.status);
      throw new Error(msg);
    }

    const blob    = await res.blob();
    const invNum  = (form.querySelector('[name="invoice_number"]')?.value || '').trim() || 'invoice';
    const dlName  = 'INV # ' + invNum + '.pdf';

    const url = URL.createObjectURL(blob);
    const a   = document.createElement('a');
    a.href     = url;
    a.download = dlName;
    a.style.display = 'none';
    document.body.appendChild(a);
    a.click();
    setTimeout(() => { document.body.removeChild(a); URL.revokeObjectURL(url); }, 2000);

  } catch (err) {
    alert('Error generating PDF:\n' + err.message);
  } finally {
    btn.disabled = false;
    spin.style.display = 'none';
    icon.style.display = 'block';
  }
});
</script>
</body>
</html>
