MediaWiki:Common.js: Perbedaan antara revisi

Tidak ada ringkasan suntingan
Tanda: Suntingan perangkat seluler Suntingan peramban seluler
Tidak ada ringkasan suntingan
 
(13 revisi perantara oleh pengguna yang sama tidak ditampilkan)
Baris 1: Baris 1:
/**
/**
  * ====================================================================
  * ====================================================================
  * MIPPEDIA DATA - ADVANCED STRUCTURED DATA SYSTEM (V8.0 EVOLUTION)
  * MIPPEDIA DATA - ADVANCED STRUCTURED DATA SYSTEM (V8.7 SECURE ULTIMATE)
  * Fitur: Full Modal UI, Smart References, Floating Guides, Dark Mode,  
  * Fitur: ALL ORIGINAL V8 FEATURES KEPT + Global Social Media Box,  
  * Toast Notifications, Advanced Validations, Mobile FAB, etc.
  * Smart Autocomplete/Preview Wikilink, Ultra-Strict Security, Mobile Ready.
  * ====================================================================
  * ====================================================================
  */
  */
Baris 19: Baris 19:
         var isLocked = false;
         var isLocked = false;
         var api = new mw.Api();
         var api = new mw.Api();
        var DRAFT_KEY = 'mippedia_data_draft_' + pageName;


         // --- MASTER DATA PLATFORM ---
         // 1. DATA MASTER PLATFORM MEDIA SOSIAL & MUSIK (FULL ASLI)
         var SOCIAL_PLATFORMS = {
         var SOCIAL_PLATFORMS = {
             applemusic: { name: 'Apple Music', base: 'https://music.apple.com/artist/', color: '#fc3c44' },
             applemusic: { name: 'Apple Music', base: 'https://music.apple.com/artist/', color: '#fc3c44', icon: '<svg width="13" height="13" viewBox="0 0 24 24" fill="currentColor"><path d="M12 2C6.477 2 2 6.477 2 12s4.477 10 10 10 10-4.477 10-10S17.523 2 12 2zm3.32 12.383c-.328.232-.82.418-1.32.418-1.238 0-1.922-.828-1.922-2.191v-4.14l4.312-.868v1.398l-2.91.586v2.805c0 .734.336 1.148.977 1.148.336 0 .617-.094.863-.258v1.102z"/></svg>' },
             spotify: { name: 'Spotify', base: 'https://open.spotify.com/artist/', color: '#1db954' },
             spotify: { name: 'Spotify', base: 'https://open.spotify.com/artist/', color: '#1db954', icon: '<svg width="13" height="13" viewBox="0 0 24 24" fill="currentColor"><path d="M12 2C6.477 2 2 6.477 2 12s4.477 10 10 10 10-4.477 10-10S17.523 2 12 2zm4.586 14.424c-.18.295-.563.387-.857.207-2.35-1.434-5.308-1.758-8.793-.963-.335.077-.67-.133-.746-.468-.077-.334.132-.67.467-.745 3.816-.87 7.092-.493 9.72 1.112.294.18.386.563.209.857zm1.213-2.71c-.226.368-.703.483-1.07.258-2.688-1.652-6.785-2.13-9.965-1.164-.413.125-.85-.108-.975-.522-.125-.413.108-.85.522-.975 3.633-1.102 8.157-.568 11.23 1.332.368.226.483.703.258 1.071zm.14-2.827c-3.225-1.915-8.54-2.092-11.614-1.16-.503.153-1.037-.133-1.19-.636-.152-.503.133-1.037.636-1.19 3.532-1.072 9.404-.865 13.115 1.338.45.267.598.85.33 1.3-.267.45-.85.598-1.3.33z"/></svg>' },
             soundcloud: { name: 'SoundCloud', base: 'https://soundcloud.com/', color: '#ff5500' },
             soundcloud: { name: 'SoundCloud', base: 'https://soundcloud.com/', color: '#ff5500', icon: '<svg width="13" height="13" viewBox="0 0 24 24" fill="currentColor"><path d="M1.175 12.225c-.062 0-.115.053-.115.116v4.636c0 .062.053.115.115.115h.411c.063 0 .116-.053.116-.115v-4.636c0-.063-.053-.116-.116-.116h-.411zm1.312-1.28c-.062 0-.115.052-.115.115v6.52c0 .063.053.115.115.115h.43c.062 0 .115-.052.115-.115v-6.52c0-.063-.053-.115-.115-.115h-.43zm1.33-1.258c-.063 0-.115.052-.115.115v8.322c0 .063.052.115.115.115h.43c.063 0 .115-.052.115-.115V9.802c0-.063-.052-.115-.115-.115h-.43zm1.33-.86c-.063 0-.115.053-.115.116v9.542c0 .063.052.115.115.115h.43c.063 0 .115-.052.115-.115V8.942c0-.063-.052-.116-.115-.116h-.43zm21.43 3.652c-.413 0-.802.08-1.157.228-.312-2.73-2.613-4.858-5.422-4.858-1.08 0-2.083.315-2.928.858-.2-.702-.592-1.332-1.12-1.826-.78-.727-1.812-1.13-2.882-1.13-.815 0-1.6.236-2.272.684v10.822c0 .063.052.115.115.115h15.666c1.666 0 3.018-1.352 3.018-3.018 0-1.666-1.352-3.018-3.018-3.018z"/></svg>' },
             instagram: { name: 'Instagram', base: 'https://instagram.com/', color: '#e1306c' },
            bandcamp: { name: 'Bandcamp', base: 'https://bandcamp.com/', color: '#1da0c3', icon: '<svg width="13" height="13" viewBox="0 0 24 24" fill="currentColor"><path d="M0 18.75l7.437-13.5H24l-7.438 13.5H0z"/></svg>' },
             tiktok: { name: 'TikTok', base: 'https://www.tiktok.com/@', color: '#000000' },
             instagram: { name: 'Instagram', base: 'https://instagram.com/', color: '#e1306c', icon: '<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="2" y="2" width="20" height="20" rx="5" ry="5"></rect><path d="M16 11.37A4 4 0 1 1 12.63 8 4 4 0 0 1 16 11.37z"></path><line x1="17.5" y1="6.5" x2="17.51" y2="6.5"></line></svg>' },
             youtube: { name: 'YouTube', base: 'https://youtube.com/@', color: '#ff0000' },
             tiktok: { name: 'TikTok', base: 'https://www.tiktok.com/@', color: '#000000', icon: '<svg width="13" height="13" viewBox="0 0 24 24" fill="currentColor"><path d="M19.59 6.69a4.83 4.83 0 0 1-3.77-4.25V2h-3.45v13.67a2.89 2.89 0 1 1-5.2-1.74 2.89 2.89 0 0 1 2.31-2.22V8.2a6.34 6.34 0 0 0-5 6.13 6.34 6.34 0 1 0 10.7-4.52A8.25 8.25 0 0 0 20 10.56V6.69z"/></svg>' },
             twitter: { name: 'X / Twitter', base: 'https://x.com/', color: '#0f1419' }
             youtube: { name: 'YouTube', base: 'https://youtube.com/@', color: '#ff0000', icon: '<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M22.54 6.42a2.78 2.78 0 0 0-1.94-2C18.88 4 12 4 12 4s-6.88 0-8.6.46a2.78 2.78 0 0 0-1.94 2A29 29 0 0 0 1 11.75a29 29 0 0 0 .46 5.33A2.78 2.78 0 0 0 3.4 19c1.72.46 8.6.46 8.6.46s6.88 0 8.6-.46a2.78 2.78 0 0 0 1.94-2 29 29 0 0 0 .46-5.25 29 29 0 0 0-.46-5.33z"></path><polygon points="9.75 15.02 15.5 11.75 9.75 8.48 9.75 15.02"></polygon></svg>' },
             twitter: { name: 'X / Twitter', base: 'https://x.com/', color: '#0f1419', icon: '<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M23 3a10.9 10.9 0 0 1-3.14 1.53 4.48 4.48 0 0 0-7.86 3v1A10.66 10.66 0 0 1 3 4s-4 9 5 13a11.64 11.64 0 0 1-7 2c9 5 20 0 20-11.5a4.5 4.5 0 0 0-.08-.83A7.72 7.72 0 0 0 23 3z"></path></svg>' },
            threads: { name: 'Threads', base: 'https://www.threads.net/@', color: '#000000', icon: '<svg width="13" height="13" viewBox="0 0 24 24" fill="currentColor"><path d="M12 2C6.477 2 2 6.477 2 12s4.477 10 10 10 10-4.477 10-10S17.523 2 12 2zm3.842 12.338c-.288 1.83-1.85 3.09-3.842 3.09-2.298 0-4.043-1.68-4.043-4.135 0-2.454 1.745-4.134 4.043-4.134 1.583 0 2.875.836 3.447 2.083l-1.28.625c-.39-.817-1.182-1.328-2.167-1.328-1.55 0-2.613 1.15-2.613 2.754 0 1.603 1.063 2.753 2.613 2.753 1.258 0 2.19-.77 2.37-1.808h-2.37v-1.38h3.842v1.48z"/></svg>' },
            facebook: { name: 'Facebook', base: 'https://facebook.com/', color: '#1877f2', icon: '<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M18 2h-3a5 5 0 0 0-5 5v3H7v4h3v8h4v-8h3l1-4h-4V7a1 1 0 0 1 1-1h3z"></path></svg>' },
            linkedin: { name: 'LinkedIn', base: 'https://linkedin.com/in/', color: '#0a66c2', icon: '<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M16 8a6 6 0 0 1 6 6v7h-4v-7a2 2 0 0 0-2-2 2 2 0 0 0-2 2v7h-4v-7a6 6 0 0 1 6-6z"></path><rect x="2" y="9" width="4" height="12"></rect><circle cx="4" cy="4" r="2"></circle></svg>' },
            github: { name: 'GitHub', base: 'https://github.com/', color: '#24292e', icon: '<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22"></path></svg>' },
            pinterest: { name: 'Pinterest', base: 'https://pinterest.com/', color: '#e60023', icon: '<svg width="13" height="13" viewBox="0 0 24 24" fill="currentColor"><path d="M12 0C5.373 0 0 5.372 0 12c0 5.084 3.163 9.426 7.627 11.174-.105-.949-.2-2.405.042-3.441.218-.937 1.407-5.965 1.407-5.965s-.359-.719-.359-1.782c0-1.668.967-2.914 2.171-2.914 1.023 0 1.518.769 1.518 1.69 0 1.029-.655 2.568-.994 3.995-.283 1.194.599 2.169 1.777 2.169 2.133 0 3.772-2.249 3.772-5.495 0-2.873-2.064-4.882-5.012-4.882-3.414 0-5.418 2.561-5.418 5.207 0 1.031.397 2.138.893 2.738.098.119.112.224.083.345l-.333 1.36c-.053.22-.174.267-.402.161-1.499-.698-2.436-2.889-2.436-4.649 0-3.785 2.75-7.262 7.929-7.262 4.163 0 7.398 2.967 7.398 6.931 0 4.136-2.607 7.464-6.227 7.464-1.216 0-2.359-.631-2.75-1.378l-.748 2.853c-.271 1.043-1.002 2.35-1.492 3.146C9.57 23.812 10.763 24 12 24c6.627 0 12-5.373 12-12 0-6.628-5.373-12-12-12z"/></svg>' }
         };
         };


        // 2. PRESET & MASTER RUJUKAN
         var PRESET_LABELS = [
         var PRESET_LABELS = [
             "Nama Lahir", "Tanggal Lahir", "Tempat Lahir", "Pekerjaan",  
             "Nama Lahir", "Tanggal Lahir", "Tempat Lahir", "Pekerjaan",  
Baris 38: Baris 46:


         var REF_TYPES = {
         var REF_TYPES = {
             "Berita": ["Berita Online", "Berita Cetak", "Wawancara"],
             "Berita": ["Berita Online", "Berita Cetak / Koran", "Wawancara Eksklusif", "Liputan Khusus", "Editorial", "Investigasi Media", "Siaran Radio / TV"],
             "Website": ["Situs Resmi", "Portal Informasi", "Database Web"],
             "Website": ["Situs Resmi", "Portal Informasi", "Database Web", "Portal Komunitas", "Forum Diskusi", "Portal Edukasi", "Direktori Web"],
             "Buku": ["Buku Cetak", "E-Book", "Jurnal Ilmiah"],
             "Buku": ["Buku Cetak", "E-Book", "Bab / Bagian Buku", "Monograf", "Katalog / Biografi Cetak", "Buku Teks Akademik"],
             "Media": ["Video YouTube", "Podcast", "Media Sosial"]
            "Jurnal": ["Jurnal Ilmiah Peer-Reviewed", "Paper Konferensi", "Artikel Review", "Pre-print / Draft Penelitian", "Tesis / Disertasi"],
            "Siaran Pers": ["Siaran Pers Resmi", "Pengumuman Instansi / BUMN", "Pernyataan Pers Hukrim", "Keterangan Pers Artis/Manajemen"],
            "Dokumen PDF": ["Laporan Tahunan / Annual Report", "Dokumen Kebijakan / Regulasi", "Brosur / Pamflet Resmi", "Naskah Akademik"],
             "Studio / Database Musik": ["MusicBrainz", "Discogs", "Genius", "AllMusic", "Spotify For Artists", "Database BPI / RIAA", "Songfacts", "Apple Music Catalogue"],
            "Video": ["YouTube Video", "Film Dokumenter", "Wawancara Video", "Arsip Siaran TV", "Vlog Resmi"],
            "Podcast": ["Episode Podcast", "Siniar Audio Resmi", "Wawancara Audio"],
            "Media Sosial": ["Postingan / Tweet", "Video Singkat (Reels/TikTok/Shorts)", "Live Stream", "Thread Resmi"],
            "Ensiklopedia": ["Ensiklopedia Cetak", "Ensiklopedia Online", "Kamus / Glosarium"],
            "Arsip": ["Arsip Nasional / Sejarah", "Web Archive (Wayback Machine)", "Dokumen Manuskrip"]
         };
         };


         // --- IKON SVG ---
        var VERIFIED_DOMAINS = [
         var svgs = {
            'kompas.com', 'kompas.id', 'detik.com', 'cnnindonesia.com', 'tribunnews.com', 'kumparan.com', 'tirto.id',
            edit: '<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"></path><path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"></path></svg>',
            'youtube.com', 'spotify.com', 'apple.com', 'musicbrainz.org', 'billboard.com', 'rollingstone.com',
            lock: '<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="11" width="18" height="11" rx="2" ry="2"></rect><path d="M7 11V7a5 5 0 0 1 10 0v4"></path></svg>',
            'bbc.com', 'nytimes.com', 'instagram.com', 'x.com', 'twitter.com', 'facebook.com', 'wikipedia.org', 'imdb.com'
            unlock: '<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="11" width="18" height="11" rx="2" ry="2"></rect><path d="M7 11V7a5 5 0 0 1 9.9-1"></path></svg>',
        ];
            ref: '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"></path><path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z"></path></svg>',
 
            copy: '<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path></svg>',
         // 3. IKON SISTEM
            close: '<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>',
         var svgEdit = '<svg class="md-icon" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"></path><path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"></path></svg>';
            external: '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path><polyline points="15 3 21 3 21 9"></polyline><line x1="10" y1="14" x2="21" y2="3"></line></svg>',
        var svgLock = '<svg class="md-icon" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="11" width="18" height="11" rx="2" ry="2"></rect><path d="M7 11V7a5 5 0 0 1 10 0v4"></path></svg>';
            help: '<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"></circle><path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"></path><line x1="12" y1="17" x2="12.01" y2="17"></line></svg>'
        var svgUnlock = '<svg class="md-icon" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="11" width="18" height="11" rx="2" ry="2"></rect><path d="M7 11V7a5 5 0 0 1 9.9-1"></path></svg>';
         };
        var svgRef = '<svg class="md-icon" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg>';
        var svgCopy = '<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path></svg>';
        var svgSearch = '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line></svg>';
        var svgCode = '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="16 18 22 12 16 6"></polyline><polyline points="8 6 2 12 8 18"></polyline></svg>';
        var svgVerified = '<svg width="15" height="15" viewBox="0 0 24 24" fill="#3b82f6" stroke="#ffffff" stroke-width="2"><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"></path><polyline points="22 4 12 14.01 9 11.01"></polyline></svg>';
        var svgHelp = '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"></circle><path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"></path><line x1="12" y1="17" x2="12.01" y2="17"></line></svg>';
 
         // 4. HELPER UTILITY & ADVANCED SECURITY
        function sanitizeHTML(str) {
            if (typeof str !== 'string') return str;
            return str.replace(/[&<>"'`=\/]/g, function(s) {
                return {
                    '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;',
                    "'": '&#39;', '/': '&#x2F;', '`': '&#x60;', '=': '&#x3D;'
                }[s];
            });
        }
        function isVerifiedSite(urlStr) {
            if(!urlStr) return false;
            var domain = extractDomain(urlStr);
            return VERIFIED_DOMAINS.some(function(vd) { return domain === vd || domain.endsWith('.' + vd); });
        }
        function formatIndonesianDate(dateStr) {
            if (!dateStr) return '';
            var parts = dateStr.split('-');
            if (parts.length !== 3) return dateStr;
            var months = ['Januari', 'Februari', 'Maret', 'April', 'Mei', 'Juni', 'Juli', 'Agustus', 'September', 'Oktober', 'November', 'Desember'];
            var day = parseInt(parts[2], 10);
            var monthIdx = parseInt(parts[1], 10) - 1;
            var year = parts[0];
            if (isNaN(day) || monthIdx < 0 || monthIdx > 11 || isNaN(year)) return sanitizeHTML(dateStr);
            return day + ' ' + months[monthIdx] + ' ' + year;
        }
        function extractDomain(urlStr) {
            try {
                if (!urlStr.match(/^https?:\/\//i)) urlStr = 'https://' + urlStr;
                return new URL(urlStr).hostname.replace(/^www\./, '');
            } catch(e) { return urlStr.replace(/^https?:\/\/(www\.)?/, '').split('/')[0]; }
        }
        function ensureHttps(urlStr) {
            if (!urlStr) return '';
            urlStr = urlStr.trim();
            var protoMatch = urlStr.match(/^([a-z0-9]+):/i);
            if (protoMatch) {
                var badProtos = ['javascript', 'data', 'vbscript', 'file', 'ws', 'wss', 'ftp'];
                if (badProtos.indexOf(protoMatch[1].toLowerCase()) !== -1) return '';
            }
            return (urlStr && !urlStr.match(/^https?:\/\//i)) ? 'https://' + urlStr : urlStr;
        }
        function getTodayString() {
            var now = new Date();
            var y = now.getFullYear();
            var m = String(now.getMonth() + 1).padStart(2, '0');
            var d = String(now.getDate()).padStart(2, '0');
            return y + '-' + m + '-' + d;
        }


         // --- STYLESHEET V8.0 (Modern UI & Animations) ---
         // 5. STYLESHEET (TERMASUK LAYOUT MEDIA SOSIAL GLOBAL & AUTOCOMPLETE)
         var css = `
         var css = `
            :root {
                --md-primary: #4f46e5; --md-primary-hover: #4338ca; --md-bg: #ffffff;
                --md-surface: #f8fafc; --md-border: #e2e8f0; --md-text: #0f172a;
                --md-text-muted: #64748b; --md-danger: #ef4444; --md-radius: 12px;
            }
            @media (prefers-color-scheme: dark) {
                :root {
                    --md-bg: #0f172a; --md-surface: #1e293b; --md-border: #334155;
                    --md-text: #f8fafc; --md-text-muted: #94a3b8;
                }
            }
             #mippedia-data-app {
             #mippedia-data-app {
                 background: var(--md-bg); border-radius: 16px; box-shadow: 0 10px 30px rgba(0,0,0,0.08);
                 background: #ffffff; border-radius: 16px; box-shadow: 0 4px 24px rgba(0,0,0,0.06);
                 padding: 24px; margin: 24px 0; font-family: system-ui, -apple-system, sans-serif;
                 padding: 20px; margin: 20px 0; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
                 border: 1px solid var(--md-border); position: relative; color: var(--md-text);
                 border: 1px solid #e2e8f0; max-width: 100%; box-sizing: border-box; overflow: hidden;
             }
             }
             .md-header { display: flex; justify-content: space-between; align-items: center; border-bottom: 1px solid var(--md-border); padding-bottom: 16px; margin-bottom: 20px; flex-wrap: wrap; gap: 10px; }
             .md-header { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; gap: 12px; margin-bottom: 16px; padding-bottom: 14px; border-bottom: 1px solid #f1f5f9; }
             .md-title { font-size: 1.3rem; font-weight: 800; margin: 0; display: flex; align-items: center; gap: 8px; }
            .md-title-container { display: flex; align-items: center; gap: 8px; flex: 1 1 auto; min-width: 180px; }
             .md-stats { font-size: 0.8rem; color: var(--md-text-muted); background: var(--md-surface); padding: 4px 10px; border-radius: 20px; font-weight: 600; }
             .md-title { font-size: 1.25rem; font-weight: 800; color: #0f172a; margin: 0; white-space: nowrap; }
             .md-actions { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
              
              
             .md-btn {
             .md-btn-icon {
                 background: var(--md-surface); border: 1px solid var(--md-border); color: var(--md-text);
                 background: #f8fafc; border: 1px solid #cbd5e1; cursor: pointer; color: #4f46e5;
                 padding: 8px 14px; border-radius: 8px; cursor: pointer; font-weight: 600; font-size: 0.85rem;
                 padding: 8px 14px; border-radius: 8px; transition: all 0.2s ease;
                 display: inline-flex; align-items: center; gap: 6px; transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
                 display: inline-flex; align-items: center; gap: 6px; font-size: 0.85rem; font-weight: 600; white-space: nowrap;
             }
             }
             .md-btn:hover { background: var(--md-primary); color: white; border-color: var(--md-primary); transform: translateY(-2px); box-shadow: 0 4px 10px rgba(79, 70, 229, 0.2); }
             .md-btn-icon:hover:not(:disabled) { background: #f1f5f9; border-color: #94a3b8; transform: translateY(-1px); }
             .md-btn-primary { background: linear-gradient(135deg, var(--md-primary), #3b82f6); color: white; border: none; }
            .md-btn-lock { color: #dc2626; background: #fef2f2; border-color: #fca5a5; }
             .md-btn-danger { background: #fef2f2; color: var(--md-danger); border-color: #fca5a5; }
 
            .md-search-box { position: relative; margin-bottom: 16px; width: 100%; box-sizing: border-box; }
            .md-search-input { width: 100%; padding: 8px 12px 8px 34px; border: 1px solid #cbd5e1; border-radius: 8px; font-size: 0.85rem; box-sizing: border-box; background: #f8fafc; transition: 0.2s; }
            .md-search-input:focus { background: #fff; border-color: #4f46e5; outline: none; }
            .md-search-icon { position: absolute; left: 10px; top: 50%; transform: translateY(-50%); color: #94a3b8; }
 
            /* Kotak Global Sosial Media Terpisah di Atas */
            .md-global-social-box { background: #f8fafc; border: 1px solid #e2e8f0; border-radius: 12px; padding: 16px; margin-bottom: 16px; box-shadow: 0 2px 8px rgba(0,0,0,0.02); }
             .md-social-box-title { font-size: 0.85rem; font-weight: 800; color: #475569; text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 12px; border-bottom: 1px dashed #cbd5e1; padding-bottom: 8px; }
            .md-social-group { display: flex; flex-wrap: wrap; gap: 8px; }
            .md-social-badge { display: inline-flex; align-items: center; gap: 6px; padding: 6px 12px; border-radius: 20px; font-size: 0.8rem; font-weight: 600; color: white !important; text-decoration: none !important; transition: transform 0.2s, opacity 0.2s; box-shadow: 0 2px 4px rgba(0,0,0,0.05); }
             .md-social-badge:hover { transform: translateY(-2px); opacity: 0.92; }
 
            .md-row-display { display: flex; justify-content: space-between; align-items: flex-start; padding: 16px 12px; border-bottom: 1px solid #f1f5f9; transition: all 0.2s; border-radius: 12px; gap: 12px; margin-bottom: 8px; background: #fff; }
            .md-row-display:hover { background: #faf5ff; box-shadow: inset 4px 0 0 #6366f1; }
              
              
             .md-row-display {
             .md-data-group { display: flex; flex-direction: column; gap: 6px; flex: 1; min-width: 0; }
                display: flex; justify-content: space-between; padding: 14px 16px; margin-bottom: 8px;
            .md-data-label { font-size: 0.72rem; color: #64748b; font-weight: 800; text-transform: uppercase; letter-spacing: 0.6px; }
                background: var(--md-surface); border-radius: var(--md-radius); border: 1px solid var(--md-border);
            .md-data-value-wrap { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
                transition: 0.3s;
            .md-data-value { font-size: 1.02rem; color: #0f172a; line-height: 1.4; font-weight: 600; word-break: break-word; }
             }
           
             .md-row-display:hover { transform: scale(1.01); border-color: var(--md-primary); box-shadow: 0 4px 12px rgba(0,0,0,0.05); }
            .md-btn-copy { background: none; border: none; color: #94a3b8; cursor: pointer; padding: 2px 4px; border-radius: 4px; transition: 0.2s; display: inline-flex; align-items: center; }
             .md-data-label { font-size: 0.75rem; text-transform: uppercase; color: var(--md-text-muted); font-weight: 800; letter-spacing: 0.5px; }
             .md-btn-copy:hover { color: #4f46e5; background: #e0e7ff; }
             .md-data-value { font-size: 1.1rem; font-weight: 700; display: block; margin-top: 4px; }
 
             .md-ref-container { margin-top: 10px; width: 100%; box-sizing: border-box; }
            .md-ref-details { background: #f8fafc; border-left: 3px solid #4f46e5; border-radius: 10px; overflow: hidden; border-top:1px solid #f1f5f9; border-right:1px solid #f1f5f9; border-bottom:1px solid #f1f5f9; transition: 0.3s; }
             .md-ref-details summary { display: flex; padding: 10px 14px; font-size: 0.85rem; font-weight: 700; color: #374151; cursor: pointer; user-select: none; list-style: none; flex-wrap: nowrap; align-items: center; gap: 8px; }
            .md-ref-details summary::-webkit-details-marker { display: none; }
             .md-ref-details[open] summary { border-bottom: 1px dashed #cbd5e1; background: #e0e7ff; color: #3730a3; }
            .md-ref-body { padding: 12px 14px; font-size: 0.85rem; display: flex; flex-direction: column; gap: 6px; }
              
              
            /* Referensi Badge */
             .md-verified-badge { cursor: pointer; display: inline-flex; align-items: center; justify-content: center; margin-left: 4px; vertical-align: middle; transition: transform 0.2s; flex-shrink: 0; }
             .md-ref-trigger {
            .md-verified-badge:hover { transform: scale(1.1); }
                background: #e0e7ff; color: var(--md-primary); border: none; padding: 4px 10px;
            .md-btn-visit { background: #f1f5f9; color: #0f172a; padding: 6px 12px; border-radius: 6px; text-decoration: none; font-size: 0.8rem; display: inline-block; width: fit-content; margin-top: 6px; font-weight:700; border:1px solid #cbd5e1; }
                border-radius: 20px; font-size: 0.75rem; font-weight: 700; cursor: pointer; margin-top: 8px;
             .md-btn-visit:hover { background: #e2e8f0; text-decoration:none; }
                display: inline-flex; align-items: center; gap: 4px; transition: 0.2s;
            }
             .md-ref-trigger:hover { background: var(--md-primary); color: white; }


            /* Modal System (Pop-ups) */
             .md-preset-wrapper { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
             .md-overlay {
             .md-preset-pill { background: #f1f5f9; border: 1px solid #cbd5e1; padding: 4px 10px; border-radius: 12px; font-size: 0.75rem; font-weight: 600; color: #475569; cursor: pointer; transition: 0.2s; }
                position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; background: rgba(0,0,0,0.5);
             .md-preset-pill:hover { background: #e0e7ff; color: #3730a3; border-color: #a5b4fc; }
                backdrop-filter: blur(8px); z-index: 99999; display: flex; justify-content: center; align-items: center;
                opacity: 0; animation: fadeIn 0.3s forwards; padding: 20px; box-sizing: border-box;
            }
             .md-modal {
                background: var(--md-bg); width: 100%; max-width: 550px; border-radius: 20px;
                box-shadow: 0 25px 50px -12px rgba(0,0,0,0.25); transform: translateY(20px);
                animation: slideUp 0.4s cubic-bezier(0.16, 1, 0.3, 1) forwards;
                max-height: 90vh; display: flex; flex-direction: column; overflow: hidden; border: 1px solid var(--md-border);
            }
            .md-modal-header { padding: 20px 24px; border-bottom: 1px solid var(--md-border); display: flex; justify-content: space-between; align-items: center; background: var(--md-surface); }
            .md-modal-title { font-size: 1.2rem; font-weight: 800; margin: 0; display: flex; align-items: center; gap: 8px; }
            .md-modal-close { background: none; border: none; color: var(--md-text-muted); cursor: pointer; padding: 5px; border-radius: 50%; transition: 0.2s; }
             .md-modal-close:hover { background: #f1f5f9; color: var(--md-danger); }
            .md-modal-body { padding: 24px; overflow-y: auto; flex: 1; }
            .md-modal-footer { padding: 16px 24px; border-top: 1px solid var(--md-border); display: flex; justify-content: flex-end; gap: 10px; background: var(--md-surface); }


             /* Formulir Inputs */
             .md-form-box { background: #ffffff; border-radius: 12px; padding: 18px; margin-top: 16px; border: 1px solid #cbd5e1; box-shadow: 0 4px 16px rgba(0,0,0,0.05); }
             .md-form-group { margin-bottom: 16px; }
            .md-form-title { font-size: 1.05rem; font-weight: 800; color: #0f172a; margin: 0 0 16px 0; border-bottom: 2px solid #e2e8f0; padding-bottom: 8px; }
             .md-form-group label { display: block; font-weight: 700; font-size: 0.85rem; margin-bottom: 6px; color: var(--md-text); }
             .md-form-group { margin-bottom: 14px; }
             .md-input {
             .md-form-group label { display: flex; align-items:center; font-size: 0.82rem; font-weight: 700; margin-bottom: 6px; color: #334155; }
                width: 100%; padding: 12px; border: 2px solid var(--md-border); border-radius: 10px;
           
                background: var(--md-bg); color: var(--md-text); font-size: 0.95rem; transition: 0.2s; box-sizing: border-box;
             .md-input, .md-select, .md-textarea { width: 100%; padding: 9px 12px; border: 1px solid #cbd5e1; border-radius: 8px; box-sizing: border-box; font-family: inherit; font-size: 0.9rem; transition: 0.2s; background: #fff; }
            }
             .md-input:focus, .md-select:focus, .md-textarea:focus { border-color: #4f46e5; outline: none; box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.15); }
             .md-input:focus { border-color: var(--md-primary); outline: none; box-shadow: 0 0 0 4px rgba(79, 70, 229, 0.1); }
           
             .md-input.error { border-color: var(--md-danger); animation: shake 0.4s; }
            /* Autocomplete Styles */
             .md-autocomplete-wrapper { position: relative; width: 100%; }
            .md-autocomplete-list { position: absolute; top: 100%; left: 0; right: 0; background: #fff; border: 1px solid #cbd5e1; border-radius: 0 0 8px 8px; box-shadow: 0 4px 12px rgba(0,0,0,0.1); z-index: 1000; display: none; max-height: 200px; overflow-y: auto; margin-top: -2px; }
            .md-autocomplete-item { padding: 10px 12px; font-size: 0.88rem; color: #0f172a; cursor: pointer; border-bottom: 1px solid #f1f5f9; transition: 0.2s; display: flex; align-items: center; gap: 8px; }
            .md-autocomplete-item:last-child { border-bottom: none; }
            .md-autocomplete-item:hover { background: #f8fafc; color: #4f46e5; padding-left: 16px; }


             /* Toast Notification */
             .md-ref-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; background: #f8fafc; padding: 12px; border-radius: 8px; border: 1px dashed #cbd5e1; }
             .md-toast {
             .md-social-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; background: #f1f5f9; padding: 12px; border-radius: 8px; border: 1px solid #cbd5e1; max-height: 280px; overflow-y: auto; }
                position: fixed; bottom: 30px; right: 30px; background: #10b981; color: white;
            .md-grid-full { grid-column: span 2; }
                padding: 12px 24px; border-radius: 12px; font-weight: 700; z-index: 100000;
           
                box-shadow: 0 10px 25px rgba(16, 185, 129, 0.4); animation: slideInRight 0.3s forwards;
            .md-cc0-notice { background: #fef2f2; color: #991b1b; padding: 12px; border-radius: 8px; font-size: 0.82rem; line-height: 1.4; border-left: 4px solid #ef4444; margin-top: 15px; margin-bottom: 15px; }
             }
            .md-edit-meta { background: #f8fafc; padding: 12px; border-radius: 8px; margin-bottom: 15px; border: 1px solid #e2e8f0; display:flex; flex-direction:column; gap:10px; }
           
            .md-help-icon { color: #64748b; cursor: pointer; margin-left: 6px; display:inline-flex; align-items:center; }
            .md-help-icon:hover { color: #4f46e5; }
            .md-tooltip-popup { position: absolute; background: #1e293b; color: #fff; padding: 10px 14px; border-radius: 8px; font-size: 0.8rem; width: 260px; max-width: calc(100vw - 30px); z-index: 1000; box-shadow: 0 4px 15px rgba(0,0,0,0.15); display: none; line-height: 1.4; text-align: left; font-weight:normal; }
             .md-tooltip-popup::after { content: ''; position: absolute; border-width: 6px; border-style: solid; border-color: #1e293b transparent transparent transparent; top: 100%; left: 15px; }


            /* Help Tooltip Box */
             .md-modal-overlay { position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0,0,0,0.5); z-index: 9999; display: flex; align-items: center; justify-content: center; backdrop-filter: blur(2px); }
             .md-help-box {
             .md-modal-box { background: #fff; padding: 24px; border-radius: 12px; max-width: 400px; text-align: center; box-shadow: 0 10px 25px rgba(0,0,0,0.2); animation: mdPopIn 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275); }
                background: linear-gradient(135deg, #1e293b, #0f172a); color: #f8fafc; padding: 16px;
             @keyframes mdPopIn { 0% { transform: scale(0.8); opacity: 0; } 100% { transform: scale(1); opacity: 1; } }
                border-radius: 12px; margin-bottom: 20px; font-size: 0.85rem; position: relative; border-left: 4px solid #38bdf8;
            }
             .md-help-box::after {
                content: ''; position: absolute; bottom: -8px; left: 20px;
                border-width: 8px 8px 0; border-style: solid; border-color: #0f172a transparent transparent transparent;
             }


             @keyframes fadeIn { to { opacity: 1; } }
             .md-form-actions { display: flex; gap: 10px; align-items: center; margin-top: 20px; padding-top: 14px; border-top: 1px solid #e2e8f0; flex-wrap: wrap; }
             @keyframes slideUp { to { transform: translateY(0); } }
            .md-btn { padding: 10px 18px; border: none; border-radius: 8px; font-weight: 700; cursor: pointer; color: white; font-size: 0.85rem; transition: 0.2s; display: inline-flex; align-items: center; gap: 6px; justify-content: center; }
             @keyframes slideInRight { from { transform: translateX(100px); opacity: 0; } to { transform: translateX(0); opacity: 1; } }
             .md-btn:hover:not(:disabled) { transform: translateY(-1px); }
             @keyframes shake { 0%, 100% { transform: translateX(0); } 25% { transform: translateX(-5px); } 75% { transform: translateX(5px); } }
             .md-btn-save { background: linear-gradient(135deg, #4f46e5, #4338ca); flex: 1; min-width: 140px; }
            .md-btn-cancel { background: #64748b; }
            .md-btn-draft { background: #10b981; }
            .md-btn-delete { background: #dc2626; margin-left: auto; }
              
            .md-spinner { display: none; width: 14px; height: 14px; border: 2px solid rgba(255,255,255,0.4); border-radius: 50%; border-top-color: #fff; animation: md-spin 0.8s linear infinite; }
            .is-loading .md-spinner { display: inline-block; }
            @keyframes md-spin { to { transform: rotate(360deg); } }


             @media (max-width: 768px) {
            /* Mobile Optimized Layout (Seluler) */
                 #mippedia-data-app { padding: 16px; }
             @media (max-width: 600px) {
                 .md-overlay { padding: 10px; align-items: flex-end; }
                 #mippedia-data-app { padding: 14px; margin: 14px 0; border-radius: 12px; }
                 .md-modal { max-height: 95vh; border-radius: 20px 20px 0 0; animation: slideUpMobile 0.4s forwards; transform: translateY(100%); }
                 .md-header { flex-direction: column; align-items: flex-start; gap: 10px; }
                 @keyframes slideUpMobile { to { transform: translateY(0); } }
                 .md-actions { width: 100%; justify-content: flex-start; overflow-x:auto; padding-bottom:5px; }
                 .md-btn-fab {
                 .md-btn-icon { padding: 7px 12px; font-size: 0.8rem; }
                    position: fixed; bottom: 20px; right: 20px; width: 60px; height: 60px; border-radius: 30px;
                 .md-ref-grid, .md-social-grid { grid-template-columns: 1fr; }
                    background: var(--md-primary); color: white; display: flex; justify-content: center; align-items: center;
                .md-grid-full { grid-column: span 1; }
                    box-shadow: 0 10px 25px rgba(79, 70, 229, 0.4); z-index: 9000; cursor: pointer; border: none;
                .md-form-actions { flex-direction: column; width: 100%; }
                }
                .md-btn { width: 100%; margin: 0 !important; }
                .md-row-display { padding: 12px 10px; flex-direction:column; align-items:stretch;}
                .edit-btn { align-self:flex-end; margin-top:8px; }
                .md-ref-details summary { align-items: flex-start; }
             }
             }
             .md-native-render { display: none; }
             .md-native-render { display: none; }
Baris 170: Baris 247:
         $('<style>').text(css).appendTo('head');
         $('<style>').text(css).appendTo('head');


         // --- HELPER FUNCTIONS ---
         // 6. POPUP, MODAL & TOOLTIPS
         function showToast(msg) {
         function showModal(title, text) {
             var $t = $('<div class="md-toast">' + msg + '</div>').appendTo('body');
            $('.md-modal-overlay').remove();
             setTimeout(() => { $t.fadeOut(300, function(){ $(this).remove(); }); }, 3000);
             var $overlay = $('<div class="md-modal-overlay"></div>');
            var $box = $('<div class="md-modal-box"><h3 style="margin-top:0; color:#0f172a;">' + sanitizeHTML(title) + '</h3><p style="font-size:0.9rem; color:#475569; margin:15px 0;">' + sanitizeHTML(text) + '</p><button class="md-btn md-btn-save" style="width:100%;">Tutup & Mengerti</button></div>');
             $box.find('button').on('click', function() { $overlay.remove(); });
            $overlay.append($box);
            $('body').append($overlay);
         }
         }


        // --- SISTEM POP-UP MODAL UTAMA ---
         function initTooltips() {
         function openModal(title, contentHtml, footerHtml, onOpen) {
             $('.md-help-icon').off('click').on('click', function(e) {
             var $overlay = $('<div class="md-overlay"></div>');
                $('.md-tooltip-popup').remove();
            var $modal = $('<div class="md-modal"></div>');
                e.stopPropagation();
           
                var $icon = $(this);
            var $header = $('<div class="md-modal-header"><h3 class="md-modal-title">' + title + '</h3><button class="md-modal-close">' + svgs.close + '</button></div>');
                var text = sanitizeHTML($icon.data('help'));  
            var $body = $('<div class="md-modal-body">' + contentHtml + '</div>');
                var $tt = $('<div class="md-tooltip-popup">' + text + '</div>');
            var $footer = $('<div class="md-modal-footer">' + footerHtml + '</div>');
                $('body').append($tt);
           
               
            $modal.append($header).append($body).append($footer);
                var offset = $icon.offset();
            $overlay.append($modal).appendTo('body');
                 var ttWidth = $tt.outerWidth();
 
                var winWidth = $(window).width();
            var closeFunc = function() {
                var leftPos = offset.left - 15;
                $modal.css('transform', 'translateY(20px)').css('opacity', '0');
               
                 $overlay.fadeOut(200, function() { $(this).remove(); });
                if (leftPos + ttWidth > winWidth - 15) leftPos = winWidth - ttWidth - 15;
            };
                if (leftPos < 10) leftPos = 10;
 
               
            $header.find('.md-modal-close').on('click', closeFunc);
                $tt.css({ top: offset.top - $tt.outerHeight() - 10, left: leftPos }).fadeIn(200);
            $overlay.on('click', function(e) { if(e.target === this) closeFunc(); });
            $(document).on('keydown.mdmodal', function(e) { if(e.key === 'Escape') { closeFunc(); $(document).off('keydown.mdmodal'); } });
 
            if(typeof onOpen === 'function') onOpen($body, $footer, closeFunc);
        }
 
        // --- 3. NOTIFIKASI GEMBOK (UNTUK BUKAN PENGURUS) ---
        function showLockNotice() {
            var content = `
                <div style="text-align:center; padding: 20px 0;">
                    <div style="background:#fef2f2; width:80px; height:80px; border-radius:40px; display:flex; align-items:center; justify-content:center; margin: 0 auto 20px; color:#ef4444;">
                        <svg width="40" height="40" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="11" width="18" height="11" rx="2" ry="2"></rect><path d="M7 11V7a5 5 0 0 1 10 0v4"></path></svg>
                    </div>
                    <h2 style="margin:0 0 10px; font-weight:800; font-size:1.4rem;">Halaman Dilindungi</h2>
                    <p style="color:var(--md-text-muted); line-height:1.6;">Struktur data pada halaman ini telah dikunci oleh Pengurus. Pengguna biasa atau anonim tidak dapat mengedit atau menambahkan data baru untuk mencegah vandalisme.</p>
                    <div style="background:var(--md-surface); border:1px solid var(--md-border); padding:12px; border-radius:8px; margin-top:20px; font-size:0.85rem; text-align:left;">
                        💡 <b>Tips:</b> Jika Anda memiliki pembaruan data yang valid, silakan hubungi pengurus melalui halaman Pembicaraan artikel ini.
                    </div>
                </div>
            `;
            openModal(svgs.lock + ' Akses Ditolak', content, '<button class="md-btn md-btn-primary md-close-btn">Mengerti</button>', function($b, $f, close) {
                $f.find('.md-close-btn').on('click', close);
             });
             });
            $(document).off('click.mdtt').on('click.mdtt', function() { $('.md-tooltip-popup').fadeOut(200, function(){ $(this).remove(); }); });
         }
         }


         // --- 1. REFERENSI POP-UP DETAIL ---
         // 7. PARSER WIKITEXT & PENYIMPANAN DATA
        function showRefDetails(refObj) {
            var dateStr = refObj.date ? new Date(refObj.date).toLocaleDateString('id-ID', {day:'numeric', month:'long', year:'numeric'}) : '-';
            var safeUrl = refObj.url ? refObj.url : '#';
            var title = refObj.title || 'Sumber Referensi';
           
            var content = `
                <div style="display:flex; flex-direction:column; gap:12px; font-size:0.95rem;">
                    <div style="background:var(--md-surface); padding:16px; border-radius:12px; border-left:4px solid var(--md-primary);">
                        <h4 style="margin:0 0 5px; font-size:1.1rem; color:var(--md-primary);">${title}</h4>
                        ${refObj.site ? `<div style="color:var(--md-text-muted); font-size:0.85rem;">Milik: <b>${refObj.site}</b></div>` : ''}
                    </div>
                   
                    <div style="display:grid; grid-template-columns:1fr 1fr; gap:12px; margin-top:10px;">
                        ${refObj.author ? `<div style="background:var(--md-surface); padding:12px; border-radius:8px;"><b>Penulis</b><br>${refObj.author}</div>` : ''}
                        ${refObj.publisher ? `<div style="background:var(--md-surface); padding:12px; border-radius:8px;"><b>Penerbit</b><br>${refObj.publisher}</div>` : ''}
                        <div style="background:var(--md-surface); padding:12px; border-radius:8px;"><b>Tipe Rujukan</b><br>${refObj.type || 'Umum'}</div>
                        <div style="background:var(--md-surface); padding:12px; border-radius:8px;"><b>Diakses Pada</b><br>${dateStr}</div>
                    </div>
 
                    <div style="margin-top:15px; padding:12px; background:#f1f5f9; border-radius:8px; font-family:monospace; font-size:0.8rem; color:#475569;">
                        <b>Format Sitasi APA:</b><br>
                        ${refObj.author ? refObj.author + '.' : 'Anonim.'} (${new Date().getFullYear()}). <i>${title}</i>. ${refObj.site || ''}. Diakses pada ${dateStr}.
                    </div>
                </div>
            `;
           
            var footer = '';
            if (refObj.url) footer += `<a href="${safeUrl}" target="_blank" class="md-btn md-btn-primary" style="text-decoration:none;">Kunjungi Website ${svgs.external}</a>`;
            footer += `<button class="md-btn md-close-btn">Tutup</button>`;
 
            openModal(svgs.ref + ' Detail Rujukan', content, footer, function($b, $f, close) {
                $f.find('.md-close-btn').on('click', close);
            });
        }
 
        // --- CORE LOAD & SAVE ---
         function loadData() {
         function loadData() {
             return api.get({ action: 'query', prop: 'revisions', titles: pageName, rvprop: 'content', rvslots: 'main', formatversion: 2 })
             return api.get({
            .then(function(data) {
                action: 'query', prop: 'revisions', titles: pageName, rvprop: 'content', rvslots: 'main', formatversion: 2
            }).then(function(data) {
                 var content = data.query.pages[0].revisions[0].slots.main.content;
                 var content = data.query.pages[0].revisions[0].slots.main.content;
                 var match = content.match(/<!-- MIPPEDIA_DATA_START \| (.*?) -->/);
                 var match = content.match(/<!-- MIPPEDIA_DATA_START \| (.*?) -->/);
                 if (match) { try { var parsed = JSON.parse(match[1]); dataItems = parsed.items || []; isLocked = parsed.locked || false; } catch(e) {} }
                 if (match) {
                    try {
                        var parsed = JSON.parse(match[1]);
                        dataItems = parsed.items || [];
                        isLocked = parsed.locked || false;
                    } catch(e) { console.error("JSON Error", e); }
                }
                 return content;  
                 return content;  
             });
             });
         }
         }


         function saveData(actionType, rawContent, $btn) {
        function buildWikitextVal(item) {
             if($btn) { $btn.prop('disabled', true).html('Menyimpan...⏳'); }
            var val = item.val;
            if (item.linkTarget && item.linkTarget.trim() !== '') {
                return "[[" + item.linkTarget.trim() + "|" + val + "]]";
            }
            if (item.linkSplit) {
                return val.replace(/([a-zA-Z0-9_À-ÿ\- ]+)/g, function(match) {
                    var trimmed = match.trim();
                    if (trimmed.length > 2 && trimmed.toLowerCase() !== 'dan' && trimmed.toLowerCase() !== 'atau') {
                        return "[[" + trimmed + "]]";
                    }
                    return match;
                });
            }
            if (item.link) {
                return "[[" + val + "]]";
            }
            return val;
        }
 
        function buildWikitextRef(refObj) {
            if (!refObj) return "";
            var title = refObj.title || "Rujukan";
            var text = refObj.url ? "[" + ensureHttps(refObj.url) + " " + title + "]" : "'''" + title + "'''";
            var details = [];
            if (refObj.author) details.push("Penulis: " + refObj.author);
            if (refObj.site) details.push("Situs: " + refObj.site);
            if (refObj.publisher) details.push("Penerbit: " + refObj.publisher);
            if (refObj.date) details.push("Tanggal Akses: " + formatIndonesianDate(refObj.date));
            if (refObj.type) details.push("Jenis: " + refObj.type + (refObj.subType ? " (" + refObj.subType + ")" : ""));
           
            if (details.length > 0) text += " &mdash; <small>" + details.join(" &bull; ") + "</small>";
            return text;
        }
 
         function saveData(actionType, $btnEl, originalContent, customSummary, isMinorEdit) {
             if ($btnEl) $btnEl.addClass('is-loading').prop('disabled', true);
              
              
            var summaryTxt = customSummary ? ('Mippedia Data: ' + customSummary) : ('Mippedia Data V8.7: ' + actionType);
             var jsonStr = JSON.stringify({ locked: isLocked, items: dataItems });
             var jsonStr = JSON.stringify({ locked: isLocked, items: dataItems });
             var wt = "<!-- MIPPEDIA_DATA_START | " + jsonStr + " -->\n<div class=\"md-native-render\">\n{| class=\"wikitable\"\n! Data !! Nilai\n";
             var wt = "<!-- MIPPEDIA_DATA_START | " + jsonStr + " -->\n";
             dataItems.forEach(function(item) { wt += "|-\n| " + item.prop + " || " + item.val + "\n"; });
            wt += "<div class=\"md-native-render\">\n{| class=\"wikitable\"\n! Data !! Nilai !! Referensi\n";
           
             dataItems.forEach(function(item) {
                var valTxt = buildWikitextVal(item);
                var refTxt = buildWikitextRef(item.ref);
                wt += "|-\n| " + item.prop + " || " + valTxt + " || " + refTxt + "\n";
            });
             wt += "|}\n</div>\n<!-- MIPPEDIA_DATA_END -->";
             wt += "|}\n</div>\n<!-- MIPPEDIA_DATA_END -->";


             var newContent = rawContent;
             var newContent;
             var regex = /<!-- MIPPEDIA_DATA_START \| .*? -->[\s\S]*?<!-- MIPPEDIA_DATA_END -->/;
             var regex = /<!-- MIPPEDIA_DATA_START \| .*? -->[\s\S]*?<!-- MIPPEDIA_DATA_END -->/;
             if (regex.test(rawContent)) newContent = rawContent.replace(regex, wt);
             if (regex.test(originalContent)) {
             else newContent = rawContent.trim() + "\n\n" + wt;
                newContent = originalContent.replace(regex, wt);
             } else {
                newContent = originalContent.trim() + "\n\n" + wt;
            }


             api.postWithToken('csrf', { action: 'edit', title: pageName, text: newContent, summary: 'Mippedia V8: ' + actionType })
             api.postWithToken('csrf', {
            .done(function() { window.location.href = location.pathname + "?refresh=" + new Date().getTime(); })
                action: 'edit', title: pageName, text: newContent, summary: summaryTxt, minor: isMinorEdit || false
            .fail(function() { showToast("Gagal menyimpan data!"); if($btn) $btn.prop('disabled', false); });
            }).done(function() {
                localStorage.removeItem(DRAFT_KEY);
                var nocacheUrl = location.pathname + "?refresh=" + new Date().getTime();
                window.location.href = nocacheUrl;
            }).fail(function(err) {
                if ($btnEl) $btnEl.removeClass('is-loading').prop('disabled', false);
                alert("Gagal menyimpan! Error: " + err);
            });
         }
         }


         // --- 2 & 4. FORMULIR MODAL DENGAN PANDUAN ---
         // 8. BUILDER UI UTAMA
         function showFormModal(index, rawContent) {
         function buildUI(rawContent) {
             var isNew = index === -1;
             var $app = $('<div id="mippedia-data-app"></div>');
             var item = isNew ? { prop:'', val:'', ref:{} } : dataItems[index];
           
             var r = item.ref || {};
            var $header = $('<div class="md-header"></div>');
             var $titleContainer = $('<div class="md-title-container"><h3 class="md-title">' + svgEdit + ' Data Terstruktur</h3></div>');
            var $actions = $('<div class="md-actions"></div>');
           
             var $jsonBtn = $('<button class="md-btn-icon" title="Ekspor/Impor JSON">' + svgCode + ' JSON</button>');
            $jsonBtn.on('click', function() { showJsonModal(rawContent); });
            $actions.append($jsonBtn);


             // 4. TEKS BANTUAN INTERAKTIF
             if (isSysop) {
            var helpUI = `
                var $lockBtn = $('<button class="md-btn-icon ' + (isLocked ? 'md-btn-unlock' : 'md-btn-lock') + '">' + (isLocked ? svgUnlock + ' Buka Kunci' : svgLock + ' Kunci') + '</button>');
                <div class="md-help-box">
                $lockBtn.on('click', function() {
                    <strong>Panduan Memasukkan Data:</strong>
                     isLocked = !isLocked;
                     <ul style="margin:5px 0 0; padding-left:20px;">
                    saveData(isLocked ? 'Mengunci data' : 'Membuka kunci data', $(this), rawContent);
                        <li><b>Label Data:</b> Gunakan kata benda (Contoh: "Pekerjaan", "Tanggal Lahir").</li>
                });
                        <li><b>Nilai Data:</b> Isi dengan data sebenarnya. Sistem mendukung format tautan otomatis.</li>
                 $actions.append($lockBtn);
                        <li><b>Referensi (Opsional):</b> Jika ada sumber, klik tab referensi di bawah untuk mengisi.</li>
             }
                    </ul>
                 </div>
             `;


             var formHtml = `
             if (!isLocked || isSysop) {
                ${isNew ? helpUI : ''}
                var $addBtn = $('<button class="md-btn-icon" title="Tambah Data Baru">' + svgEdit + ' Tambah</button>');
                <div class="md-form-group">
                 $addBtn.on('click', function() { showForm(-1, rawContent); });
                    <label>Label Data <span style="color:red">*</span></label>
                $actions.append($addBtn);
                    <input type="text" id="md-inp-prop" class="md-input" value="${item.prop}" placeholder="Cth: Tempat Lahir" autocomplete="off">
             }
                </div>
                <div class="md-form-group">
                    <label>Nilai Data <span style="color:red">*</span></label>
                    <input type="text" id="md-inp-val" class="md-input" value="${item.val}" placeholder="Cth: Jakarta, Indonesia">
                </div>
               
                <hr style="border:0; border-top:1px dashed var(--md-border); margin:20px 0;">
                 <h4 style="margin:0 0 10px; display:flex; align-items:center; gap:8px;">${svgs.ref} Tambah Referensi</h4>
               
                <div style="display:grid; grid-template-columns:1fr 1fr; gap:10px;">
                    <div class="md-form-group" style="grid-column:span 2;"><input type="url" id="md-ref-url" class="md-input" value="${r.url||''}" placeholder="URL Website (https://...)"></div>
                    <div class="md-form-group"><input type="text" id="md-ref-title" class="md-input" value="${r.title||''}" placeholder="Judul Halaman"></div>
                    <div class="md-form-group"><input type="text" id="md-ref-site" class="md-input" value="${r.site||''}" placeholder="Nama Situs"></div>
                    <div class="md-form-group"><input type="text" id="md-ref-author" class="md-input" value="${r.author||''}" placeholder="Penulis"></div>
                    <div class="md-form-group"><input type="date" id="md-ref-date" class="md-input" value="${r.date||''}"></div>
                </div>
             `;


             var footerHtml = `
             $header.append($titleContainer).append($actions);
                ${!isNew ? `<button class="md-btn md-btn-danger" id="md-btn-delete" style="margin-right:auto;">Hapus</button>` : ''}
            $app.append($header);
                <button class="md-btn md-close-btn">Batal</button>
                <button class="md-btn md-btn-primary" id="md-btn-save">${svgs.edit} Terbitkan</button>
            `;


             openModal(isNew ? 'Tambah Data Baru' : 'Edit Data', formHtml, footerHtml, function($b, $f, closeFunc) {
             // Tampilkan kotak pencarian jika data banyak
                 // Auto Capitalize Label
            if (dataItems.length > 2) {
                 $b.find('#md-inp-prop').on('input', function() {
                 var $searchBox = $('<div class="md-search-box"><span class="md-search-icon">' + svgSearch + '</span><input type="text" class="md-search-input" placeholder="Cari data terstruktur..."></div>');
                     let val = $(this).val();
                 $searchBox.find('input').on('keyup input', function() {
                     $(this).val(val.replace(/\b\w/g, l => l.toUpperCase()));
                     var q = $(this).val().toLowerCase();
                     $app.find('.md-row-display').each(function() {
                        var text = $(this).text().toLowerCase();
                        $(this).toggle(text.indexOf(q) !== -1);
                    });
                 });
                 });
                $app.append($searchBox);
            }


                // Auto Fix URL
            // MENGUMPULKAN MEDIA SOSIAL GLOBAL (Memisahkan media sosial ke atas)
                 $b.find('#md-ref-url').on('blur', function() {
            var globalSocials = {};
                    let u = $(this).val().trim();
            dataItems.forEach(function(item) {
                     if(u && !/^https?:\/\//i.test(u)) $(this).val('https://' + u);
                if (item.isPersonOrg && item.socials) {
                    Object.assign(globalSocials, item.socials);
                 }
            });
 
            if (Object.keys(globalSocials).length > 0) {
                var $topSocials = $('<div class="md-global-social-box"></div>');
                $topSocials.append('<div class="md-social-box-title">Media Sosial & Platform Resmi</div>');
                var $socialGroupGlobal = $('<div class="md-social-group"></div>');
               
                Object.keys(SOCIAL_PLATFORMS).forEach(function(key) {
                    var uname = globalSocials[key];
                     if (uname) {
                        var platform = SOCIAL_PLATFORMS[key];
                        var fullUrl = platform.base + uname.replace(/^@/, '');
                        var $badge = $('<a class="md-social-badge" href="' + sanitizeHTML(fullUrl) + '" target="_blank" rel="noopener noreferrer" style="background:' + platform.color + ';">' + platform.icon + ' ' + sanitizeHTML(platform.name) + '</a>');
                        $socialGroupGlobal.append($badge);
                    }
                 });
                 });
                $topSocials.append($socialGroupGlobal);
                $app.append($topSocials);
            }


                $f.find('.md-close-btn').on('click', closeFunc);
            var $list = $('<div class="md-list"></div>');
               
            if (dataItems.length === 0) {
                 $f.find('#md-btn-save').on('click', function() {
                 $list.append('<div style="color:#64748b; text-align:center; padding: 25px 10px; background:#f8fafc; border-radius:10px; border:1px dashed #cbd5e1; font-size:0.88rem;">Belum ada data terstruktur. Klik <b>Tambah</b> untuk membuat baru.</div>');
                     var p = $b.find('#md-inp-prop').val().trim();
            } else {
                     var v = $b.find('#md-inp-val').val().trim();
                dataItems.forEach(function(item, index) {
                     var $row = $('<div class="md-row-display"></div>');
                     var $info = $('<div class="md-data-group"></div>');
                    $info.append('<span class="md-data-label">' + sanitizeHTML(item.prop) + '</span>');
                      
                      
                     // Validasi Animasi Getar (Shake)
                     var displayValHtml = '';
                     if(!p || !v) {
                    var rawVal = item.val || '';
                         if(!p) $b.find('#md-inp-prop').addClass('error').on('animationend', function(){$(this).removeClass('error')});
 
                        if(!v) $b.find('#md-inp-val').addClass('error').on('animationend', function(){$(this).removeClass('error')});
                    if (rawVal.match(/^https?:\/\//i)) {
                         return;
                        displayValHtml = '<a href="' + sanitizeHTML(rawVal) + '" target="_blank" rel="noopener noreferrer" style="color:#2563eb; font-weight:700; text-decoration:none;">' + extractDomain(rawVal) + '</a>';
                     } else if (item.linkTarget && item.linkTarget.trim() !== '') {
                         displayValHtml = '<a href="' + mw.util.getUrl(item.linkTarget.trim()) + '" style="color:#2563eb; font-weight:700; text-decoration:none;">' + sanitizeHTML(rawVal) + '</a>';
                    } else if (item.linkSplit) {
                        var parts = rawVal.split(/([,/\s]+dan\s+|[,/\s]+atau\s+|[,/]+)/gi);
                        displayValHtml = parts.map(function(p) {
                            var trimmed = p.trim();
                            if (trimmed && !p.match(/^[,/\s]+$/) && trimmed.toLowerCase() !== 'dan' && trimmed.toLowerCase() !== 'atau') {
                                return '<a href="' + mw.util.getUrl(trimmed) + '" style="color:#2563eb; font-weight:700; text-decoration:none;">' + sanitizeHTML(trimmed) + '</a>';
                            }
                            return sanitizeHTML(p);
                        }).join('');
                    } else if (item.link) {
                        displayValHtml = '<a href="' + mw.util.getUrl(rawVal) + '" style="color:#2563eb; font-weight:700; text-decoration:none;">' + sanitizeHTML(rawVal) + '</a>';
                    } else {
                         displayValHtml = sanitizeHTML(rawVal);
                     }
                     }


                     var refObj = {
                     var $valWrap = $('<div class="md-data-value-wrap"></div>');
                        url: $b.find('#md-ref-url').val().trim(),
                    $valWrap.append('<span class="md-data-value">' + displayValHtml + '</span>');
                         title: $b.find('#md-ref-title').val().trim(),
                   
                         site: $b.find('#md-ref-site').val().trim(),
                    var $copyBtn = $('<button class="md-btn-copy" title="Salin teks">' + svgCopy + '</button>');
                         author: $b.find('#md-ref-author').val().trim(),
                    $copyBtn.on('click', function() {
                        date: $b.find('#md-ref-date').val()
                        navigator.clipboard.writeText(rawVal);
                    };
                        $(this).css('color', '#16a34a');
                    Object.keys(refObj).forEach(k => { if(!refObj[k]) delete refObj[k]; });
                         setTimeout(function(){ $copyBtn.css('color', '#94a3b8'); }, 1200);
                    });
                    $valWrap.append($copyBtn);
                    $info.append($valWrap);
                   
                    if (item.ref && (item.ref.url || item.ref.title)) {
                         var ref = item.ref;
                        var isVer = isVerifiedSite(ref.url);
                        var verBadgeHtml = isVer ? '<span class="md-verified-badge" title="Situs Populer Terverifikasi">' + svgVerified + '</span>' : '';
                       
                        var safeUrl = ref.url ? ensureHttps(ref.url) : '';
                        var refTitle = ref.title || "Sumber Rujukan";
                       
                        var $refContainer = $('<div class="md-ref-container"></div>');
                         var $refDetails = $(`
                            <details class="md-ref-details">
                                <summary>
                                    <div style="color:#4f46e5; display:inline-flex; align-items:center; gap:5px; white-space:nowrap; flex-shrink:0;">${svgRef} REFERENSI:</div>
                                    <div style="color:#374151; display:flex; align-items:center; flex-wrap:wrap; flex:1;">
                                        <span style="word-break:break-word; line-height:1.3;">${sanitizeHTML(refTitle)}</span>${verBadgeHtml}
                                    </div>
                                </summary>
                                <div class="md-ref-body">
                                    ${ref.author ? '<div><span style="color:#64748b; font-weight:700;">Penulis:</span> ' + sanitizeHTML(ref.author) + '</div>' : ''}
                                    ${ref.site ? '<div><span style="color:#64748b; font-weight:700;">Situs:</span> ' + sanitizeHTML(ref.site) + '</div>' : ''}
                                    ${ref.publisher ? '<div><span style="color:#64748b; font-weight:700;">Penerbit:</span> ' + sanitizeHTML(ref.publisher) + '</div>' : ''}
                                    ${ref.date ? '<div><span style="color:#64748b; font-weight:700;">Tanggal Akses:</span> ' + formatIndonesianDate(ref.date) + '</div>' : ''}
                                    ${ref.type ? '<div style="margin-top:4px;"><span style="background:#e2e8f0; padding:2px 8px; border-radius:6px; font-weight:700; font-size:0.75rem;">' + sanitizeHTML(ref.type) + (ref.subType ? ' &bull; ' + sanitizeHTML(ref.subType) : '') + '</span></div>' : ''}
                                    ${safeUrl ? '<a href="' + sanitizeHTML(safeUrl) + '" target="_blank" rel="noopener noreferrer" class="md-btn-visit">Kunjungi Situs</a>' : ''}
                                </div>
                            </details>
                        `);
                       
                        $refDetails.find('.md-verified-badge').on('click', function(e) {
                            e.preventDefault(); e.stopPropagation();
                            showModal('Situs Terverifikasi', 'Centang biru menandakan bahwa URL referensi ini valid dan berasal dari entitas, media publikasi besar, portal populer, atau pangkalan data resmi (seperti Kompas, YouTube, Apple Music, Spotify, dll) yang bereputasi kredibel.');
                        });


                    var newItem = { prop: p, val: v, ref: Object.keys(refObj).length ? refObj : null };
                        $refContainer.append($refDetails);
                        $info.append($refContainer);
                    }
                      
                      
                     if(isNew) dataItems.push(newItem); else dataItems[index] = newItem;
                     $row.append($info);
                    saveData(isNew ? 'Tambah data' : 'Edit data', rawContent, $(this));
                });


                $f.find('#md-btn-delete').on('click', function() {
                    if (isLocked && !isSysop) {
                    if(confirm("Yakin ingin menghapus data ini secara permanen?")) {
                        var $lockNotifyBtn = $('<button class="md-btn-icon edit-btn" style="color:#dc2626; border-color:#fca5a5; background:#fef2f2;">' + svgLock + ' Terkunci</button>');
                         dataItems.splice(index, 1);
                        $lockNotifyBtn.on('click', function() {
                         saveData('Hapus data', rawContent, $(this));
                            showModal('Halaman Dikunci', 'Halaman Data Terstruktur ini sedang dikunci sementara oleh pengurus untuk melindungi dari vandalisme atau perubahan yang tidak sah. Pengguna biasa atau anonim tidak dapat mengedit saat ini.');
                        });
                        $row.append($lockNotifyBtn);
                    } else {
                         var $editIcon = $('<button class="md-btn-icon edit-btn">' + svgEdit + ' Edit</button>');
                         $editIcon.on('click', function() { showForm(index, rawContent); });
                        $row.append($editIcon);
                     }
                     }
                   
                    $list.append($row);
                 });
                 });
             });
             }
            $app.append($list);
            $app.append('<div id="md-form-container"></div>');
 
            var $infobox = $('.infobox').first();
            $('.md-native-render').hide();
            if ($infobox.length) $app.insertAfter($infobox);
            else $('#mw-content-text .mw-parser-output').append($app);
         }
         }


         // --- MAIN UI BUILDER ---
         // 9. FORM EDIT & DRAFT LOGIC
        function buildUI(rawContent) {
        function showForm(index, rawContent) {
             var $app = $('<div id="mippedia-data-app"></div>');
            var $container = $('#md-form-container').empty();
            var isNew = index === -1;
           
            var draftData = localStorage.getItem(DRAFT_KEY);
            var currentData = isNew ? { prop: '', val: '', link: false, linkTarget: '', linkSplit: false, ref: {}, isPersonOrg: false, socials: {} } : dataItems[index];
           
            if (isNew && draftData) {
                if(confirm("Anda memiliki draft yang belum tersimpan sebelumnya. Ingin melanjutkan draft tersebut?")) {
                    try { currentData = JSON.parse(draftData); } catch(e) {}
                }
            }
 
            var currentRef = currentData.ref || {};
            var currentSocials = currentData.socials || {};
 
            var $form = $('<div class="md-form-box"></div>');
            $form.append('<h4 class="md-form-title">' + (isNew ? 'Tambah Data Baru' : 'Edit Data Terstruktur') + '</h4>');
           
            var $propGroup = $('<div class="md-form-group"></div>');
            $propGroup.append('<label>Label Data <span class="md-help-icon" data-help="Nama bidang data (contoh: Pekerjaan, Sutradara, Tempat Lahir). Klik tombol preset di bawah untuk isi otomatis.">' + svgHelp + '</span></label>');
            $propGroup.append('<input type="text" id="md-inp-prop" class="md-input" value="' + sanitizeHTML(currentData.prop || '') + '">');
           
            var $presetWrap = $('<div class="md-preset-wrapper"></div>');
            PRESET_LABELS.forEach(function(lbl) {
                var $pill = $('<span class="md-preset-pill">' + lbl + '</span>');
                $pill.on('click', function() { $('#md-inp-prop').val(lbl); });
                $presetWrap.append($pill);
            });
            $propGroup.append($presetWrap);
            $form.append($propGroup);
           
             var $valBox = $('<div class="md-form-group"></div>');
            $valBox.append('<label>Nilai Data <span class="md-help-icon" data-help="Ketik nilai. Jika halaman sudah ada di Wiki, saran akan muncul (pratinjau) dan otomatis mencentang opsi Wikilink.">' + svgHelp + '</span></label>');
              
              
             // Header & Statistik
             // FITUR AUTOCOMPLETE PRATINJAU DIMULAI DI SINI
             var $header = $('<div class="md-header"></div>');
             var $autoWrap = $('<div class="md-autocomplete-wrapper"></div>');
             $header.append(`<div class="md-title">${svgs.edit} Struktur Data <span class="md-stats">${dataItems.length} Item</span></div>`);
             var $valInput = $('<input type="text" id="md-inp-val" class="md-input" autocomplete="off" value="' + sanitizeHTML(currentData.val || '') + '">');
            var $autoList = $('<div class="md-autocomplete-list"></div>');
            $autoWrap.append($valInput).append($autoList);
            $valBox.append($autoWrap);
              
              
             var $actions = $('<div style="display:flex; gap:8px;"></div>');
             var $wikilinkOpts = $('<div style="margin-top:8px; display:flex; flex-direction:column; gap:8px; background:#f8fafc; padding:10px; border-radius:8px; border:1px solid #e2e8f0;"></div>');
            var chkLink = currentData.link ? 'checked' : '';
            var chkSplit = currentData.linkSplit ? 'checked' : '';
              
              
             // Logika Gembok
            var $linkCheck = $('<input type="checkbox" id="md-inp-link" ' + chkLink + '>');
             if(isSysop) {
            var $lblLinkCheck = $('<label style="display:flex; align-items:center; gap:8px; font-size:0.82rem; font-weight:700; cursor:pointer;"></label>');
                 var lockTxt = isLocked ? svgs.unlock + ' Buka Kunci' : svgs.lock + ' Kunci';
            $lblLinkCheck.append($linkCheck).append(' Jadikan Wikilink Standar');
                var $btnLock = $(`<button class="md-btn ${isLocked ? 'md-btn-danger' : ''}">${lockTxt}</button>`);
 
                $btnLock.on('click', function() {
             // Logika pratinjau ketika diketik
                    isLocked = !isLocked;
             var isAutoChecked = false;
                    saveData(isLocked ? 'Mengunci' : 'Membuka Kunci', rawContent, $(this));
            $valInput.on('input', function() {
                 var q = $(this).val();
               
                // Jika input dikosongkan/berubah, kembalikan centang link ke false jika tadinya otomatis centang
                if (isAutoChecked) {
                    $linkCheck.prop('checked', false);
                    isAutoChecked = false;
                }
 
                if(q.length < 1) {
                    $autoList.empty().hide();
                    return;
                }
 
                // Panggil API MediaWiki Prefix Search
                api.get({
                    action: 'query',
                    list: 'prefixsearch',
                    pssearch: q,
                    pslimit: 6,
                    format: 'json'
                }).done(function(data) {
                    $autoList.empty();
                    if(data.query && data.query.prefixsearch && data.query.prefixsearch.length > 0) {
                        data.query.prefixsearch.forEach(function(res) {
                            var $item = $('<div class="md-autocomplete-item">' + svgSearch + ' ' + sanitizeHTML(res.title) + '</div>');
                            $item.on('click', function() {
                                $valInput.val(res.title);
                                $autoList.empty().hide();
                                $linkCheck.prop('checked', true); // OTOMATIS TERCENTANG
                                isAutoChecked = true;
                            });
                            $autoList.append($item);
                        });
                        $autoList.show();
                    } else {
                        $autoList.hide();
                    }
                 });
                 });
                 $actions.append($btnLock);
            });
             } else if (isLocked) {
 
                var $btnLockedView = $(`<button class="md-btn md-btn-danger">${svgs.lock} Dilindungi</button>`);
            // Sembunyikan pratinjau saat klik di luar
                $btnLockedView.on('click', showLockNotice);
            $(document).on('click.mdauto', function(e) {
                 $actions.append($btnLockedView);
                 if(!$(e.target).closest('.md-autocomplete-wrapper').length) {
             }
                    $autoList.hide();
                }
            });
 
            $wikilinkOpts.append($lblLinkCheck);
            $wikilinkOpts.append('<label style="display:flex; align-items:center; gap:8px; font-size:0.82rem; font-weight:700; cursor:pointer;"><input type="checkbox" id="md-inp-split" ' + chkSplit + '> Smart Split Wikilink</label>');
            var $pipedGroup = $('<div style="margin-top:4px;"><label style="font-size:0.78rem; color:#475569; margin-bottom:4px;">Target Halaman Khusus (Opsional):</label><input type="text" id="md-inp-target" class="md-input" style="padding:6px 10px; font-size:0.85rem;" placeholder="Contoh: Diskografi Rumi Haitami" value="' + sanitizeHTML(currentData.linkTarget || '') + '"></div>');
            $wikilinkOpts.append($pipedGroup);
            $valBox.append($wikilinkOpts);
             $form.append($valBox);
 
            var $socialSec = $('<div class="md-form-group" style="margin-top:16px;"></div>');
            var chkPerson = currentData.isPersonOrg ? 'checked' : '';
            $socialSec.append('<label style="display:flex; align-items:center; gap:8px; cursor:pointer; background:#e0e7ff; padding:10px; border-radius:8px; font-weight:700; color:#3730a3; font-size:0.85rem;"><input type="checkbox" id="md-chk-person" ' + chkPerson + '> Simpan Profil Media Sosial (Akan muncul di paling atas) <span class="md-help-icon" data-help="Centang ini untuk mengisi data sosial media. Datanya akan dihimpun dan dimunculkan di kotak teratas data struktur.">' + svgHelp + '</span></label>');
           
            var $socialGrid = $('<div class="md-social-grid" id="md-social-box" style="display:' + (currentData.isPersonOrg ? 'grid' : 'none') + '; margin-top:8px;"></div>');
            Object.keys(SOCIAL_PLATFORMS).forEach(function(key) {
                var p = SOCIAL_PLATFORMS[key];
                var valUname = currentSocials[key] || '';
                $socialGrid.append('<div><label style="font-size:0.78rem; color:#334155; font-weight:700; margin-bottom:4px;">' + p.name + '</label><input type="text" id="md-soc-' + key + '" class="md-input" placeholder="ID / Username" value="' + sanitizeHTML(valUname) + '"></div>');
            });
            $socialSec.append($socialGrid);
            $form.append($socialSec);
 
            var $refArea = $('<div class="md-form-group" style="margin-top:20px;"></div>');
            $refArea.append('<label style="font-size:0.95rem; font-weight:800; color:#0f172a; margin-bottom:10px;">Sumber Referensi <span class="md-help-icon" data-help="Mohon berikan sumber referensi yang valid, kredibel, dan dapat dipertanggungjawabkan (seperti portal berita resmi, jurnal akademik ilmiah, buku cetak ber-ISBN, atau pangkalan data terverifikasi). Referensi yang kuat sangat membantu memastikan keakuratan informasi. Jika URL rujukan Anda mengarah ke situs web besar yang terverifikasi, sistem keamanan akan secara otomatis menampilkan lencana centang biru premium sebagai tanda sumber tepercaya.">' + svgHelp + '</span></label>');
            var $refGrid = $('<div class="md-ref-grid"></div>');
           
            var $typeSel = $('<select id="md-ref-type" class="md-select"><option value="">-- Pilih Tipe Utama --</option></select>');
            Object.keys(REF_TYPES).forEach(function(t) {
                var sel = currentRef.type === t ? 'selected' : '';
                 $typeSel.append('<option value="' + t + '" ' + sel + '>' + t + '</option>');
             });


             if(!isLocked || isSysop) {
             var $subTypeSel = $('<select id="md-ref-subtype" class="md-select"><option value="">-- Pilih Sub-Tipe --</option></select>');
                var $btnAdd = $(`<button class="md-btn md-btn-primary">${svgs.edit} Tambah</button>`);
            function updateSubTypes(mainType, selectedSub) {
                $btnAdd.on('click', function() { showFormModal(-1, rawContent); });
                 $subTypeSel.empty().append('<option value="">-- Pilih Sub-Tipe --</option>');
                 $actions.append($btnAdd);
                 if (mainType && REF_TYPES[mainType]) {
               
                    REF_TYPES[mainType].forEach(function(st) {
                // FAB untuk Mobile
                        var sel = selectedSub === st ? 'selected' : '';
                 if(window.innerWidth < 768) {
                        $subTypeSel.append('<option value="' + st + '" ' + sel + '>' + st + '</option>');
                    var $fab = $(`<button class="md-btn-fab">${svgs.edit}</button>`);
                     });
                     $fab.on('click', function() { showFormModal(-1, rawContent); });
                    $('body').append($fab);
                 }
                 }
             }
             }
            $typeSel.on('change', function() { updateSubTypes($(this).val(), ''); });
            updateSubTypes(currentRef.type, currentRef.subType);
            $refGrid.append('<div><label style="font-size:0.78rem; margin-bottom:4px;">Tipe Utama</label></div>').find('div').last().append($typeSel);
            $refGrid.append('<div><label style="font-size:0.78rem; margin-bottom:4px;">Sub-Tipe</label></div>').find('div').last().append($subTypeSel);
            var $urlInput = $('<input type="text" id="md-ref-url" class="md-input" placeholder="https://...." value="' + sanitizeHTML(currentRef.url || '') + '">');
            $urlInput.on('blur', function() {
                var u = ensureHttps($(this).val());
                $(this).val(u);
                var $siteInp = $('#md-ref-site');
                if (u && !$siteInp.val().trim()) $siteInp.val(extractDomain(u));
            });
            $refGrid.append('<div class="md-grid-full"><label style="font-size:0.78rem; margin-bottom:4px;">URL Rujukan</label></div>').find('div').last().append($urlInput);
            $refGrid.append('<div><label style="font-size:0.78rem; margin-bottom:4px;">Judul Halaman</label><input type="text" id="md-ref-title" class="md-input" placeholder="Judul Rujukan" value="' + sanitizeHTML(currentRef.title || '') + '"></div>');
            $refGrid.append('<div><label style="font-size:0.78rem; margin-bottom:4px;">Nama Situs</label><input type="text" id="md-ref-site" class="md-input" placeholder="Situs" value="' + sanitizeHTML(currentRef.site || '') + '"></div>');
            $refGrid.append('<div><label style="font-size:0.78rem; margin-bottom:4px;">Penulis</label><input type="text" id="md-ref-author" class="md-input" placeholder="Penulis" value="' + sanitizeHTML(currentRef.author || '') + '"></div>');
            $refGrid.append('<div><label style="font-size:0.78rem; margin-bottom:4px;">Penerbit</label><input type="text" id="md-ref-publisher" class="md-input" placeholder="Penerbit" value="' + sanitizeHTML(currentRef.publisher || '') + '"></div>');
           
            var $dateBox = $('<div><label style="font-size:0.78rem; margin-bottom:4px;">Tanggal Akses</label></div>');
            var $dateInpWrap = $('<div style="display:flex; gap:6px;"></div>');
            var $dateInp = $('<input type="date" id="md-ref-date" class="md-input" value="' + sanitizeHTML(currentRef.date || '') + '">');
            var $todayBtn = $('<button type="button" class="md-btn-icon" style="padding:4px 8px; font-size:0.75rem;" title="Set Hari Ini">Hari Ini</button>');
            $todayBtn.on('click', function() { $dateInp.val(getTodayString()); });
            $dateInpWrap.append($dateInp).append($todayBtn);
            $dateBox.append($dateInpWrap);
            $refGrid.append($dateBox);


             $header.append($actions);
             $refArea.append($refGrid);
             $app.append($header);
             $form.append($refArea);


             // Render List Data
             $form.append(`
            var $list = $('<div></div>');
                 <div class="md-cc0-notice">
            if(dataItems.length === 0) {
                    <b>Perhatian Lisensi:</b> Setiap data yang diterbitkan di sini akan terlihat publik dan dirilis di bawah lisensi <b>Creative Commons Zero (CC0)</b>. Jika Anda tidak ingin suntingan Anda digunakan secara bebas dan publik tanpa batas, jangan klik Terbitkan. <span class="md-help-icon" data-help="Dengan menerbitkan, Anda melepaskan seluruh hak cipta atas input data ini ke domain publik murni sesuai prinsip Wikidata.">${svgHelp}</span>
                 $list.append('<div style="text-align:center; padding:30px; color:var(--md-text-muted);">Belum ada data tersedia.</div>');
                </div>
            } else {
                <div class="md-edit-meta">
                dataItems.forEach(function(item, idx) {
                     <label style="font-size:0.85rem; font-weight:700;">Ringkasan Suntingan <span class="md-help-icon" data-help="Jelaskan secara singkat apa yang Anda ubah atau tambahkan. Contoh: Menambah data tanggal lahir rumi.">${svgHelp}</span></label>
                    var $row = $('<div class="md-row-display"></div>');
                     <input type="text" id="md-edit-summary" class="md-input" placeholder="Jelaskan perubahan Anda secara singkat...">
                    var $info = $('<div></div>');
                    <label style="font-size:0.85rem; cursor:pointer; font-weight:700; margin-top:5px; display:inline-flex; align-items:center; gap:6px;"><input type="checkbox" id="md-minor-edit"> Ini adalah suntingan kecil (minor)</label>
                   
                </div>
                    $info.append(`<div class="md-data-label">${item.prop}</div>`);
            `);
                     $info.append(`<div class="md-data-value">${item.val}</div>`);
                      
                    // 1. TAMPILAN REFERENSI BARU (TOMBOL BADGE -> POP-UP)
                    if(item.ref && (item.ref.url || item.ref.title)) {
                        var $refBtn = $(`<button class="md-ref-trigger">${svgs.ref} Referensi [${idx+1}]</button>`);
                        $refBtn.on('click', function() { showRefDetails(item.ref); });
                        $info.append($refBtn);
                    }


                     $row.append($info);
            var $actions = $('<div class="md-form-actions"></div>');
            var $btnSave = $('<button class="md-btn md-btn-save">Terbitkan <span class="md-spinner"></span></button>');
            var $btnDraft = $('<button class="md-btn md-btn-draft">Simpan Draft</button>');
            var $btnCancel = $('<button class="md-btn md-btn-cancel">Batal</button>');
           
            $actions.append($btnSave).append($btnDraft).append($btnCancel);
           
            if (draftData && isNew) {
                var $btnDelDraft = $('<button class="md-btn" style="background:#eab308; color:#fff;">Hapus Draft</button>');
                $btnDelDraft.on('click', function() {
                    localStorage.removeItem(DRAFT_KEY);
                     alert("Draft berhasil dihapus!");
                    $(this).hide();
                });
                $actions.append($btnDelDraft);
            }


                    if(!isLocked || isSysop) {
            if (!isNew) {
                        var $editBtn = $(`<button class="md-btn" style="height:fit-content;">Edit</button>`);
                var $btnDelete = $('<button class="md-btn md-btn-delete">Hapus Data <span class="md-spinner"></span></button>');
                        $editBtn.on('click', function() { showFormModal(idx, rawContent); });
                $btnDelete.on('click', function() {
                         $row.append($editBtn);
                    if(confirm('Yakin ingin menghapus item data ini?')) {
                        dataItems.splice(index, 1);
                         saveData('Menghapus data', $(this), rawContent, $('#md-edit-summary').val(), $('#md-minor-edit').is(':checked'));
                     }
                     }
                    $list.append($row);
                 });
                 });
                $actions.append($btnDelete);
             }
             }
            $form.append($actions);
            $container.append($form);
            initTooltips();
            $('#md-chk-person').on('change', function() {
                if($(this).is(':checked')) $('#md-social-box').css('display', 'grid');
                else $('#md-social-box').hide();
            });
            $('html, body').animate({ scrollTop: $form.offset().top - 60 }, 250);
            $btnCancel.on('click', function() { $container.empty(); });
            $btnDraft.on('click', function() {
                var socObj = {};
                if ($('#md-chk-person').is(':checked')) {
                    Object.keys(SOCIAL_PLATFORMS).forEach(function(k) {
                        var valU = $('#md-soc-' + k).val().trim();
                        if (valU) socObj[k] = valU;
                    });
                }
                var draftObj = {
                    prop: $('#md-inp-prop').val().trim(),
                    val: $('#md-inp-val').val().trim(),
                    link: $('#md-inp-link').is(':checked'),
                    linkSplit: $('#md-inp-split').is(':checked'),
                    linkTarget: $('#md-inp-target').val().trim(),
                    isPersonOrg: $('#md-chk-person').is(':checked'),
                    socials: socObj,
                    ref: {
                        type: $('#md-ref-type').val(), subType: $('#md-ref-subtype').val(),
                        url: ensureHttps($('#md-ref-url').val()), title: $('#md-ref-title').val().trim(),
                        site: $('#md-ref-site').val().trim(), author: $('#md-ref-author').val().trim(),
                        publisher: $('#md-ref-publisher').val().trim(), date: $('#md-ref-date').val()
                    }
                };
                localStorage.setItem(DRAFT_KEY, JSON.stringify(draftObj));
                alert("Draft berhasil disimpan di memori peramban Anda!");
            });
            $btnSave.on('click', function() {
                var newProp = $('#md-inp-prop').val().trim();
                var newVal = $('#md-inp-val').val().trim();
                if (!newProp || !newVal) {
                    alert("Label Data dan Nilai wajib diisi!"); return;
                }
                var isPerson = $('#md-chk-person').is(':checked');
                var socObj = {};
                if (isPerson) {
                    Object.keys(SOCIAL_PLATFORMS).forEach(function(k) {
                        var valU = $('#md-soc-' + k).val().trim();
                        if (valU) socObj[k] = valU;
                    });
                }
                var refObj = {
                    type: $('#md-ref-type').val(),
                    subType: $('#md-ref-subtype').val(),
                    url: ensureHttps($('#md-ref-url').val()),
                    title: $('#md-ref-title').val().trim(),
                    site: $('#md-ref-site').val().trim(),
                    author: $('#md-ref-author').val().trim(),
                    publisher: $('#md-ref-publisher').val().trim(),
                    date: $('#md-ref-date').val()
                };
                Object.keys(refObj).forEach(function(key) { if (!refObj[key]) delete refObj[key]; });
                if (Object.keys(refObj).length === 0) refObj = null;
                var newItem = {
                    prop: newProp, val: newVal,
                    link: $('#md-inp-link').is(':checked'),
                    linkSplit: $('#md-inp-split').is(':checked'),
                    linkTarget: $('#md-inp-target').val().trim(),
                    isPersonOrg: isPerson,
                    socials: socObj,
                    ref: refObj
                };
                if (isNew) dataItems.push(newItem);
                else dataItems[index] = newItem;
                saveData(isNew ? 'Tambah data' : 'Edit data', $(this), rawContent, $('#md-edit-summary').val().trim(), $('#md-minor-edit').is(':checked'));
            });
        }
        // 10. JSON EXPORT & IMPORT MODAL (ASLI UTUH)
        function showJsonModal(rawContent) {
            var $container = $('#md-form-container').empty();
            var jsonStr = JSON.stringify(dataItems, null, 2);
            var $box = $('<div class="md-form-box"></div>');
            $box.append('<h4 class="md-form-title">Ekspor / Impor JSON Data</h4>');
            $box.append('<p style="font-size:0.82rem; color:#64748b; margin-bottom:10px;">Anda dapat menyalin struktur JSON di bawah untuk cadangan atau menempelkan JSON dari artikel lain.</p>');
              
              
             $app.append($list);
            var $txt = $('<textarea class="md-textarea" rows="10" style="font-family:monospace; font-size:0.8rem;"></textarea>').val(jsonStr);
           
             $box.append($txt);
             var $infobox = $('.infobox').first();
 
             $('.md-native-render').hide();
             var $actions = $('<div class="md-form-actions"></div>');
             if($infobox.length) $app.insertAfter($infobox);
            var $btnImport = $('<button class="md-btn md-btn-save">Impor JSON & Simpan <span class="md-spinner"></span></button>');
             else $('#mw-content-text .mw-parser-output').append($app);
             var $btnCancel = $('<button class="md-btn md-btn-cancel">Tutup</button>');
 
            $actions.append($btnImport).append($btnCancel);
             $box.append($actions);
            $container.append($box);
 
            $btnCancel.on('click', function() { $container.empty(); });
             $btnImport.on('click', function() {
                try {
                    var parsed = JSON.parse($txt.val());
                    if (Array.isArray(parsed)) {
                        dataItems = parsed;
                        saveData('Impor data dari JSON', $(this), rawContent, 'Impor struktur data JSON', false);
                    } else {
                        alert("Format JSON harus berupa Array items!");
                    }
                } catch(e) {
                    alert("Format JSON tidak valid: " + e.message);
                }
            });
         }
         }


         // --- EXECUTE ---
         // 11. EXECUTE
         loadData().then(function(rawContent) { buildUI(rawContent); });
         loadData().then(function(rawContent) { buildUI(rawContent); });
     });
     });
Baris 940: Baris 1.357:
             '<div style="font-size:11px; color:#718096; font-weight:800; text-transform:uppercase; letter-spacing:1px; margin-bottom:10px;">Lisensi, Atribusi & Penggunaan Data</div>' +
             '<div style="font-size:11px; color:#718096; font-weight:800; text-transform:uppercase; letter-spacing:1px; margin-bottom:10px;">Lisensi, Atribusi & Penggunaan Data</div>' +
             '<p style="margin:0 0 10px; font-size:13px; color:#4a5568; line-height:1.6;">' +
             '<p style="margin:0 0 10px; font-size:13px; color:#4a5568; line-height:1.6;">' +
             'Seluruh data terstruktur yang tersaji dalam repositori ini merupakan milik publik dan tersedia di bawah lisensi resmi ' +
             'Seluruh data terstruktur yang tersaji dalam repositori ini merupakan milik publik dan tersedia di bawah ' +
             '<a href="https://creativecommons.org/licenses/by-sa/4.0/" target="_blank" style="color:#6a5acd; text-decoration:none; font-weight:700;">Creative Commons Attribution-ShareAlike 4.0 International</a>.' +
             '<a href="https://creativecommons.org/publicdomain/zero/1.0/"target="_blank" style="color:#6a5acd; text-decoration:none; font-weight:700;">Lisensi Creative Commons CC0</a>.' +
             '</p>' +
             '</p>' +
             '<p style="margin:0; font-size:12px; color:#a0aec0;">Akses API dan penggunaan data secara massal wajib mencantumkan atribusi kepada <strong>Mippedia Community</strong> selaku pengelola proyek.</p></div>';
             '<p style="margin:0; font-size:12px; color:#a0aec0;">Akses API dan penggunaan data secara massal wajib mencantumkan atribusi kepada <strong>Mippedia Community</strong> selaku pengelola proyek.</p></div>';