{"id":1856,"date":"2026-03-12T01:07:34","date_gmt":"2026-03-12T01:07:34","guid":{"rendered":"https:\/\/marineconservation.id\/?page_id=1856"},"modified":"2026-03-14T15:56:28","modified_gmt":"2026-03-14T15:56:28","slug":"megabenthos-data-entry","status":"publish","type":"page","link":"https:\/\/marineconservation.id\/id\/megabenthos-data-entry\/","title":{"rendered":"Megabenthos Data Entry"},"content":{"rendered":"<style>.elementor-1856 .elementor-element.elementor-element-bfc9745{--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=\"1856\" class=\"elementor elementor-1856\" data-elementor-post-type=\"page\">\n\t\t\t\t<div class=\"elementor-element elementor-element-bfc9745 e-flex e-con-boxed e-con e-parent\" data-id=\"bfc9745\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t\t<div class=\"e-con-inner\">\n\t\t\t\t<div class=\"elementor-element elementor-element-5ccd0d5 elementor-widget elementor-widget-html\" data-id=\"5ccd0d5\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t<!DOCTYPE html>\r\n<html lang=\"id\">\r\n<head>\r\n  <meta charset=\"UTF-8\">\r\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\r\n  <title>Data Entry Megabentos + Substrat LIPI<\/title>\r\n  <!-- Font Awesome -->\r\n  <link rel=\"stylesheet\" href=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/font-awesome\/6.0.0-beta3\/css\/all.min.css\">\r\n  <!-- Leaflet -->\r\n  <link rel=\"stylesheet\" href=\"https:\/\/unpkg.com\/leaflet@1.9.4\/dist\/leaflet.css\" \/>\r\n  <script src=\"https:\/\/unpkg.com\/leaflet@1.9.4\/dist\/leaflet.js\"><\/script>\r\n  <!-- SheetJS -->\r\n  <script src=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/xlsx\/0.18.5\/xlsx.full.min.js\"><\/script>\r\n  <style>\r\n    \/* ========== CSS (sama seperti sebelumnya) ========== *\/\r\n    body { font-family: 'Segoe UI', Arial, sans-serif; background: #f0f4f8; padding: 20px; }\r\n    .container { max-width: 1400px; margin: auto; background: #fff; padding: 25px; border-radius: 20px; box-shadow: 0 10px 30px rgba(0,0,0,0.1); border: 1px solid #dde3e9; }\r\n    .form-section { margin-bottom: 25px; padding: 20px; background: #f8fafd; border-radius: 12px; border: 1px solid #e2e8f0; }\r\n    .form-row { display: flex; flex-wrap: wrap; gap: 15px; margin-bottom: 15px; align-items: flex-end; }\r\n    .form-group { flex: 1 1 200px; display: flex; flex-direction: column; }\r\n    .form-group.nama-group { flex: 3; }\r\n    \/* ===== PERBAIKAN: Kolom jumlah dan ukuran diperbesar ===== *\/\r\n    .form-group.kecil-group {\r\n      flex: 2; \/* sebelumnya 0.8, sekarang 2 agar input lebih lebar *\/\r\n    }\r\n    label { font-weight: 600; margin-bottom: 5px; color: #2c3e50; font-size: 0.9rem; }\r\n    input, select, textarea { width: 100%; padding: 12px; border: 2px solid #dde3e9; border-radius: 10px; box-sizing: border-box; font-size: 15px; transition: 0.2s; }\r\n    input:focus, select:focus { border-color: #0088b0; outline: none; }\r\n    button { background: #0088b0; color: white; padding: 12px 24px; border: none; border-radius: 30px; cursor: pointer; font-size: 16px; font-weight: 600; transition: 0.2s; box-shadow: 0 4px 8px rgba(0,136,176,0.2); }\r\n    button:hover { background: #006c8e; transform: translateY(-2px); box-shadow: 0 8px 12px rgba(0,136,176,0.3); }\r\n    button.secondary { background: #6c757d; }\r\n    button.secondary:hover { background: #5a6268; }\r\n    .map { height: 300px; margin-top: 15px; border: 2px solid #dde3e9; border-radius: 12px; }\r\n    .radio-group { display: flex; gap: 25px; align-items: center; flex-wrap: wrap; }\r\n    .radio-group label { font-weight: 500; display: inline-flex; align-items: center; gap: 5px; }\r\n    table { width: 100%; border-collapse: collapse; margin-top: 20px; border-radius: 12px; overflow: hidden; box-shadow: 0 4px 12px rgba(0,0,0,0.05); }\r\n    th, td { border: 1px solid #e2e8f0; padding: 12px; text-align: left; }\r\n    th { background: #004d66; color: white; font-weight: 600; }\r\n    #entriesTable th:nth-child(1),\r\n    #entriesTable td:nth-child(1) { min-width: 250px; }\r\n    \/* ===== PERBAIKAN: Lebarkan kolom Jumlah (kolom 3) dan Ukuran (kolom 4) ===== *\/\r\n    #entriesTable th:nth-child(3),\r\n    #entriesTable td:nth-child(3),\r\n    #entriesTable th:nth-child(4),\r\n    #entriesTable td:nth-child(4) {\r\n      min-width: 100px;\r\n      white-space: nowrap; \/* agar angka tidak terpotong *\/\r\n    }\r\n    .remove-btn { background: #c0392b; color: white; border: none; padding: 6px 12px; border-radius: 20px; cursor: pointer; font-weight: 600; transition: 0.2s; }\r\n    .remove-btn:hover { background: #a93226; }\r\n    .warning { color: #856404; background-color: #fff3cd; border: 1px solid #ffeeba; padding: 8px; border-radius: 8px; margin-top: 5px; display: none; font-size: 0.9rem; }\r\n    .total-biomass { font-size: 1.5rem; font-weight: bold; margin: 15px 0; color: #0088b0; }\r\n    .export-btn { background: #27ae60; margin-right: 10px; }\r\n    .export-btn:hover { background: #219a52; }\r\n    .error-message { color: #721c24; background-color: #f8d7da; border: 1px solid #f5c6cb; padding: 12px; border-radius: 8px; margin: 10px 0; }\r\n    .format-group { display: flex; align-items: center; gap: 20px; margin-bottom: 15px; flex-wrap: wrap; }\r\n    .header-row { display: flex; justify-content: space-between; align-items: center; margin-bottom: 25px; flex-wrap: wrap; }\r\n    .header-row h2 { margin: 0; color: #004d66; font-weight: 700; }\r\n    .language-selector { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }\r\n    .lang-btn { padding: 6px 16px; border: 2px solid #0088b0; background: white; color: #0088b0; cursor: pointer; border-radius: 30px; font-weight: 600; transition: 0.2s; font-size: 14px; }\r\n    .lang-btn.active { background: #0088b0; color: white; }\r\n    .lang-btn:hover { background: #006c8e; color: white; }\r\n    #preview-box { margin-top: 25px; text-align: center; border: 1px solid #e2e8f0; padding: 20px; border-radius: 16px; background: #ffffff; display: none; box-shadow: 0 4px 12px rgba(0,0,0,0.05); }\r\n    #loader-text { font-size: 14px; color: #6b7a8a; margin-bottom: 10px; font-style: italic; }\r\n    .image-container { position: relative; min-height: 200px; display: flex; align-items: center; justify-content: center; background: #f0f4f8; border-radius: 12px; overflow: hidden; }\r\n    #megabentos-img { max-width: 100%; height: auto; max-height: 250px; transition: 0.3s ease; opacity: 0; border-radius: 8px; }\r\n    #image-source { font-size: 12px; margin-top: 12px; color: #7b8a9b; }\r\n    #worms-link { display: inline-block; padding: 10px 20px; background: #0088b0; color: white; text-decoration: none; border-radius: 30px; font-size: 13px; font-weight: 600; transition: 0.2s; box-shadow: 0 2px 8px rgba(0,136,176,0.3); margin-top: 10px; }\r\n    #worms-link:hover { background: #006c8e; }\r\n    \/* ===== Gaya untuk fitur foto kalibrasi ===== *\/\r\n    .photo-section { margin-top: 20px; }\r\n    .canvas-container { position: relative; border: 2px solid #ccc; border-radius: 8px; margin-top: 10px; background: #f0f0f0; display: inline-block; max-width: 100%; overflow: auto; }\r\n    #measureCanvas { display: block; width: 100%; height: auto; cursor: crosshair; }\r\n    .calibration-info { background: #e9ecef; padding: 10px; border-radius: 8px; margin: 10px 0; display: flex; gap: 20px; align-items: center; flex-wrap: wrap; }\r\n    .calibration-info span { font-weight: bold; color: #0088b0; }\r\n    .measure-buttons { display: flex; gap: 10px; flex-wrap: wrap; margin: 10px 0; }\r\n  <\/style>\r\n<\/head>\r\n<body>\r\n<div class=\"container\">\r\n  <!-- Header -->\r\n  <div class=\"header-row\">\r\n    <h2 id=\"mainTitle\">\ud83d\udccb Input Data Megabentos<\/h2>\r\n    <div class=\"language-selector\">\r\n      <button class=\"lang-btn active\" id=\"langID\" onclick=\"setLanguage('id')\">\ud83c\uddee\ud83c\udde9 Indonesia<\/button>\r\n      <button class=\"lang-btn\" id=\"langEN\" onclick=\"setLanguage('en')\">\ud83c\uddec\ud83c\udde7 English<\/button>\r\n      <button class=\"lang-btn\" id=\"saveProjectBtn\"><i class=\"fas fa-save\"><\/i> <span data-i18n=\"saveProject\">Simpan Proyek<\/span><\/button>\r\n      <button class=\"lang-btn\" id=\"loadProjectBtn\"><i class=\"fas fa-folder-open\"><\/i> <span data-i18n=\"loadProject\">Muat Proyek<\/span><\/button>\r\n      <input type=\"file\" id=\"loadProjectFile\" accept=\".json\" style=\"display: none;\">\r\n    <\/div>\r\n  <\/div>\r\n\r\n  <!-- Informasi Project -->\r\n  <div class=\"form-section\">\r\n    <h3 id=\"projectInfoTitle\">Informasi Project<\/h3>\r\n    <div class=\"form-row\">\r\n      <div class=\"form-group\"><label id=\"projectNameLabel\">Nama Project<\/label><input type=\"text\" id=\"projectName\" placeholder=\"Ekspedisi Megabentos\" \/><\/div>\r\n      <div class=\"form-group\"><label id=\"surveyorLabel\">Nama Surveyor<\/label><input type=\"text\" id=\"surveyor\" \/><\/div>\r\n      <div class=\"form-group\"><label id=\"datetimeLabel\">Waktu (Tanggal & Jam)<\/label><input type=\"datetime-local\" id=\"datetime\" \/><\/div>\r\n    <\/div>\r\n    <div class=\"form-row\">\r\n      <div class=\"form-group\"><label id=\"siteNameLabel\">Nama Site<\/label><input type=\"text\" id=\"siteName\" \/><\/div>\r\n      <div class=\"form-group\"><label id=\"locationDescLabel\">Lokasi (deskripsi)<\/label><input type=\"text\" id=\"locationDesc\" \/><\/div>\r\n    <\/div>\r\n    <div class=\"form-row\">\r\n      <div class=\"form-group\"><label id=\"latitudeLabel\">Latitude<\/label><input type=\"number\" step=\"any\" id=\"lat\" value=\"-6.2088\" \/><\/div>\r\n      <div class=\"form-group\"><label id=\"longitudeLabel\">Longitude<\/label><input type=\"number\" step=\"any\" id=\"lng\" value=\"106.8456\" \/><\/div>\r\n    <\/div>\r\n    <div id=\"map\" class=\"map\"><\/div>\r\n    <div class=\"form-row\">\r\n      <div class=\"form-group\"><label id=\"lineLengthLabel\">Metode \u2013 Panjang Line (m)<\/label><input type=\"number\" step=\"0.1\" id=\"lineLength\" \/><\/div>\r\n      <div class=\"form-group\"><label id=\"obsWidthLabel\">Metode \u2013 Lebar Pengamatan (m)<\/label><input type=\"number\" step=\"0.1\" id=\"obsWidth\" \/><\/div>\r\n      <div class=\"form-group\"><label id=\"waterConditionLabel\">Kondisi Perairan<\/label><input type=\"text\" id=\"waterCondition\" placeholder=\"Cerah, Berombak\" \/><\/div>\r\n      <div class=\"form-group\"><label id=\"depthLabel\">Kedalaman (m)<\/label><input type=\"number\" step=\"0.1\" id=\"depth\" \/><\/div>\r\n    <\/div>\r\n  <\/div>\r\n\r\n  <!-- Tingkat Identifikasi -->\r\n  <div class=\"form-section\">\r\n    <h3 id=\"identificationLevelTitle\">Tingkat Identifikasi<\/h3>\r\n    <div class=\"radio-group\">\r\n      <label><input type=\"radio\" name=\"level\" value=\"group\" checked> <span id=\"groupLabel\">Group<\/span><\/label>\r\n      <label><input type=\"radio\" name=\"level\" value=\"genus\"> <span id=\"genusLabel\">Genus<\/span><\/label>\r\n      <label><input type=\"radio\" name=\"level\" value=\"species\"> <span id=\"speciesLabel\">Spesies<\/span><\/label>\r\n    <\/div>\r\n  <\/div>\r\n\r\n  <!-- Form Pengisian -->\r\n  <div class=\"form-section\">\r\n    <h3 id=\"addDataTitle\">Tambah Data Megabentos<\/h3>\r\n    <div class=\"form-row\">\r\n      <div class=\"form-group nama-group\">\r\n        <label id=\"taxonLabel\">Nama Group<\/label>\r\n        <input list=\"taxonDatalist\" id=\"taxonInput\" placeholder=\"Ketik untuk mencari...\" style=\"width:100%;\" \/>\r\n        <datalist id=\"taxonDatalist\"><\/datalist>\r\n      <\/div>\r\n      <div class=\"form-group kecil-group\"><label id=\"countLabel\">Jumlah<\/label><input type=\"number\" id=\"count\" min=\"1\" value=\"1\" \/><\/div>\r\n      <div class=\"form-group kecil-group\"><label id=\"sizeLabel\">Ukuran (cm)<\/label><input type=\"number\" id=\"size\" step=\"0.01\" min=\"0\" value=\"10.00\" \/><div id=\"sizeWarning\" class=\"warning\"><\/div><\/div>\r\n      <div class=\"form-group\"><label id=\"substrateLabel\">Substrat<\/label>\r\n        <select id=\"substrate\">\r\n          <option value=\"\">Pilih Substrat<\/option>\r\n          <option value=\"HC\">HC - Coral<\/option>\r\n          <option value=\"DC\">DC - Recent Dead Coral<\/option>\r\n          <option value=\"DCA\">DCA - Dead Coral with Algae<\/option>\r\n          <option value=\"SC\">SC - Soft Coral<\/option>\r\n          <option value=\"SP\">SP - Sponge<\/option>\r\n          <option value=\"FS\">FS - Fleshy Seaweed<\/option>\r\n          <option value=\"OT\">OT - Other Biota<\/option>\r\n          <option value=\"R\">R - Rubble<\/option>\r\n          <option value=\"S\">S - Sand<\/option>\r\n          <option value=\"SI\">SI - Silt<\/option>\r\n          <option value=\"RK\">RK - Rock<\/option>\r\n        <\/select>\r\n      <\/div>\r\n      <div class=\"form-group\"><label id=\"biomassLabel\">Biomassa Total (gram)<\/label><input type=\"text\" id=\"biomassDisplay\" readonly value=\"0\" \/><\/div>\r\n      <div style=\"align-self: flex-end;\"><button id=\"addEntryBtn\">\u2795 <span id=\"addButtonText\">Tambah ke Daftar<\/span><\/button><\/div>\r\n    <\/div>\r\n  <\/div>\r\n\r\n  <!-- ===== FITUR FOTO KALIBRASI ===== -->\r\n  <div class=\"form-section photo-section\">\r\n    <h3 id=\"photoTitle\">\ud83d\udcf8 Ukur dari Foto (dengan Kalibrasi)<\/h3>\r\n    <div class=\"form-row\">\r\n      <div class=\"form-group\">\r\n        <label id=\"uploadLabel\">Upload Foto<\/label>\r\n        <input type=\"file\" id=\"photoInput\" accept=\"image\/*\" \/>\r\n      <\/div>\r\n      <div class=\"form-group\">\r\n        <label id=\"knownSizeLabel\">Panjang Referensi (cm)<\/label>\r\n        <input type=\"number\" id=\"knownSize\" step=\"0.01\" value=\"10.00\" min=\"0.1\" \/>\r\n      <\/div>\r\n    <\/div>\r\n    <div class=\"canvas-container\">\r\n      <canvas id=\"measureCanvas\"><\/canvas>\r\n    <\/div>\r\n    <div class=\"calibration-info\">\r\n      <span id=\"calibStatus\">\u26d4 Belum dikalibrasi<\/span>\r\n      <span id=\"scaleDisplay\">Skala: - px\/cm<\/span>\r\n    <\/div>\r\n    <div class=\"measure-buttons\">\r\n      <button class=\"secondary\" id=\"calibrateBtn\">\ud83d\udccf Kalibrasi (gambar garis referensi)<\/button>\r\n      <button class=\"secondary\" id=\"measureBtn\">\ud83d\udcd0 Ukur Spesies<\/button>\r\n      <button id=\"applySizeBtn\">\u2705 Gunakan ukuran ini ke field<\/button>\r\n      <button class=\"secondary\" id=\"resetPhotoBtn\">\ud83d\udd04 Reset<\/button>\r\n    <\/div>\r\n    <p><small id=\"photoHint\">* Klik tombol Kalibrasi, gambar garis pada benda dengan panjang diketahui. Lalu klik Ukur Spesies, gambar garis pada spesies. Hasil akan muncul dan bisa diaplikasikan.<\/small><\/p>\r\n  <\/div>\r\n\r\n  <!-- Preview Gambar & Link WoRMS (dari database) -->\r\n  <div id=\"preview-box\">\r\n    <div id=\"loader-text\">Mencari foto spesies...<\/div>\r\n    <div class=\"image-container\"><img decoding=\"async\" id=\"megabentos-img\" src=\"\" alt=\"Megabentos Preview\"><\/div>\r\n    <p id=\"image-source\" style=\"font-size: 11px;\">Sumber Foto: Memuat...<\/p>\r\n    <a id=\"worms-link\" href=\"#\" target=\"_blank\">\ud83d\udd0d Buka di WoRMS<\/a>\r\n  <\/div>\r\n\r\n  <!-- Daftar Entri -->\r\n  <h3 id=\"entriesTitle\">Daftar Megabentos<\/h3>\r\n  <table id=\"entriesTable\">\r\n    <thead><tr><th id=\"tableName\">Nama<\/th><th id=\"tableLevel\">Level<\/th><th id=\"tableCount\">Jumlah<\/th><th id=\"tableSize\">Ukuran (cm)<\/th><th id=\"tableSubstrate\">Substrat<\/th><th id=\"tableBiomass\">Biomassa (gram)<\/th><th id=\"tableAction\">Aksi<\/th><\/tr><\/thead>\r\n    <tbody id=\"tableBody\"><\/tbody>\r\n  <\/table>\r\n  <div class=\"total-biomass\" id=\"totalBiomass\">Total Biomassa: 0 gram<\/div>\r\n\r\n  <!-- Ekspor -->\r\n  <div class=\"format-group\">\r\n    <label id=\"exportFormatLabel\">Format Ekspor:<\/label>\r\n    <label><input type=\"radio\" name=\"exportFormat\" value=\"xlsx\" checked> Excel (.xlsx)<\/label>\r\n    <label><input type=\"radio\" name=\"exportFormat\" value=\"csv\"> CSV (.csv)<\/label>\r\n    <label><input type=\"radio\" name=\"exportFormat\" value=\"txt\"> TXT (.txt)<\/label>\r\n  <\/div>\r\n  <button class=\"export-btn\" id=\"exportBtn\">\ud83d\udce5 <span id=\"exportButtonText\">Ekspor<\/span><\/button>\r\n  <div id=\"loadError\" class=\"error-message\" style=\"display: none;\"><\/div>\r\n<\/div>\r\n\r\n<script>\r\n\/\/ ===================== DATA MEGABENTOS TERKOREKSI =====================\r\nconst MEGABENTHOS_RAW = `group,species,max_size_cm,a,b,trophic_role\r\nDrupella,Drupella cornus,4.90,0.01156,2.75300,corallivore\r\nDrupella,Drupella rugosa,4.71,0.00915,2.89000,corallivore\r\nDrupella,Drupella margariticola,4.50,0.01343,2.77800,corallivore\r\nDrupella,Drupella fragum,5.34,0.01453,2.75500,corallivore\r\nDrupella,Drupella ricinus,9.88,0.01409,2.88700,corallivore\r\nDrupella,Drupella clathrata,7.29,0.01190,2.82600,corallivore\r\nDrupella,Drupella lobata,7.40,0.00969,2.74300,corallivore\r\nDrupella,Drupella spectrum,5.55,0.01087,2.76300,corallivore\r\nSeaStar,Linckia laevigata,40.00,0.00351,3.10200,detritivore\r\nSeaStar,Linckia multifora,8.38,0.00224,3.19900,detritivore\r\nSeaStar,Protoreaster nodosus,40.00,0.00296,3.14200,detritivore\r\nSeaStar,Protoreaster lincki,45.19,0.00364,3.00700,detritivore\r\nSeaStar,Culcita novaeguineae,40.00,0.00264,3.06000,detritivore\r\nSeaStar,Fromia monilis,11.16,0.00341,3.07400,detritivore\r\nSeaStar,Fromia indica,24.82,0.00252,3.08600,detritivore\r\nSeaStar,Nardoa tuberculata,42.34,0.00395,3.06200,detritivore\r\nSeaStar,Pentaceraster regulus,24.59,0.00351,3.19500,detritivore\r\nSeaStar,Leiaster leachi,24.44,0.00233,3.02300,detritivore\r\nSeaStar,Asteropsis carinifera,60.22,0.00272,3.05400,detritivore\r\nSeaStar,Echinaster luzonicus,69.51,0.00338,3.02400,detritivore\r\nSeaStar,Iconaster longimanus,17.93,0.00258,3.04900,detritivore\r\nSeaStar,Neoferdina cumingi,76.31,0.00277,3.14600,detritivore\r\nSeaStar,Gomophia egyptiaca,37.91,0.00292,3.02600,detritivore\r\nAcanthaster,Acanthaster planci,50.00,0.00353,3.03000,corallivore\r\nAcanthaster,Acanthaster brevispinus,15.15,0.00331,3.17000,corallivore\r\nAcanthaster,Acanthaster mauritiensis,78.66,0.00324,3.10600,corallivore\r\nAcanthaster,Acanthaster solaris,22.15,0.00261,3.06900,corallivore\r\nSeaUrchin,Diadema setosum,8.40,0.00345,3.01700,grazer\r\nSeaUrchin,Diadema savignyi,8.40,0.00344,3.04400,grazer\r\nSeaUrchin,Diadema palmeri,9.00,0.00336,3.15600,grazer\r\nSeaUrchin,Echinothrix diadema,9.00,0.00210,3.01800,grazer\r\nSeaUrchin,Echinothrix calamaris,9.00,0.00356,3.12100,grazer\r\nSeaUrchin,Echinometra mathaei,9.00,0.00395,3.07300,grazer\r\nSeaUrchin,Echinometra oblonga,9.00,0.00299,3.18800,grazer\r\nSeaUrchin,Echinometra viridis,5.00,0.00321,3.16500,grazer\r\nSeaUrchin,Tripneustes gratilla,15.00,0.00322,3.01600,grazer\r\nSeaUrchin,Tripneustes ventricosus,15.00,0.00323,3.19500,grazer\r\nSeaUrchin,Tripneustes depressus,15.00,0.00389,3.07800,grazer\r\nSeaUrchin,Toxopneustes pileolus,15.00,0.00294,3.12800,grazer\r\nSeaUrchin,Lytechinus variegatus,8.00,0.00295,3.07100,grazer\r\nSeaUrchin,Strongylocentrotus purpuratus,10.00,0.00395,3.07000,grazer\r\nSeaUrchin,Strongylocentrotus droebachiensis,8.00,0.00280,3.18000,grazer\r\nSeaUrchin,Centrostephanus rodgersii,15.00,0.00384,3.14600,grazer\r\nSeaUrchin,Astropyga radiata,20.00,0.00278,3.11000,grazer\r\nSeaUrchin,Parasalenia gratiosa,5.00,0.00279,3.06900,grazer\r\nSeaCucumber,Holothuria atra,60.00,0.00187,3.16200,deposit_feeder\r\nSeaCucumber,Holothuria scabra,70.00,0.00168,3.15100,deposit_feeder\r\nSeaCucumber,Holothuria edulis,23.61,0.00222,3.12900,deposit_feeder\r\nSeaCucumber,Holothuria leucospilota,64.71,0.00204,3.11300,deposit_feeder\r\nSeaCucumber,Holothuria fuscogilva,49.68,0.00181,3.17400,deposit_feeder\r\nSeaCucumber,Holothuria nobilis,83.10,0.00228,3.19800,deposit_feeder\r\nSeaCucumber,Bohadschia argus,82.21,0.00188,3.18400,deposit_feeder\r\nSeaCucumber,Bohadschia vitiensis,85.66,0.00206,3.15800,deposit_feeder\r\nSeaCucumber,Bohadschia marmorata,80.91,0.00225,3.17800,deposit_feeder\r\nSeaCucumber,Stichopus chloronotus,94.38,0.00170,3.12400,deposit_feeder\r\nSeaCucumber,Stichopus horrens,62.90,0.00183,3.19500,deposit_feeder\r\nSeaCucumber,Stichopus vastus,80.54,0.00226,3.10600,deposit_feeder\r\nSeaCucumber,Actinopyga echinites,95.73,0.00204,3.14700,deposit_feeder\r\nSeaCucumber,Actinopyga mauritiana,78.08,0.00164,3.10500,deposit_feeder\r\nSeaCucumber,Actinopyga lecanora,64.56,0.00208,3.16500,deposit_feeder\r\nSeaCucumber,Thelenota ananas,62.71,0.00184,3.14800,deposit_feeder\r\nSeaCucumber,Thelenota anax,56.47,0.00189,3.18400,deposit_feeder\r\nSeaCucumber,Pearsonothuria graeffei,28.75,0.00174,3.14600,deposit_feeder\r\nGiantClam,Tridacna gigas,94.13,0.01187,2.85600,filter_feeder\r\nGiantClam,Tridacna derasa,97.56,0.01237,2.87800,filter_feeder\r\nGiantClam,Tridacna squamosa,123.56,0.01217,2.88100,filter_feeder\r\nGiantClam,Tridacna maxima,49.74,0.01061,2.80100,filter_feeder\r\nGiantClam,Tridacna crocea,24.96,0.01363,2.92300,filter_feeder\r\nGiantClam,Tridacna mbalavuana,26.79,0.01113,2.92600,filter_feeder\r\nGiantClam,Hippopus hippopus,115.58,0.01115,2.91600,filter_feeder\r\nGiantClam,Hippopus porcellanus,98.98,0.01031,2.85500,filter_feeder\r\nLobster,Panulirus ornatus,15.36,0.00739,3.06400,predator\r\nLobster,Panulirus versicolor,16.30,0.00755,3.00100,predator\r\nLobster,Panulirus longipes,17.35,0.00843,3.01500,predator\r\nLobster,Panulirus homarus,25.02,0.00706,3.05700,predator\r\nLobster,Panulirus penicillatus,27.08,0.00875,3.06200,predator\r\nLobster,Panulirus polyphagus,26.93,0.00771,3.00200,predator\r\nLobster,Panulirus femoristriga,24.51,0.00709,3.05900,predator\r\nLobster,Panulirus stimpsoni,27.05,0.00884,3.09600,predator\r\nLobster,Panulirus marginatus,25.05,0.00772,3.00100,predator\r\nLobster,Panulirus japonicus,20.15,0.00762,3.07600,predator\r\nTrochus,Rochia nilotica,14.62,0.01027,2.85100,grazer\r\nTrochus,Trochus maculatus,7.71,0.01408,2.72500,grazer\r\nTrochus,Phorcus richardi,3.49,0.01164,2.90000,grazer\r\nTrochus,Tectus pyramis,14.06,0.01438,2.77600,grazer\r\nTrochus,Tectus dentatus,6.88,0.01303,2.81900,grazer\r\nTrochus,Tectus fenestratus,7.48,0.00974,2.82200,grazer\r\nTrochus,Rochia conus,8.57,0.01005,2.76600,grazer`;\r\n\r\n\/\/ ===================== PARSING CSV & DEDUPLIKASI SPESIES =====================\r\nfunction parseMegabenthosCSV(csv) {\r\n  const lines = csv.trim().split('\\n');\r\n  const headers = lines[0].split(',').map(h => h.trim());\r\n  const data = [];\r\n  for (let i = 1; i < lines.length; i++) {\r\n    const line = lines[i].trim();\r\n    if (!line) continue;\r\n    const values = line.split(',').map(v => v.trim());\r\n    if (values.length !== headers.length) continue;\r\n    const obj = {};\r\n    headers.forEach((h, idx) => {\r\n      let val = values[idx];\r\n      if (!isNaN(val) && val !== '') obj[h] = parseFloat(val);\r\n      else obj[h] = val;\r\n    });\r\n    data.push(obj);\r\n  }\r\n  return data;\r\n}\r\n\r\nconst megabenthosData = parseMegabenthosCSV(MEGABENTHOS_RAW);\r\n\r\n\/\/ Bangun data unik untuk species\r\nlet speciesLookup = {};\r\nlet speciesList = [];\r\n\r\nmegabenthosData.forEach(item => {\r\n  const speciesName = item.species;\r\n  if (!speciesLookup[speciesName]) {\r\n    const speciesObj = {\r\n      Name: speciesName,\r\n      A: item.a,\r\n      B: item.b,\r\n      MaxLength: item.max_size_cm,\r\n      TrophicGroup: item.trophic_role,\r\n      FunctionalGroup: item.group\r\n    };\r\n    speciesLookup[speciesName] = speciesObj;\r\n    speciesList.push(speciesObj);\r\n  }\r\n});\r\n\r\n\/\/ Bangun data genus (rata-rata)\r\nlet genusMap = new Map();\r\nspeciesList.forEach(species => {\r\n  const genusName = species.Name.split(' ')[0];\r\n  if (!genusMap.has(genusName)) {\r\n    genusMap.set(genusName, { Name: genusName, totalA: 0, totalB: 0, maxLen: 0, count: 0 });\r\n  }\r\n  const g = genusMap.get(genusName);\r\n  g.totalA += species.A;\r\n  g.totalB += species.B;\r\n  g.maxLen = Math.max(g.maxLen, species.MaxLength);\r\n  g.count++;\r\n});\r\n\r\nlet genera = [];\r\nfor (let [name, val] of genusMap.entries()) {\r\n  genera.push({\r\n    Name: name,\r\n    A: val.totalA \/ val.count,\r\n    B: val.totalB \/ val.count,\r\n    MaxLength: val.maxLen,\r\n    TrophicGroup: 'N\/A',\r\n    FunctionalGroup: 'N\/A'\r\n  });\r\n}\r\n\r\n\/\/ Bangun data group\r\nlet groupMap = new Map();\r\nspeciesList.forEach(species => {\r\n  const groupName = species.FunctionalGroup;\r\n  if (!groupMap.has(groupName)) {\r\n    groupMap.set(groupName, { Name: groupName, totalA: 0, totalB: 0, maxLen: 0, count: 0 });\r\n  }\r\n  const gr = groupMap.get(groupName);\r\n  gr.totalA += species.A;\r\n  gr.totalB += species.B;\r\n  gr.maxLen = Math.max(gr.maxLen, species.MaxLength);\r\n  gr.count++;\r\n});\r\n\r\nlet groups = [];\r\nfor (let [name, val] of groupMap.entries()) {\r\n  groups.push({\r\n    Name: name,\r\n    A: val.totalA \/ val.count,\r\n    B: val.totalB \/ val.count,\r\n    MaxLength: val.maxLen,\r\n    TrophicGroup: 'N\/A',\r\n    FunctionalGroup: name\r\n  });\r\n}\r\n\r\n\/\/ ===================== KONFIGURASI BAHASA =====================\r\nlet currentLanguage = 'id';\r\nconst translations = {\r\n  id: {\r\n    mainTitle: '\ud83d\udccb Input Data Megabentos',\r\n    projectInfoTitle: 'Informasi Project',\r\n    projectNameLabel: 'Nama Project',\r\n    surveyorLabel: 'Nama Surveyor',\r\n    datetimeLabel: 'Waktu (Tanggal & Jam)',\r\n    siteNameLabel: 'Nama Site',\r\n    locationDescLabel: 'Lokasi (deskripsi)',\r\n    latitudeLabel: 'Latitude',\r\n    longitudeLabel: 'Longitude',\r\n    lineLengthLabel: 'Metode \u2013 Panjang Line (m)',\r\n    obsWidthLabel: 'Metode \u2013 Lebar Pengamatan (m)',\r\n    waterConditionLabel: 'Kondisi Perairan',\r\n    depthLabel: 'Kedalaman (m)',\r\n    identificationLevelTitle: 'Tingkat Identifikasi',\r\n    groupLabel: 'Group',\r\n    genusLabel: 'Genus',\r\n    speciesLabel: 'Spesies',\r\n    addDataTitle: 'Tambah Data Megabentos',\r\n    taxonLabel: 'Nama Group',\r\n    countLabel: 'Jumlah',\r\n    sizeLabel: 'Ukuran (cm)',\r\n    substrateLabel: 'Substrat',\r\n    biomassLabel: 'Biomassa Total (gram)',\r\n    addButtonText: 'Tambah ke Daftar',\r\n    loaderText: 'Mencari foto spesies...',\r\n    imageSource: 'Sumber Foto: Memuat...',\r\n    entriesTitle: 'Daftar Megabentos',\r\n    tableName: 'Nama',\r\n    tableLevel: 'Level',\r\n    tableCount: 'Jumlah',\r\n    tableSize: 'Ukuran (cm)',\r\n    tableSubstrate: 'Substrat',\r\n    tableBiomass: 'Biomassa (gram)',\r\n    tableAction: 'Aksi',\r\n    totalBiomass: 'Total Biomassa: 0 gram',\r\n    exportFormatLabel: 'Format Ekspor:',\r\n    exportButtonText: 'Ekspor',\r\n    removeButtonText: 'Hapus',\r\n    searchPlaceholder: 'Ketik untuk mencari...',\r\n    waterConditionPlaceholder: 'Cerah, Berombak',\r\n    projectNamePlaceholder: 'Ekspedisi Megabentos',\r\n    sizeWarning: '\u26a0\ufe0f Ukuran melebihi batas normal (maks ',\r\n    sizeWarningEnd: ' cm)',\r\n    alertEnterName: 'Masukkan nama terlebih dahulu!',\r\n    alertNameNotFound: 'Nama tidak ditemukan dalam database. Pilih dari saran.',\r\n    alertDataCannotAdd: 'Data tidak dapat ditambahkan.',\r\n    saveProject: 'Simpan Proyek',\r\n    loadProject: 'Muat Proyek',\r\n    photoTitle: '\ud83d\udcf8 Ukur dari Foto (dengan Kalibrasi)',\r\n    uploadLabel: 'Upload Foto',\r\n    knownSizeLabel: 'Panjang Referensi (cm)',\r\n    calibStatusNot: '\u26d4 Belum dikalibrasi',\r\n    scaleDisplay: 'Skala: - px\/cm',\r\n    photoHint: '* Klik tombol Kalibrasi, gambar garis pada benda dengan panjang diketahui. Lalu klik Ukur Spesies, gambar garis pada spesies. Hasil akan muncul dan bisa diaplikasikan.'\r\n  },\r\n  en: {\r\n    mainTitle: '\ud83d\udccb Megabenthos Data Entry',\r\n    projectInfoTitle: 'Project Information',\r\n    projectNameLabel: 'Project Name',\r\n    surveyorLabel: 'Surveyor Name',\r\n    datetimeLabel: 'Date & Time',\r\n    siteNameLabel: 'Site Name',\r\n    locationDescLabel: 'Location (description)',\r\n    latitudeLabel: 'Latitude',\r\n    longitudeLabel: 'Longitude',\r\n    lineLengthLabel: 'Method \u2013 Line Length (m)',\r\n    obsWidthLabel: 'Method \u2013 Observation Width (m)',\r\n    waterConditionLabel: 'Water Condition',\r\n    depthLabel: 'Depth (m)',\r\n    identificationLevelTitle: 'Identification Level',\r\n    groupLabel: 'Group',\r\n    genusLabel: 'Genus',\r\n    speciesLabel: 'Species',\r\n    addDataTitle: 'Add Megabenthos Data',\r\n    taxonLabel: 'Group Name',\r\n    countLabel: 'Count',\r\n    sizeLabel: 'Size (cm)',\r\n    substrateLabel: 'Substrate',\r\n    biomassLabel: 'Total Biomass (grams)',\r\n    addButtonText: 'Add to List',\r\n    loaderText: 'Searching for species photo...',\r\n    imageSource: 'Image Source: Loading...',\r\n    entriesTitle: 'Megabenthos List',\r\n    tableName: 'Name',\r\n    tableLevel: 'Level',\r\n    tableCount: 'Count',\r\n    tableSize: 'Size (cm)',\r\n    tableSubstrate: 'Substrate',\r\n    tableBiomass: 'Biomass (grams)',\r\n    tableAction: 'Action',\r\n    totalBiomass: 'Total Biomass: 0 grams',\r\n    exportFormatLabel: 'Export Format:',\r\n    exportButtonText: 'Export',\r\n    removeButtonText: 'Remove',\r\n    searchPlaceholder: 'Type to search...',\r\n    waterConditionPlaceholder: 'Clear, Wavy',\r\n    projectNamePlaceholder: 'Megabenthos Expedition',\r\n    sizeWarning: '\u26a0\ufe0f Size exceeds normal limit (max ',\r\n    sizeWarningEnd: ' cm)',\r\n    alertEnterName: 'Please enter a name first!',\r\n    alertNameNotFound: 'Name not found in database. Select from suggestions.',\r\n    alertDataCannotAdd: 'Data cannot be added.',\r\n    saveProject: 'Save Project',\r\n    loadProject: 'Load Project',\r\n    photoTitle: '\ud83d\udcf8 Measure from Photo (with Calibration)',\r\n    uploadLabel: 'Upload Photo',\r\n    knownSizeLabel: 'Reference Length (cm)',\r\n    calibStatusNot: '\u26d4 Not calibrated',\r\n    scaleDisplay: 'Scale: - px\/cm',\r\n    photoHint: '* Click Calibrate, draw a line on an object of known length. Then click Measure Species, draw a line on the species. The result will appear and can be applied.'\r\n  }\r\n};\r\n\r\nfunction setLanguage(lang) {\r\n  currentLanguage = lang;\r\n  document.getElementById('langID').classList.toggle('active', lang === 'id');\r\n  document.getElementById('langEN').classList.toggle('active', lang === 'en');\r\n\r\n  document.getElementById('mainTitle').textContent = translations[lang].mainTitle;\r\n  document.getElementById('projectInfoTitle').textContent = translations[lang].projectInfoTitle;\r\n  document.getElementById('projectNameLabel').textContent = translations[lang].projectNameLabel;\r\n  document.getElementById('surveyorLabel').textContent = translations[lang].surveyorLabel;\r\n  document.getElementById('datetimeLabel').textContent = translations[lang].datetimeLabel;\r\n  document.getElementById('siteNameLabel').textContent = translations[lang].siteNameLabel;\r\n  document.getElementById('locationDescLabel').textContent = translations[lang].locationDescLabel;\r\n  document.getElementById('latitudeLabel').textContent = translations[lang].latitudeLabel;\r\n  document.getElementById('longitudeLabel').textContent = translations[lang].longitudeLabel;\r\n  document.getElementById('lineLengthLabel').textContent = translations[lang].lineLengthLabel;\r\n  document.getElementById('obsWidthLabel').textContent = translations[lang].obsWidthLabel;\r\n  document.getElementById('waterConditionLabel').textContent = translations[lang].waterConditionLabel;\r\n  document.getElementById('depthLabel').textContent = translations[lang].depthLabel;\r\n  document.getElementById('identificationLevelTitle').textContent = translations[lang].identificationLevelTitle;\r\n  document.getElementById('groupLabel').textContent = translations[lang].groupLabel;\r\n  document.getElementById('genusLabel').textContent = translations[lang].genusLabel;\r\n  document.getElementById('speciesLabel').textContent = translations[lang].speciesLabel;\r\n  document.getElementById('addDataTitle').textContent = translations[lang].addDataTitle;\r\n  document.getElementById('countLabel').textContent = translations[lang].countLabel;\r\n  document.getElementById('sizeLabel').textContent = translations[lang].sizeLabel;\r\n  document.getElementById('substrateLabel').textContent = translations[lang].substrateLabel;\r\n  document.getElementById('biomassLabel').textContent = translations[lang].biomassLabel;\r\n  document.getElementById('addButtonText').textContent = translations[lang].addButtonText;\r\n  document.getElementById('loader-text').textContent = translations[lang].loaderText;\r\n  document.getElementById('entriesTitle').textContent = translations[lang].entriesTitle;\r\n  document.getElementById('tableName').textContent = translations[lang].tableName;\r\n  document.getElementById('tableLevel').textContent = translations[lang].tableLevel;\r\n  document.getElementById('tableCount').textContent = translations[lang].tableCount;\r\n  document.getElementById('tableSize').textContent = translations[lang].tableSize;\r\n  document.getElementById('tableSubstrate').textContent = translations[lang].tableSubstrate;\r\n  document.getElementById('tableBiomass').textContent = translations[lang].tableBiomass;\r\n  document.getElementById('tableAction').textContent = translations[lang].tableAction;\r\n  document.getElementById('exportFormatLabel').textContent = translations[lang].exportFormatLabel;\r\n  document.getElementById('exportButtonText').textContent = translations[lang].exportButtonText;\r\n  document.getElementById('taxonInput').placeholder = translations[lang].searchPlaceholder;\r\n  document.getElementById('waterCondition').placeholder = translations[lang].waterConditionPlaceholder;\r\n  document.getElementById('projectName').placeholder = translations[lang].projectNamePlaceholder;\r\n  document.getElementById('photoTitle').textContent = translations[lang].photoTitle;\r\n  document.getElementById('uploadLabel').textContent = translations[lang].uploadLabel;\r\n  document.getElementById('knownSizeLabel').textContent = translations[lang].knownSizeLabel;\r\n  document.getElementById('photoHint').textContent = translations[lang].photoHint;\r\n\r\n  const level = document.querySelector('input[name=\"level\"]:checked').value;\r\n  updateTaxonLabel(level);\r\n  updateTotalBiomass();\r\n  renderTable();\r\n}\r\n\r\nfunction updateTaxonLabel(level) {\r\n  const map = { group: 'Group', genus: 'Genus', species: 'Spesies' };\r\n  document.getElementById('taxonLabel').textContent = \r\n    (currentLanguage === 'id' ? 'Nama ' : '') + map[level] + (currentLanguage === 'id' ? '' : ' Name');\r\n}\r\n\r\n\/\/ ===================== FUNGSI DATABASE =====================\r\nfunction getConstants(level, taxonName) {\r\n  if (level === 'group') {\r\n    const g = groups.find(g => g.Name === taxonName);\r\n    return g ? { A: g.A, B: g.B } : { A: 0, B: 0 };\r\n  } else if (level === 'genus') {\r\n    const g = genera.find(g => g.Name === taxonName);\r\n    return g ? { A: g.A, B: g.B } : { A: 0, B: 0 };\r\n  } else {\r\n    const s = speciesLookup[taxonName];\r\n    return s ? { A: s.A, B: s.B } : { A: 0, B: 0 };\r\n  }\r\n}\r\n\r\nfunction calculateBiomass(level, taxonName, sizeCm) {\r\n  const { A, B } = getConstants(level, taxonName);\r\n  if (!A || !B || isNaN(A) || isNaN(B)) return 0;\r\n  return A * Math.pow(sizeCm, B);\r\n}\r\n\r\nfunction validateSize(level, taxonName, sizeCm) {\r\n  let max = 500;\r\n  if (level === 'species') {\r\n    const s = speciesLookup[taxonName];\r\n    if (s && s.MaxLength) max = s.MaxLength;\r\n  } else if (level === 'genus') {\r\n    const g = genera.find(g => g.Name === taxonName);\r\n    if (g && g.MaxLength) max = g.MaxLength;\r\n  } else {\r\n    const gr = groups.find(g => g.Name === taxonName);\r\n    if (gr && gr.MaxLength) max = gr.MaxLength;\r\n  }\r\n  if (sizeCm > max) return `\u26a0\ufe0f ${translations[currentLanguage].sizeWarning}${max}${translations[currentLanguage].sizeWarningEnd}`;\r\n  return null;\r\n}\r\n\r\n\/\/ ===================== UPDATE UI BIOMASSA =====================\r\nfunction updateBiomassDisplay() {\r\n  const level = document.querySelector('input[name=\"level\"]:checked').value;\r\n  const taxon = document.getElementById('taxonInput').value;\r\n  if (!taxon) { document.getElementById('biomassDisplay').value = '0'; return; }\r\n  const size = parseFloat(document.getElementById('size').value) || 0;\r\n  const count = parseInt(document.getElementById('count').value) || 1;\r\n  const biomass = calculateBiomass(level, taxon, size) * count;\r\n  document.getElementById('biomassDisplay').value = biomass.toFixed(2);\r\n  const warning = validateSize(level, taxon, size);\r\n  const warnDiv = document.getElementById('sizeWarning');\r\n  if (warning) { warnDiv.style.display = 'block'; warnDiv.textContent = warning; }\r\n  else warnDiv.style.display = 'none';\r\n}\r\n\r\n\/\/ ===================== FUNGSI AMBIL APHIAID DARI WORMS =====================\r\nasync function getAphiaID(speciesName) {\r\n  const url = `https:\/\/www.marinespecies.org\/rest\/AphiaIDByName\/${encodeURIComponent(speciesName)}?marine_only=false`;\r\n  try {\r\n    const response = await fetch(url);\r\n    if (response.ok) {\r\n      const text = await response.text();\r\n      if (text && text !== '-999') return text;\r\n    }\r\n  } catch (error) {\r\n    console.error('Gagal mengambil AphiaID:', error);\r\n  }\r\n  return null;\r\n}\r\n\r\n\/\/ ===================== PREVIEW GAMBAR & WORMS =====================\r\nlet searchTimeout;\r\nasync function updateSpeciesImage() {\r\n  const level = document.querySelector('input[name=\"level\"]:checked').value;\r\n  const taxon = document.getElementById('taxonInput').value.trim();\r\n  const previewBox = document.getElementById('preview-box');\r\n  const img = document.getElementById('megabentos-img');\r\n  const loader = document.getElementById('loader-text');\r\n  const sourceText = document.getElementById('image-source');\r\n  const wormsLink = document.getElementById('worms-link');\r\n\r\n  if (level !== 'species' || taxon.length < 3) {\r\n    previewBox.style.display = 'none';\r\n    return;\r\n  }\r\n\r\n  previewBox.style.display = 'block';\r\n  loader.style.display = 'block';\r\n  loader.innerText = currentLanguage === 'id' ? 'Mencari foto spesies...' : 'Searching for species photo...';\r\n  img.style.opacity = '0.1';\r\n\r\n  const aphiaID = await getAphiaID(taxon);\r\n  if (aphiaID) {\r\n    wormsLink.href = `https:\/\/www.marinespecies.org\/aphia.php?p=taxdetails&id=${aphiaID}`;\r\n  } else {\r\n    wormsLink.href = `https:\/\/www.marinespecies.org\/aphia.php?p=taxlist&tName=${encodeURIComponent(taxon)}`;\r\n  }\r\n\r\n  const parts = taxon.split(' ');\r\n  if (parts.length < 2) {\r\n    loader.innerText = currentLanguage === 'id' ? 'Ketik nama spesies lengkap (Genus spesies)' : 'Type complete species name (Genus species)';\r\n    return;\r\n  }\r\n\r\n  const wikiUrl = `https:\/\/commons.wikimedia.org\/w\/api.php?action=query&format=json&prop=pageimages&generator=search&gsrsearch=intitle:\"${encodeURIComponent(taxon)}\"&gsrlimit=1&piprop=thumbnail&pithumbsize=800&origin=*`;\r\n  try {\r\n    const resp = await fetch(wikiUrl);\r\n    const data = await resp.json();\r\n    if (data.query && data.query.pages) {\r\n      const pageId = Object.keys(data.query.pages)[0];\r\n      const page = data.query.pages[pageId];\r\n      if (page.thumbnail) {\r\n        img.src = page.thumbnail.source;\r\n        sourceText.innerText = currentLanguage === 'id' ? 'Sumber: Wikimedia Commons' : 'Source: Wikimedia Commons';\r\n      } else throw new Error();\r\n    } else throw new Error();\r\n  } catch {\r\n    img.src = 'https:\/\/via.placeholder.com\/400x200?text=Foto+Tidak+Tersedia';\r\n    sourceText.innerText = currentLanguage === 'id' ? 'Gambar tidak ditemukan' : 'Image not found';\r\n  }\r\n  img.onload = () => { loader.style.display = 'none'; img.style.opacity = '1'; };\r\n}\r\n\r\n\/\/ ===================== ENTRI =====================\r\nlet entries = [];\r\n\r\nfunction addEntry() {\r\n  const level = document.querySelector('input[name=\"level\"]:checked').value;\r\n  const taxon = document.getElementById('taxonInput').value.trim();\r\n  if (!taxon) { alert(translations[currentLanguage].alertEnterName); return; }\r\n\r\n  let valid = false;\r\n  if (level === 'group') valid = groups.some(g => g.Name === taxon);\r\n  else if (level === 'genus') valid = genera.some(g => g.Name === taxon);\r\n  else valid = speciesLookup.hasOwnProperty(taxon);\r\n  if (!valid) { alert(translations[currentLanguage].alertNameNotFound); return; }\r\n\r\n  const count = parseInt(document.getElementById('count').value) || 1;\r\n  const size = parseFloat(document.getElementById('size').value) || 0;\r\n\r\n  const warn = validateSize(level, taxon, size);\r\n  if (warn) { alert(warn + '\\n' + translations[currentLanguage].alertDataCannotAdd); return; }\r\n\r\n  const substrate = document.getElementById('substrate').value;\r\n  if (!substrate) { alert('Pilih substrat terlebih dahulu!'); return; }\r\n\r\n  const { A, B } = getConstants(level, taxon);\r\n  const biomass = calculateBiomass(level, taxon, size) * count;\r\n\r\n  let trophic = 'N\/A', functional = 'N\/A';\r\n  if (level === 'species') {\r\n    const s = speciesLookup[taxon];\r\n    if (s) { trophic = s.TrophicGroup; functional = s.FunctionalGroup; }\r\n  } else {\r\n    const g = groups.find(g => g.Name === taxon);\r\n    if (g) functional = g.FunctionalGroup;\r\n  }\r\n\r\n  entries.push({ level, taxon, count, size, substrate, biomass, constA: A, constB: B, trophic, functional });\r\n  renderTable();\r\n  updateTotalBiomass();\r\n\r\n  \/\/ Reset form\r\n  document.getElementById('count').value = 1;\r\n  document.getElementById('size').value = '10.00';\r\n  document.getElementById('taxonInput').value = '';\r\n  document.getElementById('substrate').value = '';\r\n  updateBiomassDisplay();\r\n  updateSpeciesImage();\r\n}\r\n\r\nfunction renderTable() {\r\n  const tbody = document.getElementById('tableBody');\r\n  tbody.innerHTML = '';\r\n  entries.forEach((e, idx) => {\r\n    const row = tbody.insertRow();\r\n    row.innerHTML = `<td>${e.taxon}<\/td><td>${e.level}<\/td><td>${e.count}<\/td><td>${e.size.toFixed(2)}<\/td><td>${e.substrate}<\/td><td>${e.biomass.toFixed(2)}<\/td><td><button class=\"remove-btn\" onclick=\"removeEntry(${idx})\">${translations[currentLanguage].removeButtonText}<\/button><\/td>`;\r\n  });\r\n}\r\n\r\nfunction removeEntry(idx) {\r\n  entries.splice(idx, 1);\r\n  renderTable();\r\n  updateTotalBiomass();\r\n}\r\n\r\nfunction updateTotalBiomass() {\r\n  const total = entries.reduce((sum, e) => sum + e.biomass, 0);\r\n  document.getElementById('totalBiomass').textContent = \r\n    (currentLanguage === 'id' ? 'Total Biomassa: ' : 'Total Biomass: ') + total.toFixed(2) + \r\n    (currentLanguage === 'id' ? ' gram' : ' grams');\r\n}\r\n\r\n\/\/ ===================== POPULATE DATALIST =====================\r\nfunction populateDatalist(level) {\r\n  const datalist = document.getElementById('taxonDatalist');\r\n  datalist.innerHTML = '';\r\n  let options = [];\r\n  if (level === 'group') options = groups.map(g => g.Name);\r\n  else if (level === 'genus') options = genera.map(g => g.Name);\r\n  else options = speciesList.map(s => s.Name);\r\n  options.sort().forEach(opt => {\r\n    const o = document.createElement('option');\r\n    o.value = opt;\r\n    datalist.appendChild(o);\r\n  });\r\n}\r\n\r\n\/\/ ===================== FITUR FOTO KALIBRASI =====================\r\nlet photoCanvas = document.getElementById('measureCanvas');\r\nlet ctx = photoCanvas.getContext('2d');\r\nlet img = new Image();\r\nlet isCalibrating = false;\r\nlet isMeasuring = false;\r\nlet calibrationPoints = [];\r\nlet measurePoints = [];\r\nlet scale = null; \/\/ pixel per cm\r\nlet knownSizeCm = 10;\r\n\r\ndocument.getElementById('photoInput').addEventListener('change', function(e) {\r\n  const file = e.target.files[0];\r\n  if (file) {\r\n    const reader = new FileReader();\r\n    reader.onload = function(ev) {\r\n      img.onload = function() {\r\n        photoCanvas.width = img.width;\r\n        photoCanvas.height = img.height;\r\n        ctx.drawImage(img, 0, 0);\r\n        resetMeasurementState();\r\n      };\r\n      img.src = ev.target.result;\r\n    };\r\n    reader.readAsDataURL(file);\r\n  }\r\n});\r\n\r\nfunction resetMeasurementState() {\r\n  calibrationPoints = [];\r\n  measurePoints = [];\r\n  scale = null;\r\n  isCalibrating = false;\r\n  isMeasuring = false;\r\n  document.getElementById('calibStatus').innerHTML = '\u26d4 Belum dikalibrasi';\r\n  document.getElementById('scaleDisplay').innerText = 'Skala: - px\/cm';\r\n  ctx.drawImage(img, 0, 0);\r\n}\r\n\r\ndocument.getElementById('resetPhotoBtn').addEventListener('click', function() {\r\n  if (img.src) {\r\n    ctx.drawImage(img, 0, 0);\r\n    resetMeasurementState();\r\n  }\r\n});\r\n\r\ndocument.getElementById('calibrateBtn').addEventListener('click', function() {\r\n  if (!img.src) { alert('Upload foto dulu!'); return; }\r\n  isCalibrating = true;\r\n  isMeasuring = false;\r\n  calibrationPoints = [];\r\n  measurePoints = [];\r\n  ctx.drawImage(img, 0, 0);\r\n  alert('Klik dua titik pada gambar untuk garis referensi (benda dengan panjang diketahui).');\r\n});\r\n\r\ndocument.getElementById('measureBtn').addEventListener('click', function() {\r\n  if (!img.src) { alert('Upload foto dulu!'); return; }\r\n  if (scale === null) { alert('Kalibrasi dulu!'); return; }\r\n  isMeasuring = true;\r\n  isCalibrating = false;\r\n  measurePoints = [];\r\n  ctx.drawImage(img, 0, 0);\r\n  \/\/ gambar ulang garis kalibrasi jika ada\r\n  if (calibrationPoints.length === 2) {\r\n    ctx.beginPath();\r\n    ctx.strokeStyle = 'blue';\r\n    ctx.lineWidth = 2;\r\n    ctx.moveTo(calibrationPoints[0].x, calibrationPoints[0].y);\r\n    ctx.lineTo(calibrationPoints[1].x, calibrationPoints[1].y);\r\n    ctx.stroke();\r\n    ctx.fillStyle = 'blue';\r\n    ctx.fillRect(calibrationPoints[0].x-3, calibrationPoints[0].y-3, 6, 6);\r\n    ctx.fillRect(calibrationPoints[1].x-3, calibrationPoints[1].y-3, 6, 6);\r\n  }\r\n  alert('Klik dua titik pada spesies untuk mengukur.');\r\n});\r\n\r\nphotoCanvas.addEventListener('click', function(e) {\r\n  if (!isCalibrating && !isMeasuring) return;\r\n  const rect = photoCanvas.getBoundingClientRect();\r\n  const scaleX = photoCanvas.width \/ rect.width;\r\n  const scaleY = photoCanvas.height \/ rect.height;\r\n  const x = (e.clientX - rect.left) * scaleX;\r\n  const y = (e.clientY - rect.top) * scaleY;\r\n\r\n  if (isCalibrating) {\r\n    calibrationPoints.push({ x, y });\r\n    \/\/ gambar titik\r\n    ctx.fillStyle = 'blue';\r\n    ctx.fillRect(x-3, y-3, 6, 6);\r\n    if (calibrationPoints.length === 2) {\r\n      \/\/ hitung jarak pixel\r\n      const dx = calibrationPoints[1].x - calibrationPoints[0].x;\r\n      const dy = calibrationPoints[1].y - calibrationPoints[0].y;\r\n      const distPx = Math.sqrt(dx*dx + dy*dy);\r\n      knownSizeCm = parseFloat(document.getElementById('knownSize').value) || 10;\r\n      scale = distPx \/ knownSizeCm;\r\n      document.getElementById('calibStatus').innerHTML = '\u2705 Terkalibrasi';\r\n      document.getElementById('scaleDisplay').innerText = `Skala: ${scale.toFixed(2)} px\/cm`;\r\n      \/\/ gambar garis\r\n      ctx.beginPath();\r\n      ctx.strokeStyle = 'blue';\r\n      ctx.lineWidth = 2;\r\n      ctx.moveTo(calibrationPoints[0].x, calibrationPoints[0].y);\r\n      ctx.lineTo(calibrationPoints[1].x, calibrationPoints[1].y);\r\n      ctx.stroke();\r\n      isCalibrating = false;\r\n    }\r\n  } else if (isMeasuring) {\r\n    measurePoints.push({ x, y });\r\n    ctx.fillStyle = 'red';\r\n    ctx.fillRect(x-3, y-3, 6, 6);\r\n    if (measurePoints.length === 2) {\r\n      const dx = measurePoints[1].x - measurePoints[0].x;\r\n      const dy = measurePoints[1].y - measurePoints[0].y;\r\n      const distPx = Math.sqrt(dx*dx + dy*dy);\r\n      const sizeCm = distPx \/ scale;\r\n      \/\/ tampilkan hasil\r\n      alert(`Ukuran spesies: ${sizeCm.toFixed(2)} cm`);\r\n      \/\/ tawarkan untuk mengisi field ukuran\r\n      if (confirm(`Gunakan ukuran ${sizeCm.toFixed(2)} cm ke field Ukuran?`)) {\r\n        document.getElementById('size').value = sizeCm.toFixed(2);\r\n        updateBiomassDisplay();\r\n      }\r\n      \/\/ gambar garis\r\n      ctx.beginPath();\r\n      ctx.strokeStyle = 'red';\r\n      ctx.lineWidth = 2;\r\n      ctx.moveTo(measurePoints[0].x, measurePoints[0].y);\r\n      ctx.lineTo(measurePoints[1].x, measurePoints[1].y);\r\n      ctx.stroke();\r\n      isMeasuring = false;\r\n    }\r\n  }\r\n});\r\n\r\ndocument.getElementById('applySizeBtn').addEventListener('click', function() {\r\n  if (measurePoints.length < 2) {\r\n    alert('Lakukan pengukuran terlebih dahulu.');\r\n    return;\r\n  }\r\n  const dx = measurePoints[1].x - measurePoints[0].x;\r\n  const dy = measurePoints[1].y - measurePoints[0].y;\r\n  const distPx = Math.sqrt(dx*dx + dy*dy);\r\n  const sizeCm = distPx \/ scale;\r\n  document.getElementById('size').value = sizeCm.toFixed(2);\r\n  updateBiomassDisplay();\r\n});\r\n\r\n\/\/ ===================== EKSPOR =====================\r\nfunction exportToFile() {\r\n  const format = document.querySelector('input[name=\"exportFormat\"]:checked').value;\r\n  const projectData = {\r\n    [currentLanguage === 'id' ? 'Nama Project' : 'Project Name']: document.getElementById('projectName').value,\r\n    Surveyor: document.getElementById('surveyor').value,\r\n    [currentLanguage === 'id' ? 'Waktu' : 'Date\/Time']: document.getElementById('datetime').value,\r\n    [currentLanguage === 'id' ? 'Site' : 'Site']: document.getElementById('siteName').value,\r\n    [currentLanguage === 'id' ? 'Lokasi' : 'Location']: document.getElementById('locationDesc').value,\r\n    Latitude: document.getElementById('lat').value,\r\n    Longitude: document.getElementById('lng').value,\r\n    [currentLanguage === 'id' ? 'Panjang Line (m)' : 'Line Length (m)']: document.getElementById('lineLength').value,\r\n    [currentLanguage === 'id' ? 'Lebar Pengamatan (m)' : 'Observation Width (m)']: document.getElementById('obsWidth').value,\r\n    [currentLanguage === 'id' ? 'Kondisi Perairan' : 'Water Condition']: document.getElementById('waterCondition').value,\r\n    [currentLanguage === 'id' ? 'Kedalaman (m)' : 'Depth (m)']: document.getElementById('depth').value,\r\n  };\r\n\r\n  const megabentosDataExport = entries.map(e => ({\r\n    Level: e.level,\r\n    [currentLanguage === 'id' ? 'Nama' : 'Name']: e.taxon,\r\n    [currentLanguage === 'id' ? 'Jumlah' : 'Count']: e.count,\r\n    [currentLanguage === 'id' ? 'Ukuran (cm)' : 'Size (cm)']: e.size.toFixed(2),\r\n    [currentLanguage === 'id' ? 'Substrat' : 'Substrate']: e.substrate,\r\n    [currentLanguage === 'id' ? 'Biomassa (gram)' : 'Biomass (g)']: e.biomass.toFixed(2),\r\n    'Biomass Constant A': e.constA.toFixed(6),\r\n    'Biomass Constant B': e.constB.toFixed(6),\r\n    'Trophic Group': e.trophic,\r\n    'Functional Group': e.functional\r\n  }));\r\n\r\n  if (format === 'xlsx') {\r\n    const wb = XLSX.utils.book_new();\r\n    const wsProject = XLSX.utils.aoa_to_sheet([['Field', 'Value'], ...Object.entries(projectData)]);\r\n    XLSX.utils.book_append_sheet(wb, wsProject, 'Project Info');\r\n    const wsData = XLSX.utils.json_to_sheet(megabentosDataExport);\r\n    XLSX.utils.book_append_sheet(wb, wsData, 'Megabentos Data');\r\n    const panjang = parseFloat(projectData['Panjang Line (m)'] || projectData['Line Length (m)']) || 0;\r\n    const lebar = parseFloat(projectData['Lebar Pengamatan (m)'] || projectData['Observation Width (m)']) || 0;\r\n    const luas = panjang * lebar;\r\n    const totalBiomassGram = entries.reduce((s, e) => s + e.biomass, 0);\r\n    const biomassaPerLuasan = luas > 0 ? (totalBiomassGram \/ luas).toFixed(2) : 0;\r\n    const luasanData = [\r\n      ['Parameter', 'Value'],\r\n      ['Panjang Line (m)', panjang],\r\n      ['Lebar Pengamatan (m)', lebar],\r\n      ['Luas Area (m\u00b2)', luas.toFixed(2)],\r\n      ['Total Biomassa (g)', totalBiomassGram.toFixed(2)],\r\n      ['Biomassa per Luasan (g\/m\u00b2)', biomassaPerLuasan]\r\n    ];\r\n    const wsLuasan = XLSX.utils.aoa_to_sheet(luasanData);\r\n    XLSX.utils.book_append_sheet(wb, wsLuasan, 'Biomass per Area');\r\n    XLSX.writeFile(wb, 'megabentos_data.xlsx');\r\n  } else {\r\n    let content = '';\r\n    for (let [k, v] of Object.entries(projectData)) content += `\"${k}\",\"${v}\"\\n`;\r\n    content += '\\n';\r\n    const headers = currentLanguage === 'id' \r\n      ? 'Level,Nama,Jumlah,Ukuran (cm),Substrat,Biomassa (g),Biomass Constant A,Biomass Constant B,Trophic Group,Functional Group\\n'\r\n      : 'Level,Name,Count,Size (cm),Substrate,Biomass (g),Biomass Constant A,Biomass Constant B,Trophic Group,Functional Group\\n';\r\n    content += headers;\r\n    megabentosDataExport.forEach(e => {\r\n      content += `${e.Level},\"${e.Name}\",${e.Count},${e['Ukuran (cm)'] || e['Size (cm)']},\"${e.Substrat || e.Substrate}\",${e['Biomassa (gram)'] || e['Biomass (g)']},${e['Biomass Constant A']},${e['Biomass Constant B']},\"${e['Trophic Group']}\",\"${e['Functional Group']}\"\\n`;\r\n    });\r\n    const blob = new Blob([\"\\uFEFF\" + content], { type: format === 'csv' ? 'text\/csv' : 'text\/plain' });\r\n    const link = document.createElement('a');\r\n    link.href = URL.createObjectURL(blob);\r\n    link.download = `megabentos_data.${format}`;\r\n    link.click();\r\n  }\r\n}\r\n\r\n\/\/ ===================== SIMPAN\/MUAT PROYEK =====================\r\nfunction saveProject() {\r\n  const projectInfo = {\r\n    projectName: document.getElementById('projectName').value,\r\n    surveyor: document.getElementById('surveyor').value,\r\n    datetime: document.getElementById('datetime').value,\r\n    siteName: document.getElementById('siteName').value,\r\n    locationDesc: document.getElementById('locationDesc').value,\r\n    lat: document.getElementById('lat').value,\r\n    lng: document.getElementById('lng').value,\r\n    lineLength: document.getElementById('lineLength').value,\r\n    obsWidth: document.getElementById('obsWidth').value,\r\n    waterCondition: document.getElementById('waterCondition').value,\r\n    depth: document.getElementById('depth').value,\r\n    identificationLevel: document.querySelector('input[name=\"level\"]:checked').value,\r\n    entries: entries\r\n  };\r\n  const blob = new Blob([JSON.stringify(projectInfo, null, 2)], { type: 'application\/json' });\r\n  const a = document.createElement('a');\r\n  a.href = URL.createObjectURL(blob);\r\n  a.download = `proyek_megabentos_${new Date().toISOString().slice(0,10)}.json`;\r\n  a.click();\r\n}\r\n\r\nfunction loadProject(file) {\r\n  const reader = new FileReader();\r\n  reader.onload = e => {\r\n    try {\r\n      const proj = JSON.parse(e.target.result);\r\n      document.getElementById('projectName').value = proj.projectName || '';\r\n      document.getElementById('surveyor').value = proj.surveyor || '';\r\n      document.getElementById('datetime').value = proj.datetime || '';\r\n      document.getElementById('siteName').value = proj.siteName || '';\r\n      document.getElementById('locationDesc').value = proj.locationDesc || '';\r\n      document.getElementById('lat').value = proj.lat || '-6.2088';\r\n      document.getElementById('lng').value = proj.lng || '106.8456';\r\n      document.getElementById('lineLength').value = proj.lineLength || '';\r\n      document.getElementById('obsWidth').value = proj.obsWidth || '';\r\n      document.getElementById('waterCondition').value = proj.waterCondition || '';\r\n      document.getElementById('depth').value = proj.depth || '';\r\n      const level = proj.identificationLevel || 'group';\r\n      document.querySelector(`input[name=\"level\"][value=\"${level}\"]`).checked = true;\r\n      document.querySelector(`input[name=\"level\"][value=\"${level}\"]`).dispatchEvent(new Event('change'));\r\n      entries = proj.entries || [];\r\n      renderTable();\r\n      updateTotalBiomass();\r\n      if (window.map && window.marker) {\r\n        const lat = parseFloat(proj.lat) || -6.2088;\r\n        const lng = parseFloat(proj.lng) || 106.8456;\r\n        map.setView([lat, lng], 13);\r\n        marker.setLatLng([lat, lng]);\r\n      }\r\n      populateDatalist(level);\r\n      updateBiomassDisplay();\r\n    } catch (err) { alert('Gagal memuat proyek: ' + err); }\r\n  };\r\n  reader.readAsText(file);\r\n}\r\n\r\n\/\/ ===================== PETA =====================\r\nfunction initMap() {\r\n  const lat = parseFloat(document.getElementById('lat').value) || -6.2088;\r\n  const lng = parseFloat(document.getElementById('lng').value) || 106.8456;\r\n  const map = L.map('map').setView([lat, lng], 13);\r\n  L.tileLayer('https:\/\/{s}.tile.openstreetmap.org\/{z}\/{x}\/{y}.png', { attribution: '\u00a9 OpenStreetMap' }).addTo(map);\r\n  const marker = L.marker([lat, lng], { draggable: true }).addTo(map);\r\n  marker.on('dragend', e => {\r\n    const p = e.target.getLatLng();\r\n    document.getElementById('lat').value = p.lat.toFixed(6);\r\n    document.getElementById('lng').value = p.lng.toFixed(6);\r\n  });\r\n  map.on('click', e => {\r\n    marker.setLatLng(e.latlng);\r\n    document.getElementById('lat').value = e.latlng.lat.toFixed(6);\r\n    document.getElementById('lng').value = e.latlng.lng.toFixed(6);\r\n  });\r\n  document.getElementById('lat').addEventListener('change', () => {\r\n    const newLat = parseFloat(document.getElementById('lat').value) || lat;\r\n    const newLng = parseFloat(document.getElementById('lng').value) || lng;\r\n    marker.setLatLng([newLat, newLng]);\r\n    map.setView([newLat, newLng]);\r\n  });\r\n  document.getElementById('lng').addEventListener('change', () => {\r\n    const newLng = parseFloat(document.getElementById('lng').value) || lng;\r\n    const newLat = parseFloat(document.getElementById('lat').value) || lat;\r\n    marker.setLatLng([newLat, newLng]);\r\n    map.setView([newLat, newLng]);\r\n  });\r\n  window.map = map; window.marker = marker;\r\n}\r\n\r\n\/\/ ===================== EVENT LISTENERS =====================\r\ndocument.addEventListener('DOMContentLoaded', () => {\r\n  initMap();\r\n  populateDatalist('group');\r\n\r\n  document.querySelectorAll('input[name=\"level\"]').forEach(r => {\r\n    r.addEventListener('change', function() {\r\n      const level = this.value;\r\n      updateTaxonLabel(level);\r\n      populateDatalist(level);\r\n      updateBiomassDisplay();\r\n      updateSpeciesImage();\r\n    });\r\n  });\r\n\r\n  document.getElementById('taxonInput').addEventListener('input', () => {\r\n    updateBiomassDisplay();\r\n    clearTimeout(searchTimeout);\r\n    searchTimeout = setTimeout(updateSpeciesImage, 600);\r\n  });\r\n  document.getElementById('size').addEventListener('input', updateBiomassDisplay);\r\n  document.getElementById('count').addEventListener('input', updateBiomassDisplay);\r\n  document.getElementById('addEntryBtn').addEventListener('click', addEntry);\r\n  document.getElementById('exportBtn').addEventListener('click', exportToFile);\r\n  document.getElementById('saveProjectBtn').addEventListener('click', saveProject);\r\n  document.getElementById('loadProjectBtn').addEventListener('click', () => document.getElementById('loadProjectFile').click());\r\n  document.getElementById('loadProjectFile').addEventListener('change', e => {\r\n    if (e.target.files[0]) loadProject(e.target.files[0]);\r\n    e.target.value = '';\r\n  });\r\n\r\n  setLanguage('id');\r\n});\r\n\r\nwindow.removeEntry = removeEntry;\r\nwindow.setLanguage = setLanguage;\r\n<\/script>\r\n<\/body>\r\n<\/html>\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\t\t<\/div>","protected":false},"excerpt":{"rendered":"<p>Data Entry Megabentos + Substrat LIPI \ud83d\udccb Input Data Megabentos \ud83c\uddee\ud83c\udde9 Indonesia \ud83c\uddec\ud83c\udde7 English Simpan Proyek Muat Proyek Informasi Project [&hellip;]<\/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":"","ast-disable-related-posts":"","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-1856","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>Megabenthos Data Entry - 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\/megabenthos-data-entry\/\" \/>\n<meta property=\"og:locale\" content=\"id_ID\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Megabenthos Data Entry\" \/>\n<meta property=\"og:description\" content=\"Data Entry Megabentos + Substrat LIPI \ud83d\udccb Input Data Megabentos \ud83c\uddee\ud83c\udde9 Indonesia \ud83c\uddec\ud83c\udde7 English Simpan Proyek Muat Proyek Informasi Project [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/marineconservation.id\/id\/megabenthos-data-entry\/\" \/>\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:56:28+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=\"2 menit\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/marineconservation.id\/megabenthos-data-entry\/\",\"url\":\"https:\/\/marineconservation.id\/megabenthos-data-entry\/\",\"name\":\"Megabenthos Data Entry - marineconservation.id\",\"isPartOf\":{\"@id\":\"https:\/\/marineconservation.id\/#website\"},\"datePublished\":\"2026-03-12T01:07:34+00:00\",\"dateModified\":\"2026-03-14T15:56:28+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/marineconservation.id\/megabenthos-data-entry\/#breadcrumb\"},\"inLanguage\":\"id\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/marineconservation.id\/megabenthos-data-entry\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/marineconservation.id\/megabenthos-data-entry\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/marineconservation.id\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Megabenthos Data Entry\"}]},{\"@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":"Megabenthos Data Entry - 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\/megabenthos-data-entry\/","og_locale":"id_ID","og_type":"article","og_title":"Megabenthos Data Entry","og_description":"Data Entry Megabentos + Substrat LIPI \ud83d\udccb Input Data Megabentos \ud83c\uddee\ud83c\udde9 Indonesia \ud83c\uddec\ud83c\udde7 English Simpan Proyek Muat Proyek Informasi Project [&hellip;]","og_url":"https:\/\/marineconservation.id\/id\/megabenthos-data-entry\/","og_site_name":"marineconservation.id","article_publisher":"https:\/\/www.facebook.com\/profile.php?id=61572311944591","article_modified_time":"2026-03-14T15:56:28+00:00","twitter_card":"summary_large_image","twitter_misc":{"Estimasi waktu membaca":"2 menit"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/marineconservation.id\/megabenthos-data-entry\/","url":"https:\/\/marineconservation.id\/megabenthos-data-entry\/","name":"Megabenthos Data Entry - marineconservation.id","isPartOf":{"@id":"https:\/\/marineconservation.id\/#website"},"datePublished":"2026-03-12T01:07:34+00:00","dateModified":"2026-03-14T15:56:28+00:00","breadcrumb":{"@id":"https:\/\/marineconservation.id\/megabenthos-data-entry\/#breadcrumb"},"inLanguage":"id","potentialAction":[{"@type":"ReadAction","target":["https:\/\/marineconservation.id\/megabenthos-data-entry\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/marineconservation.id\/megabenthos-data-entry\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/marineconservation.id\/"},{"@type":"ListItem","position":2,"name":"Megabenthos Data Entry"}]},{"@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\/1856","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=1856"}],"version-history":[{"count":16,"href":"https:\/\/marineconservation.id\/id\/wp-json\/wp\/v2\/pages\/1856\/revisions"}],"predecessor-version":[{"id":1930,"href":"https:\/\/marineconservation.id\/id\/wp-json\/wp\/v2\/pages\/1856\/revisions\/1930"}],"wp:attachment":[{"href":"https:\/\/marineconservation.id\/id\/wp-json\/wp\/v2\/media?parent=1856"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}