async function api(endpoint, method = 'GET', data = null) {
  const opts = {
    method,
    headers: { 'Content-Type': 'application/json', 'X-Requested-With': 'XMLHttpRequest' },
    credentials: 'same-origin',
  };
  if (data) opts.body = JSON.stringify(data);
  let res;
  try {
    res = await fetch(endpoint, opts);
  } catch (networkErr) {
    // True network failure (no connection, DNS failure, etc.)
    throw new Error('Network unavailable \u2014 please check your connection and try again.');
  }
  // Handle session expiry gracefully
  if (res.status === 401) {
    showToast('Your session has expired. Redirecting to login\u2026', 'warning');
    setTimeout(() => { window.location.href = '/login.php'; }, 2000);
    throw new Error('Session expired \u2014 please log in again');
  }
  if (!res.ok) {
    const err = await res.json().catch(() => ({ error: 'Server error (' + res.status + ')' }));
    throw new Error(err.error || 'Request failed (' + res.status + ')');
  }
  return res.json().catch(() => {
    throw new Error('Invalid server response \u2014 please try again.');
