{"id":1134,"date":"2026-03-02T03:36:22","date_gmt":"2026-03-02T03:36:22","guid":{"rendered":"https:\/\/marineconservation.id\/?page_id=1134"},"modified":"2026-03-14T15:43:10","modified_gmt":"2026-03-14T15:43:10","slug":"e-coral-id","status":"publish","type":"page","link":"https:\/\/marineconservation.id\/id\/e-coral-id\/","title":{"rendered":"e-Coral Indonesia"},"content":{"rendered":"<style>.elementor-1134 .elementor-element.elementor-element-dfd310d{--display:flex;--flex-direction:column;--container-widget-width:100%;--container-widget-height:initial;--container-widget-flex-grow:0;--container-widget-align-self:initial;--flex-wrap-mobile:wrap;}.elementor-1134 .elementor-element.elementor-element-1ba2d08{--display:flex;--flex-direction:column;--container-widget-width:100%;--container-widget-height:initial;--container-widget-flex-grow:0;--container-widget-align-self:initial;--flex-wrap-mobile:wrap;}<\/style>\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"1134\" class=\"elementor elementor-1134\" data-elementor-post-type=\"page\">\n\t\t\t\t<div class=\"elementor-element elementor-element-dfd310d e-flex e-con-boxed e-con e-parent\" data-id=\"dfd310d\" data-element_type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-056ba15 elementor-widget elementor-widget-html\" data-id=\"056ba15\" data-element_type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<div style=\"max-width:1200px; margin:0 auto; font-family:Arial, sans-serif;\">\r\n    <h2 style=\"color:#0284c7;\">\ud83c\udf0a e-Coral Indonesia<\/h2>\r\n    <div style=\"display:flex; flex-wrap:wrap; gap:20px;\">\r\n        <!-- Kolom Peta Utama (dengan filter di atas) -->\r\n        <div style=\"flex:2; min-width:300px;\">\r\n            <!-- Filter di atas peta -->\r\n            <div style=\"margin-bottom:10px; display:flex; gap:5px; flex-wrap:wrap; align-items:center;\">\r\n                <select id=\"filterProvince\" style=\"padding:5px; border:1px solid #ccc; border-radius:5px; min-width:120px;\">\r\n                    <option value=\"\">Semua Provinsi<\/option>\r\n                <\/select>\r\n                <select id=\"filterDistrict\" style=\"padding:5px; border:1px solid #ccc; border-radius:5px; min-width:120px;\">\r\n                    <option value=\"\">Semua Kab\/Kota<\/option>\r\n                <\/select>\r\n                <input type=\"text\" id=\"searchInput\" placeholder=\"Cari lokasi, surveyor...\" style=\"flex:1; min-width:150px; padding:5px; border:1px solid #ccc; border-radius:5px;\">\r\n                <select id=\"filterGenus\" style=\"width:150px; padding:5px; border:1px solid #ccc; border-radius:5px;\">\r\n                    <option value=\"\">Semua Genus<\/option>\r\n                <\/select>\r\n                <input type=\"number\" id=\"filterMinCover\" placeholder=\"Min %\" step=\"0.1\" style=\"width:80px; padding:5px; border:1px solid #ccc; border-radius:5px;\">\r\n                <button id=\"applyFilter\" style=\"background:#0284c7; color:white; border:none; padding:5px 10px; border-radius:5px; cursor:pointer;\">\ud83d\udd0d<\/button>\r\n            <\/div>\r\n            <div id=\"map\" style=\"height:500px; border-radius:10px; overflow:hidden; box-shadow:0 2px 8px rgba(0,0,0,0.1);\"><\/div>\r\n        <\/div>\r\n\r\n        <!-- Kolom Form (hanya muncul jika login) -->\r\n        <div id=\"formSection\" style=\"flex:1.2; min-width:300px; background:#f9f9f9; padding:20px; border-radius:10px; box-shadow:0 2px 8px rgba(0,0,0,0.1); display:none;\">\r\n            <!-- Form akan diisi oleh JavaScript jika login -->\r\n        <\/div>\r\n        <!-- Info jika belum login -->\r\n        <div id=\"loginPrompt\" style=\"flex:1.2; min-width:300px; background:#f9f9f9; padding:20px; border-radius:10px; box-shadow:0 2px 8px rgba(0,0,0,0.1); text-align:center;\">\r\n            <p>\ud83d\udd12 Anda belum login.<\/p>\r\n            <p>\r\n                <a href=\"\/id\/wp-login.php\/?redirect_to=<?php echo urlencode('https:\/\/marineconservation.id\/e-coral-ntb\/'); ?>\" style=\"background:#0284c7; color:white; padding:10px 20px; text-decoration:none; border-radius:5px; display:inline-block; margin-right:10px;\">Login<\/a>\r\n                <a href=\"\/id\/wp-login.php\/?action=register&redirect_to=<?php echo urlencode('https:\/\/marineconservation.id\/e-coral-ntb\/'); ?>\" style=\"background:#2e7d32; color:white; padding:10px 20px; text-decoration:none; border-radius:5px; display:inline-block;\">Daftar<\/a>\r\n            <\/p>\r\n            <p style=\"font-size:12px; color:#666;\">Peta menampilkan semua data publik. Tabel hanya menampilkan data Anda.<\/p>\r\n        <\/div>\r\n    <\/div>\r\n<\/div>\r\n\r\n<!-- Bagian Tabel dan Download -->\r\n<div style=\"margin-top:30px; background:white; padding:20px; border-radius:10px; box-shadow:0 2px 8px rgba(0,0,0,0.1);\">\r\n    <h3 style=\"margin-top:0; color:#0284c7;\">\ud83d\udccb Data Tersimpan<\/h3>\r\n    \r\n    <!-- Pilihan Format dan Tombol Download -->\r\n    <div style=\"margin-bottom:15px; display:flex; gap:10px; flex-wrap:wrap; align-items:center;\">\r\n        <select id=\"formatSelect\" style=\"padding:8px; border:1px solid #ccc; border-radius:5px; min-width:100px;\">\r\n            <option value=\"csv\">CSV<\/option>\r\n            <option value=\"xlsx\">XLSX (Excel)<\/option>\r\n            <option value=\"txt\">TXT<\/option>\r\n        <\/select>\r\n        <button id=\"downloadBtn\" style=\"background:#2e7d32; color:white; border:none; padding:8px 15px; border-radius:5px; cursor:pointer;\">\ud83d\udce5 Download (Data Saya)<\/button>\r\n    <\/div>\r\n\r\n    <!-- Tabel Data -->\r\n    <div style=\"overflow-x:auto;\">\r\n        <table id=\"dataTable\" style=\"width:100%; border-collapse:collapse; font-size:14px;\">\r\n            <thead>\r\n                <tr style=\"background:#f1f5f9;\">\r\n                    <th style=\"padding:10px; text-align:left;\">Lokasi<\/th>\r\n                    <th style=\"padding:10px; text-align:left;\">Provinsi<\/th>\r\n                    <th style=\"padding:10px; text-align:left;\">Kab\/Kota<\/th>\r\n                    <th style=\"padding:10px; text-align:left;\">Lat<\/th>\r\n                    <th style=\"padding:10px; text-align:left;\">Lng<\/th>\r\n                    <th style=\"padding:10px; text-align:left;\">Tutupan HC (%)<\/th>\r\n                    <th style=\"padding:10px; text-align:left;\">Kontributor<\/th>\r\n                    <th style=\"padding:10px; text-align:left;\">Surveyor<\/th>\r\n                    <th style=\"padding:10px; text-align:left;\">Instansi<\/th>\r\n                    <th style=\"padding:10px; text-align:left;\">Tanggal<\/th>\r\n                    <th style=\"padding:10px; text-align:left;\">Kedalaman<\/th>\r\n                    <th style=\"padding:10px; text-align:left;\">Tipe Terumbu<\/th>\r\n                    <th style=\"padding:10px; text-align:left;\">Posisi<\/th>\r\n                    <th style=\"padding:10px; text-align:left;\">Visibility<\/th>\r\n                    <th style=\"padding:10px; text-align:left;\">Metode<\/th>\r\n                    <th style=\"padding:10px; text-align:left;\">Panjang Line<\/th>\r\n                    <th style=\"padding:10px; text-align:left;\">Hard Coral Genus<\/th>\r\n                    <th style=\"padding:10px; text-align:left;\">Soft Coral Genus<\/th>\r\n                    <th style=\"padding:10px; text-align:left;\">Soft Coral (%)<\/th>\r\n                    <th style=\"padding:10px; text-align:left;\">Aksi<\/th>\r\n                <\/tr>\r\n            <\/thead>\r\n            <tbody id=\"tableBody\">\r\n                <tr><td colspan=\"20\" style=\"text-align:center; padding:20px;\">Memuat data...<\/td><\/tr>\r\n            <\/tbody>\r\n        <\/table>\r\n    <\/div>\r\n<\/div>\r\n\r\n<!-- Leaflet, SheetJS, dan MarkerCluster -->\r\n<link rel=\"stylesheet\" href=\"https:\/\/unpkg.com\/leaflet@1.9.4\/dist\/leaflet.css\" \/>\r\n<link rel=\"stylesheet\" href=\"https:\/\/unpkg.com\/leaflet.markercluster@1.4.1\/dist\/MarkerCluster.css\" \/>\r\n<link rel=\"stylesheet\" href=\"https:\/\/unpkg.com\/leaflet.markercluster@1.4.1\/dist\/MarkerCluster.Default.css\" \/>\r\n<script src=\"https:\/\/unpkg.com\/leaflet@1.9.4\/dist\/leaflet.js\"><\/script>\r\n<script src=\"https:\/\/unpkg.com\/leaflet.markercluster@1.4.1\/dist\/leaflet.markercluster.js\"><\/script>\r\n<script src=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/xlsx\/0.18.5\/xlsx.full.min.js\"><\/script>\r\n\r\n<script>\r\n\/\/ ================== OBJEK INDONESIA REGIONS ==================\r\nconst indonesiaRegions = {\r\n    \"Aceh\": [\"Aceh Barat\", \"Aceh Barat Daya\", \"Aceh Besar\", \"Aceh Jaya\", \"Aceh Selatan\", \"Aceh Singkil\", \"Aceh Tamiang\", \"Aceh Tengah\", \"Aceh Tenggara\", \"Aceh Timur\", \"Aceh Utara\", \"Bener Meriah\", \"Bireuen\", \"Gayo Lues\", \"Nagan Raya\", \"Pidie\", \"Pidie Jaya\", \"Simeulue\", \"Kota Banda Aceh\", \"Kota Langsa\", \"Kota Lhokseumawe\", \"Kota Sabang\", \"Kota Subulussalam\"],\r\n    \"Sumatera Utara\": [\"Asahan\", \"Batu Bara\", \"Dairi\", \"Deli Serdang\", \"Humbang Hasundutan\", \"Karo\", \"Labuhanbatu\", \"Labuhanbatu Selatan\", \"Labuhanbatu Utara\", \"Langkat\", \"Mandailing Natal\", \"Nias\", \"Nias Barat\", \"Nias Selatan\", \"Nias Utara\", \"Padang Lawas\", \"Padang Lawas Utara\", \"Pakpak Bharat\", \"Samosir\", \"Serdang Bedagai\", \"Simalungun\", \"Tapanuli Selatan\", \"Tapanuli Tengah\", \"Tapanuli Utara\", \"Toba Samosir\", \"Kota Binjai\", \"Kota Gunungsitoli\", \"Kota Medan\", \"Kota Padangsidimpuan\", \"Kota Pematangsiantar\", \"Kota Sibolga\", \"Kota Tanjungbalai\", \"Kota Tebing Tinggi\"],\r\n    \"Sumatera Barat\": [\"Agam\", \"Dharmasraya\", \"Kepulauan Mentawai\", \"Lima Puluh Kota\", \"Padang Pariaman\", \"Pasaman\", \"Pasaman Barat\", \"Pesisir Selatan\", \"Sijunjung\", \"Solok\", \"Solok Selatan\", \"Tanah Datar\", \"Kota Bukittinggi\", \"Kota Padang\", \"Kota Padang Panjang\", \"Kota Pariaman\", \"Kota Payakumbuh\", \"Kota Sawahlunto\", \"Kota Solok\"],\r\n    \"Riau\": [\"Bengkalis\", \"Indragiri Hilir\", \"Indragiri Hulu\", \"Kampar\", \"Kepulauan Meranti\", \"Kuantan Singingi\", \"Pelalawan\", \"Rokan Hilir\", \"Rokan Hulu\", \"Siak\", \"Kota Dumai\", \"Kota Pekanbaru\"],\r\n    \"Kepulauan Riau\": [\"Bintan\", \"Karimun\", \"Kepulauan Anambas\", \"Lingga\", \"Natuna\", \"Kota Batam\", \"Kota Tanjungpinang\"],\r\n    \"Jambi\": [\"Batanghari\", \"Bungo\", \"Kerinci\", \"Merangin\", \"Muaro Jambi\", \"Sarolangun\", \"Tanjung Jabung Barat\", \"Tanjung Jabung Timur\", \"Tebo\", \"Kota Jambi\", \"Kota Sungai Penuh\"],\r\n    \"Bengkulu\": [\"Bengkulu Selatan\", \"Bengkulu Tengah\", \"Bengkulu Utara\", \"Kaur\", \"Kepahiang\", \"Lebong\", \"Muko Muko\", \"Rejang Lebong\", \"Seluma\", \"Kota Bengkulu\"],\r\n    \"Sumatera Selatan\": [\"Banyuasin\", \"Empat Lawang\", \"Lahat\", \"Muara Enim\", \"Musi Banyuasin\", \"Musi Rawas\", \"Musi Rawas Utara\", \"Ogan Ilir\", \"Ogan Komering Ilir\", \"Ogan Komering Ulu\", \"Ogan Komering Ulu Selatan\", \"Ogan Komering Ulu Timur\", \"Penukal Abab Lematang Ilir\", \"Kota Lubuklinggau\", \"Kota Pagar Alam\", \"Kota Palembang\", \"Kota Prabumulih\"],\r\n    \"Bangka Belitung\": [\"Bangka\", \"Bangka Barat\", \"Bangka Selatan\", \"Bangka Tengah\", \"Belitung\", \"Belitung Timur\", \"Kota Pangkalpinang\"],\r\n    \"Lampung\": [\"Lampung Barat\", \"Lampung Selatan\", \"Lampung Tengah\", \"Lampung Timur\", \"Lampung Utara\", \"Mesuji\", \"Pesawaran\", \"Pesisir Barat\", \"Pringsewu\", \"Tanggamus\", \"Tulang Bawang\", \"Tulang Bawang Barat\", \"Way Kanan\", \"Kota Bandar Lampung\", \"Kota Metro\"],\r\n    \"Banten\": [\"Lebak\", \"Pandeglang\", \"Serang\", \"Tangerang\", \"Kota Cilegon\", \"Kota Serang\", \"Kota Tangerang\", \"Kota Tangerang Selatan\"],\r\n    \"DKI Jakarta\": [\"Kepulauan Seribu\", \"Kota Jakarta Barat\", \"Kota Jakarta Pusat\", \"Kota Jakarta Selatan\", \"Kota Jakarta Timur\", \"Kota Jakarta Utara\"],\r\n    \"Jawa Barat\": [\"Bandung\", \"Bandung Barat\", \"Bekasi\", \"Bogor\", \"Ciamis\", \"Cianjur\", \"Cirebon\", \"Garut\", \"Indramayu\", \"Karawang\", \"Kuningan\", \"Majalengka\", \"Pangandaran\", \"Purwakarta\", \"Subang\", \"Sukabumi\", \"Sumedang\", \"Tasikmalaya\", \"Kota Bandung\", \"Kota Banjar\", \"Kota Bekasi\", \"Kota Bogor\", \"Kota Cimahi\", \"Kota Cirebon\", \"Kota Depok\", \"Kota Sukabumi\", \"Kota Tasikmalaya\"],\r\n    \"Jawa Tengah\": [\"Banjarnegara\", \"Banyumas\", \"Batang\", \"Blora\", \"Boyolali\", \"Brebes\", \"Cilacap\", \"Demak\", \"Grobogan\", \"Jepara\", \"Karanganyar\", \"Kebumen\", \"Kendal\", \"Klaten\", \"Kudus\", \"Magelang\", \"Pati\", \"Pekalongan\", \"Pemalang\", \"Purbalingga\", \"Purworejo\", \"Rembang\", \"Semarang\", \"Sragen\", \"Sukoharjo\", \"Tegal\", \"Temanggung\", \"Wonogiri\", \"Wonosobo\", \"Kota Magelang\", \"Kota Pekalongan\", \"Kota Salatiga\", \"Kota Semarang\", \"Kota Surakarta\", \"Kota Tegal\"],\r\n    \"DI Yogyakarta\": [\"Bantul\", \"Gunungkidul\", \"Kulon Progo\", \"Sleman\", \"Kota Yogyakarta\"],\r\n    \"Jawa Timur\": [\"Bangkalan\", \"Banyuwangi\", \"Blitar\", \"Bojonegoro\", \"Bondowoso\", \"Gresik\", \"Jember\", \"Jombang\", \"Kediri\", \"Lamongan\", \"Lumajang\", \"Madiun\", \"Magetan\", \"Malang\", \"Mojokerto\", \"Nganjuk\", \"Ngawi\", \"Pacitan\", \"Pamekasan\", \"Pasuruan\", \"Ponorogo\", \"Probolinggo\", \"Sampang\", \"Sidoarjo\", \"Situbondo\", \"Sumenep\", \"Trenggalek\", \"Tuban\", \"Tulungagung\", \"Kota Batu\", \"Kota Blitar\", \"Kota Kediri\", \"Kota Madiun\", \"Kota Malang\", \"Kota Mojokerto\", \"Kota Pasuruan\", \"Kota Probolinggo\", \"Kota Surabaya\"],\r\n    \"Bali\": [\"Badung\", \"Bangli\", \"Buleleng\", \"Gianyar\", \"Jembrana\", \"Karangasem\", \"Klungkung\", \"Tabanan\", \"Kota Denpasar\"],\r\n    \"Nusa Tenggara Barat\": [\"Bima\", \"Dompu\", \"Lombok Barat\", \"Lombok Tengah\", \"Lombok Timur\", \"Lombok Utara\", \"Sumbawa\", \"Sumbawa Barat\", \"Kota Bima\", \"Kota Mataram\"],\r\n    \"Nusa Tenggara Timur\": [\"Alor\", \"Belu\", \"Ende\", \"Flores Timur\", \"Kupang\", \"Lembata\", \"Malaka\", \"Manggarai\", \"Manggarai Barat\", \"Manggarai Timur\", \"Nagekeo\", \"Ngada\", \"Rote Ndao\", \"Sabu Raijua\", \"Sikka\", \"Sumba Barat\", \"Sumba Barat Daya\", \"Sumba Tengah\", \"Sumba Timur\", \"Timor Tengah Selatan\", \"Timor Tengah Utara\", \"Kota Kupang\"],\r\n    \"Kalimantan Barat\": [\"Bengkayang\", \"Kapuas Hulu\", \"Kayong Utara\", \"Ketapang\", \"Kubu Raya\", \"Landak\", \"Melawi\", \"Mempawah\", \"Sambas\", \"Sanggau\", \"Sekadau\", \"Sintang\", \"Kota Pontianak\", \"Kota Singkawang\"],\r\n    \"Kalimantan Tengah\": [\"Barito Selatan\", \"Barito Timur\", \"Barito Utara\", \"Gunung Mas\", \"Kapuas\", \"Katingan\", \"Kotawaringin Barat\", \"Kotawaringin Timur\", \"Lamandau\", \"Murung Raya\", \"Pulang Pisau\", \"Sukamara\", \"Seruyan\", \"Kota Palangka Raya\"],\r\n    \"Kalimantan Selatan\": [\"Balangan\", \"Banjar\", \"Barito Kuala\", \"Hulu Sungai Selatan\", \"Hulu Sungai Tengah\", \"Hulu Sungai Utara\", \"Kotabaru\", \"Tabalong\", \"Tanah Bumbu\", \"Tanah Laut\", \"Tapin\", \"Kota Banjarbaru\", \"Kota Banjarmasin\"],\r\n    \"Kalimantan Timur\": [\"Berau\", \"Kutai Barat\", \"Kutai Kartanegara\", \"Kutai Timur\", \"Mahakam Ulu\", \"Paser\", \"Penajam Paser Utara\", \"Kota Balikpapan\", \"Kota Bontang\", \"Kota Samarinda\"],\r\n    \"Kalimantan Utara\": [\"Bulungan\", \"Malinau\", \"Nunukan\", \"Tana Tidung\", \"Kota Tarakan\"],\r\n    \"Sulawesi Utara\": [\"Bolaang Mongondow\", \"Bolaang Mongondow Selatan\", \"Bolaang Mongondow Timur\", \"Bolaang Mongondow Utara\", \"Kepulauan Sangihe\", \"Kepulauan Siau Tagulandang Biaro\", \"Kepulauan Talaud\", \"Minahasa\", \"Minahasa Selatan\", \"Minahasa Tenggara\", \"Minahasa Utara\", \"Kota Bitung\", \"Kota Kotamobagu\", \"Kota Manado\", \"Kota Tomohon\"],\r\n    \"Gorontalo\": [\"Boalemo\", \"Bone Bolango\", \"Gorontalo\", \"Gorontalo Utara\", \"Pohuwato\", \"Kota Gorontalo\"],\r\n    \"Sulawesi Tengah\": [\"Banggai\", \"Banggai Kepulauan\", \"Banggai Laut\", \"Buol\", \"Donggala\", \"Morowali\", \"Morowali Utara\", \"Parigi Moutong\", \"Poso\", \"Sigi\", \"Tojo Una-Una\", \"Toli-Toli\", \"Kota Palu\"],\r\n    \"Sulawesi Barat\": [\"Majene\", \"Mamasa\", \"Mamuju\", \"Mamuju Tengah\", \"Pasangkayu\", \"Polewali Mandar\"],\r\n    \"Sulawesi Selatan\": [\"Bantaeng\", \"Barru\", \"Bone\", \"Bulukumba\", \"Enrekang\", \"Gowa\", \"Jeneponto\", \"Kepulauan Selayar\", \"Luwu\", \"Luwu Timur\", \"Luwu Utara\", \"Maros\", \"Pangkajene dan Kepulauan\", \"Pinrang\", \"Sidenreng Rappang\", \"Sinjai\", \"Soppeng\", \"Takalar\", \"Tana Toraja\", \"Toraja Utara\", \"Wajo\", \"Kota Makassar\", \"Kota Palopo\", \"Kota Parepare\"],\r\n    \"Sulawesi Tenggara\": [\"Bombana\", \"Buton\", \"Buton Selatan\", \"Buton Tengah\", \"Buton Utara\", \"Kolaka\", \"Kolaka Timur\", \"Kolaka Utara\", \"Konawe\", \"Konawe Kepulauan\", \"Konawe Selatan\", \"Konawe Utara\", \"Muna\", \"Muna Barat\", \"Wakatobi\", \"Kota Bau-Bau\", \"Kota Kendari\"],\r\n    \"Maluku\": [\"Buru\", \"Buru Selatan\", \"Kepulauan Aru\", \"Maluku Barat Daya\", \"Maluku Tengah\", \"Maluku Tenggara\", \"Maluku Tenggara Barat\", \"Seram Bagian Barat\", \"Seram Bagian Timur\", \"Kota Ambon\", \"Kota Tual\"],\r\n    \"Maluku Utara\": [\"Halmahera Barat\", \"Halmahera Tengah\", \"Halmahera Timur\", \"Halmahera Selatan\", \"Halmahera Utara\", \"Kepulauan Sula\", \"Pulau Morotai\", \"Pulau Taliabu\", \"Kota Ternate\", \"Kota Tidore Kepulauan\"],\r\n    \"Papua\": [\"Asmat\", \"Biak Numfor\", \"Boven Digoel\", \"Deiyai\", \"Dogiyai\", \"Intan Jaya\", \"Jayapura\", \"Jayawijaya\", \"Keerom\", \"Kepulauan Yapen\", \"Lanny Jaya\", \"Mamberamo Raya\", \"Mamberamo Tengah\", \"Mappi\", \"Merauke\", \"Mimika\", \"Nabire\", \"Nduga\", \"Paniai\", \"Pegunungan Bintang\", \"Puncak\", \"Puncak Jaya\", \"Sarmi\", \"Supiori\", \"Tolikara\", \"Waropen\", \"Yahukimo\", \"Yalimo\", \"Kota Jayapura\"],\r\n    \"Papua Barat\": [\"Fakfak\", \"Kaimana\", \"Manokwari\", \"Manokwari Selatan\", \"Maybrat\", \"Pegunungan Arfak\", \"Raja Ampat\", \"Sorong\", \"Sorong Selatan\", \"Tambrauw\", \"Teluk Bintuni\", \"Teluk Wondama\", \"Kota Sorong\"],\r\n    \"Papua Selatan\": [\"Merauke\", \"Mappi\", \"Asmat\", \"Boven Digoel\"],\r\n    \"Papua Tengah\": [\"Nabire\", \"Puncak Jaya\", \"Paniai\", \"Mimika\", \"Puncak\", \"Dogiyai\", \"Intan Jaya\", \"Deiyai\"],\r\n    \"Papua Pegunungan\": [\"Jayawijaya\", \"Lanny Jaya\", \"Mamberamo Tengah\", \"Nduga\", \"Pegunungan Bintang\", \"Tolikara\", \"Yahukimo\", \"Yalimo\"],\r\n    \"Papua Barat Daya\": [\"Sorong\", \"Sorong Selatan\", \"Raja Ampat\", \"Tambrauw\", \"Maybrat\", \"Kota Sorong\"]\r\n};\r\n\/\/ ================== END OF INDONESIA REGIONS ==================\r\n\r\n\/\/ Daftar Hard Coral dan Soft Coral\r\nconst hardCoralList = [\r\n    \"Acanthastrea\", \"Acropora\", \"Agaricia\", \"Alveopora\", \"Anomastraea\", \"Astrea\", \"Astrangia\", \"Astreopora\",\r\n    \"Australogyra\", \"Australomussa\", \"Balanophyllia\", \"Barabattoia\", \"Blastomussa\", \"Boninastrea\", \"Cantharellus\",\r\n    \"Catalaphyllia\", \"Caulastrea\", \"Cladocora\", \"Coelastrea\", \"Coeloseris\", \"Colpophyllia\", \"Coscinaraea\", \"Ctenactis\",\r\n    \"Ctenella\", \"Cycloseris\", \"Cynarina\", \"Cyphastrea\", \"Dendrogyra\", \"Diaseris\", \"Dichocoenia\", \"Diploastrea\",\r\n    \"Diploria\", \"Dipsastraea\", \"Duncanopsammia\", \"Echinomorpha\", \"Echinophyllia\", \"Echinopora\", \"Erythrastrea\",\r\n    \"Euphyllia\", \"Eusmilia\", \"Favia\", \"Favites\", \"Fungia\", \"Galaxea\", \"Goniastrea\", \"Goniopora\", \"Gyrosmilia\",\r\n    \"Halomitra\", \"Heliofungia\", \"Heliopora\", \"Herpolitha\", \"Heterocyathus\", \"Heteropsammia\", \"Horastrea\", \"Hydnophora\",\r\n    \"Indophyllia\", \"Isophyllia\", \"Isopora\", \"Leptastrea\", \"Leptoria\", \"Leptoseris\", \"Lithophyllon\", \"Lobophyllia\",\r\n    \"Madracis\", \"Manicina\", \"Meandrina\", \"Merulina\", \"Micromussa\", \"Millepora\", \"Montastrea\", \"Montigyra\", \"Montipora\",\r\n    \"Moseleya\", \"Mussa\", \"Mussismilia\", \"Mycedium\", \"Mycetophyllia\", \"Nemenzophyllia\", \"Oculina\", \"Oulastrea\",\r\n    \"Oulophyllia\", \"Oxypora\", \"Pachyseris\", \"Palauastrea\", \"Paraclavarina\", \"Paragoniastrea\", \"Parasimplastrea\",\r\n    \"Pavona\", \"Pectinia\", \"Physogyra\", \"Physophyllia\", \"Platygyra\", \"Plerogyra\", \"Plesiastrea\", \"Pocillopora\",\r\n    \"Podabacia\", \"Polyphyllia\", \"Porites\", \"Poritipora\", \"Psammocora\", \"Pseudosiderastrea\", \"Sandalolitha\",\r\n    \"Scapophyllia\", \"Schizoculina\", \"Scolymia\", \"Seriatopora\", \"Siderastrea\", \"Simplastrea\", \"Solenastrea\",\r\n    \"Stephanocoenia\", \"Stylaraea\", \"Stylocoeniella\", \"Stylophora\", \"Symphyllia\", \"Trachyphyllia\", \"Tubipora\",\r\n    \"Turbinaria\", \"Zoopilus\"\r\n];\r\nconst softCoralList = [\r\n    \"Acrossota\", \"Anthelia\", \"Anthellia\", \"Antipathes (Black Coral)\", \"Asterospicularia\", \"Carijoa\",\r\n    \"Cespitularia\", \"Cladiella\", \"Clavularia\", \"Corallium (Precious Coral)\", \"Dendronephthya\", \"Efflatounaria\",\r\n    \"Heteroxenia\", \"Isis\", \"Klyxum\", \"Litophyton\", \"Lobophytum\", \"Nephthea\", \"Ovabunda\", \"Rumphella\",\r\n    \"Sansibia\", \"Sarcophyton\", \"Sarcothelia\", \"Sinularia\", \"Sympodium\", \"Xenia\"\r\n];\r\n\r\n\/\/ Gabungan semua genus untuk dropdown filter\r\nconst allGenusList = [...new Set([...hardCoralList, ...softCoralList])].sort();\r\n\r\n\/\/ ================== DAFTAR SUBSTRAT BARU ==================\r\nconst substrateList = [\r\n    { code: 'SP', name: 'Sponge', category: 'SP' },\r\n    { code: 'ZO', name: 'Zoanthid', category: 'OT' },\r\n    { code: 'OT', name: 'Other(Fauna)', category: 'OT' },\r\n    { code: 'AA', name: 'Algal assemblage', category: 'FS' },\r\n    { code: 'CA', name: 'Coralline algae', category: 'OT' },\r\n    { code: 'HA', name: 'Halimeda', category: 'OT' },\r\n    { code: 'MA', name: 'Makro Algae', category: 'FS' },\r\n    { code: 'TA', name: 'Turf Algae', category: 'DCA' },\r\n    { code: 'S', name: 'Sand', category: 'S' },\r\n    { code: 'R', name: 'Rubble', category: 'R' },\r\n    { code: 'SI', name: 'Silt', category: 'SI' },\r\n    { code: 'RK', name: 'Rock', category: 'RK' }\r\n];\r\n\/\/ ============================================================\r\n\r\n\/\/ ========== FUNGSI MEMBUAT HTML GRAFIK SUBSTRAT ==========\r\nfunction getSubstrateChartHTML(data) {\r\n    let html = '<div style=\"max-height:200px; overflow-y:auto; border:1px solid #ddd; padding:5px; border-radius:5px;\">';\r\n    substrateList.forEach(s => {\r\n        let val = parseFloat(data[`substrate_${s.code}`]) || 0;\r\n        let percent = val.toFixed(1);\r\n        html += `<div style=\"margin-bottom:8px; display:flex; align-items:center;\">\r\n            <span style=\"display:inline-block; width:40px; font-size:11px; font-weight:bold;\">${s.code}<\/span>\r\n            <span style=\"display:inline-block; width:35px; font-size:11px;\">${percent}%<\/span>\r\n            <div style=\"display:inline-block; width:120px; height:14px; background:#eee; border-radius:7px; overflow:hidden;\">\r\n                <div style=\"height:14px; width:${Math.min(percent,100)}%; background:#0284c7; border-radius:7px;\"><\/div>\r\n            <\/div>\r\n        <\/div>`;\r\n    });\r\n    html += '<\/div>';\r\n    return html;\r\n}\r\n\/\/ ============================================================\r\n\r\nlet currentUser = null;\r\nlet isSuperAdmin = false;\r\nlet allData = [];\r\nlet filteredAllData = [];\r\nlet filteredUserData = [];\r\n\r\n\/\/ ================== FUNGSI REVERSE GEOCODING DENGAN RADIUS ==================\r\nasync function fillFromCoordinates(lat, lng) {\r\n    const radii = [0, 5000, 10000, 20000, 50000, 100000];\r\n    let provinceFound = false;\r\n    let provinceName = \"\";\r\n    let responseData = null;\r\n\r\n    for (let radius of radii) {\r\n        try {\r\n            const url = `https:\/\/api.bigdatacloud.net\/data\/reverse-geocode-client?latitude=${lat}&longitude=${lng}&localityLanguage=id&radius=${radius}`;\r\n            const response = await fetch(url);\r\n            const data = await response.json();\r\n\r\n            if (!data || !data.localityInfo) continue;\r\n\r\n            data.localityInfo.administrative.forEach(admin => {\r\n                if (admin.adminLevel === 4) {\r\n                    provinceName = admin.name;\r\n                }\r\n            });\r\n\r\n            if (provinceName) {\r\n                responseData = data;\r\n                provinceFound = true;\r\n                break;\r\n            }\r\n        } catch (err) {\r\n            console.error(`Gagal dengan radius ${radius}:`, err);\r\n        }\r\n    }\r\n\r\n    if (!provinceFound) return;\r\n\r\n    const provinceMapping = {\r\n        \"Jakarta\": \"DKI Jakarta\",\r\n        \"Daerah Khusus Ibukota Jakarta\": \"DKI Jakarta\",\r\n        \"Yogyakarta\": \"DI Yogyakarta\",\r\n        \"Daerah Istimewa Yogyakarta\": \"DI Yogyakarta\",\r\n        \"Bali Province\": \"Bali\",\r\n        \"West Java\": \"Jawa Barat\",\r\n        \"Central Java\": \"Jawa Tengah\",\r\n        \"East Java\": \"Jawa Timur\",\r\n        \"West Nusa Tenggara\": \"Nusa Tenggara Barat\",\r\n        \"East Nusa Tenggara\": \"Nusa Tenggara Timur\",\r\n        \"North Sumatra\": \"Sumatera Utara\",\r\n        \"West Sumatra\": \"Sumatera Barat\",\r\n        \"South Sumatra\": \"Sumatera Selatan\",\r\n        \"Bangka Belitung Islands\": \"Bangka Belitung\",\r\n        \"Riau Islands\": \"Kepulauan Riau\",\r\n        \"Lampung\": \"Lampung\"\r\n    };\r\n    if (provinceMapping[provinceName]) provinceName = provinceMapping[provinceName];\r\n\r\n    const provinceSelect = document.getElementById(\"provinceSelect\");\r\n    const citySelect = document.getElementById(\"districtSelect\");\r\n    if (!provinceSelect) return;\r\n\r\n    let provinceMatched = false;\r\n    Array.from(provinceSelect.options).forEach(opt => {\r\n        if (opt.text.trim().toLowerCase() === provinceName.trim().toLowerCase()) {\r\n            provinceSelect.value = opt.value;\r\n            provinceMatched = true;\r\n        }\r\n    });\r\n    if (!provinceMatched) return;\r\n\r\n    provinceSelect.dispatchEvent(new Event('change'));\r\n\r\n    setTimeout(() => {\r\n        const selectedProv = provinceSelect.value;\r\n        if (!selectedProv || !indonesiaRegions[selectedProv]) return;\r\n\r\n        const possibleCities = indonesiaRegions[selectedProv];\r\n        let cityFound = \"\";\r\n\r\n        responseData.localityInfo.administrative.forEach(admin => {\r\n            possibleCities.forEach(city => {\r\n                const cleanApi = admin.name.toLowerCase()\r\n                    .replace(\"kota \", \"\")\r\n                    .replace(\"kabupaten \", \"\")\r\n                    .trim();\r\n                const cleanLocal = city.toLowerCase()\r\n                    .replace(\"kota \", \"\")\r\n                    .replace(\"kabupaten \", \"\")\r\n                    .trim();\r\n                if (cleanApi === cleanLocal) {\r\n                    cityFound = city;\r\n                }\r\n            });\r\n        });\r\n\r\n        if (cityFound) {\r\n            Array.from(citySelect.options).forEach(opt => {\r\n                if (opt.text === cityFound) {\r\n                    citySelect.value = opt.value;\r\n                }\r\n            });\r\n        }\r\n    }, 600);\r\n}\r\n\r\n\/\/ ================== FUNGSI CLUSTERING ==================\r\nfunction haversine(lat1, lon1, lat2, lon2) {\r\n    const R = 6371;\r\n    const dLat = (lat2 - lat1) * Math.PI \/ 180;\r\n    const dLon = (lon2 - lon1) * Math.PI \/ 180;\r\n    const a = Math.sin(dLat\/2) * Math.sin(dLat\/2) +\r\n              Math.cos(lat1 * Math.PI\/180) * Math.cos(lat2 * Math.PI\/180) *\r\n              Math.sin(dLon\/2) * Math.sin(dLon\/2);\r\n    const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));\r\n    return R * c;\r\n}\r\n\r\nfunction clusterByDistance(points, thresholdKm = 1.0) {\r\n    const n = points.length;\r\n    if (n === 0) return [];\r\n\r\n    const validIndices = [];\r\n    const coords = [];\r\n    points.forEach((p, idx) => {\r\n        const lat = parseFloat(p.latitude);\r\n        const lng = parseFloat(p.longitude);\r\n        if (!isNaN(lat) && !isNaN(lng)) {\r\n            validIndices.push(idx);\r\n            coords.push({ lat, lng, origIdx: idx });\r\n        }\r\n    });\r\n\r\n    const m = coords.length;\r\n    if (m === 0) return [];\r\n\r\n    const parent = Array.from({ length: m }, (_, i) => i);\r\n    function find(x) {\r\n        if (parent[x] !== x) parent[x] = find(parent[x]);\r\n        return parent[x];\r\n    }\r\n    function union(x, y) {\r\n        const rx = find(x), ry = find(y);\r\n        if (rx !== ry) parent[ry] = rx;\r\n    }\r\n\r\n    for (let i = 0; i < m; i++) {\r\n        for (let j = i + 1; j < m; j++) {\r\n            const d = haversine(coords[i].lat, coords[i].lng, coords[j].lat, coords[j].lng);\r\n            if (d <= thresholdKm) {\r\n                union(i, j);\r\n            }\r\n        }\r\n    }\r\n\r\n    const clustersMap = new Map();\r\n    for (let i = 0; i < m; i++) {\r\n        const root = find(i);\r\n        if (!clustersMap.has(root)) clustersMap.set(root, []);\r\n        clustersMap.get(root).push(coords[i].origIdx);\r\n    }\r\n    return Array.from(clustersMap.values());\r\n}\r\n\r\n\/\/ ================== INISIALISASI DOKUMEN ==================\r\ndocument.addEventListener('DOMContentLoaded', function() {\r\n    \/\/ Isi dropdown filter genus dengan daftar semua genus\r\n    const genusFilter = document.getElementById('filterGenus');\r\n    allGenusList.forEach(genus => {\r\n        const option = document.createElement('option');\r\n        option.value = genus;\r\n        option.textContent = genus;\r\n        genusFilter.appendChild(option);\r\n    });\r\n\r\n    \/\/ Cek login\r\n    fetch('\/cek_login.php')\r\n        .then(response => response.json())\r\n        .then(data => {\r\n            currentUser = data.logged_in ? data.username : null;\r\n            isSuperAdmin = (currentUser === 'ckradiwijaya@gmail.com');\r\n            \r\n            const formSection = document.getElementById('formSection');\r\n            const loginPrompt = document.getElementById('loginPrompt');\r\n            \r\n            if (data.logged_in) {\r\n                loginPrompt.style.display = 'none';\r\n                formSection.style.display = 'block';\r\n\r\n                \/\/ Buat HTML untuk input substrat berdasarkan substrateList\r\n                let substrateHtml = '';\r\n                substrateList.forEach(s => {\r\n                    substrateHtml += `<div><label>${s.code} - ${s.name}<\/label><input type=\"number\" step=\"0.1\" min=\"0\" max=\"100\" name=\"substrate_${s.code}\" style=\"width:100%; padding:4px;\"><\/div>`;\r\n                });\r\n                \r\n                \/\/ Isi form dengan HTML (termasuk substrat dan soft coral %)\r\n                formSection.innerHTML = `\r\n                    <h3 style=\"margin-top:0;\">\u2795 Tambah Data Baru<\/h3>\r\n                    <form id=\"coralForm\" method=\"post\" action=\"\/simpan_data.php\">\r\n                        <!-- Nama Site -->\r\n                        <div style=\"margin-bottom:12px;\">\r\n                            <label style=\"display:block; font-weight:bold; margin-bottom:5px;\">Nama Site <span style=\"color:red;\">*<\/span><\/label>\r\n                            <input type=\"text\" name=\"location_name\" required style=\"width:100%; padding:8px; border:1px solid #ccc; border-radius:5px;\">\r\n                        <\/div>\r\n\r\n                        <!-- Peta mini -->\r\n                        <div style=\"margin-bottom:12px;\">\r\n                            <label style=\"display:block; font-weight:bold; margin-bottom:5px;\">Pilih Titik Koordinat (klik peta)<\/label>\r\n                            <div id=\"mini-map\" style=\"height:200px; border-radius:5px; margin-bottom:5px;\"><\/div>\r\n                            <div style=\"display:flex; gap:5px;\">\r\n                                <input type=\"number\" step=\"any\" id=\"lat\" name=\"latitude\" required placeholder=\"Latitude\" style=\"flex:1; padding:8px; border:1px solid #ccc; border-radius:5px;\">\r\n                                <input type=\"number\" step=\"any\" id=\"lng\" name=\"longitude\" required placeholder=\"Longitude\" style=\"flex:1; padding:8px; border:1px solid #ccc; border-radius:5px;\">\r\n                            <\/div>\r\n                        <\/div>\r\n\r\n                        <!-- Wilayah -->\r\n                        <div style=\"display:grid; grid-template-columns:1fr 1fr; gap:10px; margin-bottom:10px;\">\r\n                            <div>\r\n                                <select name=\"province\" id=\"provinceSelect\" style=\"width:100%; padding:8px;\">\r\n                                    <option value=\"\">Pilih Provinsi<\/option>\r\n                                <\/select>\r\n                            <\/div>\r\n                            <div>\r\n                                <select name=\"district\" id=\"districtSelect\" style=\"width:100%; padding:8px;\">\r\n                                    <option value=\"\">Pilih Kab\/Kota<\/option>\r\n                                <\/select>\r\n                            <\/div>\r\n                        <\/div>\r\n\r\n                        <!-- Surveyor dan Instansi -->\r\n                        <div style=\"display:grid; grid-template-columns:1fr 1fr; gap:10px;\">\r\n                            <div><input type=\"text\" name=\"surveyor\" placeholder=\"Nama Surveyor\" style=\"width:100%; padding:8px;\"><\/div>\r\n                            <div><input type=\"text\" name=\"institution\" placeholder=\"Instansi\" style=\"width:100%; padding:8px;\"><\/div>\r\n                        <\/div>\r\n\r\n                        <!-- Tanggal dan Kedalaman -->\r\n                        <div style=\"display:grid; grid-template-columns:1fr 1fr; gap:10px; margin-top:10px;\">\r\n                            <div><input type=\"date\" name=\"survey_date\" style=\"width:100%; padding:8px;\"><\/div>\r\n                            <div><input type=\"number\" step=\"0.1\" name=\"depth\" placeholder=\"Kedalaman (m)\" style=\"width:100%; padding:8px;\"><\/div>\r\n                        <\/div>\r\n\r\n                        <!-- Tipe terumbu dan posisi -->\r\n                        <div style=\"display:grid; grid-template-columns:1fr 1fr; gap:10px; margin-top:10px;\">\r\n                            <div>\r\n                                <select name=\"reef_type\" style=\"width:100%; padding:8px;\">\r\n                                    <option value=\"\">Tipe Terumbu<\/option>\r\n                                    <option value=\"Fringing\">Fringing<\/option>\r\n                                    <option value=\"Barrier\">Barrier<\/option>\r\n                                    <option value=\"Atoll\">Atoll<\/option>\r\n                                    <option value=\"Patch\">Patch<\/option>\r\n                                <\/select>\r\n                            <\/div>\r\n                            <div>\r\n                                <select name=\"reef_position\" style=\"width:100%; padding:8px;\">\r\n                                    <option value=\"\">Posisi Karang<\/option>\r\n                                    <option value=\"Fore reef\">Fore reef<\/option>\r\n                                    <option value=\"Reef flat\">Reef flat<\/option>\r\n                                    <option value=\"Back reef\">Back reef<\/option>\r\n                                    <option value=\"Reef crest\">Reef crest<\/option>\r\n                                <\/select>\r\n                            <\/div>\r\n                        <\/div>\r\n\r\n                        <!-- Visibility dan metode -->\r\n                        <div style=\"display:grid; grid-template-columns:1fr 1fr; gap:10px; margin-top:10px;\">\r\n                            <div><input type=\"number\" step=\"0.1\" name=\"visibility\" placeholder=\"Visibility (m)\" style=\"width:100%; padding:8px;\"><\/div>\r\n                            <div>\r\n                                <select name=\"method\" style=\"width:100%; padding:8px;\">\r\n                                    <option value=\"\">Metode<\/option>\r\n                                    <option value=\"LIT\">LIT<\/option>\r\n                                    <option value=\"PIT\">PIT<\/option>\r\n                                    <option value=\"UPT\">UPT<\/option>\r\n                                <\/select>\r\n                            <\/div>\r\n                        <\/div>\r\n\r\n                        <!-- Panjang line -->\r\n                        <div style=\"margin-top:10px;\">\r\n                            <input type=\"number\" step=\"0.1\" name=\"line_length\" placeholder=\"Panjang Line (m)\" style=\"width:100%; padding:8px;\">\r\n                        <\/div>\r\n\r\n                        <!-- Tutupan HC (Hard Coral) -->\r\n                        <div style=\"margin-top:10px;\">\r\n                            <input type=\"number\" step=\"0.1\" name=\"coral_cover\" required placeholder=\"Tutupan Hard Coral (%) *\" style=\"width:100%; padding:8px;\">\r\n                        <\/div>\r\n\r\n                        <!-- Status login -->\r\n                        <div style=\"margin-top:10px; background:#e8f0fe; padding:10px; border-radius:5px;\">\r\n                            \u2705 Anda login sebagai <strong>${data.username}<\/strong>\r\n                        <\/div>\r\n\r\n                        <!-- Hard Coral Genus -->\r\n                        <div style=\"margin-top:15px; border-top:2px solid #0284c7; padding-top:15px;\">\r\n                            <h4 style=\"margin:0 0 10px; color:#0284c7;\">\ud83e\uddf1 Hard Coral<\/h4>\r\n                            <label style=\"display:block; font-weight:bold; margin-bottom:5px;\">Genus Hard Coral (opsional, bisa tambah beberapa)<\/label>\r\n                            <div style=\"display:flex; gap:5px;\">\r\n                                <select id=\"hardGenusSelect\" style=\"flex:2; padding:8px;\">\r\n                                    <option value=\"\">-- Pilih Hard Coral --<\/option>\r\n                                <\/select>\r\n                                <button type=\"button\" id=\"addHardGenusBtn\" style=\"flex:0.5; background:#0284c7; color:white; border:none; border-radius:5px; cursor:pointer;\">Tambah<\/button>\r\n                            <\/div>\r\n                            <div id=\"hardGenusList\" style=\"display:flex; flex-wrap:wrap; gap:8px; margin-top:10px;\"><\/div>\r\n                            <input type=\"hidden\" name=\"coral_genus\" id=\"hardCoralGenus\" value=\"\">\r\n                        <\/div>\r\n\r\n                        <!-- Soft Coral Genus + Persentase -->\r\n                        <div style=\"margin-top:15px; border-top:2px solid #2e7d32; padding-top:15px;\">\r\n                            <h4 style=\"margin:0 0 10px; color:#2e7d32;\">\ud83e\udeb8 Soft Coral<\/h4>\r\n                            <label style=\"display:block; font-weight:bold; margin-bottom:5px;\">Genus Soft Coral (opsional, bisa tambah beberapa)<\/label>\r\n                            <div style=\"display:flex; gap:5px;\">\r\n                                <select id=\"softGenusSelect\" style=\"flex:2; padding:8px;\">\r\n                                    <option value=\"\">-- Pilih Soft Coral --<\/option>\r\n                                <\/select>\r\n                                <button type=\"button\" id=\"addSoftGenusBtn\" style=\"flex:0.5; background:#2e7d32; color:white; border:none; border-radius:5px; cursor:pointer;\">Tambah<\/button>\r\n                            <\/div>\r\n                            <div id=\"softGenusList\" style=\"display:flex; flex-wrap:wrap; gap:8px; margin-top:10px;\"><\/div>\r\n                            <input type=\"hidden\" name=\"soft_coral_genus\" id=\"softCoralGenus\" value=\"\">\r\n\r\n                            <!-- Soft Coral Persentase -->\r\n                            <div style=\"margin-top:10px;\">\r\n                                <label style=\"display:block; font-weight:bold; margin-bottom:5px;\">Soft Coral (%) (opsional)<\/label>\r\n                                <input type=\"number\" step=\"0.1\" min=\"0\" max=\"100\" name=\"soft_coral_cover\" style=\"width:100%; padding:8px;\">\r\n                            <\/div>\r\n                        <\/div>\r\n\r\n                        <!-- ================== BAGIAN SUBSTRAT PERSENTASE (REVISI) ================== -->\r\n                        <div style=\"margin-top:15px; border-top:2px solid #9ca3af; padding-top:15px;\">\r\n                            <h4 style=\"margin:0 0 10px; color:#4b5563;\">\ud83e\udde9 Substrat Lainnya (Persentase)<\/h4>\r\n                            <p style=\"font-size:12px; color:#666; margin-bottom:10px;\">Isi persentase penutupan (0-100) untuk masing-masing kategori substrat (opsional).<\/p>\r\n                            <div style=\"display:grid; grid-template-columns:repeat(auto-fill, minmax(150px,1fr)); gap:10px;\">\r\n                                ${substrateHtml}\r\n                            <\/div>\r\n                        <\/div>\r\n\r\n                        <button type=\"submit\" style=\"background:#0284c7; color:white; border:none; padding:12px; border-radius:5px; cursor:pointer; width:100%; font-size:16px; margin-top:15px;\">\ud83d\udcbe Simpan Data<\/button>\r\n                    <\/form>\r\n                    <p style=\"font-size:12px; color:#666; margin-top:15px;\">*Field wajib diisi. Klik peta mini untuk mengisi koordinat.<\/p>\r\n                `;\r\n\r\n                \/\/ Inisialisasi komponen\r\n                initRegionDropdowns();\r\n                initMiniMap();\r\n                initHardGenusFeature();\r\n                initSoftGenusFeature();\r\n            } else {\r\n                loginPrompt.style.display = 'block';\r\n                formSection.style.display = 'none';\r\n            }\r\n        })\r\n        .catch(err => {\r\n            console.error('Gagal cek login', err);\r\n            document.getElementById('loginPrompt').innerHTML = '\u274c Gagal cek login. Pastikan file cek_login.php tersedia.';\r\n        });\r\n\r\n    \/\/ ========== PETA UTAMA ==========\r\n    var map = L.map('map').setView([-2.5, 118], 5);\r\n    L.tileLayer('https:\/\/server.arcgisonline.com\/ArcGIS\/rest\/services\/World_Imagery\/MapServer\/tile\/{z}\/{y}\/{x}', {\r\n        attribution: 'Tiles &copy; Esri'\r\n    }).addTo(map);\r\n    var markersCluster = L.markerClusterGroup();\r\n\r\n    function initMiniMap() {\r\n        try {\r\n            var miniMap = L.map('mini-map').setView([-2.5, 118], 5);\r\n            L.tileLayer('https:\/\/server.arcgisonline.com\/ArcGIS\/rest\/services\/World_Imagery\/MapServer\/tile\/{z}\/{y}\/{x}', {\r\n                attribution: 'Tiles &copy; Esri'\r\n            }).addTo(miniMap);\r\n            var marker;\r\n\r\n            function updateMarkerFromInput() {\r\n                var lat = parseFloat(document.getElementById('lat').value);\r\n                var lng = parseFloat(document.getElementById('lng').value);\r\n                if (!isNaN(lat) && !isNaN(lng)) {\r\n                    if (marker) miniMap.removeLayer(marker);\r\n                    marker = L.marker([lat, lng]).addTo(miniMap);\r\n                    miniMap.setView([lat, lng], 10);\r\n                    fillFromCoordinates(lat, lng).catch(e => console.error(e));\r\n                } else {\r\n                    if (marker) miniMap.removeLayer(marker);\r\n                    marker = null;\r\n                }\r\n            }\r\n\r\n            miniMap.on('click', function(e) {\r\n                var lat = e.latlng.lat.toFixed(6);\r\n                var lng = e.latlng.lng.toFixed(6);\r\n                document.getElementById('lat').value = lat;\r\n                document.getElementById('lng').value = lng;\r\n                updateMarkerFromInput();\r\n            });\r\n\r\n            document.getElementById('lat').addEventListener('input', updateMarkerFromInput);\r\n            document.getElementById('lng').addEventListener('input', updateMarkerFromInput);\r\n            updateMarkerFromInput();\r\n        } catch (e) {\r\n            console.error('Error di initMiniMap:', e);\r\n        }\r\n    }\r\n\r\n    function initRegionDropdowns() {\r\n        try {\r\n            const provinceSelect = document.getElementById('provinceSelect');\r\n            const districtSelect = document.getElementById('districtSelect');\r\n            if (!provinceSelect || !districtSelect) return;\r\n\r\n            provinceSelect.innerHTML = '<option value=\"\">Pilih Provinsi<\/option>';\r\n            districtSelect.innerHTML = '<option value=\"\">Pilih Kab\/Kota<\/option>';\r\n\r\n            const provinces = Object.keys(indonesiaRegions).sort();\r\n            provinces.forEach(prov => {\r\n                const option = document.createElement('option');\r\n                option.value = prov;\r\n                option.textContent = prov;\r\n                provinceSelect.appendChild(option);\r\n            });\r\n\r\n            provinceSelect.addEventListener('change', function() {\r\n                const selectedProv = this.value;\r\n                districtSelect.innerHTML = '<option value=\"\">Pilih Kab\/Kota<\/option>';\r\n                if (selectedProv && indonesiaRegions[selectedProv]) {\r\n                    const cities = indonesiaRegions[selectedProv].sort();\r\n                    cities.forEach(city => {\r\n                        const option = document.createElement('option');\r\n                        option.value = city;\r\n                        option.textContent = city;\r\n                        districtSelect.appendChild(option);\r\n                    });\r\n                }\r\n            });\r\n        } catch (e) {\r\n            console.error('Error di initRegionDropdowns:', e);\r\n        }\r\n    }\r\n\r\n    function initHardGenusFeature() {\r\n        const select = document.getElementById('hardGenusSelect');\r\n        const addBtn = document.getElementById('addHardGenusBtn');\r\n        const listDiv = document.getElementById('hardGenusList');\r\n        const hidden = document.getElementById('hardCoralGenus');\r\n        let selected = [];\r\n\r\n        hardCoralList.sort().forEach(g => {\r\n            const option = document.createElement('option');\r\n            option.value = g;\r\n            option.textContent = g;\r\n            select.appendChild(option);\r\n        });\r\n\r\n        function updateDisplay() {\r\n            listDiv.innerHTML = '';\r\n            selected.forEach((genre, index) => {\r\n                const chip = document.createElement('span');\r\n                chip.style.backgroundColor = '#e0f2fe';\r\n                chip.style.padding = '4px 10px';\r\n                chip.style.borderRadius = '20px';\r\n                chip.style.display = 'inline-flex';\r\n                chip.style.alignItems = 'center';\r\n                chip.style.gap = '5px';\r\n                chip.style.border = '1px solid #0284c7';\r\n                chip.style.fontSize = '13px';\r\n                \r\n                const text = document.createTextNode(genre);\r\n                const closeBtn = document.createElement('span');\r\n                closeBtn.innerHTML = '&times;';\r\n                closeBtn.style.cursor = 'pointer';\r\n                closeBtn.style.fontWeight = 'bold';\r\n                closeBtn.style.marginLeft = '5px';\r\n                closeBtn.onclick = function() {\r\n                    selected.splice(index, 1);\r\n                    updateDisplay();\r\n                };\r\n                \r\n                chip.appendChild(text);\r\n                chip.appendChild(closeBtn);\r\n                listDiv.appendChild(chip);\r\n            });\r\n            hidden.value = selected.join(', ');\r\n        }\r\n\r\n        addBtn.addEventListener('click', function() {\r\n            const val = select.value;\r\n            if (val && !selected.includes(val)) {\r\n                selected.push(val);\r\n                updateDisplay();\r\n            }\r\n            select.value = '';\r\n        });\r\n    }\r\n\r\n    function initSoftGenusFeature() {\r\n        const select = document.getElementById('softGenusSelect');\r\n        const addBtn = document.getElementById('addSoftGenusBtn');\r\n        const listDiv = document.getElementById('softGenusList');\r\n        const hidden = document.getElementById('softCoralGenus');\r\n        let selected = [];\r\n\r\n        softCoralList.sort().forEach(g => {\r\n            const option = document.createElement('option');\r\n            option.value = g;\r\n            option.textContent = g;\r\n            select.appendChild(option);\r\n        });\r\n\r\n        function updateDisplay() {\r\n            listDiv.innerHTML = '';\r\n            selected.forEach((genre, index) => {\r\n                const chip = document.createElement('span');\r\n                chip.style.backgroundColor = '#e8f5e9';\r\n                chip.style.padding = '4px 10px';\r\n                chip.style.borderRadius = '20px';\r\n                chip.style.display = 'inline-flex';\r\n                chip.style.alignItems = 'center';\r\n                chip.style.gap = '5px';\r\n                chip.style.border = '1px solid #2e7d32';\r\n                chip.style.fontSize = '13px';\r\n                \r\n                const text = document.createTextNode(genre);\r\n                const closeBtn = document.createElement('span');\r\n                closeBtn.innerHTML = '&times;';\r\n                closeBtn.style.cursor = 'pointer';\r\n                closeBtn.style.fontWeight = 'bold';\r\n                closeBtn.style.marginLeft = '5px';\r\n                closeBtn.onclick = function() {\r\n                    selected.splice(index, 1);\r\n                    updateDisplay();\r\n                };\r\n                \r\n                chip.appendChild(text);\r\n                chip.appendChild(closeBtn);\r\n                listDiv.appendChild(chip);\r\n            });\r\n            hidden.value = selected.join(', ');\r\n        }\r\n\r\n        addBtn.addEventListener('click', function() {\r\n            const val = select.value;\r\n            if (val && !selected.includes(val)) {\r\n                selected.push(val);\r\n                updateDisplay();\r\n            }\r\n            select.value = '';\r\n        });\r\n    }\r\n\r\n    \/\/ ========== FUNGSI TABEL DAN PETA ==========\r\n    function loadDataAndRender() {\r\n        fetch('\/get_data.php')\r\n            .then(response => response.json())\r\n            .then(data => {\r\n                allData = data;\r\n                const provinces = [...new Set(data.map(item => item.province).filter(p => p))];\r\n                const districts = [...new Set(data.map(item => item.district).filter(d => d))];\r\n                \r\n                document.getElementById('filterProvince').innerHTML = '<option value=\"\">Semua Provinsi<\/option>' + provinces.sort().map(p => `<option value=\"${p}\">${p}<\/option>`).join('');\r\n                document.getElementById('filterDistrict').innerHTML = '<option value=\"\">Semua Kab\/Kota<\/option>' + districts.sort().map(d => `<option value=\"${d}\">${d}<\/option>`).join('');\r\n                \r\n                filterData();\r\n            })\r\n            .catch(err => {\r\n                document.getElementById('tableBody').innerHTML = '<tr><td colspan=\"20\" style=\"text-align:center; padding:20px; color:red;\">Gagal memuat data.<\/td><\/tr>';\r\n                console.error(err);\r\n            });\r\n    }\r\n\r\n    function filterData() {\r\n        const province = document.getElementById('filterProvince').value;\r\n        const district = document.getElementById('filterDistrict').value;\r\n        const search = document.getElementById('searchInput').value.toLowerCase();\r\n        const selectedGenus = document.getElementById('filterGenus').value;\r\n        const minCover = parseFloat(document.getElementById('filterMinCover').value);\r\n\r\n        filteredAllData = allData.filter(item => {\r\n            \/\/ Filter provinsi\r\n            if (province && item.province !== province) return false;\r\n            \/\/ Filter kabupaten\r\n            if (district && item.district !== district) return false;\r\n            \/\/ Filter pencarian umum (di semua field)\r\n            if (search) {\r\n                const rowText = Object.values(item).join(' ').toLowerCase();\r\n                if (!rowText.includes(search)) return false;\r\n            }\r\n            \/\/ Filter genus (hard coral atau soft coral)\r\n            if (selectedGenus) {\r\n                const hardGenus = (item.coral_genus || '').split(',').map(g => g.trim().toLowerCase());\r\n                const softGenus = (item.soft_coral_genus || '').split(',').map(g => g.trim().toLowerCase());\r\n                const genusLower = selectedGenus.toLowerCase();\r\n                if (!hardGenus.includes(genusLower) && !softGenus.includes(genusLower)) return false;\r\n            }\r\n            \/\/ Filter tutupan minimal (hard coral cover)\r\n            if (!isNaN(minCover)) {\r\n                const cover = parseFloat(item.coral_cover) || 0;\r\n                if (cover < minCover) return false;\r\n            }\r\n            return true;\r\n        });\r\n\r\n        if (isSuperAdmin) {\r\n            filteredUserData = filteredAllData;\r\n        } else if (currentUser) {\r\n            filteredUserData = filteredAllData.filter(item => item.user_login === currentUser);\r\n        } else {\r\n            filteredUserData = [];\r\n        }\r\n\r\n        renderTable(filteredUserData);\r\n        updateMapMarkers(filteredAllData);\r\n    }\r\n\r\n    function renderTable(data) {\r\n        const tbody = document.getElementById('tableBody');\r\n        if (!currentUser) {\r\n            tbody.innerHTML = '<tr><td colspan=\"20\" style=\"text-align:center; padding:20px;\">Silakan login untuk melihat data Anda.<\/td><\/tr>';\r\n            return;\r\n        }\r\n        if (data.length === 0) {\r\n            tbody.innerHTML = '<tr><td colspan=\"20\" style=\"text-align:center; padding:20px;\">Anda belum memiliki data atau tidak ada data sesuai filter.<\/td><\/tr>';\r\n            return;\r\n        }\r\n        let html = '';\r\n        data.forEach(item => {\r\n            const canEdit = (item.user_login === currentUser);\r\n            const actionButtons = canEdit ? `\r\n                <a href=\"\/edit-data\/?id=${item.id}\" style=\"background:#0284c7; color:white; padding:4px 8px; border-radius:4px; text-decoration:none; font-size:12px; margin-right:5px;\">Edit<\/a>\r\n                <a href=\"javascript:void(0)\" onclick=\"confirmDelete(${item.id})\" style=\"background:#dc2626; color:white; padding:4px 8px; border-radius:4px; text-decoration:none; font-size:12px;\">Hapus<\/a>\r\n            ` : '';\r\n            html += `<tr>\r\n                <td style=\"padding:8px; border-bottom:1px solid #e2e8f0;\">${item.location_name || ''}<\/td>\r\n                <td style=\"padding:8px; border-bottom:1px solid #e2e8f0;\">${item.province || ''}<\/td>\r\n                <td style=\"padding:8px; border-bottom:1px solid #e2e8f0;\">${item.district || ''}<\/td>\r\n                <td style=\"padding:8px; border-bottom:1px solid #e2e8f0;\">${item.latitude || ''}<\/td>\r\n                <td style=\"padding:8px; border-bottom:1px solid #e2e8f0;\">${item.longitude || ''}<\/td>\r\n                <td style=\"padding:8px; border-bottom:1px solid #e2e8f0;\">${item.coral_cover || ''}<\/td>\r\n                <td style=\"padding:8px; border-bottom:1px solid #e2e8f0;\">${item.contributor || ''}<\/td>\r\n                <td style=\"padding:8px; border-bottom:1px solid #e2e8f0;\">${item.surveyor || ''}<\/td>\r\n                <td style=\"padding:8px; border-bottom:1px solid #e2e8f0;\">${item.institution || ''}<\/td>\r\n                <td style=\"padding:8px; border-bottom:1px solid #e2e8f0;\">${item.survey_date || ''}<\/td>\r\n                <td style=\"padding:8px; border-bottom:1px solid #e2e8f0;\">${item.depth || ''}<\/td>\r\n                <td style=\"padding:8px; border-bottom:1px solid #e2e8f0;\">${item.reef_type || ''}<\/td>\r\n                <td style=\"padding:8px; border-bottom:1px solid #e2e8f0;\">${item.reef_position || ''}<\/td>\r\n                <td style=\"padding:8px; border-bottom:1px solid #e2e8f0;\">${item.visibility || ''}<\/td>\r\n                <td style=\"padding:8px; border-bottom:1px solid #e2e8f0;\">${item.method || ''}<\/td>\r\n                <td style=\"padding:8px; border-bottom:1px solid #e2e8f0;\">${item.line_length || ''}<\/td>\r\n                <td style=\"padding:8px; border-bottom:1px solid #e2e8f0;\">${item.coral_genus || ''}<\/td>\r\n                <td style=\"padding:8px; border-bottom:1px solid #e2e8f0;\">${item.soft_coral_genus || ''}<\/td>\r\n                <td style=\"padding:8px; border-bottom:1px solid #e2e8f0;\">${item.soft_coral_cover !== undefined ? item.soft_coral_cover : ''}<\/td>\r\n                <td style=\"padding:8px; border-bottom:1px solid #e2e8f0;\">${actionButtons}<\/td>\r\n            <\/tr>`;\r\n        });\r\n        tbody.innerHTML = html;\r\n    }\r\n\r\n    window.confirmDelete = function(id) {\r\n        if (confirm('Apakah Anda yakin ingin menghapus data ini? Data yang dihapus tidak dapat dikembalikan.')) {\r\n            fetch('\/delete_data.php?id=' + id, { method: 'DELETE' })\r\n                .then(response => {\r\n                    if (response.ok) {\r\n                        alert('Data berhasil dihapus.');\r\n                        window.location.reload();\r\n                    } else {\r\n                        return response.text().then(text => { throw new Error(text); });\r\n                    }\r\n                })\r\n                .catch(err => alert('Gagal menghapus: ' + err.message));\r\n        }\r\n    };\r\n\r\n    function updateMapMarkers(data) {\r\n        \/\/ Hapus semua marker dari cluster\r\n        markersCluster.clearLayers();\r\n\r\n        \/\/ Tambahkan marker baru ke cluster\r\n        data.forEach(item => {\r\n            var lat = parseFloat(item.latitude);\r\n            var lng = parseFloat(item.longitude);\r\n            if (isNaN(lat) || isNaN(lng)) return;\r\n            var marker = L.marker([lat, lng]);\r\n            \r\n            \/\/ MODIFIKASI: Tampilkan grafik substrat dan info metode\r\n            var popupContent = `\r\n                <b>${item.location_name}<\/b><br>\r\n                \ud83d\uddfa\ufe0f Lat: ${lat}, Lng: ${lng}<br>\r\n                \ud83c\udfdb\ufe0f Provinsi: ${item.province || '-'}<br>\r\n                \ud83c\udfd9\ufe0f Kab\/Kota: ${item.district || '-'}<br>\r\n                \ud83e\udeb8 Tutupan HC: ${item.coral_cover}%<br>\r\n                \ud83e\udeb8 Tutupan SC: ${item.soft_coral_cover || '0'}%<br>\r\n                \ud83d\udc64 Surveyor: ${item.surveyor || '-'}<br>\r\n                \ud83d\udccf Kedalaman: ${item.depth || '-'} m<br>\r\n                \ud83e\uddf1 Hard Coral: ${item.coral_genus || '-'}<br>\r\n                \ud83e\udeb8 Soft Coral: ${item.soft_coral_genus || '-'}<br>\r\n                <hr>\r\n                <b>Substrat Lainnya (%):<\/b><br>\r\n                ${getSubstrateChartHTML(item)}\r\n                <hr>\r\n                <b>Metode:<\/b> ${item.method || '-'} <br>\r\n                <b>Panjang Line:<\/b> ${item.line_length || '-'} m\r\n            `;\r\n            marker.bindPopup(popupContent);\r\n            markersCluster.addLayer(marker);\r\n        });\r\n\r\n        \/\/ Tambahkan cluster ke peta (hapus dulu jika sudah ada)\r\n        if (map.hasLayer(markersCluster)) {\r\n            map.removeLayer(markersCluster);\r\n        }\r\n        map.addLayer(markersCluster);\r\n\r\n        \/\/ Zoom ke bounding box semua marker jika ada data\r\n        if (data.length > 0) {\r\n            var group = L.featureGroup(\r\n                data.map(item => L.marker([parseFloat(item.latitude), parseFloat(item.longitude)]))\r\n            );\r\n            map.fitBounds(group.getBounds().pad(0.1));\r\n        } else {\r\n            \/\/ Jika tidak ada data, set view ke default Indonesia\r\n            map.setView([-2.5, 118], 5);\r\n        }\r\n    }\r\n\r\n    \/\/ Event listener filter\r\n    document.getElementById('applyFilter').addEventListener('click', filterData);\r\n    document.getElementById('searchInput').addEventListener('keyup', function(e) { if (e.key === 'Enter') filterData(); });\r\n    document.getElementById('filterProvince').addEventListener('change', filterData);\r\n    document.getElementById('filterDistrict').addEventListener('change', filterData);\r\n    document.getElementById('filterGenus').addEventListener('change', filterData); \/\/ langsung filter saat ganti\r\n    document.getElementById('filterMinCover').addEventListener('keyup', function(e) { if (e.key === 'Enter') filterData(); });\r\n\r\n    \/\/ ================== FUNGSI DOWNLOAD ==================\r\n    document.getElementById('downloadBtn').addEventListener('click', function() {\r\n        if (!currentUser) { alert('Anda harus login untuk mendownload data.'); return; }\r\n        const password = prompt('Masukkan password untuk mendownload data:');\r\n        if (password !== '17agustus1945') { alert('Password salah!'); return; }\r\n        if (filteredUserData.length === 0) { alert('Tidak ada data sesuai filter.'); return; }\r\n\r\n        const format = document.getElementById('formatSelect').value;\r\n        \r\n        \/\/ Header umum + header substrat (menggunakan kode dari substrateList)\r\n        const commonHeaders = [\r\n            'Lokasi','Provinsi','Kab\/Kota','Lat','Lng','Tutupan HC (%)','Kontributor',\r\n            'Surveyor','Instansi','Tanggal','Kedalaman','Tipe Terumbu','Posisi',\r\n            'Visibility','Metode','Panjang Line','Hard Coral Genus','Soft Coral Genus','Soft Coral (%)'\r\n        ];\r\n        const substrateHeaders = substrateList.map(s => s.code); \/\/ misal: SP, ZO, OT, ...\r\n        const headers = [...commonHeaders, ...substrateHeaders];\r\n        \r\n        const rows = filteredUserData.map(item => {\r\n            \/\/ data umum\r\n            const base = [\r\n                item.location_name || '', item.province || '', item.district || '', \r\n                item.latitude || '', item.longitude || '',\r\n                item.coral_cover || '', item.contributor || '', \r\n                item.surveyor || '', item.institution || '', item.survey_date || '',\r\n                item.depth || '', item.reef_type || '', item.reef_position || '',\r\n                item.visibility || '', item.method || '', item.line_length || '',\r\n                item.coral_genus || '', item.soft_coral_genus || '',\r\n                item.soft_coral_cover !== undefined ? item.soft_coral_cover : 0\r\n            ];\r\n            \/\/ data substrat (dengan nama field substrate_XX)\r\n            const substrateData = substrateList.map(s => {\r\n                const field = `substrate_${s.code}`;\r\n                return item[field] !== undefined ? item[field] : 0;\r\n            });\r\n            return [...base, ...substrateData];\r\n        });\r\n\r\n        if (format === 'csv') {\r\n            let csv = headers.join(',') + '\\n';\r\n            rows.forEach(row => { csv += row.map(val => `\"${val}\"`).join(',') + '\\n'; });\r\n            downloadBlob(csv, 'text\/csv;charset=utf-8;', 'data_terumbu_karang.csv');\r\n        } else if (format === 'xlsx') {\r\n            (async () => {\r\n                try {\r\n                    const wb = XLSX.utils.book_new();\r\n\r\n                    \/\/ Sheet 1: Data Detail\r\n                    const wsData = [headers, ...rows];\r\n                    const ws = XLSX.utils.aoa_to_sheet(wsData);\r\n                    XLSX.utils.book_append_sheet(wb, ws, 'Data');\r\n\r\n                    \/\/ Sheet 2: Luasan Karang\r\n                    const luasanRows = [];\r\n                    luasanRows.push(['Nama Lokasi', 'Jumlah Titik', 'Rata-rata Tutupan HC (%)', 'Std Dev', 'Std Error', 'Estimasi Luasan (m\u00b2\/ha)', 'CI 95% Bawah', 'CI 95% Atas']);\r\n\r\n                    if (filteredUserData.length > 0) {\r\n                        const clusters = clusterByDistance(filteredUserData, 1.5);\r\n                        if (clusters.length === 0) {\r\n                            luasanRows.push(['Tidak ada titik dengan koordinat valid']);\r\n                        } else {\r\n                            for (let idx = 0; idx < clusters.length; idx++) {\r\n                                const clusterIndices = clusters[idx];\r\n                                const clusterData = clusterIndices.map(i => filteredUserData[i]);\r\n\r\n                                let clusterName = `Cluster ${idx+1}`;\r\n                                if (clusterData.length > 0) {\r\n                                    const provinceCounts = {};\r\n                                    const districtCounts = {};\r\n                                    clusterData.forEach(d => {\r\n                                        if (d.province) provinceCounts[d.province] = (provinceCounts[d.province] || 0) + 1;\r\n                                        if (d.district) districtCounts[d.district] = (districtCounts[d.district] || 0) + 1;\r\n                                    });\r\n                                    const commonProvince = Object.keys(provinceCounts).reduce((a, b) => provinceCounts[a] > provinceCounts[b] ? a : b, '');\r\n                                    const commonDistrict = Object.keys(districtCounts).reduce((a, b) => districtCounts[a] > districtCounts[b] ? a : b, '');\r\n                                    clusterName = commonDistrict ? `${commonDistrict}, ${commonProvince}` : (commonProvince || `Cluster ${idx+1}`);\r\n                                }\r\n\r\n                                const n = clusterData.length;\r\n                                const covers = clusterData.map(d => parseFloat(d.coral_cover)).filter(v => !isNaN(v));\r\n                                if (covers.length === 0) {\r\n                                    luasanRows.push([clusterName, n, 'Data tutupan tidak valid', '', '', '', '', '']);\r\n                                    continue;\r\n                                }\r\n                                const mean = covers.reduce((a, b) => a + b, 0) \/ covers.length;\r\n                                let sd = 0;\r\n                                if (covers.length > 1) {\r\n                                    const sumSqDiff = covers.reduce((acc, val) => acc + Math.pow(val - mean, 2), 0);\r\n                                    sd = Math.sqrt(sumSqDiff \/ (covers.length - 1));\r\n                                }\r\n                                const se = covers.length > 1 ? sd \/ Math.sqrt(covers.length) : 0;\r\n                                const estimasiLuasan = mean * 100;\r\n                                let ciLower = '', ciUpper = '';\r\n                                if (covers.length > 1 && se > 0) {\r\n                                    const margin = 1.96 * se;\r\n                                    ciLower = (mean - margin).toFixed(2);\r\n                                    ciUpper = (mean + margin).toFixed(2);\r\n                                } else if (covers.length === 1) {\r\n                                    ciLower = 'N\/A (n=1)';\r\n                                    ciUpper = 'N\/A (n=1)';\r\n                                }\r\n                                luasanRows.push([clusterName, n, mean.toFixed(2), sd.toFixed(2), se.toFixed(2), estimasiLuasan.toFixed(2), ciLower, ciUpper]);\r\n                            }\r\n                        }\r\n                    } else {\r\n                        luasanRows.push(['Tidak ada data untuk diekspor']);\r\n                    }\r\n                    const ws2 = XLSX.utils.aoa_to_sheet(luasanRows);\r\n                    XLSX.utils.book_append_sheet(wb, ws2, 'Luasan Karang');\r\n\r\n                    \/\/ ========== SHEET 3: RINGKASAN UNTUK GRAFIK (menggunakan substrateList) ==========\r\n                    const ringkasanRows = [];\r\n                    ringkasanRows.push(['Kategori Substrat', 'Total (%)', 'Rata-rata (%)', 'Jumlah Titik dengan Nilai > 0']);\r\n                    \r\n                    \/\/ Gunakan substrateList untuk perhitungan\r\n                    substrateList.forEach(s => {\r\n                        const key = `substrate_${s.code}`;\r\n                        let total = 0;\r\n                        let count = 0;\r\n                        let nonZeroCount = 0;\r\n                        filteredUserData.forEach(item => {\r\n                            const val = parseFloat(item[key]) || 0;\r\n                            total += val;\r\n                            count++;\r\n                            if (val > 0) nonZeroCount++;\r\n                        });\r\n                        const average = count > 0 ? total \/ count : 0;\r\n                        ringkasanRows.push([`${s.code} - ${s.name}`, total.toFixed(2), average.toFixed(2), nonZeroCount]);\r\n                    });\r\n\r\n                    ringkasanRows.push([]);\r\n                    ringkasanRows.push(['Statistik Tutupan Karang', '', '', '']);\r\n                    \r\n                    const totalHCCover = filteredUserData.reduce((sum, item) => sum + (parseFloat(item.coral_cover) || 0), 0);\r\n                    const avgHCCover = filteredUserData.length > 0 ? totalHCCover \/ filteredUserData.length : 0;\r\n                    const totalSCCover = filteredUserData.reduce((sum, item) => sum + (parseFloat(item.soft_coral_cover) || 0), 0);\r\n                    const avgSCCover = filteredUserData.length > 0 ? totalSCCover \/ filteredUserData.length : 0;\r\n\r\n                    ringkasanRows.push(['Rata-rata Tutupan Hard Coral (%)', avgHCCover.toFixed(2), '', '']);\r\n                    ringkasanRows.push(['Rata-rata Tutupan Soft Coral (%)', avgSCCover.toFixed(2), '', '']);\r\n                    ringkasanRows.push(['Jumlah Titik Data', filteredUserData.length, '', '']);\r\n                    \r\n                    ringkasanRows.push([]);\r\n                    ringkasanRows.push(['Catatan: Gunakan data di sheet \"Data\" dan \"Ringkasan\" untuk membuat grafik di Excel.']);\r\n\r\n                    const ws3 = XLSX.utils.aoa_to_sheet(ringkasanRows);\r\n                    XLSX.utils.book_append_sheet(wb, ws3, 'Ringkasan');\r\n\r\n                    const wbout = XLSX.write(wb, { bookType: 'xlsx', type: 'array' });\r\n                    downloadBlob(new Blob([wbout], { type: 'application\/octet-stream' }), 'application\/octet-stream', 'data_terumbu_karang.xlsx');\r\n                } catch (e) {\r\n                    console.error('Error saat export XLSX:', e);\r\n                    alert('Terjadi kesalahan saat mengexport data.');\r\n                }\r\n            })();\r\n        } else if (format === 'txt') {\r\n            let txt = headers.join('\\t') + '\\n';\r\n            rows.forEach(row => { txt += row.join('\\t') + '\\n'; });\r\n            downloadBlob(txt, 'text\/plain;charset=utf-8;', 'data_terumbu_karang.txt');\r\n        }\r\n    });\r\n\r\n    function downloadBlob(content, mimeType, filename) {\r\n        const blob = new Blob([content], { type: mimeType });\r\n        const url = URL.createObjectURL(blob);\r\n        const a = document.createElement('a');\r\n        a.href = url;\r\n        a.download = filename;\r\n        a.click();\r\n        URL.revokeObjectURL(url);\r\n    }\r\n\r\n    loadDataAndRender();\r\n});\r\n<\/script>\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-1ba2d08 e-flex e-con-boxed e-con e-parent\" data-id=\"1ba2d08\" data-element_type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>","protected":false},"excerpt":{"rendered":"<p>\ud83c\udf0a e-Coral Indonesia Semua Provinsi Semua Kab\/Kota Semua Genus \ud83d\udd0d \ud83d\udd12 Anda belum login.<\/p>","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"site-sidebar-layout":"no-sidebar","site-content-layout":"","ast-site-content-layout":"full-width-container","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"disabled","ast-breadcrumbs-content":"","ast-featured-img":"disabled","footer-sml-layout":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"default","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":""},"class_list":["post-1134","page","type-page","status-publish","hentry"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v22.3 (Yoast SEO v24.7) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>e-Coral Indonesia - marineconservation.id<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/marineconservation.id\/id\/e-coral-id\/\" \/>\n<meta property=\"og:locale\" content=\"id_ID\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"e-Coral Indonesia\" \/>\n<meta property=\"og:description\" content=\"\ud83c\udf0a e-Coral Indonesia Semua Provinsi Semua Kab\/Kota Semua Genus \ud83d\udd0d \ud83d\udd12 Anda belum login.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/marineconservation.id\/id\/e-coral-id\/\" \/>\n<meta property=\"og:site_name\" content=\"marineconservation.id\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/profile.php?id=61572311944591\" \/>\n<meta property=\"article:modified_time\" content=\"2026-03-14T15:43:10+00:00\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Estimasi waktu membaca\" \/>\n\t<meta name=\"twitter:data1\" content=\"1 menit\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/marineconservation.id\/e-coral-id\/\",\"url\":\"https:\/\/marineconservation.id\/e-coral-id\/\",\"name\":\"e-Coral Indonesia - marineconservation.id\",\"isPartOf\":{\"@id\":\"https:\/\/marineconservation.id\/#website\"},\"datePublished\":\"2026-03-02T03:36:22+00:00\",\"dateModified\":\"2026-03-14T15:43:10+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/marineconservation.id\/e-coral-id\/#breadcrumb\"},\"inLanguage\":\"id\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/marineconservation.id\/e-coral-id\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/marineconservation.id\/e-coral-id\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/marineconservation.id\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"e-Coral Indonesia\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/marineconservation.id\/#website\",\"url\":\"https:\/\/marineconservation.id\/\",\"name\":\"marineconservation.id\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\/\/marineconservation.id\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/marineconservation.id\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"id\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/marineconservation.id\/#organization\",\"name\":\"marineconservation.id\",\"url\":\"https:\/\/marineconservation.id\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"id\",\"@id\":\"https:\/\/marineconservation.id\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/marineconservation.id\/wp-content\/uploads\/2025\/02\/Marine-Conservation-Indonesia.png\",\"contentUrl\":\"https:\/\/marineconservation.id\/wp-content\/uploads\/2025\/02\/Marine-Conservation-Indonesia.png\",\"width\":500,\"height\":500,\"caption\":\"marineconservation.id\"},\"image\":{\"@id\":\"https:\/\/marineconservation.id\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.facebook.com\/profile.php?id=61572311944591\",\"https:\/\/www.instagram.com\/marineconservation.id\/\",\"https:\/\/www.youtube.com\/watch?v=nOmjtk-dTg8&list=LL\"]}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"e-Coral Indonesia - marineconservation.id","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/marineconservation.id\/id\/e-coral-id\/","og_locale":"id_ID","og_type":"article","og_title":"e-Coral Indonesia","og_description":"\ud83c\udf0a e-Coral Indonesia Semua Provinsi Semua Kab\/Kota Semua Genus \ud83d\udd0d \ud83d\udd12 Anda belum login.","og_url":"https:\/\/marineconservation.id\/id\/e-coral-id\/","og_site_name":"marineconservation.id","article_publisher":"https:\/\/www.facebook.com\/profile.php?id=61572311944591","article_modified_time":"2026-03-14T15:43:10+00:00","twitter_card":"summary_large_image","twitter_misc":{"Estimasi waktu membaca":"1 menit"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/marineconservation.id\/e-coral-id\/","url":"https:\/\/marineconservation.id\/e-coral-id\/","name":"e-Coral Indonesia - marineconservation.id","isPartOf":{"@id":"https:\/\/marineconservation.id\/#website"},"datePublished":"2026-03-02T03:36:22+00:00","dateModified":"2026-03-14T15:43:10+00:00","breadcrumb":{"@id":"https:\/\/marineconservation.id\/e-coral-id\/#breadcrumb"},"inLanguage":"id","potentialAction":[{"@type":"ReadAction","target":["https:\/\/marineconservation.id\/e-coral-id\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/marineconservation.id\/e-coral-id\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/marineconservation.id\/"},{"@type":"ListItem","position":2,"name":"e-Coral Indonesia"}]},{"@type":"WebSite","@id":"https:\/\/marineconservation.id\/#website","url":"https:\/\/marineconservation.id\/","name":"marineconservation.id","description":"","publisher":{"@id":"https:\/\/marineconservation.id\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/marineconservation.id\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"id"},{"@type":"Organization","@id":"https:\/\/marineconservation.id\/#organization","name":"marineconservation.id","url":"https:\/\/marineconservation.id\/","logo":{"@type":"ImageObject","inLanguage":"id","@id":"https:\/\/marineconservation.id\/#\/schema\/logo\/image\/","url":"https:\/\/marineconservation.id\/wp-content\/uploads\/2025\/02\/Marine-Conservation-Indonesia.png","contentUrl":"https:\/\/marineconservation.id\/wp-content\/uploads\/2025\/02\/Marine-Conservation-Indonesia.png","width":500,"height":500,"caption":"marineconservation.id"},"image":{"@id":"https:\/\/marineconservation.id\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/profile.php?id=61572311944591","https:\/\/www.instagram.com\/marineconservation.id\/","https:\/\/www.youtube.com\/watch?v=nOmjtk-dTg8&list=LL"]}]}},"_links":{"self":[{"href":"https:\/\/marineconservation.id\/id\/wp-json\/wp\/v2\/pages\/1134","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/marineconservation.id\/id\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/marineconservation.id\/id\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/marineconservation.id\/id\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/marineconservation.id\/id\/wp-json\/wp\/v2\/comments?post=1134"}],"version-history":[{"count":386,"href":"https:\/\/marineconservation.id\/id\/wp-json\/wp\/v2\/pages\/1134\/revisions"}],"predecessor-version":[{"id":1927,"href":"https:\/\/marineconservation.id\/id\/wp-json\/wp\/v2\/pages\/1134\/revisions\/1927"}],"wp:attachment":[{"href":"https:\/\/marineconservation.id\/id\/wp-json\/wp\/v2\/media?parent=1134"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}