<?php
require_once 'includes/config.php';
require_once 'includes/functions.php';
requireLogin();

$uid  = $_SESSION['user_id'];
$userQ = $pdo->prepare("SELECT * FROM users WHERE id=?");
$userQ->execute([$uid]);
$user = $userQ->fetch();

require_once 'includes/header.php';
renderHeader('Biometric Login', 'profile');
?>

<style>
@import url('https://fonts.googleapis.com/css2?family=Outfit:wght@400;500;600;700;800;900&family=Plus+Jakarta+Sans:wght@400;500;600;700&display=swap');

:root {
  --bm-font: 'Outfit', sans-serif;
  --bm-body: 'Plus Jakarta Sans', sans-serif;
  --bm-cyan: rgba(6,182,212,1);
  --bm-cyan-soft: rgba(6,182,212,.12);
  --bm-cyan-border: rgba(6,182,212,.28);
}

.bm-wrap {
  font-family: var(--bm-body);
  max-width: 620px;
  margin: 0 auto;
  padding-bottom: 60px;
}

/* ── Back ── */
.bm-back {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  color: var(--text-muted);
  font-size: 13px;
  font-weight: 600;
  text-decoration: none;
  margin-bottom: 26px;
  transition: color .18s;
}
.bm-back:hover { color: var(--text-primary); }

/* ── Hero banner ── */
.bm-hero {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 22px;
  padding: 32px 28px;
  margin-bottom: 20px;
  text-align: center;
  position: relative;
  overflow: hidden;
  animation: bm-rise .4s ease both;
}
.bm-hero::before {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(ellipse at 50% -20%, rgba(6,182,212,.1) 0%, transparent 65%);
  pointer-events: none;
}
.bm-hero-icon {
  width: 76px; height: 76px;
  border-radius: 50%;
  background: var(--bm-cyan-soft);
  border: 2px solid var(--bm-cyan-border);
  display: flex; align-items: center; justify-content: center;
  margin: 0 auto 16px;
  font-size: 34px;
  position: relative;
  z-index: 1;
}
.bm-hero-title {
  font-family: var(--bm-font);
  font-size: 22px; font-weight: 800;
  color: var(--text-primary);
  letter-spacing: -.3px;
  margin-bottom: 8px;
  position: relative; z-index: 1;
}
.bm-hero-desc {
  font-size: 14px;
  color: var(--text-muted);
  line-height: 1.7;
  max-width: 400px;
  margin: 0 auto;
  position: relative; z-index: 1;
}

/* ── How it works chips ── */
.bm-how-row {
  display: flex;
  gap: 10px;
  justify-content: center;
  flex-wrap: wrap;
  margin-top: 20px;
  position: relative; z-index: 1;
}
.bm-how-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: var(--bg-secondary);
  border: 1px solid var(--border);
  border-radius: 99px;
  padding: 5px 13px;
  font-size: 12px; font-weight: 600;
  color: var(--text-muted);
}

/* ── Not supported banner ── */
.bm-unsupported {
  background: rgba(245,158,11,.06);
  border: 1px solid rgba(245,158,11,.22);
  border-radius: 16px;
  padding: 18px 20px;
  display: flex; align-items: flex-start; gap: 12px;
  margin-bottom: 20px;
  display: none;
  animation: bm-rise .4s ease both;
}
.bm-unsupported-icon { font-size: 22px; flex-shrink: 0; margin-top: 1px; }
.bm-unsupported-title { font-size: 14px; font-weight: 700; color: #fbbf24; margin-bottom: 3px; }
.bm-unsupported-desc  { font-size: 13px; color: var(--text-muted); line-height: 1.6; }

/* ── Card ── */
.bm-card {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 18px;
  padding: 22px 24px;
  margin-bottom: 16px;
  animation: bm-rise .4s .06s ease both;
}
.bm-card-hd {
  display: flex; align-items: center; gap: 10px;
  margin-bottom: 18px;
}
.bm-card-icon {
  width: 36px; height: 36px;
  border-radius: 10px;
  background: var(--bm-cyan-soft);
  display: flex; align-items: center; justify-content: center;
  font-size: 17px; flex-shrink: 0;
}
.bm-card-title {
  font-family: var(--bm-font);
  font-size: 15px; font-weight: 700;
  color: var(--text-primary);
}
.bm-card-sub { font-size: 12px; color: var(--text-muted); margin-top: 2px; }

/* ── Device list ── */
.bm-device-list { margin-bottom: 6px; }
.bm-device-empty {
  text-align: center;
  padding: 24px 16px;
  color: var(--text-muted);
  font-size: 13px;
}
.bm-device-empty-icon { font-size: 32px; margin-bottom: 8px; opacity: .5; }

.bm-device-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 13px 15px;
  background: var(--bg-secondary);
  border: 1px solid var(--border);
  border-radius: 13px;
  margin-bottom: 8px;
  transition: border-color .18s;
}
.bm-device-item:hover { border-color: var(--bm-cyan-border); }
.bm-device-left { display: flex; align-items: center; gap: 13px; }
.bm-device-emoji {
  width: 40px; height: 40px;
  border-radius: 10px;
  background: var(--bm-cyan-soft);
  border: 1px solid var(--bm-cyan-border);
  display: flex; align-items: center; justify-content: center;
  font-size: 19px; flex-shrink: 0;
}
.bm-device-name  { font-size: 14px; font-weight: 700; color: var(--text-primary); }
.bm-device-meta  { font-size: 11px; color: var(--text-muted); margin-top: 2px; }
.bm-device-badge {
  display: inline-flex; align-items: center; gap: 4px;
  background: rgba(16,185,129,.1);
  border: 1px solid rgba(16,185,129,.25);
  border-radius: 99px;
  padding: 2px 8px;
  font-size: 10px; font-weight: 700;
  color: #10b981;
  margin-left: 6px;
  vertical-align: middle;
}
.bm-remove-btn {
  flex-shrink: 0;
  width: 34px; height: 34px;
  border-radius: 9px;
  background: rgba(239,68,68,.08);
  border: 1px solid rgba(239,68,68,.18);
  color: #ef4444;
  font-size: 15px;
  cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  transition: background .18s, border-color .18s, transform .12s;
}
.bm-remove-btn:hover {
  background: rgba(239,68,68,.18);
  border-color: rgba(239,68,68,.4);
  transform: scale(1.08);
}
.bm-remove-btn:disabled { opacity: .45; cursor: not-allowed; transform: none; }

/* ── Add device form ── */
.bm-add-card {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 18px;
  padding: 22px 24px;
  margin-bottom: 16px;
  animation: bm-rise .4s .1s ease both;
}
.bm-add-inner {
  background: var(--bg-secondary);
  border: 1px dashed var(--bm-cyan-border);
  border-radius: 14px;
  padding: 20px;
}
.bm-add-title {
  font-family: var(--bm-font);
  font-size: 14px; font-weight: 700;
  color: var(--text-primary);
  margin-bottom: 14px;
}
.bm-add-row {
  display: flex; gap: 10px; align-items: flex-end; flex-wrap: wrap;
}
.bm-add-input-wrap { flex: 1; min-width: 160px; }
.bm-add-label {
  display: block;
  font-size: 11px; font-weight: 700;
  color: var(--text-muted);
  text-transform: uppercase; letter-spacing: .7px;
  margin-bottom: 7px;
}
.bm-register-btn {
  padding: 12px 22px;
  background: linear-gradient(135deg, rgba(6,182,212,.15), rgba(6,182,212,.08));
  border: 1.5px solid var(--bm-cyan-border);
  border-radius: 12px;
  color: var(--bm-cyan);
  font-family: var(--bm-body);
  font-size: 14px; font-weight: 700;
  cursor: pointer;
  white-space: nowrap;
  display: flex; align-items: center; gap: 7px;
  transition: background .18s, border-color .18s, transform .12s;
}
.bm-register-btn:hover {
  background: linear-gradient(135deg, rgba(6,182,212,.25), rgba(6,182,212,.15));
  border-color: var(--bm-cyan);
  transform: translateY(-1px);
}
.bm-register-btn:disabled { opacity: .5; cursor: not-allowed; transform: none; }

/* ── Toast popup ── */
#bmToastContainer {
  position: fixed;
  top: 20px;
  right: 20px;
  z-index: 99999;
  display: flex;
  flex-direction: column;
  gap: 10px;
  pointer-events: none;
}
.bm-toast {
  display: flex;
  align-items: flex-start;
  gap: 11px;
  min-width: 280px;
  max-width: 360px;
  padding: 14px 16px;
  border-radius: 14px;
  font-family: var(--bm-body);
  font-size: 13px;
  font-weight: 600;
  line-height: 1.5;
  pointer-events: all;
  cursor: pointer;
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  box-shadow: 0 8px 32px rgba(0,0,0,.35), 0 2px 8px rgba(0,0,0,.2);
  animation: bm-toast-in .32s cubic-bezier(.34,1.56,.64,1) both;
  position: relative;
  overflow: hidden;
}
.bm-toast.success {
  background: rgba(16,185,129,.15);
  border: 1px solid rgba(16,185,129,.35);
  color: #6ee7b7;
}
.bm-toast.error {
  background: rgba(239,68,68,.15);
  border: 1px solid rgba(239,68,68,.35);
  color: #fca5a5;
}
.bm-toast-icon { font-size: 18px; flex-shrink: 0; margin-top: 1px; }
.bm-toast-body { flex: 1; }
.bm-toast-title { font-size: 13px; font-weight: 700; margin-bottom: 1px; color: inherit; }
.bm-toast-msg   { font-size: 12px; font-weight: 500; opacity: .85; }
.bm-toast-close {
  flex-shrink: 0;
  width: 20px; height: 20px;
  border-radius: 6px;
  background: rgba(255,255,255,.08);
  border: none;
  color: inherit;
  font-size: 13px;
  cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  opacity: .7;
  transition: opacity .15s, background .15s;
  padding: 0;
}
.bm-toast-close:hover { opacity: 1; background: rgba(255,255,255,.15); }
/* Progress bar */
.bm-toast-bar {
  position: absolute;
  bottom: 0; left: 0;
  height: 3px;
  border-radius: 0 0 0 14px;
  animation: bm-toast-bar linear forwards;
}
.bm-toast.success .bm-toast-bar { background: #10b981; }
.bm-toast.error   .bm-toast-bar { background: #ef4444; }
/* Leaving */
.bm-toast.leaving {
  animation: bm-toast-out .25s ease forwards;
}
@keyframes bm-toast-in {
  from { opacity: 0; transform: translateX(60px) scale(.92); }
  to   { opacity: 1; transform: translateX(0) scale(1); }
}
@keyframes bm-toast-out {
  from { opacity: 1; transform: translateX(0) scale(1);   max-height: 120px; margin-bottom: 0; }
  to   { opacity: 0; transform: translateX(60px) scale(.92); max-height: 0;   margin-bottom: -10px; }
}
@keyframes bm-toast-bar {
  from { width: 100%; }
  to   { width: 0%; }
}
@media(max-width:480px){
  #bmToastContainer { top: auto; bottom: 20px; right: 12px; left: 12px; }
  .bm-toast { min-width: unset; max-width: unset; width: 100%; }
}

/* ── Info tips ── */
.bm-tips-card {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 18px;
  padding: 20px 22px;
  animation: bm-rise .4s .14s ease both;
}
.bm-tips-hd {
  font-family: var(--bm-font);
  font-size: 13px; font-weight: 700;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: .6px;
  margin-bottom: 14px;
}
.bm-tip-item {
  display: flex; gap: 11px;
  padding: 10px 0;
  border-bottom: 1px solid var(--border);
  font-size: 13px;
  color: var(--text-muted);
  line-height: 1.6;
}
.bm-tip-item:last-child { border-bottom: none; padding-bottom: 0; }
.bm-tip-icon { font-size: 16px; flex-shrink: 0; margin-top: 1px; }

/* ── Scanning pulse animation ── */
@keyframes bm-pulse {
  0%,100% { box-shadow: 0 0 0 0 rgba(6,182,212,.5); }
  50%      { box-shadow: 0 0 0 12px rgba(6,182,212,0); }
}
.bm-scanning { animation: bm-pulse 1.2s ease infinite; }

/* ── Loading skeleton ── */
.bm-skeleton {
  background: linear-gradient(90deg, var(--bg-secondary) 25%, var(--border) 50%, var(--bg-secondary) 75%);
  background-size: 200% 100%;
  animation: bm-shimmer 1.4s infinite;
  border-radius: 10px;
  height: 60px;
  margin-bottom: 8px;
}
@keyframes bm-shimmer {
  0%   { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}

/* ── Rise animation ── */
@keyframes bm-rise {
  from { opacity:0; transform:translateY(14px); }
  to   { opacity:1; transform:translateY(0); }
}
</style>

<div class="bm-wrap">

  <!-- Back -->
  <a href="javascript:history.back()" class="bm-back">
    <svg width="16" height="16" fill="none" stroke="currentColor" stroke-width="2.5" viewBox="0 0 24 24">
      <path d="M19 12H5M12 5l-7 7 7 7"/>
    </svg>
    Back
  </a>

  <!-- Hero -->
  <div class="bm-hero">
    <div class="bm-hero-icon" id="heroIcon">🔐</div>
    <div class="bm-hero-title">Biometric Login (Passkeys)</div>
    <div class="bm-hero-desc">
      Sign in faster and more securely using your fingerprint, face ID, or device PIN — no password needed.
    </div>
    <div class="bm-how-row">
      <span class="bm-how-chip">👆 Fingerprint</span>
      <span class="bm-how-chip">👤 Face ID</span>
      <span class="bm-how-chip">🔑 Device PIN</span>
      <span class="bm-how-chip">⚡ Instant Login</span>
    </div>
  </div>

  <!-- Not Supported -->
  <div class="bm-unsupported" id="bmUnsupported">
    <div class="bm-unsupported-icon">⚠️</div>
    <div>
      <div class="bm-unsupported-title">Biometric Login Not Supported</div>
      <div class="bm-unsupported-desc">
        Your browser or device doesn't support WebAuthn / Passkeys.
        Try using Chrome, Safari, or Edge on a device with a fingerprint reader or Face ID.
      </div>
    </div>
  </div>

  <!-- Supported section -->
  <div id="bmSupported" style="display:none">

    <!-- Alert handled by toast popup -->

    <!-- Registered Devices -->
    <div class="bm-card">
      <div class="bm-card-hd">
        <div class="bm-card-icon">🛡️</div>
        <div>
          <div class="bm-card-title">Registered Devices</div>
          <div class="bm-card-sub">Devices you can use to sign in biometrically</div>
        </div>
      </div>
      <div class="bm-device-list" id="bmDeviceList">
        <!-- skeleton -->
        <div class="bm-skeleton"></div>
        <div class="bm-skeleton" style="width:75%;height:60px"></div>
      </div>
    </div>

    <!-- Add New Device -->
    <div class="bm-add-card">
      <div class="bm-card-hd">
        <div class="bm-card-icon">➕</div>
        <div>
          <div class="bm-card-title">Add New Device</div>
          <div class="bm-card-sub">Register your current device for biometric login</div>
        </div>
      </div>
      <div class="bm-add-inner">
        <div class="bm-add-title">Device Name <span style="font-weight:400;color:var(--text-muted)">(optional)</span></div>
        <div class="bm-add-row">
          <div class="bm-add-input-wrap">
            <input type="text" id="bmDeviceName" class="form-control"
                   placeholder="e.g. My iPhone, Work Laptop, Tablet">
          </div>
          <button id="bmRegisterBtn" onclick="bmRegister()" class="bm-register-btn">
            <svg width="16" height="16" fill="none" stroke="currentColor" stroke-width="2.2" viewBox="0 0 24 24">
              <rect x="3" y="11" width="18" height="11" rx="2"/><path d="M7 11V7a5 5 0 0110 0v4"/>
            </svg>
            Register This Device
          </button>
        </div>
        <div style="margin-top:12px;font-size:12px;color:var(--text-muted);display:flex;align-items:center;gap:6px">
          <svg width="13" height="13" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/></svg>
          Your browser will prompt you to verify your identity using your device's biometric sensor.
        </div>
      </div>
    </div>

    <!-- Tips -->
    <div class="bm-tips-card">
      <div class="bm-tips-hd">💡 How Passkeys Work</div>
      <div class="bm-tip-item">
        <span class="bm-tip-icon">🔒</span>
        <span>Your biometric data <strong style="color:var(--text-primary)">never leaves your device</strong>. StudyTrack only stores a cryptographic key, not your fingerprint or face data.</span>
      </div>
      <div class="bm-tip-item">
        <span class="bm-tip-icon">📱</span>
        <span>You can register multiple devices — your phone, laptop, tablet — and switch between them freely.</span>
      </div>
      <div class="bm-tip-item">
        <span class="bm-tip-icon">🗑️</span>
        <span>Removing a device here won't affect your other registered devices. You can always add it back later.</span>
      </div>
      <div class="bm-tip-item">
        <span class="bm-tip-icon">🌐</span>
        <span>Works best on Chrome, Safari, Edge, and Firefox on modern devices with fingerprint or face sensors.</span>
      </div>
    </div>

  </div><!-- /#bmSupported -->

</div><!-- /.bm-wrap -->

<!-- Toast container -->
<div id="bmToastContainer"></div>

<script>
(function () {
  'use strict';

  const WEBAUTHN_URL = '<?= SITE_URL ?>/webauthn';

  // ── Base64 helpers ─────────────────────────────────────────────
  function b64d(str) {
    str = str.replace(/-/g, '+').replace(/_/g, '/');
    while (str.length % 4) str += '=';
    return Uint8Array.from(atob(str), c => c.charCodeAt(0));
  }
  function b64e(buf) {
    const b = new Uint8Array(buf);
    let s = '';
    b.forEach(x => s += String.fromCharCode(x));
    return btoa(s).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
  }

  // ── Toast popup ───────────────────────────────────────────────
  function showAlert(msg, type = 'error') {
    const container = document.getElementById('bmToastContainer');
    const duration  = type === 'success' ? 4000 : 6000;

    const icons = { success: '✅', error: '⚠️' };
    const titles = { success: 'Success', error: 'Error' };

    const toast = document.createElement('div');
    toast.className = 'bm-toast ' + type;
    toast.innerHTML = `
      <div class="bm-toast-icon">${icons[type]}</div>
      <div class="bm-toast-body">
        <div class="bm-toast-title">${titles[type]}</div>
        <div class="bm-toast-msg">${msg}</div>
      </div>
      <button class="bm-toast-close" aria-label="Close">✕</button>
      <div class="bm-toast-bar" style="animation-duration:${duration}ms"></div>
    `;

    // Close on click
    function dismiss() {
      if (toast.classList.contains('leaving')) return;
      toast.classList.add('leaving');
      setTimeout(() => toast.remove(), 260);
    }
    toast.addEventListener('click', dismiss);
    toast.querySelector('.bm-toast-close').addEventListener('click', e => { e.stopPropagation(); dismiss(); });

    container.appendChild(toast);
    setTimeout(dismiss, duration);
  }

  // ── Device emoji by name ───────────────────────────────────────
  function deviceEmoji(name) {
    const n = (name || '').toLowerCase();
    if (n.includes('iphone'))  return '📱';
    if (n.includes('ipad'))    return '📟';
    if (n.includes('android')) return '📱';
    if (n.includes('mac'))     return '💻';
    if (n.includes('windows') || n.includes('pc') || n.includes('laptop')) return '💻';
    if (n.includes('tablet'))  return '📟';
    return '🔐';
  }

  // ── Load registered devices ────────────────────────────────────
  async function loadDevices() {
    try {
      const res  = await fetch(WEBAUTHN_URL + '?action=list-credentials');
      const data = await res.json();
      const list = document.getElementById('bmDeviceList');

      if (!data.credentials || data.credentials.length === 0) {
        list.innerHTML = `
          <div class="bm-device-empty">
            <div class="bm-device-empty-icon">🔐</div>
            No biometric devices registered yet.<br>
            <span style="font-size:12px">Add your first device below ↓</span>
          </div>`;
        return;
      }

      let html = '';
      data.credentials.forEach((cr, idx) => {
        const added = new Date(cr.created_at).toLocaleDateString('en-GB', { day:'numeric', month:'short', year:'numeric' });
        const used  = cr.last_used_at
          ? new Date(cr.last_used_at).toLocaleDateString('en-GB', { day:'numeric', month:'short', year:'numeric' })
          : 'Never';
        const isRecent = cr.last_used_at && (Date.now() - new Date(cr.last_used_at)) < 7 * 86400000;
        html += `
          <div class="bm-device-item" id="bmDevice_${cr.id}">
            <div class="bm-device-left">
              <div class="bm-device-emoji">${deviceEmoji(cr.device_name)}</div>
              <div>
                <div class="bm-device-name">
                  ${htmlEsc(cr.device_name)}
                  ${isRecent ? '<span class="bm-device-badge">● Recently used</span>' : ''}
                </div>
                <div class="bm-device-meta">Added: ${added} &nbsp;·&nbsp; Last used: ${used}</div>
              </div>
            </div>
            <button class="bm-remove-btn" onclick="bmRemove(${cr.id},this)" title="Remove this device">
              <svg width="14" height="14" fill="none" stroke="currentColor" stroke-width="2.5" viewBox="0 0 24 24">
                <polyline points="3 6 5 6 21 6"/>
                <path d="M19 6l-1 14a2 2 0 01-2 2H8a2 2 0 01-2-2L5 6"/>
                <path d="M10 11v6M14 11v6"/>
              </svg>
            </button>
          </div>`;
      });
      list.innerHTML = html;
    } catch (e) {
      console.error('Load devices error:', e);
      document.getElementById('bmDeviceList').innerHTML =
        '<div style="font-size:13px;color:var(--text-muted);padding:10px">Could not load devices. Please refresh.</div>';
    }
  }

  // ── Remove device ──────────────────────────────────────────────
  window.bmRemove = async function (id, btn) {
    if (!(await stConfirm('Remove this biometric device? You can always add it back later.'))) return;
    btn.disabled = true;
    btn.innerHTML = '<span class="spinner" style="width:14px;height:14px"></span>';
    try {
      const fd = new FormData();
      fd.append('action', 'remove-credential');
      fd.append('id', id);
      const res  = await fetch(WEBAUTHN_URL, { method: 'POST', body: fd });
      const data = await res.json();
      if (data.success) {
        const el = document.getElementById('bmDevice_' + id);
        if (el) { el.style.transition='opacity .3s,transform .3s'; el.style.opacity='0'; el.style.transform='translateX(20px)'; setTimeout(()=>el.remove(),320); }
        showAlert(data.message, 'success');
        setTimeout(loadDevices, 400);
      } else {
        showAlert(data.message || 'Could not remove device.');
        btn.disabled = false;
        btn.innerHTML = '<svg width="14" height="14" fill="none" stroke="currentColor" stroke-width="2.5" viewBox="0 0 24 24"><polyline points="3 6 5 6 21 6"/><path d="M19 6l-1 14a2 2 0 01-2 2H8a2 2 0 01-2-2L5 6"/><path d="M10 11v6M14 11v6"/></svg>';
      }
    } catch (e) {
      showAlert('Connection error. Please try again.');
      btn.disabled = false;
    }
  };

  // ── Register device ────────────────────────────────────────────
  window.bmRegister = async function () {
    const btn = document.getElementById('bmRegisterBtn');
    const dn  = document.getElementById('bmDeviceName').value.trim() || detectDevice();

    btn.disabled = true;
    btn.innerHTML = '<span class="spinner" style="width:14px;height:14px"></span> Waiting for sensor…';

    // Pulse the hero icon
    const hero = document.getElementById('heroIcon');
    hero.classList.add('bm-scanning');

    try {
      // Step 1: Get options
      const fd = new FormData();
      fd.append('action', 'get-register-options');
      const optRes = await fetch(WEBAUTHN_URL, { method: 'POST', body: fd });
      const options = await optRes.json();
      if (!options.success) throw new Error(options.message || 'Could not get registration options');

      // Step 2: Create credential
      const credential = await navigator.credentials.create({
        publicKey: {
          challenge:               b64d(options.challenge),
          rp:                      options.rp,
          user:                    { id: b64d(options.user.id), name: options.user.name, displayName: options.user.displayName },
          pubKeyCredParams:        options.pubKeyCredParams,
          authenticatorSelection:  options.authenticatorSelection,
          timeout:                 options.timeout,
          attestation:             options.attestation,
          excludeCredentials:      (options.excludeCredentials || []).map(c => ({ id: b64d(c.id), type: c.type })),
        }
      });

      btn.innerHTML = '<span class="spinner" style="width:14px;height:14px"></span> Registering…';

      // Step 3: Verify
      const payload = {
        id:                b64e(credential.rawId),
        clientDataJSON:    b64e(credential.response.clientDataJSON),
        attestationObject: b64e(credential.response.attestationObject),
        deviceName:        dn,
      };
      const verRes = await fetch(WEBAUTHN_URL + '?action=verify-register', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(payload),
      });
      const result = await verRes.json();

      if (result.success) {
        showAlert(result.message || 'Device registered successfully! 🎉', 'success');
        document.getElementById('bmDeviceName').value = '';
        loadDevices();
      } else {
        throw new Error(result.message || 'Registration failed');
      }
    } catch (err) {
      if      (err.name === 'NotAllowedError')   showAlert('Biometric prompt was cancelled or timed out. Please try again.');
      else if (err.name === 'InvalidStateError') showAlert('This device is already registered.');
      else if (err.name === 'NotSupportedError') showAlert('Your device doesn\'t support the requested authenticator type.');
      else showAlert(err.message || 'Registration failed. Please try again.');
    } finally {
      btn.disabled = false;
      btn.innerHTML = `<svg width="16" height="16" fill="none" stroke="currentColor" stroke-width="2.2" viewBox="0 0 24 24"><rect x="3" y="11" width="18" height="11" rx="2"/><path d="M7 11V7a5 5 0 0110 0v4"/></svg> Register This Device`;
      hero.classList.remove('bm-scanning');
    }
  };

  // ── Detect device name ─────────────────────────────────────────
  function detectDevice() {
    const ua = navigator.userAgent;
    if (/iPhone/.test(ua))       return 'iPhone';
    if (/iPad/.test(ua))         return 'iPad';
    if (/Android/.test(ua))      return 'Android Device';
    if (/Mac OS X/.test(ua))     return 'Mac';
    if (/Windows/.test(ua))      return 'Windows PC';
    if (/Linux/.test(ua))        return 'Linux Device';
    return 'My Device';
  }

  // ── HTML escape ────────────────────────────────────────────────
  function htmlEsc(str) {
    return String(str)
      .replace(/&/g, '&amp;').replace(/</g, '&lt;')
      .replace(/>/g, '&gt;').replace(/"/g, '&quot;');
  }

  // ── Check WebAuthn support ─────────────────────────────────────
  async function init() {
    if (!window.PublicKeyCredential) {
      document.getElementById('bmUnsupported').style.display = 'flex';
      return;
    }
    try {
      const avail = await PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable();
      if (avail) {
        document.getElementById('bmSupported').style.display = 'block';
        loadDevices();
        // Pre-fill device name
        document.getElementById('bmDeviceName').placeholder = detectDevice() + ' (detected)';
      } else {
        document.getElementById('bmUnsupported').style.display = 'flex';
      }
    } catch (e) {
      document.getElementById('bmUnsupported').style.display = 'flex';
    }
  }

  init();
})();
</script>

<?php require_once 'includes/footer.php'; renderFooter(); ?>