// assets/js/app.js — WebGIS Bansos (Versi Lengkap — Fixed)

const App = (() => {
  /* ══════════════════════════════════════════════════
     STATE
  ══════════════════════════════════════════════════ */
  let map;
  let activeRadiusCircle = null, activeRadiusIbadahId = null;
  let radiusMeters = 500;
  let addMode = null, tempMarker = null;
  let ibadahMarkers = {}, wargaMarkers = {};
  let ibadahData = [], wargaData = [];
  let ibadahLayerGroup, wargaLayerGroup;
  let anggotaRows = [];
  let currentUser = null;

  async function checkAuthStatus() {
    try {
      const res = await fetch('api/auth.php?action=status');
      const json = await res.json();
      if (json.success && json.logged_in) {
        currentUser = json.user;
        updateUserUI();

        // Auto-switch to overview for admin/petugas if they are on default tab
        const activeTab = document.querySelector('.tab-btn.active')?.dataset.tab;
        if (['admin', 'petugas'].includes(currentUser.role) && activeTab === 'ibadah') {
          const overviewBtn = document.querySelector('.tab-btn[data-tab="overview"]');
          if (overviewBtn) overviewBtn.click();
        }
      } else {
        currentUser = null;
        updateUserUI();
      }
      applyRoleUI();

      if (window.FiturBaru && FiturBaru.Kebutuhan && typeof FiturBaru.Kebutuhan.load === 'function') {
        FiturBaru.Kebutuhan.load();
      }

      if (window.FiturBaru && FiturBaru.Laporan && typeof FiturBaru.Laporan.loadList === 'function' && currentUser) {
        FiturBaru.Laporan.loadList();
      }

      // Force refresh Kebutuhan tab if it's currently showing when auth status changes
      if (window.FiturBaru && FiturBaru.Kebutuhan && typeof FiturBaru.Kebutuhan.refreshIfActive === 'function') {
        FiturBaru.Kebutuhan.refreshIfActive();
      }
    } catch (e) {
      console.error('Error checking auth status:', e);
      currentUser = null;
      updateUserUI();
      applyRoleUI();
    }
  }

  function updateUserUI() {
    const avatar = document.getElementById('user-avatar');
    const nameEl = document.getElementById('user-display-name');
    const roleEl = document.getElementById('user-display-role');
    const btnToggle = document.getElementById('btn-auth-toggle');

    if (currentUser) {
      if (avatar) {
        avatar.textContent = currentUser.username.charAt(0).toUpperCase();
        avatar.className = 'user-avatar';
      }
      if (nameEl) nameEl.textContent = currentUser.username;
      if (roleEl) {
        roleEl.textContent = currentUser.role.toUpperCase();
        roleEl.className = 'user-role-badge badge-' + currentUser.role;
      }
      if (btnToggle) btnToggle.textContent = 'Logout';
    } else {
      if (avatar) {
        avatar.textContent = 'G';
        avatar.className = 'user-avatar avatar-guest';
      }
      if (nameEl) nameEl.textContent = 'Guest Mode';
      if (roleEl) {
        roleEl.textContent = 'Pengunjung';
        roleEl.className = 'user-role-badge badge-guest';
      }
      if (btnToggle) btnToggle.textContent = 'Login';
    }
  }

  function applyRoleUI() {
    const role = currentUser ? currentUser.role : 'guest';

    // Tab buttons
    const btnOverview = document.querySelector('.tab-btn[data-tab="overview"]');
    const btnIbadah = document.getElementById('tab-btn-ibadah');
    const btnWarga = document.getElementById('tab-btn-warga');
    const btnKebutuhan = document.getElementById('tab-btn-kebutuhan');
    const btnLaporan = document.getElementById('tab-btn-laporan');

    if (btnOverview) btnOverview.style.display = (role !== 'guest' && role !== 'kontributor') ? '' : 'none';
    if (btnIbadah) btnIbadah.style.display = ['admin', 'petugas', 'koordinator', 'kontributor', 'guest'].includes(role) ? '' : 'none';
    if (btnWarga) btnWarga.style.display = ['admin', 'petugas', 'koordinator'].includes(role) ? '' : 'none';
    if (btnLaporan) btnLaporan.style.display = role !== 'guest' ? '' : 'none';

    // Kebutuhan tab: explicit rule so changes to guest handling don't remove kontributor access
    const kebutuhanAllowed = ['admin', 'koordinator', 'kontributor', 'guest'];
    if (btnKebutuhan) btnKebutuhan.style.display = kebutuhanAllowed.includes(role) ? '' : 'none';

    // If currently selected tab is hidden, switch to a visible one
    const activeTabBtn = document.querySelector('.tab-btn.active');
    if (activeTabBtn && activeTabBtn.style.display === 'none') {
      const fallbackTab = (role === 'guest' || role === 'kontributor') ? 'ibadah' : 'overview';
      const fallbackBtn = document.querySelector(`.tab-btn[data-tab="${fallbackTab}"]`);
      if (fallbackBtn) fallbackBtn.click();
    }

    // Add buttons
    const btnAddIbadah = document.getElementById('btn-add-ibadah');
    const btnAddWarga = document.getElementById('btn-add-warga');

    if (btnAddIbadah) btnAddIbadah.style.display = role === 'admin' ? '' : 'none';
    if (btnAddWarga) btnAddWarga.style.display = ['admin', 'koordinator'].includes(role) ? '' : 'none';

    // Advanced Features inside Overview
    const advancedCards = document.querySelectorAll('.ekon-card');
    advancedCards.forEach(card => {
      const onclickAttr = card.getAttribute('onclick') || '';
      if (onclickAttr.includes('Redistribusi')) {
        card.style.display = role === 'admin' ? 'flex' : 'none';
      } else if (onclickAttr.includes('Verifikasi')) {
        card.style.display = ['admin', 'petugas'].includes(role) ? 'flex' : 'none';
      } else if (onclickAttr.includes('Kemandirian')) {
        card.style.display = ['admin', 'petugas'].includes(role) ? 'flex' : 'none';
      }
    });

    // Hide admin-only Overview sections for koordinator & petugas (Ekonomi & Kependudukan, Kontrol Radius)
    if (['koordinator', 'petugas'].includes(role)) {
      document.querySelectorAll('.section-title').forEach(el => {
        const txt = (el.textContent || '').trim();
        if (txt.includes('Ekonomi & Kependudukan') || txt.includes('Kontrol Radius')) {
          el.style.display = 'none';
          const next = el.nextElementSibling;
          if (next) next.style.display = 'none';
        }
      });
    } else {
      // ensure visibility for non-koordinator/petugas roles
      document.querySelectorAll('.section-title').forEach(el => {
        const txt = (el.textContent || '').trim();
        if (txt.includes('Ekonomi & Kependudukan') || txt.includes('Kontrol Radius')) {
          el.style.display = '';
          const next = el.nextElementSibling;
          if (next) next.style.display = '';
        }
      });
    }

    // Hide Verifikasi Konfigurasi for non-admins
    const verifTabKonfig = document.querySelector('[data-fbtab="konfig"]');
    if (verifTabKonfig) {
      verifTabKonfig.style.display = role === 'admin' ? '' : 'none';
      if (role !== 'admin' && verifTabKonfig.classList.contains('active')) {
        const verifTabList = document.querySelector('[data-fbtab="list"]');
        if (verifTabList) window.switchFbTab(verifTabList, 'verifikasi');
      }
    }
  }

  function showAuthModal(intendedAction) {
    sessionStorage.setItem('intendedAction', JSON.stringify(intendedAction));
    document.getElementById('modal-login').classList.add('show');
  }

  async function handleRegister() {
    const username = document.getElementById('register-username').value.trim();
    const email = document.getElementById('register-email').value.trim();
    const password = document.getElementById('register-password').value.trim();
    const phone = document.getElementById('register-phone')?.value.trim() || '';
    const role = document.getElementById('register-role').value;
    const rumahIbadahSelect = document.getElementById('register-rumah-ibadah');
    const rumahIbadahId = rumahIbadahSelect && rumahIbadahSelect.value ? parseInt(rumahIbadahSelect.value) : null;
    const errorEl = document.getElementById('register-error-msg');

    if (!username || !email || !password || !phone || !role) {
      if (errorEl) { errorEl.textContent = 'Semua field wajib diisi.'; errorEl.style.display = 'block'; }
      return;
    }
    if (password.length < 6) {
      if (errorEl) { errorEl.textContent = 'Password minimal 6 karakter.'; errorEl.style.display = 'block'; }
      return;
    }

    const payload = { username, email, password, no_telp: phone, role };
    if (role === 'koordinator' && rumahIbadahId) payload.rumah_ibadah_id = rumahIbadahId;

    try {
      const res = await fetch('api/auth.php?action=register', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(payload)
      });
      const json = await res.json();
      if (json.success) {
        if (errorEl) errorEl.style.display = 'none';
        showToast(json.message, 'success');
        // Auto login after registration
        document.getElementById('login-username').value = username;
        document.getElementById('login-password').value = password;
        await handleLogin();
      } else {
        if (errorEl) { errorEl.textContent = json.message || 'Registrasi gagal.'; errorEl.style.display = 'block'; }
      }
    } catch (e) {
      if (errorEl) { errorEl.textContent = 'Kesalahan jaringan.'; errorEl.style.display = 'block'; }
    }
  }

  // Populate rumah ibadah dropdown for koordinator registration
  async function loadRumahIbadahOptions() {
    const select = document.getElementById('register-rumah-ibadah');
    if (!select) return;
    try {
      const res = await fetch('api/rumah_ibadah.php');
      const json = await res.json();
      if (!json.success) return;
      const data = json.data || [];
      // Clear existing options except placeholder
      select.innerHTML = '<option value="">-- Pilih Rumah Ibadah --</option>';
      data.forEach(item => {
        const opt = document.createElement('option');
        opt.value = item.id;
        opt.textContent = item.nama;
        select.appendChild(opt);
      });
    } catch (e) { console.error('Failed load rumah ibadah options', e); }
  }

  // Toggle register/login forms
  function toggleToRegister() {
    document.getElementById('login-form-container').style.display = 'none';
    document.getElementById('register-form-container').style.display = 'block';
    document.getElementById('btn-login-submit').style.display = 'none';
    document.getElementById('btn-register-submit').style.display = 'inline-block';
    loadRumahIbadahOptions();
  }
  function toggleToLogin() {
    document.getElementById('login-form-container').style.display = 'block';
    document.getElementById('register-form-container').style.display = 'none';
    document.getElementById('btn-login-submit').style.display = 'inline-block';
    document.getElementById('btn-register-submit').style.display = 'none';
  }

  // Show/hide rumah ibadah selector based on role
  function handleRoleChange() {
    const role = document.getElementById('register-role').value;
    const group = document.getElementById('register-rumah-ibadah-group');
    if (group) group.style.display = role === 'koordinator' ? 'block' : 'none';
  }

  // Event listeners registration
  document.addEventListener('DOMContentLoaded', () => {
    const linkReg = document.getElementById('link-show-register');
    if (linkReg) linkReg.addEventListener('click', e => { e.preventDefault(); toggleToRegister(); });
    const linkLogin = document.getElementById('link-show-login');
    if (linkLogin) linkLogin.addEventListener('click', e => { e.preventDefault(); toggleToLogin(); });
    const roleSelect = document.getElementById('register-role');
    if (roleSelect) roleSelect.addEventListener('change', handleRoleChange);
    const btnReg = document.getElementById('btn-register-submit');
    if (btnReg) btnReg.addEventListener('click', e => { e.preventDefault(); handleRegister(); });
  });

  function checkAuth(intendedAction, callback) {
    if (currentUser) {
      callback();
    } else {
      showAuthModal(intendedAction);
    }
  }

  async function handleLogin() {
    const userVal = document.getElementById('login-username').value.trim();
    const passVal = document.getElementById('login-password').value.trim();
    const errorEl = document.getElementById('login-error-msg');

    if (!userVal || !passVal) {
      if (errorEl) {
        errorEl.textContent = 'Username dan password wajib diisi!';
        errorEl.style.display = 'block';
      }
      return;
    }

    try {
      const res = await fetch('api/auth.php?action=login', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ username: userVal, password: passVal })
      });
      const json = await res.json();
      if (json.success) {
        if (errorEl) errorEl.style.display = 'none';
        showToast(json.message, 'success');
        document.getElementById('modal-login').classList.remove('show');

        document.getElementById('login-username').value = '';
        document.getElementById('login-password').value = '';

        await checkAuthStatus();
        await loadAllData();

        const intended = sessionStorage.getItem('intendedAction');
        if (intended) {
          sessionStorage.removeItem('intendedAction');
          const action = JSON.parse(intended);
          executeIntendedAction(action);
        }
      } else {
        if (errorEl) {
          errorEl.textContent = json.message || 'Login gagal!';
          errorEl.style.display = 'block';
        }
      }
    } catch (e) {
      if (errorEl) {
        errorEl.textContent = 'Terjadi kesalahan server saat login.';
        errorEl.style.display = 'block';
      }
    }
  }

  async function handleLogout() {
    // Show custom logout confirmation modal (browser confirm() often gets blocked)
    document.getElementById('modal-logout-confirm')?.classList.add('show');
  }

  async function doLogout() {
    document.getElementById('modal-logout-confirm')?.classList.remove('show');
    try {
      const res = await fetch('api/auth.php?action=logout', { method: 'POST' });
      const json = await res.json();
      if (json.success) {
        showToast(json.message, 'info');
        currentUser = null;
        updateUserUI();
        applyRoleUI();
        clearRadius(); // Bersihkan radius dan data highlight saat logout
        await loadAllData();
        if (window.FiturBaru && FiturBaru.Kebutuhan && typeof FiturBaru.Kebutuhan.load === 'function') {
          FiturBaru.Kebutuhan.load();
        }
        // Force refresh Kebutuhan tab if it's currently showing
        if (window.FiturBaru && FiturBaru.Kebutuhan && typeof FiturBaru.Kebutuhan.refreshIfActive === 'function') {
          FiturBaru.Kebutuhan.refreshIfActive();
        }
        // Switch to ibadah tab for guest
        const overviewBtn = document.querySelector('.tab-btn[data-tab="overview"]');
        if (overviewBtn) overviewBtn.style.display = 'none';
        const wargaBtn = document.getElementById('tab-btn-warga');
        if (wargaBtn) wargaBtn.style.display = 'none';
        const ibadahBtn = document.querySelector('.tab-btn[data-tab="ibadah"]');
        if (ibadahBtn) ibadahBtn.click();
      }
    } catch (e) {
      showToast('Gagal logout', 'error');
    }
  }

  function executeIntendedAction(action) {
    if (!action) return;
    if (action.type === 'add_ibadah') {
      setAddMode('ibadah');
      showToast('Klik peta untuk menentukan lokasi Rumah Ibadah', 'info');
    } else if (action.type === 'add_warga') {
      setAddMode('warga');
      showToast('Klik peta untuk menentukan lokasi Rumah Warga', 'info');
    } else if (action.type === 'edit_ibadah') {
      editIbadah(action.id);
    } else if (action.type === 'edit_warga') {
      editWarga(action.id);
    } else if (action.type === 'delete_ibadah') {
      deleteIbadah(action.id);
    } else if (action.type === 'delete_warga') {
      deleteWarga(action.id);
    } else if (action.type === 'donate') {
      if (window.FiturBaru && FiturBaru.Kebutuhan && typeof FiturBaru.Kebutuhan.openDonationModal === 'function') {
        FiturBaru.Kebutuhan.openDonationModal(action.kebutuhan_id, action.sisa, action.jenis, action.ibadah_nama);
      }
    }
  }

  /* ══════════════════════════════════════════════════
     SVG LIBRARY
  ══════════════════════════════════════════════════ */
  const SVG = {
    mosque: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 22V11c0-3.31 3.58-6 8-6s8 2.69 8 6v11"/><path d="M2 22h20"/><path d="M12 5V3"/><path d="M8 22v-4a4 4 0 0 1 8 0v4"/></svg>`,
    church: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M18 22V11l-6-6-6 6v11"/><path d="M2 22h20"/><line x1="12" y1="5" x2="12" y2="2"/><line x1="10" y1="3.5" x2="14" y2="3.5"/></svg>`,
    temple: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M3 22h18"/><path d="M6 18V9l6-6 6 6v9"/><path d="M4 14h16"/><path d="M4 18h16"/></svg>`,
    star: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"/></svg>`,
    wheel: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><circle cx="12" cy="12" r="10"/><circle cx="12" cy="12" r="3"/><line x1="12" y1="2" x2="12" y2="9"/><line x1="12" y1="15" x2="12" y2="22"/><line x1="2" y1="12" x2="9" y2="12"/><line x1="15" y1="12" x2="22" y2="12"/></svg>`,
    building: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><rect x="3" y="3" width="18" height="18" rx="2"/><path d="M9 22V12h6v10"/></svg>`,
    home: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/><polyline points="9 22 9 12 15 12 15 22"/></svg>`,
    users: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M23 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></svg>`,
    pin: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M21 10c0 7-9 13-9 13S3 17 3 10a9 9 0 0 1 18 0z"/><circle cx="12" cy="10" r="3"/></svg>`,
    check: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><polyline points="20 6 9 17 4 12"/></svg>`,
    x: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>`,
    info: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><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>`,
    edit: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/><path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"/></svg>`,
    trash: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><polyline points="3 6 5 6 21 6"/><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v2"/></svg>`,
    gift: `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><polyline points="20 12 20 22 4 22 4 12"/><rect x="2" y="7" width="20" height="5"/><path d="M12 22V7"/><path d="M12 7H7.5a2.5 2.5 0 0 1 0-5C11 2 12 7 12 7z"/><path d="M12 7h4.5a2.5 2.5 0 0 0 0-5C13 2 12 7 12 7z"/></svg>`,
  };

  const JENIS_CONFIG = {
    masjid: { svgKey: 'mosque', label: 'Masjid' },
    gereja: { svgKey: 'church', label: 'Gereja' },
    klenteng: { svgKey: 'temple', label: 'Klenteng' },
    pura: { svgKey: 'star', label: 'Pura' },
    vihara: { svgKey: 'wheel', label: 'Vihara' },
    lainnya: { svgKey: 'building', label: 'Lainnya' },
  };

  const KATEGORI_CONFIG = {
    sangat_miskin: { label: 'Sangat Kurang Mampu', color: '#f87171', badgeCls: 'badge-sangat-miskin' },
    miskin: { label: 'Kurang Mampu', color: '#6366f1', badgeCls: 'badge-miskin' },
    rentan_miskin: { label: 'Rentan Kurang Mampu', color: '#fbbf24', badgeCls: 'badge-rentan-miskin' },
  };

  const STATUS_CONFIG = {
    belum_terima: { label: 'Belum Terima', cls: 'badge-belum-terima' },
    sudah_terima: { label: 'Sudah Terima', cls: 'badge-sudah-terima' },
    sedang_proses: { label: 'Sedang Proses', cls: 'badge-sedang-proses' },
  };

  const REK_CONFIG = {
    bantuan_rutin: { label: 'Bantuan Rutin', cls: 'badge-bantuan-rutin', boxCls: 'rutin', desc: 'Keluarga ini memerlukan bantuan sosial rutin (sembako, tunai, dll) karena tidak memiliki anggota produktif yang mampu bekerja.' },
    bantuan_pelatihan: { label: 'Bantuan Pelatihan', cls: 'badge-bantuan-pelatihan', boxCls: 'pelatihan', desc: 'Terdapat anggota keluarga usia produktif yang belum bekerja tetap. Direkomendasikan pelatihan keterampilan atau program pemberdayaan.' },
    keduanya: { label: 'Rutin + Pelatihan', cls: 'badge-keduanya', boxCls: 'keduanya', desc: 'Keluarga ini memerlukan bantuan rutin sekaligus ada potensi pemberdayaan melalui pelatihan kerja.' },
    tidak_ada: { label: 'Tidak Diperlukan', cls: 'badge-tidak-ada', boxCls: 'tidak-ada', desc: 'Kondisi keluarga sudah cukup mandiri. Tidak ada rekomendasi bantuan khusus saat ini.' },
  };

  /* ══════════════════════════════════════════════════
     HELPER FUNCTIONS
  ══════════════════════════════════════════════════ */
  function panToPoint(lat, lng, minZoom = 15) {
    const cur = map.getZoom();
    const z = Math.max(cur, minZoom);
    if (cur === z) map.panTo([lat, lng], { animate: true, duration: 0.5 });
    else map.flyTo([lat, lng], z, { duration: 0.6 });
  }

  function haversine(lat1, lng1, lat2, lng2) {
    const R = 6371000;
    const dLat = (lat2 - lat1) * Math.PI / 180;
    const dLng = (lng2 - lng1) * Math.PI / 180;
    const a = Math.sin(dLat / 2) ** 2 + Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) * Math.sin(dLng / 2) ** 2;
    return R * 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
  }

  function hitungUsia(tglLahir) {
    if (!tglLahir) return null;
    const lahir = new Date(tglLahir);
    const today = new Date();
    let usia = today.getFullYear() - lahir.getFullYear();
    const m = today.getMonth() - lahir.getMonth();
    if (m < 0 || (m === 0 && today.getDate() < lahir.getDate())) usia--;
    return usia;
  }

  function rekomendasiLocal(anggotaList, penghasilan, statusPekerjaan) {
    let adaProd = false, adaProdBisa = false, semuaProdTakBisa = true;
    anggotaList.forEach(a => {
      const usia = hitungUsia(a.tanggal_lahir);
      if (usia !== null && usia >= 18 && usia <= 55) {
        adaProd = true;
        const bisaKerja = parseInt(a.dapat_bekerja) === 1 && ['sehat', 'sakit_ringan'].includes(a.kondisi_kesehatan);
        if (bisaKerja) semuaProdTakBisa = false;
        if (bisaKerja && a.status_bekerja !== 'bekerja') adaProdBisa = true;
      }
    });
    const perluRutin = !adaProd || (adaProd && semuaProdTakBisa) || parseFloat(penghasilan) < 500000 || statusPekerjaan === 'tidak_bekerja';
    const perluPelatihan = adaProdBisa;
    if (perluRutin && perluPelatihan) return 'keduanya';
    if (perluRutin) return 'bantuan_rutin';
    if (perluPelatihan) return 'bantuan_pelatihan';
    return 'tidak_ada';
  }

  function formatRupiah(n) {
    return 'Rp ' + parseInt(n || 0).toLocaleString('id-ID');
  }

  function svgIcon(key, w = 14, h = 14) {
    return SVG[key]?.replace('<svg', `<svg width="${w}" height="${h}"`) || '';
  }

  /* ══════════════════════════════════════════════════
     INIT MAP
  ══════════════════════════════════════════════════ */
  function initMap() {
    map = L.map('map', { zoomControl: false }).setView([-0.0263, 109.3425], 14);
    L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { maxZoom: 19, attribution: '© OpenStreetMap' }).addTo(map);
    ibadahLayerGroup = L.layerGroup().addTo(map);
    wargaLayerGroup = L.layerGroup().addTo(map);
    map.on('click', onMapClick);
    loadAllData();
  }

  /* ══════════════════════════════════════════════════
     LOAD DATA
  ══════════════════════════════════════════════════ */
  async function loadAllData() {
    const role = currentUser ? currentUser.role : 'guest';
    const promises = [loadIbadah()];

    if (['admin', 'petugas', 'koordinator', 'kontributor', 'guest'].includes(role)) {
      promises.push(loadWarga());
    } else {
      wargaData = [];
      renderWargaMarkers();
      renderWargaList();
    }

    try {
      await Promise.all(promises);
      loadStats();

      // Terbang otomatis ke rumah ibadah koordinator saat login/muat data
      if (currentUser?.role === 'koordinator' && currentUser.rumah_ibadah_id) {
        flyToIbadah(currentUser.rumah_ibadah_id);
      }
    } catch (e) {
      console.error('Error in loadAllData:', e);
    }
  }

  async function loadIbadah() {
    try {
      const res = await fetch('api/rumah_ibadah.php');
      const text = await res.text();
      let json;
      try { json = JSON.parse(text); } catch (e) { throw new Error('Invalid JSON response'); }
      if (!res.ok || !json.success) {
        throw new Error(json.message || 'HTTP ' + res.status);
      }
      ibadahData = json.data || [];
      renderIbadahMarkers();
      renderIbadahList();
    } catch (err) {
      console.error('loadIbadah error:', err);
      showToast(err.message || 'Gagal memuat data rumah ibadah', 'error');
    }
  }

  async function loadWarga() {
    try {
      const res = await fetch('api/rumah_warga.php');
      const text = await res.text();
      let json;
      try { json = JSON.parse(text); } catch (e) { throw new Error('Invalid JSON response'); }
      if (!res.ok || !json.success) {
        throw new Error(json.message || 'HTTP ' + res.status);
      }
      wargaData = json.data || [];
      renderWargaMarkers();
      renderWargaList();
    } catch (err) {
      console.error('loadWarga error:', err);
      showToast(err.message || 'Gagal memuat data rumah warga', 'error');
    }
  }

  async function loadStats() {
    try {
      const res = await fetch('api/statistik.php');
      const text = await res.text();
      let json;
      try { json = JSON.parse(text); } catch (e) { throw new Error('Invalid JSON response'); }
      if (!res.ok || !json.success) {
        showToast(json.message || 'Gagal memuat statistik', 'error');
        return;
      }
      const d = json.data;

      const set = (id, val) => { const el = document.getElementById(id); if (el) el.textContent = val; };

      set('stat-ibadah', d.total_ibadah || 0);
      set('stat-warga', d.total_warga || 0);
      set('stat-jiwa', d.total_jiwa || 0);
      set('stat-bansos', d.status_bansos?.sudah_terima || 0);

      const rutin = (d.rekomendasi_bantuan?.bantuan_rutin || 0) + (d.rekomendasi_bantuan?.keduanya || 0);
      const pelatihan = (d.rekomendasi_bantuan?.bantuan_pelatihan || 0) + (d.rekomendasi_bantuan?.keduanya || 0);
      set('stat-rutin', rutin);
      set('stat-pelatihan', pelatihan);

      // Field baru dari statistik.php
      const avgPh = parseInt(d.rata_penghasilan || 0);
      set('stat-avg-penghasilan', 'Rp ' + avgPh.toLocaleString('id-ID'));
      set('stat-anggota-db', (d.total_anggota_db || 0) + ' jiwa');

    } catch { /* silent */ }
  }

  /* ══════════════════════════════════════════════════
     MARKERS IBADAH
  ══════════════════════════════════════════════════ */
  function renderIbadahMarkers() {
    ibadahLayerGroup.clearLayers();
    ibadahMarkers = {};
    ibadahData.forEach(d => {
      const cfg = JENIS_CONFIG[d.jenis] || JENIS_CONFIG.lainnya;
      const icon = L.divIcon({
        className: '',
        html: `<div style="width:38px;height:38px;border-radius:10px;background:#fff;border:1.5px solid #e2e8f0;display:flex;align-items:center;justify-content:center;color:#64748b;box-shadow:0 2px 8px rgba(0,0,0,0.12);cursor:pointer;">${svgIcon(cfg.svgKey, 18, 18)}</div>`,
        iconSize: [38, 38], iconAnchor: [19, 19],
      });

      const marker = L.marker([d.latitude, d.longitude], { icon, draggable: true })
        .on('click', () => { if (!addMode) onIbadahClick(d, marker); })
        .on('dragend', async e => {
          const { lat, lng } = e.target.getLatLng();
          d.latitude = lat; d.longitude = lng;
          const res = await fetch('api/rumah_ibadah.php', {
            method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({
              id: d.id, nama: d.nama, jenis: d.jenis,
              penanggung_jawab: d.penanggung_jawab, kontak: d.kontak,
              alamat: d.alamat, kelurahan: d.kelurahan, kecamatan: d.kecamatan, kota: d.kota,
              keterangan: d.keterangan,
              kapasitas_kk: d.kapasitas_kk ?? 20,
              radius_primer: d.radius_primer ?? 500,
              anggaran_bulanan: d.anggaran_bulanan ?? 0,
              latitude: lat, longitude: lng
            })
          });
          const json = await res.json();
          if (json.success) {
            showToast('Koordinat diperbarui', 'success');
            await loadIbadah();
          } else {
            showToast('Gagal menyimpan koordinat', 'error');
          }
          if (activeRadiusIbadahId == d.id) { activeRadiusCircle.setLatLng([lat, lng]); refreshRadiusIfActive(); }
        });

      ibadahLayerGroup.addLayer(marker);
      ibadahMarkers[d.id] = marker;
    });
  }

  /* ══════════════════════════════════════════════════
     MARKERS WARGA
  ══════════════════════════════════════════════════ */
  function renderWargaMarkers(highlightIds = new Set()) {
    wargaLayerGroup.clearLayers();
    wargaMarkers = {};
    const isKontributor = currentUser && currentUser.role === 'kontributor';
    const canDrag = currentUser && ['admin', 'petugas'].includes(currentUser.role);
    const visibleWarga = getWargaForRole();
    visibleWarga.forEach(d => {
      const inRadius = highlightIds.has(parseInt(d.id));
      const cfg = KATEGORI_CONFIG[d.kategori_kemiskinan] || KATEGORI_CONFIG.miskin;
      let markerColor;
      if (inRadius) {
        markerColor = (d.status_bantuan === 'sudah_terima') ? '#10b981' : '#ef4444';
      } else {
        markerColor = cfg.color;
      }

      let htmlContent = '';
      let iconSize = [13, 13];
      let iconAnchor = [6.5, 6.5];

      if (inRadius) {
        iconSize = [28, 28];
        iconAnchor = [14, 28];
        const pulse = isKontributor ? `<div style="position:absolute;bottom:0;left:50%;transform:translate(-50%, 50%);width:14px;height:14px;border-radius:50%;border:1.5px dashed ${markerColor};opacity:0.5;animation:pulse-ring 2.5s infinite;"></div>` : '';
        htmlContent = `
          <div style="position:relative; width:28px; height:28px; display:flex; justify-content:center; align-items:flex-end; cursor:pointer;">
            ${pulse}
            <svg viewBox="0 0 24 24" width="28" height="28" fill="${markerColor}" stroke="#ffffff" stroke-width="1.5" style="filter: drop-shadow(0px 3px 4px rgba(0,0,0,0.3)); z-index:2; position:relative;">
              <path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"></path>
              <circle cx="12" cy="10" r="3.5" fill="#ffffff" stroke="none"></circle>
            </svg>
          </div>
        `;
      } else {
        const size = 13;
        const shadow = '0 2px 6px rgba(0,0,0,0.2)';
        const pulse = isKontributor ? `<div style="position:absolute;top:-3px;left:-3px;width:${size + 6}px;height:${size + 6}px;border-radius:50%;border:1.5px dashed ${markerColor};opacity:0.45;animation:pulse-ring 2.5s ease-out infinite;"></div>` : '';
        htmlContent = `
          <div style="position:relative;width:${size}px;height:${size}px;">
            ${pulse}
            <div style="width:${size}px;height:${size}px;border-radius:50%;background:${markerColor};border:2px solid ${markerColor};box-shadow:${shadow};cursor:pointer;transition:all 0.25s;"></div>
          </div>
        `;
      }

      const icon = L.divIcon({
        className: '',
        html: htmlContent,
        iconSize: iconSize,
        iconAnchor: iconAnchor,
      });

      const marker = L.marker([d.latitude, d.longitude], { icon, draggable: canDrag })
        .on('click', () => { if (!addMode) onWargaClick(d); });

      // Only attach drag handler for roles that can edit
      if (canDrag) {
        marker.on('dragend', async e => {
          const { lat, lng } = e.target.getLatLng();
          d.latitude = lat; d.longitude = lng;
          const resW = await fetch('api/rumah_warga.php', {
            method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({
              id: d.id, no_kk: d.no_kk, nama_kepala_keluarga: d.nama_kepala_keluarga, nik: d.nik,
              alamat: d.alamat, kelurahan: d.kelurahan, kecamatan: d.kecamatan, kota: d.kota,
              jumlah_tanggungan: d.jumlah_tanggungan, penghasilan_bulanan: d.penghasilan_bulanan,
              pekerjaan: d.pekerjaan, status_pekerjaan: d.status_pekerjaan,
              luas_rumah: d.luas_rumah, jenis_lantai: d.jenis_lantai, jenis_dinding: d.jenis_dinding,
              sumber_air: d.sumber_air, status_tempat_tinggal: d.status_tempat_tinggal,
              kategori_kemiskinan: d.is_kategori_manual ? d.kategori_kemiskinan : 'sistem',
              status_bantuan: d.status_bantuan,
              rekomendasi_bantuan: d.is_rekomendasi_manual ? d.rekomendasi_bantuan : 'sistem',
              keterangan: d.keterangan,
              latitude: lat, longitude: lng
            })
          });
          const jsonW = await resW.json();
          if (jsonW.success) {
            showToast('Koordinat diperbarui', 'success');
            await loadWarga();
          } else {
            showToast('Gagal menyimpan koordinat', 'error');
          }
          refreshRadiusIfActive();
        });
      }

      // Tooltip for kontributor: location indicator only
      if (isKontributor) {
        marker.bindTooltip('📍 Lokasi Penerima Manfaat', {
          direction: 'top', offset: [0, -8], opacity: 0.9,
          className: 'kontributor-tooltip'
        });
      }

      wargaLayerGroup.addLayer(marker);
      wargaMarkers[d.id] = marker;
    });
  }

  /* ══════════════════════════════════════════════════
     CLICK HANDLERS
  ══════════════════════════════════════════════════ */
  function onIbadahClick(d, marker) {
    if (addMode) return;
    drawRadius(d, marker);
    showInfoIbadah(d);
    panToPoint(d.latitude, d.longitude, 15);
  }

  async function onWargaClick(d) {
    if (addMode) return;
    await showInfoWarga(d);
    panToPoint(d.latitude, d.longitude, 16);
  }

  /* ══════════════════════════════════════════════════
     RADIUS
  ══════════════════════════════════════════════════ */
  function drawRadius(ibadah, marker) {
    if (activeRadiusCircle) map.removeLayer(activeRadiusCircle);
    activeRadiusCircle = L.circle([ibadah.latitude, ibadah.longitude], {
      radius: radiusMeters, color: '#6366f1', fillColor: '#6366f1',
      fillOpacity: 0.07, weight: 1.5, dashArray: '6 4',
    }).addTo(map);
    activeRadiusIbadahId = ibadah.id;
    refreshRadiusData(ibadah);
  }

  function getWargaInRadius(ibadahId, lat, lng, r) {
    return getWargaForRole().filter(w => {
      const kelolaId = w.dikelola_oleh_ibadah_id ? parseInt(w.dikelola_oleh_ibadah_id) : null;
      if (kelolaId) {
        // Jika ada penugasan eksplisit, tampilkan jika dia milik ibadah ini
        return kelolaId === parseInt(ibadahId);
      } else {
        // Jika belum ada penugasan, cek radius Haversine
        return haversine(lat, lng, parseFloat(w.latitude), parseFloat(w.longitude)) <= r;
      }
    });
  }

  function getWargaForRole() {
    if (currentUser?.role === 'koordinator' && currentUser.rumah_ibadah_id) {
      const myId = parseInt(currentUser.rumah_ibadah_id);
      const myIbadah = ibadahData.find(x => parseInt(x.id) === myId);
      if (myIbadah) {
        return wargaData.filter(w => {
          const kelolaId = w.dikelola_oleh_ibadah_id ? parseInt(w.dikelola_oleh_ibadah_id) : null;
          if (kelolaId) {
            return kelolaId === myId;
          } else {
            return haversine(parseFloat(myIbadah.latitude), parseFloat(myIbadah.longitude), parseFloat(w.latitude), parseFloat(w.longitude)) <= radiusMeters;
          }
        });
      }
      return [];
    }
    return wargaData;
  }

  function refreshRadiusData(ibadah) {
    const inRadius = getWargaInRadius(ibadah.id, ibadah.latitude, ibadah.longitude, radiusMeters);
    const ids = new Set(inRadius.map(m => parseInt(m.id)));
    renderWargaMarkers(ids);
    showRadiusInfo(ibadah.nama, radiusMeters, inRadius.length);
    if (currentUser?.role === 'koordinator') {
      renderWargaList();
    }
  }

  function refreshRadiusIfActive() {
    if (currentUser?.role === 'koordinator' && currentUser.rumah_ibadah_id) {
      if (activeRadiusCircle) {
        activeRadiusCircle.setRadius(radiusMeters);
      }
      const ibadah = ibadahData.find(d => parseInt(d.id) === parseInt(currentUser.rumah_ibadah_id));
      if (ibadah) {
        refreshRadiusData(ibadah);
      }
      return;
    }

    if (!activeRadiusCircle || !activeRadiusIbadahId) return;
    const ibadah = ibadahData.find(d => parseInt(d.id) === parseInt(activeRadiusIbadahId));
    if (!ibadah) return;
    activeRadiusCircle.setRadius(radiusMeters);
    refreshRadiusData(ibadah);
  }

  function clearRadius() {
    if (activeRadiusCircle) { map.removeLayer(activeRadiusCircle); activeRadiusCircle = null; }
    activeRadiusIbadahId = null;
    renderWargaMarkers(new Set());
    hideRadiusInfo();
  }

  function showRadiusInfo(nama, r, count) {
    const bar = document.getElementById('radius-info');
    bar.querySelector('.ri-val').textContent = r >= 1000 ? (r / 1000).toFixed(1) + ' km' : r + ' m';
    bar.querySelector('.ri-count').textContent = count + ' rumah';
    bar.classList.add('show');
  }
  function hideRadiusInfo() { document.getElementById('radius-info').classList.remove('show'); }

  /* ══════════════════════════════════════════════════
     RADIUS CONTROL
  ══════════════════════════════════════════════════ */
  function initRadiusControl() {
    const slider = document.getElementById('radius-slider');
    const display = document.getElementById('radius-display');
    const input = document.getElementById('radius-input');

    const updateGrad = () => {
      const pct = (radiusMeters - slider.min) / (slider.max - slider.min) * 100;
      slider.style.background = `linear-gradient(to right,#6366f1 0%,#6366f1 ${pct}%,#e2e8f0 ${pct}%)`;
    };

    slider.addEventListener('input', () => {
      radiusMeters = parseInt(slider.value);
      display.textContent = radiusMeters >= 1000 ? (radiusMeters / 1000).toFixed(1) + ' km' : radiusMeters + ' m';
      input.value = radiusMeters;
      updateGrad();
      refreshRadiusIfActive();
    });

    input.addEventListener('change', () => {
      radiusMeters = Math.max(50, Math.min(5000, parseInt(input.value) || 500));
      slider.value = radiusMeters;
      slider.dispatchEvent(new Event('input'));
    });

    document.querySelectorAll('.preset-btn').forEach(btn => {
      btn.addEventListener('click', () => {
        document.querySelectorAll('.preset-btn').forEach(b => b.classList.remove('active'));
        btn.classList.add('active');
        radiusMeters = parseInt(btn.dataset.r);
        slider.value = radiusMeters;
        slider.dispatchEvent(new Event('input'));
      });
    });

    updateGrad();
  }

  /* ══════════════════════════════════════════════════
     INFO PANEL
  ══════════════════════════════════════════════════ */
  function showInfoIbadah(d) {
    const cfg = JENIS_CONFIG[d.jenis] || JENIS_CONFIG.lainnya;
    const panel = document.getElementById('info-panel');
    const header = document.getElementById('info-panel-title');
    const body = document.getElementById('info-panel-body');

    header.innerHTML = `<div class="info-title-icon">${svgIcon(cfg.svgKey, 14, 14)}</div><span>${d.nama}</span>`;
    body.innerHTML = `
      <div class="address-box"><span class="addr-icon">${svgIcon('pin', 11, 11)}</span><span id="info-address">Memuat alamat...</span></div>
      <div class="info-row"><span class="info-key">Jenis</span><span class="info-val">${cfg.label}</span></div>
      ${d.penanggung_jawab ? `<div class="info-row"><span class="info-key">Penanggung Jwb</span><span class="info-val">${d.penanggung_jawab}</span></div>` : ''}
      ${d.kontak ? `<div class="info-row"><span class="info-key">Kontak</span><span class="info-val">${d.kontak}</span></div>` : ''}
      ${d.kelurahan ? `<div class="info-row"><span class="info-key">Kelurahan</span><span class="info-val">${d.kelurahan}</span></div>` : ''}
      ${d.kecamatan ? `<div class="info-row"><span class="info-key">Kecamatan</span><span class="info-val">${d.kecamatan}</span></div>` : ''}
      ${d.kota ? `<div class="info-row"><span class="info-key">Kota</span><span class="info-val">${d.kota}</span></div>` : ''}
      ${d.keterangan ? `<div class="info-row"><span class="info-key">Ket.</span><span class="info-val">${d.keterangan}</span></div>` : ''}
      <div class="info-coords">${parseFloat(d.latitude).toFixed(6)}, ${parseFloat(d.longitude).toFixed(6)}</div>
      ${(currentUser && currentUser.role === 'admin') ? `
      <div style="display:flex;gap:6px;margin-top:10px">
        <button class="btn btn-primary btn-sm" style="flex:1" onclick="App.editIbadah(${d.id})">${svgIcon('edit', 12, 12)} Edit</button>
        <button class="btn btn-danger btn-sm" onclick="App.deleteIbadah(${d.id})">${svgIcon('trash', 12, 12)}</button>
      </div>` : ''}`;

    panel.classList.add('show');
    reverseGeocode(d.latitude, d.longitude, addr => { const el = document.getElementById('info-address'); if (el) el.textContent = addr; });
  }

  async function showInfoWarga(d) {
    const isKoor = currentUser && currentUser.role === 'koordinator';
    const isKontributor = currentUser && currentUser.role === 'kontributor';
    const isGuest = !currentUser;
    const cat = d.kategori_kemiskinan ? (KATEGORI_CONFIG[d.kategori_kemiskinan] || KATEGORI_CONFIG.miskin) : null;
    const sts = STATUS_CONFIG[d.status_bantuan] || STATUS_CONFIG.belum_terima;
    const rek = REK_CONFIG[d.rekomendasi_bantuan] || REK_CONFIG.tidak_ada;
    const panel = document.getElementById('info-panel');
    const header = document.getElementById('info-panel-title');
    const body = document.getElementById('info-panel-body');

    if (isKontributor || isGuest) {
      const title = isGuest ? 'Lokasi Penerima Manfaat' : 'Rumah Penerima Manfaat';
      header.innerHTML = `<div class="info-title-icon">${svgIcon('home', 14, 14)}</div><span>${title}</span>`;

      let htmlContent = `
        <div class="address-box"><span class="addr-icon">${svgIcon('pin', 11, 11)}</span><span id="info-address">Memuat alamat...</span></div>
        <div class="info-row"><span class="info-key">Kategori</span><span class="info-val"><span class="badge ${cat ? cat.badgeCls : 'badge-miskin'}">${cat ? cat.label : 'Kurang Mampu'}</span></span></div>
        <div class="info-row"><span class="info-key">Status Bansos</span><span class="info-val"><span class="badge ${sts.cls}">${sts.label}</span></span></div>
        <div class="info-coords">${parseFloat(d.latitude).toFixed(6)}, ${parseFloat(d.longitude).toFixed(6)}</div>
        
        <div style="margin-top: 15px; padding: 12px; border-radius: 8px; background: rgba(99, 102, 241, 0.08); border: 1px solid rgba(99, 102, 241, 0.15); display: flex; flex-direction: column; gap: 6px;">
          <div style="display: flex; align-items: center; gap: 8px; font-weight: 600; color: #4f46e5; font-size: 12px;">
            <span>🔒</span> Privasi Terjaga
          </div>
          <div style="font-size: 11px; color: #4b5563; line-height: 1.4;">
            Detail informasi pribadi warga disembunyikan untuk menjaga privasi penerima manfaat.
          </div>
        </div>
      `;

      if (isKontributor) {
        htmlContent += `
          <button class="btn-laporkan" onclick="FiturBaru.Laporan.bukaModalLaporan(${d.id}, '${d.nama_kepala_keluarga ? d.nama_kepala_keluarga.replace(/'/g, "\\'") : 'Penerima Manfaat'}')">
            <svg viewBox="0 0 24 24"><path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg>
            Laporkan Data Tidak Sesuai
          </button>
        `;
      }
      body.innerHTML = htmlContent;
      panel.classList.add('show');
      reverseGeocode(d.latitude, d.longitude, addr => { const el = document.getElementById('info-address'); if (el) el.textContent = addr; });
      return;
    }

    header.innerHTML = `<div class="info-title-icon">${svgIcon('home', 14, 14)}</div><span>${d.nama_kepala_keluarga}</span>`;

    let htmlContent = `
      <div class="address-box"><span class="addr-icon">${svgIcon('pin', 11, 11)}</span><span id="info-address">Memuat alamat...</span></div>
    `;

    if (!isKoor) {
      htmlContent += `
        ${d.no_kk ? `<div class="info-row"><span class="info-key">No. KK</span><span class="info-val" style="font-family:var(--mono);font-size:10px">${d.no_kk}</span></div>` : ''}
        ${d.nik ? `<div class="info-row"><span class="info-key">NIK</span><span class="info-val" style="font-family:var(--mono);font-size:10px">${d.nik}</span></div>` : ''}
        <div class="info-row"><span class="info-key">Tanggungan</span><span class="info-val">${d.jumlah_tanggungan} jiwa</span></div>
        <div class="info-row"><span class="info-key">Penghasilan</span><span class="info-val">${formatRupiah(d.penghasilan_bulanan)}/bln</span></div>
        ${d.pekerjaan ? `<div class="info-row"><span class="info-key">Pekerjaan</span><span class="info-val">${d.pekerjaan}</span></div>` : ''}
        <div class="info-row"><span class="info-key">Kategori</span><span class="info-val"><span class="badge ${cat.badgeCls}">${cat.label}</span></span></div>
      `;
    }

    htmlContent += `
      <div class="info-row"><span class="info-key">Bansos</span><span class="info-val"><span class="badge ${sts.cls}">${sts.label}</span></span></div>
      <div class="info-row"><span class="info-key">Rekomendasi</span><span class="info-val"><span class="badge ${rek.cls}">${rek.label}</span></span></div>
      ${d.dikelola_oleh_ibadah_id ? (() => {
        const ibadah = ibadahData.find(i => parseInt(i.id) === parseInt(d.dikelola_oleh_ibadah_id));
        return ibadah ? `<div style="margin-top:8px;padding:10px;background:var(--bg-tertiary);border-radius:6px;border:1px solid var(--border);"><div style="font-size:12px;color:var(--text-muted);margin-bottom:4px">Penanggung Bantuan:</div><div style="font-weight:bold;font-size:12px;color:var(--primary);display:flex;align-items:center;gap:4px">${ibadah.nama}</div></div>` : '';
      })() : ''}
      ${!isKoor ? `<div class="rek-box ${rek.boxCls}"><div class="rek-box-title">${rek.label}</div><div class="rek-box-desc">${rek.desc}</div></div>` : ''}
      ${d.kelurahan ? `<div class="info-row"><span class="info-key">Kelurahan</span><span class="info-val">${d.kelurahan}</span></div>` : ''}
      ${d.kecamatan ? `<div class="info-row"><span class="info-key">Kecamatan</span><span class="info-val">${d.kecamatan}</span></div>` : ''}
      ${d.kota ? `<div class="info-row"><span class="info-key">Kota</span><span class="info-val">${d.kota}</span></div>` : ''}
      ${!isKoor && d.keterangan ? `<div class="info-row"><span class="info-key">Ket.</span><span class="info-val">${d.keterangan}</span></div>` : ''}
      <div class="info-coords">${parseFloat(d.latitude).toFixed(6)}, ${parseFloat(d.longitude).toFixed(6)}</div>
    `;

    if (!isKoor) {
      htmlContent += `
        <div class="info-section-title">${svgIcon('users', 11, 11)} Anggota Keluarga</div>
        <div id="anggota-info-list"><div class="loading"><div class="spinner"></div></div></div>
      `;
    }

    if (currentUser && (currentUser.role === 'admin' || currentUser.role === 'petugas' || currentUser.role === 'koordinator')) {
      htmlContent += `
        <div style="display:flex;gap:6px;margin-top:10px">
          <button class="btn btn-primary btn-sm" style="flex:1" onclick="App.editWarga(${d.id})">${svgIcon('edit', 12, 12)} Edit</button>
          ${currentUser.role === 'admin' ? `<button class="btn btn-danger btn-sm" onclick="App.deleteWarga(${d.id})">${svgIcon('trash', 12, 12)}</button>` : ''}
        </div>
      `;
    }

    if (currentUser && (currentUser.role === 'kontributor' || currentUser.role === 'koordinator')) {
      htmlContent += `
        <button class="btn-laporkan" onclick="FiturBaru.Laporan.bukaModalLaporan(${d.id}, '${d.nama_kepala_keluarga ? d.nama_kepala_keluarga.replace(/'/g, "\\'") : 'Penerima Manfaat'}')">
          <svg viewBox="0 0 24 24"><path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg>
          Laporkan Data Tidak Sesuai
        </button>
      `;
    }

    body.innerHTML = htmlContent;

    panel.classList.add('show');
    reverseGeocode(d.latitude, d.longitude, addr => { const el = document.getElementById('info-address'); if (el) el.textContent = addr; });

    if (!isKoor) {
      try {
        const res = await fetch(`api/anggota_keluarga.php?rumah_warga_id=${d.id}`);
        const json = await res.json();
        const container = document.getElementById('anggota-info-list');
        if (!container) return;
        if (!json.data?.length) { container.innerHTML = `<div style="text-align:center;color:var(--text-muted);font-size:11px;padding:10px">Belum ada data anggota</div>`; return; }
        const PEND = { tidak_sekolah: 'Tdk Sekolah', sd: 'SD', smp: 'SMP', sma: 'SMA', d3: 'D3', s1: 'S1', s2: 'S2', s3: 'S3' };
        container.innerHTML = `<div class="anggota-list">${json.data.map(a => {
          const usia = a.usia !== null ? `${a.usia} th` : '–';
          const prod = a.usia >= 18 && a.usia <= 55;
          const bisaKerja = parseInt(a.dapat_bekerja) === 1 && ['sehat', 'sakit_ringan'].includes(a.kondisi_kesehatan);
          const dotColor = prod && bisaKerja ? '#10b981' : (prod ? '#fbbf24' : '#94a3b8');
          return `<div class="anggota-item">
            <div class="anggota-dot" style="background:${dotColor}"></div>
            <div class="anggota-info">
              <div class="anggota-name">${a.nama} <span style="font-size:9px;color:var(--text-muted)">(${usia})</span></div>
              <div class="anggota-meta">
                ${a.jenis_kelamin === 'laki_laki' ? '♂' : '♀'} · ${PEND[a.pendidikan] || a.pendidikan}
                ${a.pekerjaan ? ' · ' + a.pekerjaan : ''}
                ${a.kondisi_kesehatan !== 'sehat' ? ` · <span style="color:var(--warning)">${a.kondisi_kesehatan.replace(/_/g, ' ')}</span>` : ''}
                ${parseInt(a.dapat_bekerja) ? '' : ' · <span style="color:var(--danger)">Tdk bisa kerja</span>'}
              </div>
            </div>
          </div>`;
        }).join('')}</div>`;
      } catch { /* silent */ }
    }
  }

  /* ══════════════════════════════════════════════════
     REVERSE GEOCODING
  ══════════════════════════════════════════════════ */
  async function reverseGeocode(lat, lng, cb) {
    try {
      const res = await fetch(`https://nominatim.openstreetmap.org/reverse?lat=${lat}&lon=${lng}&format=json&accept-language=id`);
      const json = await res.json();
      cb(json.display_name || `${lat}, ${lng}`, json.address || {});
    } catch { cb(`${lat}, ${lng}`, {}); }
  }

  /* ══════════════════════════════════════════════════
     ADD MODE
  ══════════════════════════════════════════════════ */
  function setAddMode(mode) {
    addMode = mode;
    if (tempMarker) { map.removeLayer(tempMarker); tempMarker = null; }
    const ind = document.getElementById('mode-indicator');
    if (mode === 'ibadah') {
      ind.innerHTML = `<div class="mode-dot ibadah"></div> Klik peta untuk menentukan lokasi Rumah Ibadah`;
      ind.classList.add('show');
      map.getContainer().style.cursor = 'crosshair';
    } else if (mode === 'warga') {
      ind.innerHTML = `<div class="mode-dot warga"></div> Klik peta untuk menentukan lokasi Rumah Warga`;
      ind.classList.add('show');
      map.getContainer().style.cursor = 'crosshair';
    } else {
      ind.classList.remove('show');
      map.getContainer().style.cursor = '';
    }
  }

  function cancelAddMode() {
    setAddMode(null);
    if (tempMarker) { map.removeLayer(tempMarker); tempMarker = null; }
  }

  function onMapClick(e) {
    if (!addMode) return;
    const { lat, lng } = e.latlng;
    if (tempMarker) map.removeLayer(tempMarker);

    if (addMode === 'ibadah') {
      document.getElementById('ibadah-lat').value = lat;
      document.getElementById('ibadah-lng').value = lng;
      updateCoordDisplay('ibadah', lat, lng);
      tempMarker = L.marker([lat, lng], { icon: L.divIcon({ className: '', html: `<div style="width:38px;height:38px;border-radius:10px;background:#fff;border:1.5px dashed #6366f1;display:flex;align-items:center;justify-content:center;color:#818cf8;">${svgIcon('mosque', 18, 18)}</div>`, iconSize: [38, 38], iconAnchor: [19, 19] }) }).addTo(map);
      // reverseGeocode is called inside openIbadahModal — no need to call again here

      // Setelah memilih titik untuk rumah ibadah, buka modal pre-filled dan keluar dari add mode
      openIbadahModal(null, lat, lng);
      cancelAddMode();
    } else if (addMode === 'warga') {
      document.getElementById('warga-lat').value = lat;
      document.getElementById('warga-lng').value = lng;
      updateCoordDisplay('warga', lat, lng);
      tempMarker = L.marker([lat, lng], { icon: L.divIcon({ className: '', html: `<div style="width:14px;height:14px;border-radius:50%;background:#6366f1;border:2px dashed #818cf8;opacity:0.85;"></div>`, iconSize: [14, 14], iconAnchor: [7, 7] }) }).addTo(map);
      // reverseGeocode is called inside openWargaModal — no need to call again here

      // Setelah memilih titik untuk rumah warga, buka modal pre-filled dan keluar dari add mode
      openWargaModal(null, lat, lng);
      cancelAddMode();
    }
  }

  function updateCoordDisplay(type, lat, lng) {
    const el = document.getElementById(`${type}-coord-display`);
    if (el) el.textContent = lat && lng ? `${parseFloat(lat).toFixed(6)}, ${parseFloat(lng).toFixed(6)}` : 'Belum dipilih — klik di peta';
  }

  /* ══════════════════════════════════════════════════
     MODAL IBADAH
  ══════════════════════════════════════════════════ */
  function openIbadahModal(data = null, lat = null, lng = null) {
    document.getElementById('modal-ibadah-title').textContent = data ? 'Edit Rumah Ibadah' : 'Tambah Rumah Ibadah';
    document.getElementById('ibadah-id').value = data?.id || '';
    document.getElementById('ibadah-nama').value = data?.nama || '';
    document.getElementById('ibadah-jenis').value = data?.jenis || 'masjid';
    document.getElementById('ibadah-pj').value = data?.penanggung_jawab || '';
    document.getElementById('ibadah-kontak').value = data?.kontak || '';
    document.getElementById('ibadah-alamat').value = data?.alamat || '';
    document.getElementById('ibadah-kelurahan').value = data?.kelurahan || '';
    document.getElementById('ibadah-kecamatan').value = data?.kecamatan || '';
    document.getElementById('ibadah-kota').value = data?.kota || '';
    document.getElementById('ibadah-ket').value = data?.keterangan || '';
    document.getElementById('ibadah-kapasitas').value = data?.kapasitas_kk || 20;
    document.getElementById('ibadah-radius').value = data?.radius_primer || 500;
    document.getElementById('ibadah-anggaran').value = data?.anggaran_bulanan || 0;
    const latVal = data ? data.latitude : (lat || '');
    const lngVal = data ? data.longitude : (lng || '');
    document.getElementById('ibadah-lat').value = latVal;
    document.getElementById('ibadah-lng').value = lngVal;
    updateCoordDisplay('ibadah', latVal, lngVal);
    if (latVal && lngVal) reverseGeocode(latVal, lngVal, (addr, details) => {
      const h = document.getElementById('ibadah-addr-hint');
      if (h) h.textContent = addr;

      if (!data) {
        if (details && Object.keys(details).length > 0) {
          const kel = details.village || details.suburb || details.neighbourhood || '';
          const kec = details.county || details.city_district || details.town || '';
          const kot = details.city || details.municipality || details.regency || details.county || '';

          if (kel && !document.getElementById('ibadah-kelurahan').value) document.getElementById('ibadah-kelurahan').value = kel;
          if (kec && !document.getElementById('ibadah-kecamatan').value) document.getElementById('ibadah-kecamatan').value = kec;
          if (kot && !document.getElementById('ibadah-kota').value) document.getElementById('ibadah-kota').value = kot;
        } else {
          if (h) h.innerHTML = addr + ' <span style="color:#f59e0b">(Alamat detail tidak didapatkan, silahkan isi manual)</span>';
        }
      }
    });
    document.getElementById('modal-ibadah').classList.add('show');
  }

  async function saveIbadah() {
    const id = document.getElementById('ibadah-id').value;
    const nama = document.getElementById('ibadah-nama').value.trim();
    const lat = document.getElementById('ibadah-lat').value;
    const lng = document.getElementById('ibadah-lng').value;
    if (!nama) { showToast('Nama wajib diisi', 'error'); return; }
    if (!lat || !lng) { showToast('Pilih lokasi di peta terlebih dahulu', 'error'); return; }

    const payload = {
      id, nama,
      jenis: document.getElementById('ibadah-jenis').value,
      penanggung_jawab: document.getElementById('ibadah-pj').value,
      kontak: document.getElementById('ibadah-kontak').value,
      alamat: document.getElementById('ibadah-alamat').value,
      kelurahan: document.getElementById('ibadah-kelurahan').value,
      kecamatan: document.getElementById('ibadah-kecamatan').value,
      kota: document.getElementById('ibadah-kota').value,
      keterangan: document.getElementById('ibadah-ket').value,
      kapasitas_kk: document.getElementById('ibadah-kapasitas').value,
      radius_primer: document.getElementById('ibadah-radius').value,
      anggaran_bulanan: document.getElementById('ibadah-anggaran').value,
      latitude: lat, longitude: lng,
    };

    try {
      const res = await fetch('api/rumah_ibadah.php', { method: id ? 'PUT' : 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) });
      const json = await res.json();
      if (json.success) { showToast(json.message, 'success'); closeModal('modal-ibadah'); cancelAddMode(); await loadIbadah(); loadStats(); refreshRadiusIfActive(); }
      else showToast(json.message, 'error');
    } catch { showToast('Terjadi kesalahan', 'error'); }
  }

  /* ══════════════════════════════════════════════════
     MODAL WARGA — ANGGOTA ROWS
  ══════════════════════════════════════════════════ */
  function buildAnggotaRow(data = {}, index = 0) {
    return `<div class="anggota-form-item" id="arow-${index}" data-arow="${index}">
      <div class="anggota-form-header">
        <div class="anggota-form-title">Anggota ${typeof index === 'number' ? index + 1 : ''}</div>
        <button class="btn btn-xs btn-ghost" onclick="App.removeAnggotaRow(${index})" style="color:var(--danger)">Hapus</button>
      </div>
      <div class="anggota-form-body">
        <div class="form-group" style="grid-column:1/-1">
          <label class="form-label">Nama <span>*</span></label>
          <input type="text" class="form-control" name="nama" value="${data.nama || ''}" placeholder="Nama lengkap" data-arow="${index}">
        </div>
        <div class="form-group">
          <label class="form-label">NIK</label>
          <input type="text" class="form-control" name="nik" value="${data.nik || ''}" maxlength="16" data-arow="${index}">
        </div>
        <div class="form-group">
          <label class="form-label">Tgl Lahir</label>
          <input type="date" class="form-control" name="tanggal_lahir" value="${data.tanggal_lahir || ''}" data-arow="${index}" oninput="App.previewRek()">
        </div>
        <div class="form-group">
          <label class="form-label">Jenis Kelamin</label>
          <select class="form-control" name="jenis_kelamin" data-arow="${index}">
            <option value="laki_laki" ${(data.jenis_kelamin || 'laki_laki') === 'laki_laki' ? 'selected' : ''}>Laki-laki</option>
            <option value="perempuan" ${data.jenis_kelamin === 'perempuan' ? 'selected' : ''}>Perempuan</option>
          </select>
        </div>
        <div class="form-group">
          <label class="form-label">Pendidikan</label>
          <select class="form-control" name="pendidikan" data-arow="${index}">
            ${['tidak_sekolah', 'sd', 'smp', 'sma', 'd3', 's1', 's2', 's3'].map(p => `<option value="${p}" ${(data.pendidikan || 'sd') === p ? 'selected' : ''}>${p.replace('_', ' ').toUpperCase()}</option>`).join('')}
          </select>
        </div>
        <div class="form-group">
          <label class="form-label">Pekerjaan</label>
          <input type="text" class="form-control" name="pekerjaan" value="${data.pekerjaan || ''}" data-arow="${index}">
        </div>
        <div class="form-group">
          <label class="form-label">Status Bekerja</label>
          <select class="form-control" name="status_bekerja" data-arow="${index}" oninput="App.previewRek()">
            <option value="bekerja" ${(data.status_bekerja || '') === 'bekerja' ? 'selected' : ''}>Bekerja</option>
            <option value="tidak_bekerja" ${(data.status_bekerja || 'tidak_bekerja') === 'tidak_bekerja' ? 'selected' : ''}>Tidak Bekerja</option>
            <option value="pelajar" ${(data.status_bekerja || '') === 'pelajar' ? 'selected' : ''}>Pelajar/Mahasiswa</option>
            <option value="pensiunan" ${(data.status_bekerja || '') === 'pensiunan' ? 'selected' : ''}>Pensiunan</option>
          </select>
        </div>
        <div class="form-group">
          <label class="form-label">Kondisi Kesehatan</label>
          <select class="form-control" name="kondisi_kesehatan" data-arow="${index}" oninput="App.previewRek()">
            <option value="sehat" ${(data.kondisi_kesehatan || 'sehat') === 'sehat' ? 'selected' : ''}>Sehat</option>
            <option value="sakit_ringan" ${(data.kondisi_kesehatan || '') === 'sakit_ringan' ? 'selected' : ''}>Sakit Ringan</option>
            <option value="sakit_berat" ${(data.kondisi_kesehatan || '') === 'sakit_berat' ? 'selected' : ''}>Sakit Berat</option>
            <option value="disabilitas" ${(data.kondisi_kesehatan || '') === 'disabilitas' ? 'selected' : ''}>Disabilitas</option>
          </select>
        </div>
        <div class="form-group">
          <label class="form-label">Dapat Bekerja</label>
          <select class="form-control" name="dapat_bekerja" data-arow="${index}" oninput="App.previewRek()">
            <option value="1" ${parseInt(data.dapat_bekerja ?? 1) === 1 ? 'selected' : ''}>Ya</option>
            <option value="0" ${parseInt(data.dapat_bekerja ?? 1) === 0 ? 'selected' : ''}>Tidak</option>
          </select>
        </div>
      </div>
    </div>`;
  }

  function collectAnggotaRows() {
    const container = document.getElementById('anggota-form-container');
    if (!container) return [];
    const items = container.querySelectorAll('[data-arow]');
    const result = [], seen = new Set();
    items.forEach(el => {
      const idx = el.dataset.arow;
      if (seen.has(idx)) return;
      seen.add(idx);
      const row = { dapat_bekerja: 1 };
      const inputs = container.querySelectorAll(`[name][data-arow="${idx}"]`);
      inputs.forEach(i => { row[i.name] = i.tagName === 'SELECT' ? i.value : i.value.trim(); });
      if (row.nama) result.push(row);
    });
    return result;
  }

  function kategoriLocal(penghasilan, tanggungan, tinggal, air) {
    let p = tanggungan > 0 ? penghasilan / tanggungan : penghasilan;
    let skor = 0;
    if (p < 300000) skor += 40;
    else if (p < 600000) skor += 20;

    if (tinggal === 'numpang' || tinggal === 'sewa') skor += 20;
    if (air === 'sungai' || air === 'hujan') skor += 10;

    if (skor >= 50) return 'sangat_miskin';
    if (skor >= 20) return 'miskin';
    return 'rentan_miskin';
  }

  function previewRek() {
    const anggota = collectAnggotaRows();
    const penghasilan = parseFloat(document.getElementById('warga-penghasilan')?.value || 0);
    const tanggungan = parseInt(document.getElementById('warga-tanggungan')?.value || 1);
    const tinggal = document.getElementById('warga-tempat')?.value || 'milik_sendiri';
    const air = document.getElementById('warga-air')?.value || 'sumur';
    const stsPekerjaan = document.getElementById('warga-stspekerjaan')?.value || 'tidak_bekerja';
    const isKatSistem = document.getElementById('warga-kategori')?.value === 'sistem';

    const rek = rekomendasiLocal(anggota, penghasilan, stsPekerjaan);
    const cfg = REK_CONFIG[rek] || REK_CONFIG.tidak_ada;

    const box = document.getElementById('rek-preview-box');
    if (box) {
      let html = `<div style="font-weight:700;color:var(--text-primary);margin-bottom:2px">Prediksi Bantuan: <span class="badge ${cfg.cls}">${cfg.label}</span></div><div style="font-size:10px;color:var(--text-muted);margin-top:4px">${cfg.desc}</div>`;
      if (isKatSistem) {
        const kat = kategoriLocal(penghasilan, tanggungan, tinggal, air);
        let katLabel = '';
        if (kat === 'sangat_miskin') katLabel = 'Sangat Kurang Mampu';
        else if (kat === 'miskin') katLabel = 'Kurang Mampu';
        else if (kat === 'rentan_miskin') katLabel = 'Rentan Kurang Mampu';

        let katCls = 'badge-miskin';
        if (kat === 'sangat_miskin') katCls = 'badge-sangat-miskin';
        else if (kat === 'rentan_miskin') katCls = 'badge-rentan-miskin';

        html = `<div style="font-weight:700;color:var(--text-primary);margin-bottom:6px">Prediksi Kategori: <span class="fb-badge ${katCls}">${katLabel}</span></div>` + html;
      }
      box.innerHTML = html;
    }
  }

  /* ══════════════════════════════════════════════════
     MODAL WARGA
     FIX: openWargaModal sekarang reset sub-tab dengan
     cara yang aman (tidak bergantung pada querySelector
     global yang bisa bentrok dengan elemen lain)
  ══════════════════════════════════════════════════ */
  async function openWargaModal(data = null, lat = null, lng = null) {
    const isKoor = currentUser && currentUser.role === 'koordinator';
    document.getElementById('modal-warga-title').textContent = data ? 'Edit Rumah Warga' : 'Tambah Rumah Warga';

    // Reset sub-tab modal warga — pakai scope modal biar aman
    const modalEl = document.getElementById('modal-warga');
    modalEl.querySelectorAll('.modal-tab-btn').forEach(b => b.classList.remove('active'));
    modalEl.querySelectorAll('.modal-tab-panel').forEach(p => p.classList.remove('active'));
    const firstTabBtn = modalEl.querySelector('.modal-tab-btn[data-mtab="data-pokok"]');
    const firstTabPanel = document.getElementById('mtab-data-pokok');
    if (firstTabBtn) firstTabBtn.classList.add('active');
    if (firstTabPanel) firstTabPanel.classList.add('active');

    // Hide tabs if coordinator
    const tabRumahBtn = modalEl.querySelector('.modal-tab-btn[data-mtab="rumah"]');
    const tabAnggotaBtn = modalEl.querySelector('.modal-tab-btn[data-mtab="anggota"]');
    if (tabRumahBtn) tabRumahBtn.style.display = isKoor ? 'none' : '';
    if (tabAnggotaBtn) tabAnggotaBtn.style.display = isKoor ? 'none' : '';

    const toggleField = (id, show) => {
      const el = document.getElementById(id);
      if (el) {
        const fg = el.closest('.form-group');
        if (fg) fg.style.display = show ? '' : 'none';
      }
    };
    const disableField = (id, disable) => {
      const el = document.getElementById(id);
      if (el) el.disabled = disable;
    };

    const fieldsToToggle = [
      'warga-nokk', 'warga-nik', 'warga-tanggungan', 'warga-penghasilan',
      'warga-pekerjaan', 'warga-stspekerjaan', 'warga-kategori',
      'warga-rekomendasi', 'warga-ket', 'warga-coord-display'
    ];
    fieldsToToggle.forEach(fId => toggleField(fId, !isKoor));

    const fieldsToDisable = [
      'warga-nama', 'warga-alamat', 'warga-kelurahan', 'warga-kecamatan', 'warga-kota'
    ];
    fieldsToDisable.forEach(fId => disableField(fId, isKoor));

    const isAdmin = currentUser && currentUser.role === 'admin';
    disableField('warga-dikelola-oleh', !isAdmin);

    // Also hide prediction/preview box if coordinator
    const previewBox = document.getElementById('rek-preview-box');
    if (previewBox) previewBox.style.display = isKoor ? 'none' : '';

    // Hide empty form-rows (rows where all child form-groups are hidden) for clean layout
    if (isKoor) {
      const dataPokokPanel = document.getElementById('mtab-data-pokok');
      if (dataPokokPanel) {
        dataPokokPanel.querySelectorAll('.form-row').forEach(row => {
          const groups = row.querySelectorAll('.form-group');
          const allHidden = Array.from(groups).every(g => g.style.display === 'none');
          row.style.display = allHidden ? 'none' : '';
        });
      }
    } else {
      // Restore all form-rows for non-coordinator
      modalEl.querySelectorAll('.form-row').forEach(row => { row.style.display = ''; });
    }

    document.getElementById('warga-id').value = data?.id || '';
    document.getElementById('warga-nokk').value = data?.no_kk || '';
    document.getElementById('warga-nama').value = data?.nama_kepala_keluarga || '';
    document.getElementById('warga-nik').value = data?.nik || '';
    document.getElementById('warga-tanggungan').value = data?.jumlah_tanggungan || 1;
    document.getElementById('warga-penghasilan').value = data?.penghasilan_bulanan || 0;
    document.getElementById('warga-pekerjaan').value = data?.pekerjaan || '';
    document.getElementById('warga-stspekerjaan').value = data?.status_pekerjaan || 'tidak_bekerja';
    document.getElementById('warga-alamat').value = data?.alamat || '';
    document.getElementById('warga-kelurahan').value = data?.kelurahan || '';
    document.getElementById('warga-kecamatan').value = data?.kecamatan || '';
    document.getElementById('warga-kota').value = data?.kota || '';
    // Set manual kategori if active
    if (data && parseInt(data.is_kategori_manual) === 1) {
      document.getElementById('warga-kategori').value = data.kategori_kemiskinan || 'miskin';
    } else {
      document.getElementById('warga-kategori').value = 'sistem';
    }

    document.getElementById('warga-stsbantuan').value = data?.status_bantuan || 'belum_terima';

    // Set manual recommendation if active
    if (data && parseInt(data.is_rekomendasi_manual) === 1) {
      document.getElementById('warga-rekomendasi').value = data.rekomendasi_bantuan || 'sistem';
    } else {
      document.getElementById('warga-rekomendasi').value = 'sistem';
    }

    document.getElementById('warga-luas').value = data?.luas_rumah || '';
    document.getElementById('warga-lantai').value = data?.jenis_lantai || 'semen';
    document.getElementById('warga-dinding').value = data?.jenis_dinding || 'tembok';
    document.getElementById('warga-air').value = data?.sumber_air || 'sumur';
    document.getElementById('warga-tempat').value = data?.status_tempat_tinggal || 'milik_sendiri';
    document.getElementById('warga-ket').value = data?.keterangan || '';

    const latVal = data ? data.latitude : (lat || '');
    const lngVal = data ? data.longitude : (lng || '');
    document.getElementById('warga-lat').value = latVal;
    document.getElementById('warga-lng').value = lngVal;
    updateCoordDisplay('warga', latVal, lngVal);

    // Populate dropdown Penanggung Bantuan
    const selectPj = document.getElementById('warga-dikelola-oleh');
    if (selectPj) {
      let optionsHtml = '<option value="">-- Tidak Ada / Default Radius --</option>';
      let closestIbadahId = null;
      let minDistance = Infinity;

      if (typeof ibadahData !== 'undefined' && Array.isArray(ibadahData)) {
        ibadahData.forEach(ib => {
          optionsHtml += `<option value="${ib.id}">${ib.nama}</option>`;
          if (!data && latVal && lngVal && typeof haversine === 'function') {
            const dist = haversine(parseFloat(latVal), parseFloat(lngVal), parseFloat(ib.latitude), parseFloat(ib.longitude));
            if (dist < minDistance) { minDistance = dist; closestIbadahId = ib.id; }
          }
        });
      }
      selectPj.innerHTML = optionsHtml;

      if (data && data.dikelola_oleh_ibadah_id) {
        selectPj.value = data.dikelola_oleh_ibadah_id;
      } else if (!data && closestIbadahId) {
        selectPj.value = closestIbadahId;
      } else {
        selectPj.value = '';
      }
    }

    if (latVal && lngVal) reverseGeocode(latVal, lngVal, (addr, details) => {
      const h = document.getElementById('warga-addr-hint');
      if (h) h.textContent = addr;

      if (!data) {
        if (details && Object.keys(details).length > 0) {
          const kel = details.village || details.suburb || details.neighbourhood || '';
          const kec = details.county || details.city_district || details.town || '';
          const kot = details.city || details.municipality || details.regency || details.county || '';

          if (kel && !document.getElementById('warga-kelurahan').value) document.getElementById('warga-kelurahan').value = kel;
          if (kec && !document.getElementById('warga-kecamatan').value) document.getElementById('warga-kecamatan').value = kec;
          if (kot && !document.getElementById('warga-kota').value) document.getElementById('warga-kota').value = kot;
        } else {
          if (h) h.innerHTML = addr + ' <span style="color:#f59e0b">(Alamat detail tidak didapatkan, silahkan isi manual)</span>';
        }
      }
    });

    // Load anggota existing
    anggotaRows = [];
    const container = document.getElementById('anggota-form-container');
    container.innerHTML = '';
    if (data?.id && !isKoor) {
      try {
        const res = await fetch(`api/anggota_keluarga.php?rumah_warga_id=${data.id}`);
        const json = await res.json();
        if (json.data?.length) {
          json.data.forEach((a, i) => { anggotaRows.push(i); container.insertAdjacentHTML('beforeend', buildAnggotaRow(a, i)); });
        }
      } catch { /* silent */ }
    }
    previewRek();

    // Adjust footer buttons based on mode (Add vs Edit)
    const btnVerifyDirect = document.getElementById('btn-verify-warga-direct');
    const btnSave = document.getElementById('btn-save-warga');
    if (data?.id && !isKoor) {
      if (btnVerifyDirect) btnVerifyDirect.style.display = 'inline-flex';
      if (btnSave) btnSave.innerHTML = '<svg viewBox="0 0 24 24" width="13" height="13" stroke="currentColor" fill="none" stroke-width="2" style="margin-right:4px"><path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z"/><polyline points="17 21 17 13 7 13 7 21"/><polyline points="7 3 7 8 15 8"/></svg> Simpan &amp; Verifikasi';
    } else {
      if (btnVerifyDirect) btnVerifyDirect.style.display = 'none';
      if (btnSave) {
        if (isKoor) {
          btnSave.innerHTML = 'Simpan';
        } else {
          btnSave.innerHTML = 'Simpan';
        }
      }
    }

    // Buka modal setelah semua data terisi
    modalEl.classList.add('show');
    if (document.getElementById('modal-premium-verifikasi')?.classList.contains('show')) {
      document.body.classList.add('side-by-side-modals');
    }
  }

  async function saveWarga() {
    const isKoor = currentUser && currentUser.role === 'koordinator';
    const id = document.getElementById('warga-id').value;
    const nokk = document.getElementById('warga-nokk').value.trim();
    const nama = document.getElementById('warga-nama').value.trim();
    const lat = document.getElementById('warga-lat').value;
    const lng = document.getElementById('warga-lng').value;

    if (!isKoor) {
      if (!nama) { showToast('Nama Kepala Keluarga wajib diisi', 'error'); return; }
      if (!lat || !lng) { showToast('Pilih lokasi di peta terlebih dahulu', 'error'); return; }
      if (!nokk || !/^\d{16}$/.test(nokk)) { showToast('No. KK harus 16 digit angka', 'error'); return; }
    } else {
      if (!id) { showToast('ID Warga wajib terisi', 'error'); return; }
    }

    const payload = isKoor ? {
      id,
      status_bantuan: document.getElementById('warga-stsbantuan').value
    } : {
      id, no_kk: nokk, nama_kepala_keluarga: nama,
      nik: document.getElementById('warga-nik').value,
      jumlah_tanggungan: document.getElementById('warga-tanggungan').value,
      penghasilan_bulanan: document.getElementById('warga-penghasilan').value,
      pekerjaan: document.getElementById('warga-pekerjaan').value,
      status_pekerjaan: document.getElementById('warga-stspekerjaan').value,
      alamat: document.getElementById('warga-alamat').value,
      kelurahan: document.getElementById('warga-kelurahan').value,
      kecamatan: document.getElementById('warga-kecamatan').value,
      kota: document.getElementById('warga-kota').value,
      kategori_kemiskinan: document.getElementById('warga-kategori').value,
      status_bantuan: document.getElementById('warga-stsbantuan').value,
      rekomendasi_bantuan: document.getElementById('warga-rekomendasi').value,
      luas_rumah: document.getElementById('warga-luas').value,
      jenis_lantai: document.getElementById('warga-lantai').value,
      jenis_dinding: document.getElementById('warga-dinding').value,
      sumber_air: document.getElementById('warga-air').value,
      status_tempat_tinggal: document.getElementById('warga-tempat').value,
      keterangan: document.getElementById('warga-ket').value,
      dikelola_oleh_ibadah_id: document.getElementById('warga-dikelola-oleh') ? document.getElementById('warga-dikelola-oleh').value : '',
      latitude: lat, longitude: lng,
      anggota: collectAnggotaRows(),
    };

    try {
      const res = await fetch('api/rumah_warga.php', { method: id ? 'PUT' : 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) });
      const json = await res.json();
      if (json.success) {
        const rekLabel = json.rekomendasi ? (REK_CONFIG[json.rekomendasi]?.label || json.rekomendasi) : '';

        // Auto-verify pasca-simpan (baru maupun edit)
        const targetId = id || json.id;
        if (targetId) {
          try {
            await fetch('api/verifikasi.php', {
              method: 'POST',
              headers: { 'Content-Type': 'application/json' },
              body: JSON.stringify({
                warga_id: parseInt(targetId),
                petugas: currentUser ? (currentUser.role === 'koordinator' ? `Koordinator (${currentUser.username})` : currentUser.username) : 'Sistem',
                tanggal: new Date().toLocaleDateString('en-CA'),
                catatan: id ? 'Verifikasi otomatis pasca-edit data warga' : 'Verifikasi otomatis pendaftaran warga baru'
              })
            });
          } catch (e) { console.error('Auto-verify error:', e); }
        }

        showToast(`${json.message}${rekLabel ? ' · Rek: ' + rekLabel : ''}`, 'success');
        try { closeModal('modal-warga'); } catch (e) { }
        try { cancelAddMode(); } catch (e) { }
        try { await loadWarga(); } catch (e) { }
        try { loadStats(); } catch (e) { }
        try { refreshRadiusIfActive(); } catch (e) { }

        if (window.FiturBaru && FiturBaru.Verifikasi) {
          try { FiturBaru.Verifikasi.load(document.getElementById('filter-verif-status')?.value || ''); } catch (e) { }
        }
      } else {
        showToast(json.message, 'error');
      }
    } catch (err) {
      console.error('SaveWarga Error:', err);
      showToast('Terjadi kesalahan', 'error');
    }
  }

  /* ══════════════════════════════════════════════════
     EDIT / DELETE
  ══════════════════════════════════════════════════ */
  function editIbadah(id) {
    checkAuth({ type: 'edit_ibadah', id }, () => {
      if (currentUser.role !== 'admin') {
        showToast('Hanya Admin yang berhak merubah data rumah ibadah', 'error');
        return;
      }
      const d = ibadahData.find(x => parseInt(x.id) === parseInt(id));
      if (d) { document.getElementById('info-panel').classList.remove('show'); openIbadahModal(d); }
    });
  }

  async function editWarga(id) {
    checkAuth({ type: 'edit_warga', id }, async () => {
      if (!['admin', 'petugas', 'koordinator'].includes(currentUser.role)) {
        showToast('Anda tidak memiliki izin untuk mengedit data warga', 'error');
        return;
      }
      const d = wargaData.find(x => parseInt(x.id) === parseInt(id));
      if (d) { document.getElementById('info-panel').classList.remove('show'); await openWargaModal(d); }
    });
  }

  async function deleteIbadah(id) {
    checkAuth({ type: 'delete_ibadah', id }, async () => {
      if (currentUser.role !== 'admin') {
        showToast('Hanya Admin yang berhak menghapus data rumah ibadah', 'error');
        return;
      }
      if (!confirm('Hapus data rumah ibadah ini?')) return;
      try {
        const res = await fetch(`api/rumah_ibadah.php?id=${id}`, { method: 'DELETE' });
        const json = await res.json();
        if (json.success) { showToast(json.message, 'success'); document.getElementById('info-panel').classList.remove('show'); if (parseInt(activeRadiusIbadahId) === parseInt(id)) clearRadius(); await loadIbadah(); loadStats(); }
        else showToast(json.message, 'error');
      } catch { showToast('Terjadi kesalahan', 'error'); }
    });
  }

  async function deleteWarga(id) {
    checkAuth({ type: 'delete_warga', id }, async () => {
      if (currentUser.role !== 'admin') {
        showToast('Hanya Admin yang berhak menghapus data warga', 'error');
        return;
      }
      if (!confirm('Hapus data rumah warga ini?')) return;
      try {
        const res = await fetch(`api/rumah_warga.php?id=${id}`, { method: 'DELETE' });
        const json = await res.json();
        if (json.success) { showToast(json.message, 'success'); document.getElementById('info-panel').classList.remove('show'); await loadWarga(); loadStats(); refreshRadiusIfActive(); }
        else showToast(json.message, 'error');
      } catch { showToast('Terjadi kesalahan', 'error'); }
    });
  }

  /* ══════════════════════════════════════════════════
     DATA LISTS
  ══════════════════════════════════════════════════ */
  function renderIbadahList() {
    const search = document.getElementById('search-ibadah')?.value || '';
    const jenis = document.getElementById('filter-ibadah-jenis')?.value || '';
    const container = document.getElementById('ibadah-list');
    if (!container) return;
    const filtered = ibadahData.filter(d => {
      const matchSearch = !search || d.nama.toLowerCase().includes(search.toLowerCase());
      const matchJenis = !jenis || d.jenis === jenis;
      return matchSearch && matchJenis;
    });

    const isKoor = currentUser?.role === 'koordinator';
    let html = '';

    if (isKoor && currentUser.rumah_ibadah_id) {
      const myIbadah = ibadahData.find(x => parseInt(x.id) === parseInt(currentUser.rumah_ibadah_id));
      if (myIbadah) {
        const cfg = JENIS_CONFIG[myIbadah.jenis] || JENIS_CONFIG.lainnya;
        html += `<div style="margin-bottom:12px">
          <div style="font-size:10px;font-weight:600;color:var(--text-muted);text-transform:uppercase;letter-spacing:.5px;margin-bottom:6px;padding:0 2px">Rumah Ibadah Saya</div>
          <div class="data-item" style="border:1.5px solid #6366f1;background:rgba(99,102,241,0.06)" onclick="App.flyToIbadah(${myIbadah.id})">
            <div class="item-icon" style="color:#6366f1">${svgIcon(cfg.svgKey, 13, 13)}</div>
            <div class="item-info">
              <div class="item-name" style="font-weight:600">${myIbadah.nama}</div>
              <div class="item-sub">${myIbadah.kelurahan || '–'} ${myIbadah.kecamatan ? '· ' + myIbadah.kecamatan : ''}</div>
            </div>
            <span class="item-badge" style="background:rgba(99,102,241,0.15);color:#6366f1">${cfg.label}</span>
          </div>
        </div>
        <div style="font-size:10px;font-weight:600;color:var(--text-muted);text-transform:uppercase;letter-spacing:.5px;margin-bottom:6px;padding:0 2px">Semua Rumah Ibadah</div>`;
      }
    }

    if (!filtered.length) {
      container.innerHTML = html + `<div class="empty-state">${svgIcon('building', 26, 26)}<div>Tidak ada data</div></div>`;
      return;
    }

    const listHTML = filtered.map(d => {
      const cfg = JENIS_CONFIG[d.jenis] || JENIS_CONFIG.lainnya;
      const isMyIbadah = isKoor && parseInt(d.id) === parseInt(currentUser.rumah_ibadah_id);
      const styleAttr = isMyIbadah ? ` style="border:1.5px solid #6366f1;background:rgba(99,102,241,0.06)"` : '';
      return `<div class="data-item"${styleAttr} onclick="App.flyToIbadah(${d.id})">
        <div class="item-icon">${svgIcon(cfg.svgKey, 13, 13)}</div>
        <div class="item-info">
          <div class="item-name">${d.nama}</div>
          <div class="item-sub">${d.kelurahan || '–'} ${d.kecamatan ? '· ' + d.kecamatan : ''}</div>
        </div>
        <span class="item-badge" style="background:rgba(99,102,241,0.1);color:#6366f1">${cfg.label}</span>
      </div>`;
    }).join('');

    container.innerHTML = html + listHTML;
  }

  function renderWargaList() {
    const search = document.getElementById('search-warga')?.value || '';
    const kategori = document.getElementById('filter-warga-kategori')?.value || '';
    const status = document.getElementById('filter-warga-status')?.value || '';
    const rekomendasi = document.getElementById('filter-warga-rekomendasi')?.value || '';
    const container = document.getElementById('warga-list');
    if (!container) return;
    const visibleWarga = getWargaForRole();
    const filtered = visibleWarga.filter(d => {
      const matchSearch = !search || d.nama_kepala_keluarga.toLowerCase().includes(search.toLowerCase()) || (d.no_kk || '').includes(search) || (d.nik || '').includes(search);
      const matchKat = !kategori || (d.kategori_kemiskinan && d.kategori_kemiskinan === kategori);
      const matchSts = !status || (d.status_bantuan && d.status_bantuan === status);
      const matchRek = !rekomendasi || (d.rekomendasi_bantuan && d.rekomendasi_bantuan === rekomendasi);
      return matchSearch && matchKat && matchSts && matchRek;
    });
    if (!filtered.length) { container.innerHTML = `<div class="empty-state">${svgIcon('home', 26, 26)}<div>Tidak ada data</div></div>`; return; }
    container.innerHTML = filtered.map(d => {
      const rek = REK_CONFIG[d.rekomendasi_bantuan] || REK_CONFIG.tidak_ada;
      const cat = d.kategori_kemiskinan ? (KATEGORI_CONFIG[d.kategori_kemiskinan] || KATEGORI_CONFIG.miskin) : null;
      const sts = STATUS_CONFIG[d.status_bantuan] || STATUS_CONFIG.belum_terima;
      const subInfo = cat
        ? `${cat.label}${d.jumlah_tanggungan != null ? ' · ' + d.jumlah_tanggungan + ' jiwa' : ''}`
        : `<span class="badge ${sts.cls}">${sts.label}</span>`;
      return `<div class="data-item" onclick="App.flyToWarga(${d.id})">
        <div class="item-icon">${svgIcon('home', 13, 13)}</div>
        <div class="item-info">
          <div class="item-name">${d.nama_kepala_keluarga}</div>
          <div class="item-sub">${subInfo}</div>
        </div>
        <span class="item-badge ${rek.cls}">${rek.label}</span>
      </div>`;
    }).join('');
  }

  function flyToIbadah(id) {
    const d = ibadahData.find(x => parseInt(x.id) === parseInt(id));
    if (!d) return;
    panToPoint(d.latitude, d.longitude, 16);
    setTimeout(() => {
      const m = ibadahMarkers[id];
      if (m) { drawRadius(d, m); showInfoIbadah(d); }
    }, 600);
  }

  function flyToWarga(id) {
    const d = wargaData.find(x => parseInt(x.id) === parseInt(id));
    if (!d) return;
    panToPoint(d.latitude, d.longitude, 17);
    setTimeout(() => showInfoWarga(d), 600);
  }

  /* ══════════════════════════════════════════════════
     MODAL HELPERS
  ══════════════════════════════════════════════════ */
  function closeModal(id) {
    document.getElementById(id).classList.remove('show');
    if (tempMarker) { map.removeLayer(tempMarker); tempMarker = null; }
    if (addMode) cancelAddMode();
    if (id === 'modal-warga') {
      document.body.classList.remove('side-by-side-modals');
    }
  }

  /* ══════════════════════════════════════════════════
     TOAST
  ══════════════════════════════════════════════════ */
  function showToast(msg, type = 'info', duration = 3500) {
    const container = document.getElementById('toast-container');
    const toast = document.createElement('div');
    toast.className = `toast ${type}`;
    const icons = { success: svgIcon('check', 14, 14), error: svgIcon('x', 14, 14), info: svgIcon('info', 14, 14) };
    toast.innerHTML = `<span class="toast-icon">${icons[type] || icons.info}</span><span>${msg}</span>`;
    container.appendChild(toast);
    setTimeout(() => { toast.style.cssText += ';opacity:0;transform:translateX(16px);transition:all 0.25s'; setTimeout(() => toast.remove(), 250); }, duration);
  }

  /* ══════════════════════════════════════════════════
     TABS
  ══════════════════════════════════════════════════ */
  function initTabs() {
    // Sidebar tabs
    document.querySelectorAll('.tab-btn').forEach(btn => {
      btn.addEventListener('click', () => {
        document.querySelectorAll('.tab-btn').forEach(b => b.classList.remove('active'));
        document.querySelectorAll('.tab-panel').forEach(p => p.classList.remove('active'));
        btn.classList.add('active');
        document.getElementById('tab-' + btn.dataset.tab).classList.add('active');

        if (btn.dataset.tab === 'laporan' && window.FiturBaru && FiturBaru.Laporan) {
          FiturBaru.Laporan.loadList();
        }
      });
    });

    // Modal sub-tabs — scope ke dalam masing-masing modal
    document.querySelectorAll('.modal-overlay').forEach(modalOverlay => {
      modalOverlay.querySelectorAll('.modal-tab-btn').forEach(btn => {
        btn.addEventListener('click', () => {
          modalOverlay.querySelectorAll('.modal-tab-btn').forEach(b => b.classList.remove('active'));
          modalOverlay.querySelectorAll('.modal-tab-panel').forEach(p => p.classList.remove('active'));
          btn.classList.add('active');
          const panelId = 'mtab-' + btn.dataset.mtab;
          const panel = document.getElementById(panelId);
          if (panel) panel.classList.add('active');
        });
      });
    });
  }

  /* ══════════════════════════════════════════════════
     SEARCH & FILTER
  ══════════════════════════════════════════════════ */
  function initSearchFilter() {
    document.getElementById('search-ibadah')?.addEventListener('input', renderIbadahList);
    document.getElementById('filter-ibadah-jenis')?.addEventListener('change', renderIbadahList);
    document.getElementById('filter-ibadah-reset')?.addEventListener('click', () => {
      document.getElementById('search-ibadah').value = '';
      document.getElementById('filter-ibadah-jenis').value = '';
      renderIbadahList();
    });

    document.getElementById('search-warga')?.addEventListener('input', renderWargaList);
    document.getElementById('filter-warga-kategori')?.addEventListener('change', renderWargaList);
    document.getElementById('filter-warga-status')?.addEventListener('change', renderWargaList);
    document.getElementById('filter-warga-rekomendasi')?.addEventListener('change', renderWargaList);
    document.getElementById('filter-warga-reset')?.addEventListener('click', () => {
      document.getElementById('search-warga').value = '';
      document.getElementById('filter-warga-kategori').value = '';
      document.getElementById('filter-warga-status').value = '';
      document.getElementById('filter-warga-rekomendasi').value = '';
      renderWargaList();
    });

    document.getElementById('warga-penghasilan')?.addEventListener('input', previewRek);
    document.getElementById('warga-stspekerjaan')?.addEventListener('change', previewRek);
  }

  /* ══════════════════════════════════════════════════
     ANGGOTA ROWS
  ══════════════════════════════════════════════════ */
  function addAnggotaRow() {
    const container = document.getElementById('anggota-form-container');
    const idx = Date.now();
    anggotaRows.push(idx);
    container.insertAdjacentHTML('beforeend', buildAnggotaRow({}, idx));
    previewRek();
  }

  function removeAnggotaRow(idx) {
    const el = document.getElementById(`arow-${idx}`);
    if (el) el.remove();
    anggotaRows = anggotaRows.filter(r => r !== idx);
    previewRek();
  }

  async function verifyWargaNoChanges() {
    const wargaId = document.getElementById('warga-id').value;
    if (!wargaId) return;
    try {
      const today = new Date().toLocaleDateString('en-CA');
      const res = await fetch('api/verifikasi.php', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          warga_id: parseInt(wargaId),
          petugas: 'Admin',
          tanggal: today,
          catatan: 'Verifikasi langsung (data sesuai, tidak ada perubahan)'
        })
      });
      const json = await res.json();
      if (json.success) {
        showToast('Verifikasi berhasil dicatat (Data Sesuai)', 'success');
        closeModal('modal-warga');
        await loadWarga();
        loadStats();
        if (window.FiturBaru && FiturBaru.Verifikasi) {
          FiturBaru.Verifikasi.load(document.getElementById('filter-verif-status')?.value || '');
        }
      } else {
        showToast(json.message || 'Gagal verifikasi', 'error');
      }
    } catch (e) {
      showToast('Gagal memproses verifikasi', 'error');
    }
  }

  /* ══════════════════════════════════════════════════
     PUBLIC API
  ══════════════════════════════════════════════════ */
  return {
    init() {
      initMap();
      initTabs();
      initRadiusControl();
      initSearchFilter();

      checkAuthStatus();

      // Bind login submit button
      document.getElementById('btn-login-submit')?.addEventListener('click', handleLogin);

      // Support enter key on login modal
      document.getElementById('login-password')?.addEventListener('keydown', e => {
        if (e.key === 'Enter') handleLogin();
      });

      // Bind login/logout toggle button
      document.getElementById('btn-auth-toggle')?.addEventListener('click', () => {
        if (currentUser) {
          handleLogout();
        } else {
          showAuthModal({ type: 'login' });
        }
      });

      // Bind logout confirmation button
      document.getElementById('btn-confirm-logout')?.addEventListener('click', doLogout);

      // Tombol tambah
      document.getElementById('btn-add-ibadah')?.addEventListener('click', () => {
        checkAuth({ type: 'add_ibadah' }, () => {
          setAddMode('ibadah');
          showToast('Klik peta untuk menentukan lokasi Rumah Ibadah', 'info');
        });
      });
      document.getElementById('btn-add-warga')?.addEventListener('click', () => {
        checkAuth({ type: 'add_warga' }, () => {
          setAddMode('warga');
          showToast('Klik peta untuk menentukan lokasi Rumah Warga', 'info');
        });
      });

      document.getElementById('btn-add-anggota-row')?.addEventListener('click', addAnggotaRow);
      document.getElementById('btn-save-ibadah')?.addEventListener('click', saveIbadah);
      document.getElementById('btn-save-warga')?.addEventListener('click', saveWarga);

      document.getElementById('tool-fit')?.addEventListener('click', () => {
        const all = [...ibadahData, ...wargaData];
        if (!all.length) return;
        map.fitBounds(L.latLngBounds(all.map(d => [d.latitude, d.longitude])), { padding: [40, 40] });
      });
      document.getElementById('tool-clear-radius')?.addEventListener('click', clearRadius);
      document.getElementById('info-close')?.addEventListener('click', () => document.getElementById('info-panel').classList.remove('show'));
      document.getElementById('radius-info-close')?.addEventListener('click', clearRadius);

      document.querySelectorAll('[data-modal-close]').forEach(btn => {
        btn.addEventListener('click', () => closeModal(btn.dataset.modalClose));
      });

      document.addEventListener('keydown', e => {
        if (e.key === 'Escape') {
          cancelAddMode();
          document.getElementById('info-panel').classList.remove('show');
          document.querySelectorAll('.modal-overlay').forEach(m => m.classList.remove('show'));
        }
      });
    },

    // Exposed untuk onclick di HTML
    editIbadah, deleteIbadah,
    editWarga, deleteWarga,
    flyToIbadah, flyToWarga,
    removeAnggotaRow,
    previewRek,
    verifyWargaNoChanges,

    // Exposed helper functions
    getCurrentUser() { return currentUser; },
    checkAuth,
    showAuthModal,
    doLogout,
    handleAuthToggle() {
      if (currentUser) {
        handleLogout();
      } else {
        showAuthModal({ type: 'login' });
      }
    },
    getIbadahData() { return ibadahData; },
    getWargaData() { return wargaData; },
    loadWarga,
    haversine
  };
})();

// Expose App globally
window.App = App;

document.addEventListener('DOMContentLoaded', () => {
  App.init();

  // Mobile menu toggle
  const mobileMenuBtn = document.getElementById('mobile-menu-btn');
  const sidebar = document.getElementById('sidebar');
  let overlay = document.querySelector('.sidebar-overlay');
  
  if (!overlay) {
    overlay = document.createElement('div');
    overlay.className = 'sidebar-overlay';
    document.body.appendChild(overlay);
  }

  if (mobileMenuBtn && sidebar) {
    mobileMenuBtn.addEventListener('click', () => {
      sidebar.classList.toggle('show');
      overlay.classList.toggle('show');
    });

    overlay.addEventListener('click', () => {
      sidebar.classList.remove('show');
      overlay.classList.remove('show');
    });

    // Close sidebar on tab click in mobile
    document.querySelectorAll('.tab-btn').forEach(btn => {
      btn.addEventListener('click', () => {
        if (window.innerWidth <= 768) {
          sidebar.classList.remove('show');
          overlay.classList.remove('show');
        }
      });
    });
  }
});