Lompat ke isi

MediaWiki:Common.js: Perbedaan antara revisi

Dari Mippedia Data, basis data terbuka
Admin (bicara | kontrib)
Tidak ada ringkasan suntingan
Tanda: Suntingan perangkat seluler Suntingan peramban seluler
Admin (bicara | kontrib)
Tidak ada ringkasan suntingan
Tanda: Suntingan perangkat seluler Suntingan peramban seluler
Baris 1: Baris 1:
/**
/**
  * ====================================================================
  * ====================================================================
  * MIPPEDIA DATA - ADVANCED STRUCTURED DATA SYSTEM (V8.0 ULTIMATE PRO)
  * MIPPEDIA DATA - ADVANCED STRUCTURED DATA SYSTEM (V8.0 EVOLUTION)
  * Fitur: Smart Collapsible Refs, Dark Mode, Reorder, Duplicate, Toast
  * Fitur: Full Modal UI, Smart References, Floating Guides, Dark Mode,  
  * Notifications, LocalStorage Draft, Glass UI, Mobile-First, Auto-Domain
  * Toast Notifications, Advanced Validations, Mobile FAB, etc.
  * ====================================================================
  * ====================================================================
  */
  */
Baris 20: Baris 20:
         var api = new mw.Api();
         var api = new mw.Api();


         // 1. DATA MASTER PLATFORM MEDIA SOSIAL & MUSIK (Ditambah)
         // --- MASTER DATA PLATFORM ---
         var SOCIAL_PLATFORMS = {
         var SOCIAL_PLATFORMS = {
             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>' },
             applemusic: { name: 'Apple Music', base: 'https://music.apple.com/artist/', color: '#fc3c44' },
             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>' },
             spotify: { name: 'Spotify', base: 'https://open.spotify.com/artist/', color: '#1db954' },
             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>' },
             soundcloud: { name: 'SoundCloud', base: 'https://soundcloud.com/', color: '#ff5500' },
             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>' },
             instagram: { name: 'Instagram', base: 'https://instagram.com/', color: '#e1306c' },
             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>' },
             tiktok: { name: 'TikTok', base: 'https://www.tiktok.com/@', color: '#000000' },
             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>' },
             youtube: { name: 'YouTube', base: 'https://youtube.com/@', color: '#ff0000' },
             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>' },
             twitter: { name: 'X / Twitter', base: 'https://x.com/', color: '#0f1419' }
            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>' },
            reddit: { name: 'Reddit', base: 'https://reddit.com/user/', color: '#ff4500', icon: '<svg width="13" height="13" viewBox="0 0 24 24" fill="currentColor"><path d="M24 11.5c0-1.65-1.35-3-3-3-.96 0-1.86.48-2.42 1.24-1.64-1-3.75-1.64-6.07-1.72.08-1.1.4-3.05 1.52-3.7.72-.4 1.73-.24 3 .5C17.2 6.3 18.46 7.5 20 7.5c1.65 0 3-1.35 3-3s-1.35-3-3-3c-1.38 0-2.54.94-2.88 2.22-1.43-.72-2.64-.8-3.6-.25-1.64.94-1.95 3.47-2 4.55-2.33.08-4.45.7-6.1 1.72C4.86 8.98 3.96 8.5 3 8.5c-1.65 0-3 1.35-3 3 0 1.32.84 2.44 2.05 2.84-.03.22-.05.44-.05.66 0 3.86 4.5 7 10 7s10-3.14 10-7c0-.22-.02-.44-.05-.66 1.2-.4 2.05-1.54 2.05-2.84zM2.3 13.37C1.5 13.07 1 12.35 1 11.5c0-1.1.9-2 2-2 .64 0 1.22.32 1.6.82-1.1.85-1.92 1.9-2.3 3.05zm3.7.13c0-1.1.9-2 2-2s2 .9 2 2-.9 2-2 2-2-.9-2-2zm9.8 4.8c-1.08.63-2.42.96-3.8.96-1.4 0-2.74-.34-3.8-.95-.24-.13-.32-.44-.2-.68.15-.24.46-.32.7-.18 1.83 1.06 4.76 1.06 6.6 0 .23-.13.53-.05.67.2.14.23.06.54-.18.67zm.2-2.8c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2zm5.7-2.13c-.38-1.16-1.2-2.2-2.3-3.05.38-.5.96-.82 1.6-.82 1.1 0 2 .9 2 2 0 .84-.53 1.57-1.3 1.87z"/></svg>' },
            discord: { name: 'Discord', base: 'https://discord.com/users/', color: '#5865F2', icon: '<svg width="13" height="13" viewBox="0 0 24 24" fill="currentColor"><path d="M20.317 4.3698a19.7913 19.7913 0 00-4.8851-1.5152.0741.0741 0 00-.0785.0371c-.211.3753-.4447.8648-.6083 1.2495-1.8447-.2762-3.68-.2762-5.4868 0-.1636-.3933-.4058-.8742-.6177-1.2495a.077.077 0 00-.0785-.037 19.7363 19.7363 0 00-4.8852 1.515.0699.0699 0 00-.0321.0277C.5334 9.0458-.319 13.5799.0992 18.0578a.0824.0824 0 00.0312.0561c2.0528 1.5076 4.0413 2.4228 5.9929 3.0294a.0777.0777 0 00.0842-.0276c.4616-.6304.8731-1.2952 1.226-1.9942a.076.076 0 00-.0416-.1057c-.6528-.2476-1.2743-.5495-1.8722-.8923a.077.077 0 01-.0076-.1277c.1258-.0943.2517-.1923.3718-.2914a.0743.0743 0 01.0776-.0105c3.9278 1.7933 8.18 1.7933 12.0614 0a.0739.0739 0 01.0785.0095c.1202.099.246.1981.3728.2924a.077.077 0 01-.0066.1276 12.2986 12.2986 0 01-1.873.8914.0766.0766 0 00-.0407.1067c.3604.698.7719 1.3628 1.225 1.9932a.076.076 0 00.0842.0286c1.961-.6067 3.9495-1.5219 6.0023-3.0294a.077.077 0 00.0313-.0552c.5004-5.177-.8382-9.6739-3.5485-13.6604a.061.061 0 00-.0312-.0286zM8.02 15.3312c-1.1825 0-2.1569-1.0857-2.1569-2.419 0-1.3332.9555-2.4189 2.157-2.4189 1.2108 0 2.1757 1.0952 2.1568 2.419 0 1.3332-.9555 2.4189-2.1569 2.4189zm7.9748 0c-1.1825 0-2.1569-1.0857-2.1569-2.419 0-1.3332.9554-2.4189 2.1569-2.4189 1.2108 0 2.1757 1.0952 2.1568 2.419 0 1.3332-.946 2.4189-2.1568 2.4189z"/></svg>' },
            twitch: { name: 'Twitch', base: 'https://twitch.tv/', color: '#9146FF', icon: '<svg width="13" height="13" viewBox="0 0 24 24" fill="currentColor"><path d="M2.149 0L.537 4.119v16.836h5.731V24h3.224l3.045-3.045h4.657l6.269-6.269V0H2.149zm19.164 13.612l-4.298 4.298h-5.373l-3.045 3.045v-3.045H4.119V2.149h17.194v11.463zm-3.582-7.343v6.269h-2.149V6.269h2.149zm-5.731 0v6.269h-2.149V6.269h2.149z"/></svg>' },
            telegram: { name: 'Telegram', base: 'https://t.me/', color: '#26A5E4', icon: '<svg width="13" height="13" viewBox="0 0 24 24" fill="currentColor"><path d="M11.944 0A12 12 0 0 0 0 12a12 12 0 0 0 12 12 12 12 0 0 0 12-12A12 12 0 0 0 12 0a12 12 0 0 0-.056 0zm4.962 7.224c.1-.002.321.023.465.14a.506.506 0 0 1 .171.325c.016.093.036.306.02.472-.18 1.898-.962 6.502-1.36 8.627-.168.9-.499 1.201-.82 1.23-.696.065-1.225-.46-1.9-.902-1.056-.693-1.653-1.124-2.678-1.8-1.185-.78-.417-1.21.258-1.91.177-.184 3.247-2.977 3.307-3.23.007-.032.014-.15-.056-.212s-.174-.041-.249-.024c-.106.024-1.793 1.14-5.061 3.345-.48.33-.913.49-1.302.48-.428-.008-1.252-.241-1.865-.44-.752-.245-1.349-.374-1.297-.789.027-.216.325-.437.893-.663 3.498-1.524 5.83-2.529 6.998-3.014 3.332-1.386 4.025-1.627 4.476-1.635z"/></svg>' },
            whatsapp: { name: 'WhatsApp', base: 'https:///', color: '#25D366', icon: '<svg width="13" height="13" viewBox="0 0 24 24" fill="currentColor"><path d="M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51a5.8 5.8 0 0 0-.57-.01c-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347m-5.421 7.403h-.004a9.87 9.87 0 0 1-5.031-1.378l-.361-.214-3.741.982.998-3.648-.235-.374a9.86 9.86 0 0 1-1.51-5.26c.001-5.45 4.436-9.884 9.888-9.884 2.64 0 5.122 1.03 6.988 2.898a9.82 9.82 0 0 1 2.893 6.994c-.003 5.45-4.437 9.884-9.885 9.884m8.413-18.297A11.815 11.815 0 0 0 12.05 0C5.495 0 .16 5.335.157 11.892c0 2.096.547 4.142 1.588 5.945L.057 24l6.305-1.654a11.882 11.882 0 0 0 5.683 1.448h.005c6.554 0 11.89-5.335 11.893-11.893a11.821 11.821 0 0 0-3.48-8.413z"/></svg>' }
         };
         };


        // 2. PRESET TEMPLATES LABEL LENGKAP (Diperluas)
         var PRESET_LABELS = [
         var PRESET_LABELS = [
             "Nama Lahir", "Tanggal Lahir", "Tempat Lahir", "Pekerjaan",  
             "Nama Lahir", "Tanggal Lahir", "Tempat Lahir", "Pekerjaan",  
             "Kebangsaan", "Agama", "Pendidikan", "Genre", "Instrumen",  
             "Kebangsaan", "Genre", "Instrumen", "Label Rekaman",  
            "Label Rekaman", "Tahun Aktif", "Situs Web Resmi", "Pasangan",  
            "Tahun Aktif", "Situs Web Resmi", "Pasangan", "Orang Tua"
            "Orang Tua", "Anak", "Penghargaan", "Agensi", "Tinggi Badan"
         ];
         ];


        // 3. MASTER TIPE RUJUKAN
         var REF_TYPES = {
         var REF_TYPES = {
             "Berita": ["Berita Online", "Berita Cetak / Koran", "Wawancara Eksklusif", "Liputan Khusus", "Editorial", "Investigasi Media", "Siaran Radio / TV"],
             "Berita": ["Berita Online", "Berita Cetak", "Wawancara"],
             "Website": ["Situs Resmi", "Portal Informasi", "Database Web", "Portal Komunitas", "Forum Diskusi", "Portal Edukasi", "Direktori Web"],
             "Website": ["Situs Resmi", "Portal Informasi", "Database Web"],
             "Buku": ["Buku Cetak", "E-Book", "Bab / Bagian Buku", "Monograf", "Katalog / Biografi Cetak", "Buku Teks Akademik"],
             "Buku": ["Buku Cetak", "E-Book", "Jurnal Ilmiah"],
            "Jurnal": ["Jurnal Ilmiah Peer-Reviewed", "Paper Konferensi", "Artikel Review", "Pre-print / Draft Penelitian", "Tesis / Disertasi"],
             "Media": ["Video YouTube", "Podcast", "Media Sosial"]
             "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"]
         };
         };


         // 4. IKON SISTEM (Diperbarui dengan ikon tajam & bersih)
         // --- IKON 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>';
         var svgs = {
        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>';
            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>',
        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>';
            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>',
        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>';
            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>',
        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>';
            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>',
        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>';
            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>',
        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>';
            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 svgUp = '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="18 15 12 9 6 15"></polyline></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 svgDown = '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="6 9 12 15 18 9"></polyline></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 svgDuplicate = '<svg width="14" height="14" 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 svgMoon = '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path></svg>';
        var svgLinkExt = '<svg width="13" height="13" 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 svgVerified = '<svg width="13" height="13" viewBox="0 0 24 24" fill="#3b82f6" stroke="#fff" stroke-width="2"><polygon points="12 2 15.09 5.09 19.5 5.5 20.41 9.91 23.5 13 20.41 16.09 19.5 20.5 15.09 20.91 12 24 8.91 20.91 4.5 20.5 3.59 16.09 0.5 13 3.59 9.91 4.5 5.5 8.91 5.09 12 2"></polygon><polyline points="8 12.5 11 15.5 16 9.5" fill="none"></polyline></svg>';
 
        // 5. HELPER UTILITY CANGGIH
        function showToast(msg, type) {
            $('.md-toast').remove();
            var bg = type === 'error' ? '#ef4444' : '#10b981';
            var $toast = $('<div class="md-toast" style="position:fixed; bottom:20px; right:20px; background:' + bg + '; color:white; padding:10px 16px; border-radius:8px; font-weight:600; font-size:0.85rem; box-shadow:0 4px 12px rgba(0,0,0,0.15); z-index:9999; display:none; flex-align:center; gap:8px;">' + msg + '</div>');
            $('body').append($toast);
            $toast.fadeIn(300).delay(2500).fadeOut(300, function() { $(this).remove(); });
        }
 
        function formatIndonesianDate(dateStr) {
            if (!dateStr) return '';
            var parts = dateStr.split('-');
            if (parts.length !== 3) return dateStr;
            var months = ['Jan', 'Feb', 'Mar', 'Apr', 'Mei', 'Jun', 'Jul', 'Agt', 'Sep', 'Okt', 'Nov', 'Des'];
            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 dateStr;
            return day + ' ' + months[monthIdx] + ' ' + year;
        }
 
        function extractDomain(urlStr) {
            try {
                if (!urlStr.match(/^https?:\/\//i)) urlStr = 'https://' + urlStr;
                var parsed = new URL(urlStr);
                return parsed.hostname.replace(/^www\./, '');
            } catch(e) {
                return urlStr.replace(/^https?:\/\/(www\.)?/, '').split('/')[0];
            }
        }
 
        function ensureHttps(urlStr) {
            if (!urlStr) return '';
            urlStr = urlStr.trim();
            if (urlStr && !urlStr.match(/^https?:\/\//i)) {
                return 'https://' + urlStr;
            }
            return 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;
         }
 
        function isVerifiedSite(domain) {
            var officialSites = ['wikipedia.org', 'imdb.com', 'spotify.com', 'apple.com', 'bbc.com', 'cnn.com', 'nytimes.com', 'gov', 'edu'];
            return officialSites.some(function(site) { return domain.indexOf(site) !== -1; });
        }


         // 6. STYLESHEET MODERN V8.0 ULTIMATE PRO
         // --- STYLESHEET V8.0 (Modern UI & Animations) ---
         var css = `
         var css = `
             :root {
             :root {
                 --md-bg: #ffffff; --md-border: #e2e8f0; --md-text: #0f172a; --md-text-muted: #64748b;
                 --md-primary: #4f46e5; --md-primary-hover: #4338ca; --md-bg: #ffffff;
                 --md-bg-hover: #f8fafc; --md-primary: #4f46e5; --md-primary-hover: #4338ca;
                 --md-surface: #f8fafc; --md-border: #e2e8f0; --md-text: #0f172a;
                 --md-card-bg: #fff; --md-ref-bg: #f8fafc; --md-input-bg: #f8fafc;
                 --md-text-muted: #64748b; --md-danger: #ef4444; --md-radius: 12px;
                --md-shadow: 0 4px 24px rgba(0,0,0,0.06);
             }
             }
             .md-dark-mode {
             @media (prefers-color-scheme: dark) {
                 --md-bg: #0f172a; --md-border: #334155; --md-text: #f8fafc; --md-text-muted: #94a3b8;
                 :root {
                --md-bg-hover: #1e293b; --md-primary: #6366f1; --md-primary-hover: #818cf8;
                    --md-bg: #0f172a; --md-surface: #1e293b; --md-border: #334155;
                --md-card-bg: #1e293b; --md-ref-bg: #0f172a; --md-input-bg: #0f172a;
                    --md-text: #f8fafc; --md-text-muted: #94a3b8;
                 --md-shadow: 0 4px 24px rgba(0,0,0,0.3);
                 }
             }
             }
             #mippedia-data-app {
             #mippedia-data-app {
                 background: var(--md-bg); border-radius: 16px; box-shadow: var(--md-shadow);
                 background: var(--md-bg); border-radius: 16px; box-shadow: 0 10px 30px rgba(0,0,0,0.08);
                 padding: 20px; margin: 20px 0; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
                 padding: 24px; margin: 24px 0; font-family: system-ui, -apple-system, sans-serif;
                 border: 1px solid var(--md-border); max-width: 100%; box-sizing: border-box; overflow: hidden;
                 border: 1px solid var(--md-border); position: relative; color: var(--md-text);
                color: var(--md-text); transition: background 0.3s, color 0.3s;
             }
             }
            .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-title { font-size: 1.3rem; font-weight: 800; margin: 0; display: flex; align-items: center; gap: 8px; }
            .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-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 var(--md-border); }
             .md-btn {
            .md-title-container { display: flex; align-items: center; gap: 8px; flex: 1 1 auto; min-width: 180px; }
                background: var(--md-surface); border: 1px solid var(--md-border); color: var(--md-text);
             .md-title { font-size: 1.25rem; font-weight: 800; color: var(--md-text); margin: 0; white-space: nowrap; letter-spacing: -0.3px; }
                padding: 8px 14px; border-radius: 8px; cursor: pointer; font-weight: 600; font-size: 0.85rem;
             .md-actions { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
                display: inline-flex; align-items: center; gap: 6px; transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
            }
             .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-primary { background: linear-gradient(135deg, var(--md-primary), #3b82f6); color: white; border: none; }
            .md-btn-danger { background: #fef2f2; color: var(--md-danger); border-color: #fca5a5; }
              
              
            .md-btn-icon {
                background: var(--md-bg-hover); border: 1px solid var(--md-border); cursor: pointer; color: var(--md-primary);
                padding: 8px 14px; border-radius: 8px; transition: all 0.2s ease;
                display: inline-flex; align-items: center; gap: 6px; font-size: 0.85rem; font-weight: 600; white-space: nowrap;
            }
            .md-btn-icon:hover:not(:disabled) { border-color: var(--md-text-muted); transform: translateY(-1px); box-shadow: 0 2px 8px rgba(0,0,0,0.05); }
            .md-btn-lock { color: #dc2626; background: #fef2f2; 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 var(--md-border); border-radius: 8px; font-size: 0.85rem; box-sizing: border-box; background: var(--md-input-bg); color: var(--md-text); transition: 0.2s; }
            .md-search-input:focus { border-color: var(--md-primary); outline: none; box-shadow: 0 0 0 3px rgba(99,102,241,0.15); }
            .md-search-icon { position: absolute; left: 10px; top: 50%; transform: translateY(-50%); color: var(--md-text-muted); }
            /* Row Display Fix */
             .md-row-display {
             .md-row-display {
                 display: flex; justify-content: space-between; align-items: flex-start;
                 display: flex; justify-content: space-between; padding: 14px 16px; margin-bottom: 8px;
                padding: 16px 12px; border-bottom: 1px solid var(--md-border); transition: all 0.2s;
                background: var(--md-surface); border-radius: var(--md-radius); border: 1px solid var(--md-border);
                border-radius: 12px; gap: 12px; margin-bottom: 8px; background: var(--md-card-bg);
                transition: 0.3s;
             }
             }
             .md-row-display:hover { background: var(--md-bg-hover); box-shadow: inset 4px 0 0 var(--md-primary); }
             .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-data-label { font-size: 0.75rem; text-transform: uppercase; color: var(--md-text-muted); font-weight: 800; letter-spacing: 0.5px; }
            .md-data-value { font-size: 1.1rem; font-weight: 700; display: block; margin-top: 4px; }
              
              
             .md-data-group { display: flex; flex-direction: column; gap: 6px; flex: 1; min-width: 0; }
             /* Referensi Badge */
             .md-data-label { font-size: 0.72rem; color: var(--md-text-muted); font-weight: 800; text-transform: uppercase; letter-spacing: 0.6px; }
             .md-ref-trigger {
            .md-data-value-wrap { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
                background: #e0e7ff; color: var(--md-primary); border: none; padding: 4px 10px;
            .md-data-value { font-size: 1.02rem; color: var(--md-text); line-height: 1.4; font-weight: 600; word-break: break-word; }
                border-radius: 20px; font-size: 0.75rem; font-weight: 700; cursor: pointer; margin-top: 8px;
           
                display: inline-flex; align-items: center; gap: 4px; transition: 0.2s;
            .md-btn-copy { background: none; border: none; color: var(--md-text-muted); cursor: pointer; padding: 2px 4px; border-radius: 4px; transition: 0.2s; display: inline-flex; align-items: center; }
            }
             .md-btn-copy:hover { color: var(--md-primary); background: var(--md-border); }
             .md-ref-trigger:hover { background: var(--md-primary); color: white; }


             /* Tampilan Referensi V8.0 (COLLAPSIBLE / ACCORDION) */
             /* Modal System (Pop-ups) */
             .md-ref-wrapper { margin-top: 8px; width: 100%; box-sizing: border-box; }
             .md-overlay {
            .md-ref-toggle {
                position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; background: rgba(0,0,0,0.5);
                background: var(--md-ref-bg); border: 1px solid var(--md-border); border-radius: 6px;
                backdrop-filter: blur(8px); z-index: 99999; display: flex; justify-content: center; align-items: center;
                padding: 6px 12px; font-size: 0.78rem; font-weight: 700; color: var(--md-primary);
                 opacity: 0; animation: fadeIn 0.3s forwards; padding: 20px; box-sizing: border-box;
                 cursor: pointer; display: inline-flex; align-items: center; gap: 6px; transition: 0.2s;
             }
             }
             .md-ref-toggle:hover { background: var(--md-bg-hover); transform: translateX(2px); }
             .md-modal {
            .md-ref-toggle.active { border-bottom-left-radius: 0; border-bottom-right-radius: 0; border-bottom: none; }
                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);
            .md-ref-card {
                 animation: slideUp 0.4s cubic-bezier(0.16, 1, 0.3, 1) forwards;
                background: var(--md-ref-bg); padding: 12px 14px; border-radius: 0 6px 6px 6px;
                max-height: 90vh; display: flex; flex-direction: column; overflow: hidden; border: 1px solid var(--md-border);
                 border: 1px solid var(--md-border); font-size: 0.85rem; display: none; flex-direction: column; gap: 8px;
                box-sizing: border-box; animation: mdFadeIn 0.3s ease-in-out;
             }
             }
             @keyframes mdFadeIn { from { opacity: 0; transform: translateY(-5px); } to { opacity: 1; transform: translateY(0); } }
             .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); }


             .md-ref-header { font-weight: 700; color: var(--md-text); font-size: 0.9rem; word-break: break-word; display: flex; align-items: center; gap: 5px;}
             /* Formulir Inputs */
             .md-ref-details-grid { display: flex; flex-direction: column; gap: 4px; }
             .md-form-group { margin-bottom: 16px; }
             .md-ref-detail-row { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 6px; font-size: 0.82rem; color: var(--md-text-muted); }
             .md-form-group label { display: block; font-weight: 700; font-size: 0.85rem; margin-bottom: 6px; color: var(--md-text); }
             .md-ref-lbl { font-weight: 700; white-space: nowrap; flex-shrink: 0; }
             .md-input {
            .md-ref-val { color: var(--md-text); font-weight: 500; word-break: break-word; }
                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-ref-actions { display: flex; gap: 8px; margin-top: 6px; flex-wrap: wrap; }
            .md-ref-visit-btn {
                 background: var(--md-primary); color: white; padding: 5px 12px; border-radius: 6px;
                font-size: 0.75rem; font-weight: 700; text-decoration: none; display: inline-flex; align-items: center; gap: 4px; transition: 0.2s;
             }
             }
             .md-ref-visit-btn:hover { background: var(--md-primary-hover); transform: translateY(-1px); color: white; text-decoration: none; }
             .md-input:focus { border-color: var(--md-primary); outline: none; box-shadow: 0 0 0 4px rgba(79, 70, 229, 0.1); }
             .md-ref-badge { display: inline-block; background: var(--md-border); color: var(--md-text); padding: 3px 8px; border-radius: 6px; font-weight: 700; font-size: 0.72rem; }
             .md-input.error { border-color: var(--md-danger); animation: shake 0.4s; }


             /* Media Sosial Badges V8 */
             /* Toast Notification */
             .md-social-group { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
             .md-toast {
            .md-social-badge { display: inline-flex; align-items: center; gap: 6px; padding: 5px 11px; border-radius: 18px; font-size: 0.78rem; font-weight: 600; color: white; text-decoration: none; transition: transform 0.2s, opacity 0.2s; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }
                position: fixed; bottom: 30px; right: 30px; background: #10b981; color: white;
            .md-social-badge:hover { transform: translateY(-2px); opacity: 0.92; color: white; text-decoration: none; }
                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;
            }


             /* Toolbars List */
             /* Help Tooltip Box */
             .md-row-tools { display: flex; flex-direction: column; gap: 4px; align-items: flex-end; }
             .md-help-box {
             .md-row-tools-group { display: flex; gap: 4px; }
                background: linear-gradient(135deg, #1e293b, #0f172a); color: #f8fafc; padding: 16px;
                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;
            }


             /* Preset Pill Badges */
             @keyframes fadeIn { to { opacity: 1; } }
            .md-preset-wrapper { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
             @keyframes slideUp { to { transform: translateY(0); } }
             .md-preset-pill { background: var(--md-bg-hover); border: 1px solid var(--md-border); padding: 4px 10px; border-radius: 12px; font-size: 0.75rem; font-weight: 600; color: var(--md-text-muted); cursor: pointer; transition: 0.2s; }
            @keyframes slideInRight { from { transform: translateX(100px); opacity: 0; } to { transform: translateX(0); opacity: 1; } }
             .md-preset-pill:hover { background: #e0e7ff; color: #3730a3; border-color: #a5b4fc; }
             @keyframes shake { 0%, 100% { transform: translateX(0); } 25% { transform: translateX(-5px); } 75% { transform: translateX(5px); } }


             /* Form Elements Responsif */
             @media (max-width: 768px) {
            .md-form-box { background: var(--md-card-bg); border-radius: 12px; padding: 18px; margin-top: 16px; border: 1px solid var(--md-border); box-shadow: var(--md-shadow); backdrop-filter: blur(10px); }
                #mippedia-data-app { padding: 16px; }
            .md-form-title { font-size: 1.05rem; font-weight: 800; color: var(--md-text); margin: 0 0 16px 0; border-bottom: 2px solid var(--md-border); padding-bottom: 8px; position: sticky; top: 0; background: var(--md-card-bg); z-index: 10; }
                .md-overlay { padding: 10px; align-items: flex-end; }
            .md-form-group { margin-bottom: 14px; }
                .md-modal { max-height: 95vh; border-radius: 20px 20px 0 0; animation: slideUpMobile 0.4s forwards; transform: translateY(100%); }
            .md-form-group label { display: block; font-size: 0.82rem; font-weight: 700; margin-bottom: 6px; color: var(--md-text-muted); }
                @keyframes slideUpMobile { to { transform: translateY(0); } }
            .md-input, .md-select, .md-textarea { width: 100%; padding: 9px 12px; border: 1px solid var(--md-border); border-radius: 8px; box-sizing: border-box; font-family: inherit; font-size: 0.9rem; transition: 0.2s; background: var(--md-input-bg); color: var(--md-text); }
                .md-btn-fab {
            .md-input:focus, .md-select:focus, .md-textarea:focus { border-color: var(--md-primary); outline: none; box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.15); }
                    position: fixed; bottom: 20px; right: 20px; width: 60px; height: 60px; border-radius: 30px;
            .md-input.error { border-color: #ef4444; background: #fef2f2; }
                    background: var(--md-primary); color: white; display: flex; justify-content: center; align-items: center;
           
                    box-shadow: 0 10px 25px rgba(79, 70, 229, 0.4); z-index: 9000; cursor: pointer; border: none;
            .md-ref-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; background: var(--md-bg-hover); padding: 12px; border-radius: 8px; border: 1px dashed var(--md-border); }
                 }
            .md-social-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; background: var(--md-bg-hover); padding: 12px; border-radius: 8px; border: 1px solid var(--md-border); max-height: 280px; overflow-y: auto; }
            .md-grid-full { grid-column: span 2; }
           
            .md-form-actions { display: flex; gap: 10px; align-items: center; margin-top: 20px; padding-top: 14px; border-top: 1px solid var(--md-border); flex-wrap: wrap; }
            .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; }
            .md-btn:hover:not(:disabled) { transform: translateY(-1px); box-shadow: 0 4px 10px rgba(0,0,0,0.15); }
            .md-btn-save { background: linear-gradient(135deg, var(--md-primary), var(--md-primary-hover)); flex: 1; min-width: 140px; }
            .md-btn-cancel { background: #64748b; }
            .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: 600px) {
                #mippedia-data-app { padding: 14px; margin: 14px 0; border-radius: 12px; }
                .md-header { flex-direction: column; align-items: flex-start; gap: 10px; }
                .md-actions { width: 100%; justify-content: flex-start; overflow-x: auto; padding-bottom: 4px; }
                .md-btn-icon { padding: 7px 12px; font-size: 0.8rem; }
                .md-ref-grid, .md-social-grid { grid-template-columns: 1fr; }
                .md-grid-full { grid-column: span 1; }
                .md-form-actions { flex-direction: column; width: 100%; }
                .md-btn { width: 100%; margin: 0 !important; }
                .md-row-display { flex-direction: column; padding: 14px; }
                 .md-row-tools { flex-direction: row; width: 100%; justify-content: space-between; margin-top: 10px; padding-top: 10px; border-top: 1px dashed var(--md-border); }
             }
             }
             .md-native-render { display: none; }
             .md-native-render { display: none; }
Baris 272: Baris 170:
         $('<style>').text(css).appendTo('head');
         $('<style>').text(css).appendTo('head');


         // 7. PARSER & PENYIMPANAN DATA
         // --- HELPER FUNCTIONS ---
         function loadData() {
         function showToast(msg) {
             return api.get({
             var $t = $('<div class="md-toast">' + msg + '</div>').appendTo('body');
                action: 'query', prop: 'revisions', titles: pageName, rvprop: 'content', rvslots: 'main', formatversion: 2
            setTimeout(() => { $t.fadeOut(300, function(){ $(this).remove(); }); }, 3000);
            }).then(function(data) {
                var content = data.query.pages[0].revisions[0].slots.main.content;
                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) { console.error("JSON Error", e); }
                }
                return content;  
            });
         }
         }


         function buildWikitextVal(item) {
        // --- SISTEM POP-UP MODAL UTAMA ---
             var val = item.val;
         function openModal(title, contentHtml, footerHtml, onOpen) {
             if (item.linkTarget && item.linkTarget.trim() !== '') { return "[[" + item.linkTarget.trim() + "|" + val + "]]"; }
             var $overlay = $('<div class="md-overlay"></div>');
             if (item.linkSplit) {
             var $modal = $('<div class="md-modal"></div>');
                 return val.replace(/([a-zA-Z0-9_À-ÿ\- ]+)/g, function(match) {
           
                    var trimmed = match.trim();
            var $header = $('<div class="md-modal-header"><h3 class="md-modal-title">' + title + '</h3><button class="md-modal-close">' + svgs.close + '</button></div>');
                    if (trimmed.length > 2 && trimmed.toLowerCase() !== 'dan' && trimmed.toLowerCase() !== 'atau') { return "[[" + trimmed + "]]"; }
            var $body = $('<div class="md-modal-body">' + contentHtml + '</div>');
                    return match;
            var $footer = $('<div class="md-modal-footer">' + footerHtml + '</div>');
                });
           
            }
            $modal.append($header).append($body).append($footer);
             if (item.link) { return "[[" + val + "]]"; }
             $overlay.append($modal).appendTo('body');
            return val;
 
            var closeFunc = function() {
                 $modal.css('transform', 'translateY(20px)').css('opacity', '0');
                $overlay.fadeOut(200, function() { $(this).remove(); });
            };
 
            $header.find('.md-modal-close').on('click', closeFunc);
            $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);
         }
         }


         function buildWikitextRef(refObj) {
        // --- 3. NOTIFIKASI GEMBOK (UNTUK BUKAN PENGURUS) ---
             if (!refObj) return "";
         function showLockNotice() {
            var title = refObj.title || "Rujukan";
             var content = `
            var text = refObj.url ? "[" + ensureHttps(refObj.url) + " " + title + "]" : "'''" + title + "'''";
                <div style="text-align:center; padding: 20px 0;">
            var details = [];
                    <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;">
            if (refObj.author) details.push("Penulis: " + refObj.author);
                        <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>
            if (refObj.site) details.push("Situs: " + refObj.site);
                    </div>
            if (refObj.publisher) details.push("Penerbit: " + refObj.publisher);
                    <h2 style="margin:0 0 10px; font-weight:800; font-size:1.4rem;">Halaman Dilindungi</h2>
            if (refObj.date) details.push("Tanggal Akses: " + formatIndonesianDate(refObj.date));
                    <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>
            if (refObj.type) details.push("Jenis: " + refObj.type + (refObj.subType ? " (" + refObj.subType + ")" : ""));
                    <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.
             if (details.length > 0) text += " &mdash; <small>" + details.join(" &bull; ") + "</small>";
                    </div>
             return text;
                </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);
             });
         }
         }


         function saveData(actionType, $btnEl, originalContent) {
        // --- 1. REFERENSI POP-UP DETAIL ---
             if ($btnEl) $btnEl.addClass('is-loading').prop('disabled', true);
         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';
              
              
             // Auto-Save ke localstorage sebelum kirim API untuk cadangan
             var content = `
            localStorage.setItem('md_backup_' + pageName, JSON.stringify(dataItems));
                <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>


            var jsonStr = JSON.stringify({ locked: isLocked, items: dataItems });
                    <div style="margin-top:15px; padding:12px; background:#f1f5f9; border-radius:8px; font-family:monospace; font-size:0.8rem; color:#475569;">
            var wt = "<!-- MIPPEDIA_DATA_START | " + jsonStr + " -->\n";
                        <b>Format Sitasi APA:</b><br>
            wt += "<div class=\"md-native-render\">\n{| class=\"wikitable\"\n! Data !! Nilai !! Referensi\n";
                        ${refObj.author ? refObj.author + '.' : 'Anonim.'} (${new Date().getFullYear()}). <i>${title}</i>. ${refObj.site || ''}. Diakses pada ${dateStr}.
                    </div>
                </div>
            `;
              
              
             dataItems.forEach(function(item) {
             var footer = '';
                 var valTxt = buildWikitextVal(item);
            if (refObj.url) footer += `<a href="${safeUrl}" target="_blank" class="md-btn md-btn-primary" style="text-decoration:none;">Kunjungi Website ${svgs.external}</a>`;
                 var refTxt = buildWikitextRef(item.ref);
            footer += `<button class="md-btn md-close-btn">Tutup</button>`;
                 wt += "|-\n| " + item.prop + " || " + valTxt + " || " + refTxt + "\n";
 
            openModal(svgs.ref + ' Detail Rujukan', content, footer, function($b, $f, close) {
                 $f.find('.md-close-btn').on('click', close);
            });
        }
 
        // --- CORE LOAD & SAVE ---
        function loadData() {
            return api.get({ 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 match = content.match(/<!-- MIPPEDIA_DATA_START \| (.*?) -->/);
                if (match) { try { var parsed = JSON.parse(match[1]); dataItems = parsed.items || []; isLocked = parsed.locked || false; } catch(e) {} }
                return content;  
             });
             });
        }
        function saveData(actionType, rawContent, $btn) {
            if($btn) { $btn.prop('disabled', true).html('Menyimpan...⏳'); }
           
            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";
            dataItems.forEach(function(item) { wt += "|-\n| " + item.prop + " || " + item.val + "\n"; });
             wt += "|}\n</div>\n<!-- MIPPEDIA_DATA_END -->";
             wt += "|}\n</div>\n<!-- MIPPEDIA_DATA_END -->";


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


             api.postWithToken('csrf', {
             api.postWithToken('csrf', { action: 'edit', title: pageName, text: newContent, summary: 'Mippedia V8: ' + actionType })
                action: 'edit', title: pageName, text: newContent, summary: 'Mippedia Data V8: ' + actionType, minor: false
             .done(function() { window.location.href = location.pathname + "?refresh=" + new Date().getTime(); })
             }).done(function() {
             .fail(function() { showToast("Gagal menyimpan data!"); if($btn) $btn.prop('disabled', false); });
                localStorage.removeItem('md_backup_' + pageName); // Hapus backup jika sukses
                showToast("Berhasil menyimpan!", "success");
                setTimeout(function() {
                    var nocacheUrl = location.pathname + "?refresh=" + new Date().getTime();
                    window.location.href = nocacheUrl;
                }, 800);
             }).fail(function(err) {
                if ($btnEl) $btnEl.removeClass('is-loading').prop('disabled', false);
                showToast("Gagal menyimpan! Error: " + err, "error");
            });
         }
         }


         // 8. BUILDER UI UTAMA
         // --- 2 & 4. FORMULIR MODAL DENGAN PANDUAN ---
         function buildUI(rawContent) {
         function showFormModal(index, rawContent) {
             var $app = $('<div id="mippedia-data-app"></div>');
             var isNew = index === -1;
           
             var item = isNew ? { prop:'', val:'', ref:{} } : dataItems[index];
            // HEADER
             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>');
           
            // Tombol Dark Mode
             var $themeBtn = $('<button class="md-btn-icon" title="Toggle Dark Mode">' + svgMoon + '</button>');
            $themeBtn.on('click', function() { $('#mippedia-data-app').toggleClass('md-dark-mode'); });
            $actions.append($themeBtn);


             // Tombol JSON
             // 4. TEKS BANTUAN INTERAKTIF
             var $jsonBtn = $('<button class="md-btn-icon" title="Ekspor/Impor JSON">' + svgCode + ' JSON</button>');
             var helpUI = `
            $jsonBtn.on('click', function() { showJsonModal(rawContent); });
                <div class="md-help-box">
             $actions.append($jsonBtn);
                    <strong>Panduan Memasukkan Data:</strong>
                    <ul style="margin:5px 0 0; padding-left:20px;">
                        <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>
                        <li><b>Referensi (Opsional):</b> Jika ada sumber, klik tab referensi di bawah untuk mengisi.</li>
                    </ul>
                </div>
             `;


             if (isSysop) {
             var formHtml = `
                 var $lockBtn = $('<button class="md-btn-icon ' + (isLocked ? 'md-btn-lock' : '') + '">' + (isLocked ? svgUnlock + ' Kunci Terbuka' : svgLock + ' Kunci') + ' <span class="md-spinner"></span></button>');
                 ${isNew ? helpUI : ''}
                 $lockBtn.on('click', function() {
                <div class="md-form-group">
                     isLocked = !isLocked;
                    <label>Label Data <span style="color:red">*</span></label>
                     saveData(isLocked ? 'Mengunci data' : 'Membuka kunci data', $(this), rawContent);
                    <input type="text" id="md-inp-prop" class="md-input" value="${item.prop}" placeholder="Cth: Tempat Lahir" autocomplete="off">
                });
                </div>
                 $actions.append($lockBtn);
                <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>
             `;


             if (!isLocked || isSysop) {
             var footerHtml = `
                 var $addBtn = $('<button class="md-btn-icon" title="Tambah Data Baru">' + svgEdit + ' Tambah</button>');
                 ${!isNew ? `<button class="md-btn md-btn-danger" id="md-btn-delete" style="margin-right:auto;">Hapus</button>` : ''}
                 $addBtn.on('click', function() { showForm(-1, rawContent); });
                 <button class="md-btn md-close-btn">Batal</button>
                 $actions.append($addBtn);
                 <button class="md-btn md-btn-primary" id="md-btn-save">${svgs.edit} Terbitkan</button>
             }
             `;


             $header.append($titleContainer).append($actions);
             openModal(isNew ? 'Tambah Data Baru' : 'Edit Data', formHtml, footerHtml, function($b, $f, closeFunc) {
            $app.append($header);
                // Auto Capitalize Label
                $b.find('#md-inp-prop').on('input', function() {
                    let val = $(this).val();
                    $(this).val(val.replace(/\b\w/g, l => l.toUpperCase()));
                });


            // SEARCH BAR
                // Auto Fix URL
            if (dataItems.length > 2) {
                 $b.find('#md-ref-url').on('blur', 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 u = $(this).val().trim();
                var searchTimeout;
                     if(u && !/^https?:\/\//i.test(u)) $(this).val('https://' + u);
                $searchBox.find('input').on('input', function() {
                     var q = $(this).val().toLowerCase();
                     clearTimeout(searchTimeout);
                    searchTimeout = setTimeout(function() {
                        $app.find('.md-row-display').each(function() {
                            var text = $(this).text().toLowerCase();
                            $(this).toggle(text.indexOf(q) !== -1);
                        });
                    }, 200); // Debounce
                 });
                 });
                $app.append($searchBox);
            }


            // DAFTAR BARIS DATA
                $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:var(--md-text-muted); text-align:center; padding: 25px 10px; background:var(--md-bg-hover); border-radius:10px; border:1px dashed var(--md-border); 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">' + item.prop + '</span>');
                      
                      
                     // RENDER NILAI DATA
                     // 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;
                         var domain = extractDomain(rawVal);
                        displayValHtml = '<a href="' + rawVal + '" target="_blank" style="color:var(--md-primary); font-weight:700; text-decoration:none;">' + domain + '</a>';
                    } else if (item.linkTarget && item.linkTarget.trim() !== '') {
                        displayValHtml = '<a href="' + mw.util.getUrl(item.linkTarget.trim()) + '" style="color:var(--md-primary); font-weight:700; text-decoration:none;">' + 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:var(--md-primary); font-weight:700; text-decoration:none;">' + trimmed + '</a>';
                            }
                            return p;
                        }).join('');
                    } else if (item.link) {
                        displayValHtml = '<a href="' + mw.util.getUrl(rawVal) + '" style="color:var(--md-primary); font-weight:700; text-decoration:none;">' + rawVal + '</a>';
                    } else {
                         displayValHtml = rawVal;
                     }
                     }


                     var $valWrap = $('<div class="md-data-value-wrap"></div>');
                     var refObj = {
                    $valWrap.append('<span class="md-data-value">' + displayValHtml + '</span>');
                        url: $b.find('#md-ref-url').val().trim(),
                   
                        title: $b.find('#md-ref-title').val().trim(),
                    var $copyBtn = $('<button class="md-btn-copy" title="Salin teks">' + svgCopy + '</button>');
                        site: $b.find('#md-ref-site').val().trim(),
                    $copyBtn.on('click', function() {
                        author: $b.find('#md-ref-author').val().trim(),
                         navigator.clipboard.writeText(rawVal);
                         date: $b.find('#md-ref-date').val()
                        showToast("Disalin: " + rawVal, "success");
                     };
                     });
                     Object.keys(refObj).forEach(k => { if(!refObj[k]) delete refObj[k]; });
                     $valWrap.append($copyBtn);
                    $info.append($valWrap);


                     // RENDER MEDIA SOSIAL & MUSIK
                     var newItem = { prop: p, val: v, ref: Object.keys(refObj).length ? refObj : null };
                    if (item.isPersonOrg && item.socials) {
                        var $socialGroup = $('<div class="md-social-group"></div>');
                        var hasSocial = false;
                        Object.keys(SOCIAL_PLATFORMS).forEach(function(key) {
                            var uname = item.socials[key];
                            if (uname) {
                                hasSocial = true;
                                var platform = SOCIAL_PLATFORMS[key];
                                var fullUrl = platform.base + uname.replace(/^@/, '');
                                var $badge = $('<a class="md-social-badge" href="' + fullUrl + '" target="_blank" style="background:' + platform.color + ';">' + platform.icon + ' ' + platform.name + '</a>');
                                $socialGroup.append($badge);
                            }
                        });
                        if (hasSocial) $info.append($socialGroup);
                    }
                      
                      
                     // RENDER REFERENSI EKSPLISIT COLLAPSIBLE (V8.0)
                     if(isNew) dataItems.push(newItem); else dataItems[index] = newItem;
                    if (item.ref && (item.ref.url || item.ref.title)) {
                    saveData(isNew ? 'Tambah data' : 'Edit data', rawContent, $(this));
                        var ref = item.ref;
                });
                        var $refContainer = $('<div class="md-ref-wrapper"></div>');
                       
                        var typeLabel = ref.type ? ref.type : "Sumber Rujukan";
                        var $refToggle = $('<button class="md-ref-toggle" title="Klik untuk lihat detail referensi">' + svgRef + ' Lihat Referensi (' + typeLabel + ')</button>');
                        var $refCard = $('<div class="md-ref-card"></div>');


                        var refTitle = ref.title || "Referensi Terpaut";
                $f.find('#md-btn-delete').on('click', function() {
                        var headerContent = refTitle;
                    if(confirm("Yakin ingin menghapus data ini secara permanen?")) {
                        if (ref.site && isVerifiedSite(ref.site)) { headerContent += " " + svgVerified; }
                         dataItems.splice(index, 1);
                       
                         saveData('Hapus data', rawContent, $(this));
                        $refCard.append('<div class="md-ref-header">' + headerContent + '</div>');
 
                        var $detailsGrid = $('<div class="md-ref-details-grid"></div>');
                        if (ref.author) { $detailsGrid.append('<div class="md-ref-detail-row"><span class="md-ref-lbl">Penulis:</span><span class="md-ref-val">' + ref.author + '</span></div>'); }
                        if (ref.site) { $detailsGrid.append('<div class="md-ref-detail-row"><span class="md-ref-lbl">Situs:</span><span class="md-ref-val">' + ref.site + '</span></div>'); }
                        if (ref.publisher) { $detailsGrid.append('<div class="md-ref-detail-row"><span class="md-ref-lbl">Penerbit:</span><span class="md-ref-val">' + ref.publisher + '</span></div>'); }
                        if (ref.date) { $detailsGrid.append('<div class="md-ref-detail-row"><span class="md-ref-lbl">Diakses pada:</span><span class="md-ref-val">' + formatIndonesianDate(ref.date) + '</span></div>'); }
                         $refCard.append($detailsGrid);
 
                        var $refActions = $('<div class="md-ref-actions"></div>');
                         if (ref.subType) { $refActions.append('<span class="md-ref-badge">' + ref.subType + '</span>'); }
                       
                        if (ref.url) {
                            var safeUrl = ensureHttps(ref.url);
                            $refActions.append('<a href="' + safeUrl + '" target="_blank" class="md-ref-visit-btn">' + svgLinkExt + ' Kunjungi Situs</a>');
                        }
                       
                        $refCard.append($refActions);
                       
                        // Toggle Logic
                        $refToggle.on('click', function() {
                            $refCard.slideToggle(200);
                            $(this).toggleClass('active');
                            if ($(this).hasClass('active')) {
                                $(this).html(svgRef + ' Tutup Referensi');
                            } else {
                                $(this).html(svgRef + ' Lihat Referensi (' + typeLabel + ')');
                            }
                        });
 
                        $refContainer.append($refToggle).append($refCard);
                        $info.append($refContainer);
                     }
                     }
                   
                    $row.append($info);
                    if (!isLocked || isSysop) {
                        var $toolsBox = $('<div class="md-row-tools"></div>');
                       
                        var $btnEdit = $('<button class="md-btn-icon edit-btn" style="padding:6px 10px;" title="Edit data">' + svgEdit + ' Edit</button>');
                        $btnEdit.on('click', function() { showForm(index, rawContent); });
                        $toolsBox.append($btnEdit);
                        var $upDownGroup = $('<div class="md-row-tools-group"></div>');
                       
                        var $btnUp = $('<button class="md-btn-icon" style="padding:6px; margin-right:4px;" title="Pindah ke Atas" ' + (index === 0 ? 'disabled' : '') + '>' + svgUp + '</button>');
                        $btnUp.on('click', function() {
                            if (index > 0) {
                                var temp = dataItems[index]; dataItems[index] = dataItems[index - 1]; dataItems[index - 1] = temp;
                                saveData('Reorder data (Up)', $(this), rawContent);
                            }
                        });
                        var $btnDown = $('<button class="md-btn-icon" style="padding:6px;" title="Pindah ke Bawah" ' + (index === dataItems.length - 1 ? 'disabled' : '') + '>' + svgDown + '</button>');
                        $btnDown.on('click', function() {
                            if (index < dataItems.length - 1) {
                                var temp = dataItems[index]; dataItems[index] = dataItems[index + 1]; dataItems[index + 1] = temp;
                                saveData('Reorder data (Down)', $(this), rawContent);
                            }
                        });
                       
                        var $btnDuplicate = $('<button class="md-btn-icon" style="padding:6px; margin-left:4px;" title="Duplikat baris ini">' + svgDuplicate + '</button>');
                        $btnDuplicate.on('click', function() {
                            var cloned = JSON.parse(JSON.stringify(dataItems[index]));
                            dataItems.splice(index + 1, 0, cloned);
                            saveData('Duplikat data', $(this), rawContent);
                        });
                        $upDownGroup.append($btnUp).append($btnDown).append($btnDuplicate);
                        $toolsBox.append($upDownGroup);
                       
                        $row.append($toolsBox);
                    }
                    $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);
         }
         }


         // 9. FORM EDIT DENGAN PRESET & PLATFORM LENGKAP
         // --- MAIN UI BUILDER ---
         function showForm(index, rawContent) {
         function buildUI(rawContent) {
             var $container = $('#md-form-container');
             var $app = $('<div id="mippedia-data-app"></div>');
            $container.empty();
 
            var isNew = index === -1;
            var currentData = isNew ? { prop: '', val: '', link: false, linkTarget: '', linkSplit: false, ref: {}, isPersonOrg: false, socials: {} } : dataItems[index];
            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>');
              
              
             // Label Data + Preset Fast Selector
             // Header & Statistik
             var $propGroup = $('<div class="md-form-group"><label>Label Data (Cth: Pekerjaan, Sutradara)</label><input type="text" id="md-inp-prop" class="md-input" value="' + (currentData.prop || '') + '"></div>');
             var $header = $('<div class="md-header"></div>');
             var $presetWrap = $('<div class="md-preset-wrapper"></div>');
             $header.append(`<div class="md-title">${svgs.edit} Struktur Data <span class="md-stats">${dataItems.length} Item</span></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);
              
              
            // Nilai Data & Wikilink Options
             var $actions = $('<div style="display:flex; gap:8px;"></div>');
             var $valBox = $('<div class="md-form-group"></div>');
            $valBox.append('<label>Nilai Data</label><input type="text" id="md-inp-val" class="md-input" value="' + (currentData.val || '') + '">');
              
              
             // Auto Capitalize for certain inputs
             // Logika Gembok
             $('#md-inp-prop').on('blur', function() {
             if(isSysop) {
                var val = $(this).val();
                var lockTxt = isLocked ? svgs.unlock + ' Buka Kunci' : svgs.lock + ' Kunci';
                 $(this).val(val.charAt(0).toUpperCase() + val.slice(1));
                var $btnLock = $(`<button class="md-btn ${isLocked ? 'md-btn-danger' : ''}">${lockTxt}</button>`);
             });
                $btnLock.on('click', function() {
                    isLocked = !isLocked;
                    saveData(isLocked ? 'Mengunci' : 'Membuka Kunci', rawContent, $(this));
                });
                $actions.append($btnLock);
            } else if (isLocked) {
                 var $btnLockedView = $(`<button class="md-btn md-btn-danger">${svgs.lock} Dilindungi</button>`);
                $btnLockedView.on('click', showLockNotice);
                $actions.append($btnLockedView);
             }


             var $wikilinkOpts = $('<div style="margin-top:8px; display:flex; flex-direction:column; gap:8px; background:var(--md-bg-hover); padding:10px; border-radius:8px; border:1px solid var(--md-border);"></div>');
             if(!isLocked || isSysop) {
           
                var $btnAdd = $(`<button class="md-btn md-btn-primary">${svgs.edit} Tambah</button>`);
            var chkLink = currentData.link ? 'checked' : '';
                $btnAdd.on('click', function() { showFormModal(-1, rawContent); });
            var chkSplit = currentData.linkSplit ? 'checked' : '';
                $actions.append($btnAdd);
           
               
            $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-link" ' + chkLink + '> Jadikan Wikilink Standar</label>');
                // FAB untuk Mobile
            $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 (Koma/Dan)</label>');
                if(window.innerWidth < 768) {
           
                    var $fab = $(`<button class="md-btn-fab">${svgs.edit}</button>`);
            var $pipedGroup = $('<div style="margin-top:4px;"><label style="font-size:0.78rem; color:var(--md-text-muted);">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 Mippedia" value="' + (currentData.linkTarget || '') + '"></div>');
                    $fab.on('click', function() { showFormModal(-1, rawContent); });
            $wikilinkOpts.append($pipedGroup);
                    $('body').append($fab);
           
            $valBox.append($wikilinkOpts);
            $form.append($valBox);
 
            // MEDIA SOSIAL & MUSIK LENGKAP
            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:rgba(79, 70, 229, 0.1); padding:10px; border-radius:8px; font-weight:700; color:var(--md-primary); font-size:0.85rem;"><input type="checkbox" id="md-chk-person" ' + chkPerson + '> Aktifkan Kolom Media Sosial / Musik</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:var(--md-text); font-weight:700;">' + p.name + '</label><input type="text" id="md-soc-' + key + '" class="md-input" placeholder="Username / ID" value="' + valUname + '"></div>');
            });
            $socialSec.append($socialGrid);
            $form.append($socialSec);
 
            // GRID DETAIL RUJUKAN LENGKAP
            var $refArea = $('<div class="md-form-group" style="margin-top:20px;"></div>');
            $refArea.append('<label style="font-size:0.95rem; font-weight:800; color:var(--md-text);">Sumber Referensi Cerdas</label>');
           
            var $refGrid = $('<div class="md-ref-grid"></div>');
           
            var $typeSel = $('<select id="md-ref-type" class="md-select"><option value="">-- Pilih Tipe --</option></select>');
            Object.keys(REF_TYPES).forEach(function(t) {
                var sel = currentRef.type === t ? 'selected' : '';
                $typeSel.append('<option value="' + t + '" ' + sel + '>' + t + '</option>');
            });
 
            var $subTypeSel = $('<select id="md-ref-subtype" class="md-select"><option value="">-- Sub-Tipe --</option></select>');
           
            function updateSubTypes(mainType, selectedSub) {
                $subTypeSel.empty().append('<option value="">-- Sub-Tipe --</option>');
                if (mainType && REF_TYPES[mainType]) {
                    REF_TYPES[mainType].forEach(function(st) {
                        var sel = selectedSub === st ? 'selected' : '';
                        $subTypeSel.append('<option value="' + st + '" ' + sel + '>' + st + '</option>');
                    });
                 }
                 }
             }
             }


             $typeSel.on('change', function() { updateSubTypes($(this).val(), ''); });
             $header.append($actions);
             updateSubTypes(currentRef.type, currentRef.subType);
             $app.append($header);


             $refGrid.append('<div><label style="font-size:0.78rem;">Tipe Utama</label></div>').find('div').last().append($typeSel);
             // Render List Data
            $refGrid.append('<div><label style="font-size:0.78rem;">Kategori Spesifik</label></div>').find('div').last().append($subTypeSel);
            var $list = $('<div></div>');
 
            if(dataItems.length === 0) {
            var $urlInput = $('<input type="text" id="md-ref-url" class="md-input" placeholder="https://..." value="' + (currentRef.url || '') + '">');
                $list.append('<div style="text-align:center; padding:30px; color:var(--md-text-muted);">Belum ada data tersedia.</div>');
            $urlInput.on('blur', function() {
            } else {
                var u = $(this).val().trim();
                dataItems.forEach(function(item, idx) {
                if(u) {
                    var $row = $('<div class="md-row-display"></div>');
                     var safe = ensureHttps(u);
                    var $info = $('<div></div>');
                     $(this).val(safe);
                      
                    var $siteInp = $('#md-ref-site');
                     $info.append(`<div class="md-data-label">${item.prop}</div>`);
                     if (!$siteInp.val().trim()) { $siteInp.val(extractDomain(safe)); }
                     $info.append(`<div class="md-data-value">${item.val}</div>`);
                      
                      
                     // Validasi regex dasar
                     // 1. TAMPILAN REFERENSI BARU (TOMBOL BADGE -> POP-UP)
                     if(!/^https?:\/\/[^\s$.?#].[^\s]*$/.test(safe)) { $(this).addClass('error'); showToast('URL sepertinya tidak valid', 'error'); }
                     if(item.ref && (item.ref.url || item.ref.title)) {
                    else { $(this).removeClass('error'); }
                        var $refBtn = $(`<button class="md-ref-trigger">${svgs.ref} Referensi [${idx+1}]</button>`);
                } else { $(this).removeClass('error'); }
                        $refBtn.on('click', function() { showRefDetails(item.ref); });
            });
                        $info.append($refBtn);
                    }


            $refGrid.append('<div class="md-grid-full"><label style="font-size:0.78rem;">URL Rujukan Penuh</label></div>').find('div').last().append($urlInput);
                    $row.append($info);
            $refGrid.append('<div><label style="font-size:0.78rem;">Judul Konten/Artikel</label><input type="text" id="md-ref-title" class="md-input" placeholder="Judul..." value="' + (currentRef.title || '') + '"></div>');
            $refGrid.append('<div><label style="font-size:0.78rem;">Nama Situs</label><input type="text" id="md-ref-site" class="md-input" placeholder="Cth: Kompas.com" value="' + (currentRef.site || '') + '"></div>');
            $refGrid.append('<div><label style="font-size:0.78rem;">Penulis/Kreator</label><input type="text" id="md-ref-author" class="md-input" placeholder="Nama..." value="' + (currentRef.author || '') + '"></div>');
            $refGrid.append('<div><label style="font-size:0.78rem;">Penerbit / Agensi</label><input type="text" id="md-ref-publisher" class="md-input" placeholder="Cth: Gramedia" value="' + (currentRef.publisher || '') + '"></div>');
           
            // Tanggal Akses + Hari Ini
            var $dateBox = $('<div><label style="font-size:0.78rem;">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="' + (currentRef.date || '') + '">');
            var $todayBtn = $('<button type="button" class="md-btn-icon" style="padding:4px 8px; font-size:0.75rem;" title="Set Hari Ini">Set Hari Ini</button>');
            $todayBtn.on('click', function() { $dateInp.val(getTodayString()); });
            $dateInpWrap.append($dateInp).append($todayBtn);
            $dateBox.append($dateInpWrap);
            $refGrid.append($dateBox);


            $refArea.append($refGrid);
                    if(!isLocked || isSysop) {
            $form.append($refArea);
                        var $editBtn = $(`<button class="md-btn" style="height:fit-content;">Edit</button>`);
 
                        $editBtn.on('click', function() { showFormModal(idx, rawContent); });
            // TOMBOL AKSI FORM
                         $row.append($editBtn);
            var $actions = $('<div class="md-form-actions"></div>');
            var $btnSave = $('<button class="md-btn md-btn-save">Simpan Data<span class="md-spinner"></span></button>');
            var $btnCancel = $('<button class="md-btn md-btn-cancel">Batal</button>');
           
            $actions.append($btnSave).append($btnCancel);
           
            if (!isNew) {
                var $btnDelete = $('<button class="md-btn md-btn-delete">Hapus Baris Ini<span class="md-spinner"></span></button>');
                $btnDelete.on('click', function() {
                    if(confirm('Hapus permanen data ini?')) {
                         dataItems.splice(index, 1);
                        saveData('Menghapus data', $(this), rawContent);
                     }
                     }
                    $list.append($row);
                 });
                 });
                $actions.append($btnDelete);
             }
             }
            $form.append($actions);
            $container.append($form);
            $('#md-chk-person').on('change', function() {
                if($(this).is(':checked')) $('#md-social-box').slideDown(200).css('display', 'grid');
                else $('#md-social-box').slideUp(200);
            });
            $('html, body').animate({ scrollTop: $form.offset().top - 80 }, 300);
            $btnCancel.on('click', function() { $container.empty(); });
            $btnSave.on('click', function() {
                var newProp = $('#md-inp-prop').val().trim();
                var newVal = $('#md-inp-val').val().trim();
                if (!newProp || !newVal) {
                    showToast("Harap isi Label dan Nilai!", "error"); return;
                }
                // Cek Duplikat Label (Hanya Peringatan, tidak di-block)
                if(isNew && dataItems.some(function(item) { return item.prop.toLowerCase() === newProp.toLowerCase(); })) {
                    if(!confirm('Label "' + newProp + '" sudah ada. Lanjutkan menyimpan?')) 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);
            });
        }
        // 10. JSON EXPORT & IMPORT MODAL
        function showJsonModal(rawContent) {
            var $container = $('#md-form-container');
            $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 (Tingkat Lanjut)</h4>');
            $box.append('<p style="font-size:0.82rem; color:var(--md-text-muted); margin-bottom:10px;">Salin JSON di bawah untuk cadangan, atau timpa teks untuk melakukan Impor Massal.</p>');
              
              
             var $txt = $('<textarea class="md-textarea" rows="12" style="font-family:monospace; font-size:0.8rem;"></textarea>').val(jsonStr);
             $app.append($list);
            $box.append($txt);
           
 
             var $infobox = $('.infobox').first();
             var $actions = $('<div class="md-form-actions"></div>');
             $('.md-native-render').hide();
            var $btnImport = $('<button class="md-btn md-btn-save">Simpan Perubahan JSON <span class="md-spinner"></span></button>');
             if($infobox.length) $app.insertAfter($infobox);
             var $btnCancel = $('<button class="md-btn md-btn-cancel">Tutup</button>');
             else $('#mw-content-text .mw-parser-output').append($app);
 
            $actions.append($btnImport).append($btnCancel);
             $box.append($actions);
            $container.append($box);
 
             $('html, body').animate({ scrollTop: $box.offset().top - 80 }, 300);
 
            $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);
                    } else {
                        showToast("JSON harus berupa Array List!", "error");
                    }
                } catch(e) {
                    showToast("Format JSON Salah! Error: " + e.message, "error");
                }
            });
         }
         }


         // 11. EXECUTE
         // --- EXECUTE ---
         loadData().then(function(rawContent) { buildUI(rawContent); });
         loadData().then(function(rawContent) { buildUI(rawContent); });
     });
     });

Revisi per 18 Agustus 2026 01.27

/**
 * ====================================================================
 * MIPPEDIA DATA - ADVANCED STRUCTURED DATA SYSTEM (V8.0 EVOLUTION)
 * Fitur: Full Modal UI, Smart References, Floating Guides, Dark Mode, 
 * Toast Notifications, Advanced Validations, Mobile FAB, etc.
 * ====================================================================
 */
(function($, mw) {
    'use strict';

    if (mw.config.get('wgNamespaceNumber') !== 0 || mw.config.get('wgIsMainPage')) return;
    if (mw.config.get('wgAction') !== 'view') return;

    mw.loader.using(['mediawiki.api', 'mediawiki.util']).then(function() {
        
        var pageName = mw.config.get('wgPageName');
        var isSysop = mw.config.get('wgUserGroups').indexOf('sysop') !== -1;
        var dataItems = [];
        var isLocked = false;
        var api = new mw.Api();

        // --- MASTER DATA PLATFORM ---
        var SOCIAL_PLATFORMS = {
            applemusic: { name: 'Apple Music', base: 'https://music.apple.com/artist/', color: '#fc3c44' },
            spotify: { name: 'Spotify', base: 'https://open.spotify.com/artist/', color: '#1db954' },
            soundcloud: { name: 'SoundCloud', base: 'https://soundcloud.com/', color: '#ff5500' },
            instagram: { name: 'Instagram', base: 'https://instagram.com/', color: '#e1306c' },
            tiktok: { name: 'TikTok', base: 'https://www.tiktok.com/@', color: '#000000' },
            youtube: { name: 'YouTube', base: 'https://youtube.com/@', color: '#ff0000' },
            twitter: { name: 'X / Twitter', base: 'https://x.com/', color: '#0f1419' }
        };

        var PRESET_LABELS = [
            "Nama Lahir", "Tanggal Lahir", "Tempat Lahir", "Pekerjaan", 
            "Kebangsaan", "Genre", "Instrumen", "Label Rekaman", 
            "Tahun Aktif", "Situs Web Resmi", "Pasangan", "Orang Tua"
        ];

        var REF_TYPES = {
            "Berita": ["Berita Online", "Berita Cetak", "Wawancara"],
            "Website": ["Situs Resmi", "Portal Informasi", "Database Web"],
            "Buku": ["Buku Cetak", "E-Book", "Jurnal Ilmiah"],
            "Media": ["Video YouTube", "Podcast", "Media Sosial"]
        };

        // --- IKON SVG ---
        var svgs = {
            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>',
            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>',
            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>',
            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>',
            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>',
            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>'
        };

        // --- STYLESHEET V8.0 (Modern UI & Animations) ---
        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 {
                background: var(--md-bg); border-radius: 16px; box-shadow: 0 10px 30px rgba(0,0,0,0.08);
                padding: 24px; margin: 24px 0; font-family: system-ui, -apple-system, sans-serif;
                border: 1px solid var(--md-border); position: relative; color: var(--md-text);
            }
            .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-title { font-size: 1.3rem; font-weight: 800; margin: 0; display: flex; align-items: center; gap: 8px; }
            .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-btn {
                background: var(--md-surface); border: 1px solid var(--md-border); color: var(--md-text);
                padding: 8px 14px; border-radius: 8px; cursor: pointer; font-weight: 600; font-size: 0.85rem;
                display: inline-flex; align-items: center; gap: 6px; transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
            }
            .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-primary { background: linear-gradient(135deg, var(--md-primary), #3b82f6); color: white; border: none; }
            .md-btn-danger { background: #fef2f2; color: var(--md-danger); border-color: #fca5a5; }
            
            .md-row-display {
                display: flex; justify-content: space-between; padding: 14px 16px; margin-bottom: 8px;
                background: var(--md-surface); border-radius: var(--md-radius); border: 1px solid var(--md-border);
                transition: 0.3s;
            }
            .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-data-label { font-size: 0.75rem; text-transform: uppercase; color: var(--md-text-muted); font-weight: 800; letter-spacing: 0.5px; }
            .md-data-value { font-size: 1.1rem; font-weight: 700; display: block; margin-top: 4px; }
            
            /* Referensi Badge */
            .md-ref-trigger {
                background: #e0e7ff; color: var(--md-primary); border: none; padding: 4px 10px;
                border-radius: 20px; font-size: 0.75rem; font-weight: 700; cursor: pointer; margin-top: 8px;
                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-overlay {
                position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; background: rgba(0,0,0,0.5);
                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-group { margin-bottom: 16px; }
            .md-form-group label { display: block; font-weight: 700; font-size: 0.85rem; margin-bottom: 6px; color: var(--md-text); }
            .md-input {
                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: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; }

            /* Toast Notification */
            .md-toast {
                position: fixed; bottom: 30px; right: 30px; background: #10b981; color: white;
                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;
            }

            /* Help Tooltip Box */
            .md-help-box {
                background: linear-gradient(135deg, #1e293b, #0f172a); color: #f8fafc; padding: 16px;
                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; } }
            @keyframes slideUp { to { transform: translateY(0); } }
            @keyframes slideInRight { from { transform: translateX(100px); opacity: 0; } to { transform: translateX(0); opacity: 1; } }
            @keyframes shake { 0%, 100% { transform: translateX(0); } 25% { transform: translateX(-5px); } 75% { transform: translateX(5px); } }

            @media (max-width: 768px) {
                #mippedia-data-app { padding: 16px; }
                .md-overlay { padding: 10px; align-items: flex-end; }
                .md-modal { max-height: 95vh; border-radius: 20px 20px 0 0; animation: slideUpMobile 0.4s forwards; transform: translateY(100%); }
                @keyframes slideUpMobile { to { transform: translateY(0); } }
                .md-btn-fab {
                    position: fixed; bottom: 20px; right: 20px; width: 60px; height: 60px; border-radius: 30px;
                    background: var(--md-primary); color: white; display: flex; justify-content: center; align-items: center;
                    box-shadow: 0 10px 25px rgba(79, 70, 229, 0.4); z-index: 9000; cursor: pointer; border: none;
                }
            }
            .md-native-render { display: none; }
        `;
        $('<style>').text(css).appendTo('head');

        // --- HELPER FUNCTIONS ---
        function showToast(msg) {
            var $t = $('<div class="md-toast">' + msg + '</div>').appendTo('body');
            setTimeout(() => { $t.fadeOut(300, function(){ $(this).remove(); }); }, 3000);
        }

        // --- SISTEM POP-UP MODAL UTAMA ---
        function openModal(title, contentHtml, footerHtml, onOpen) {
            var $overlay = $('<div class="md-overlay"></div>');
            var $modal = $('<div class="md-modal"></div>');
            
            var $header = $('<div class="md-modal-header"><h3 class="md-modal-title">' + title + '</h3><button class="md-modal-close">' + svgs.close + '</button></div>');
            var $body = $('<div class="md-modal-body">' + contentHtml + '</div>');
            var $footer = $('<div class="md-modal-footer">' + footerHtml + '</div>');
            
            $modal.append($header).append($body).append($footer);
            $overlay.append($modal).appendTo('body');

            var closeFunc = function() {
                $modal.css('transform', 'translateY(20px)').css('opacity', '0');
                $overlay.fadeOut(200, function() { $(this).remove(); });
            };

            $header.find('.md-modal-close').on('click', closeFunc);
            $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);
            });
        }

        // --- 1. REFERENSI POP-UP DETAIL ---
        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() {
            return api.get({ 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 match = content.match(/<!-- MIPPEDIA_DATA_START \| (.*?) -->/);
                if (match) { try { var parsed = JSON.parse(match[1]); dataItems = parsed.items || []; isLocked = parsed.locked || false; } catch(e) {} }
                return content; 
            });
        }

        function saveData(actionType, rawContent, $btn) {
            if($btn) { $btn.prop('disabled', true).html('Menyimpan...⏳'); }
            
            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";
            dataItems.forEach(function(item) { wt += "|-\n| " + item.prop + " || " + item.val + "\n"; });
            wt += "|}\n</div>\n<!-- MIPPEDIA_DATA_END -->";

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

            api.postWithToken('csrf', { action: 'edit', title: pageName, text: newContent, summary: 'Mippedia V8: ' + actionType })
            .done(function() { window.location.href = location.pathname + "?refresh=" + new Date().getTime(); })
            .fail(function() { showToast("Gagal menyimpan data!"); if($btn) $btn.prop('disabled', false); });
        }

        // --- 2 & 4. FORMULIR MODAL DENGAN PANDUAN ---
        function showFormModal(index, rawContent) {
            var isNew = index === -1;
            var item = isNew ? { prop:'', val:'', ref:{} } : dataItems[index];
            var r = item.ref || {};

            // 4. TEKS BANTUAN INTERAKTIF
            var helpUI = `
                <div class="md-help-box">
                    <strong>Panduan Memasukkan Data:</strong>
                    <ul style="margin:5px 0 0; padding-left:20px;">
                        <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>
                        <li><b>Referensi (Opsional):</b> Jika ada sumber, klik tab referensi di bawah untuk mengisi.</li>
                    </ul>
                </div>
            `;

            var formHtml = `
                ${isNew ? helpUI : ''}
                <div class="md-form-group">
                    <label>Label Data <span style="color:red">*</span></label>
                    <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 = `
                ${!isNew ? `<button class="md-btn md-btn-danger" id="md-btn-delete" style="margin-right:auto;">Hapus</button>` : ''}
                <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) {
                // Auto Capitalize Label
                $b.find('#md-inp-prop').on('input', function() {
                    let val = $(this).val();
                    $(this).val(val.replace(/\b\w/g, l => l.toUpperCase()));
                });

                // Auto Fix URL
                $b.find('#md-ref-url').on('blur', function() {
                    let u = $(this).val().trim();
                    if(u && !/^https?:\/\//i.test(u)) $(this).val('https://' + u);
                });

                $f.find('.md-close-btn').on('click', closeFunc);
                
                $f.find('#md-btn-save').on('click', function() {
                    var p = $b.find('#md-inp-prop').val().trim();
                    var v = $b.find('#md-inp-val').val().trim();
                    
                    // Validasi Animasi Getar (Shake)
                    if(!p || !v) {
                        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')});
                        return;
                    }

                    var refObj = {
                        url: $b.find('#md-ref-url').val().trim(),
                        title: $b.find('#md-ref-title').val().trim(),
                        site: $b.find('#md-ref-site').val().trim(),
                        author: $b.find('#md-ref-author').val().trim(),
                        date: $b.find('#md-ref-date').val()
                    };
                    Object.keys(refObj).forEach(k => { if(!refObj[k]) delete refObj[k]; });

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

                $f.find('#md-btn-delete').on('click', function() {
                    if(confirm("Yakin ingin menghapus data ini secara permanen?")) {
                        dataItems.splice(index, 1);
                        saveData('Hapus data', rawContent, $(this));
                    }
                });
            });
        }

        // --- MAIN UI BUILDER ---
        function buildUI(rawContent) {
            var $app = $('<div id="mippedia-data-app"></div>');
            
            // Header & Statistik
            var $header = $('<div class="md-header"></div>');
            $header.append(`<div class="md-title">${svgs.edit} Struktur Data <span class="md-stats">${dataItems.length} Item</span></div>`);
            
            var $actions = $('<div style="display:flex; gap:8px;"></div>');
            
            // Logika Gembok
            if(isSysop) {
                var lockTxt = isLocked ? svgs.unlock + ' Buka Kunci' : svgs.lock + ' Kunci';
                var $btnLock = $(`<button class="md-btn ${isLocked ? 'md-btn-danger' : ''}">${lockTxt}</button>`);
                $btnLock.on('click', function() {
                    isLocked = !isLocked;
                    saveData(isLocked ? 'Mengunci' : 'Membuka Kunci', rawContent, $(this));
                });
                $actions.append($btnLock);
            } else if (isLocked) {
                var $btnLockedView = $(`<button class="md-btn md-btn-danger">${svgs.lock} Dilindungi</button>`);
                $btnLockedView.on('click', showLockNotice);
                $actions.append($btnLockedView);
            }

            if(!isLocked || isSysop) {
                var $btnAdd = $(`<button class="md-btn md-btn-primary">${svgs.edit} Tambah</button>`);
                $btnAdd.on('click', function() { showFormModal(-1, rawContent); });
                $actions.append($btnAdd);
                
                // FAB untuk Mobile
                if(window.innerWidth < 768) {
                    var $fab = $(`<button class="md-btn-fab">${svgs.edit}</button>`);
                    $fab.on('click', function() { showFormModal(-1, rawContent); });
                    $('body').append($fab);
                }
            }

            $header.append($actions);
            $app.append($header);

            // Render List Data
            var $list = $('<div></div>');
            if(dataItems.length === 0) {
                $list.append('<div style="text-align:center; padding:30px; color:var(--md-text-muted);">Belum ada data tersedia.</div>');
            } else {
                dataItems.forEach(function(item, idx) {
                    var $row = $('<div class="md-row-display"></div>');
                    var $info = $('<div></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);

                    if(!isLocked || isSysop) {
                        var $editBtn = $(`<button class="md-btn" style="height:fit-content;">Edit</button>`);
                        $editBtn.on('click', function() { showFormModal(idx, rawContent); });
                        $row.append($editBtn);
                    }
                    $list.append($row);
                });
            }
            
            $app.append($list);
            
            var $infobox = $('.infobox').first();
            $('.md-native-render').hide();
            if($infobox.length) $app.insertAfter($infobox);
            else $('#mw-content-text .mw-parser-output').append($app);
        }

        // --- EXECUTE ---
        loadData().then(function(rawContent) { buildUI(rawContent); });
    });

})(jQuery, mediaWiki);

/* ==========================================================
   ⚡ MIPPEDIA SPEED OPTIMIZER - PURE SPEED & STABLE (V1.1)
   Features: Instant Link Pre-fetching Engine (No Animation/Pure Performance).
   Optimization: Zero-flicker, scoped lifecycle protection, advanced anti-cache clutter.
   Target: Built for maximum long-term stability and bulletproof caching.
   ========================================================= */

(function() {
    // Ambil nama host secara dinamis (contoh: data.mippedia.org)
    var currentHost = window.location.hostname;

    // --- 🗲 ENGINE PRE-FETCH CORES ---
    function injectPrefetchLink(url) {
        // Jaring Pengaman 1: Jangan injeksi jika link prefetch untuk URL ini sudah ada di head browser
        if (document.querySelector('link[href="' + url + '"]')) return;

        var prefetcher = document.createElement('link');
        prefetcher.rel = 'prefetch';
        prefetcher.href = url;
        
        // Jaring Pengaman 2: Failsafe anti-eror cache jika network mendadak sibuk
        prefetcher.onerror = function() { prefetcher.remove(); };
        
        document.head.appendChild(prefetcher);
    }

    function initPrefetchDispatch(href) {
        // Memanfaatkan requestIdleCallback agar proses prefetch hanya berjalan saat browser senggang 
        // sehingga tidak akan membuat scrolling halaman terasa berat/patah-patah
        if (window.requestIdleCallback) {
            window.requestIdleCallback(function() { injectPrefetchLink(href); });
        } else {
            setTimeout(function() { injectPrefetchLink(href); }, 20);
        }
    }

    // --- 🎮 COGNITIVE EVENT LISTENERS (UNIVERSAL HOVER & TOUCH) ---
    // Mendengarkan area konten utama MediaWiki (Desktop & Tampilan Mobile HP)
    $(document).on('mouseenter pointerdown', '#mw-content-text a, .mw-body-content a, #bodyContent a, .mw-parser-output a', function() {
        var $link = $(this);
        var href = $link.attr('href');

        // --- 🛡️ FILTER STRATA TINGGI: ABREVIASI LINK BERGUNA (ANTI CRASH CACHE) ---
        // 1. Abaikan link kosong, javascript void, atau buka tab baru (_blank)
        if (!href || href.startsWith('#') || href.startsWith('javascript:') || $link.attr('target') === '_blank') return;
        
        // 2. Abaikan link merah (artikel belum ada), link sunting teks, riwayat versi, dan aksi form MediaWiki
        if ($link.hasClass('new') || href.includes('action=') || href.includes('diff=') || href.includes('oldid=')) return;
        
        // 3. Abaikan link perkakas krusial pengurus / sistem otentikasi (hindari prefetch logout tidak sengaja)
        if (href.includes('Istimewa:') || href.includes('Special:') || href.includes('do=logout')) return;

        // Pastikan hanya mengeksekusi routing internal ekosistem Mippedia
        var isInternal = href.indexOf(currentHost) !== -1 || href.startsWith('/') || !href.includes('://');
        if (isInternal) {
            initPrefetchDispatch(href);
        }
    });
})();

/* ==========================================================
   🧠 MIPPEDIA DATA - SMART CONTEXT + AUTO THUMBNAIL (V10.1)
   Features: Priority Check (ID > EN > CONCISE), Auto-Age, 
             Auto-Bold, Smart Links, Dynamic Context,
             Targeted Isolation (Safe for Forms), Dynamic Noindex,
             Aesthetic Centered Empty State + 🚀 Instant Action Hub (3 Buttons)
   Fixes: Mobile View Visibility & Custom Short URL Route (No /w/)
   ========================================================= */
(function() {
    $(document).ready(function() {
        var $descSection = $('#mip-desc-section'), $descBox = $('#mip-auto-description'),
            $sourceInfo = $('#mip-source-info'), $portalLinks = $('#mip-portal-links'),
            $projectPortal = $('#mip-project-portal'), $mainContent = $('#mw-content-text');
        
        if (!$descBox.length) return;

        var pageTitle = mw.config.get('wgPageName').replace(/_/g, ' '),
            cacheKey = 'mip_smart_context_thumb_' + pageTitle, now = new Date().getTime(),
            currentYear = 2026;

        // --- KONFIGURASI PROYEK ---
        var projects = [
            { id: 'id', name: 'Mippedia bahasa Indonesia', url: 'https://id.mippedia.org/api.php', base: 'https://id.mippedia.org/wiki/', label: 'Mippedia Indonesia' },
            { id: 'en', name: 'Mippedia bahasa Inggris', url: 'https://en.mippedia.org/api.php', base: 'https://en.mippedia.org/wiki/', label: 'Mippedia Inggris' },
            { id: 'concise', name: 'Mippedia bahasa Indonesia ringkas', url: 'https://concise.mippedia.org/api.php', base: 'https://concise.mippedia.org/wiki/', label: 'Mippedia Ringkas' }
        ];

        // --- 🎨 ANIMASI, HOVER EFFECT & RESPONSIVE STYLE ---
        if (!$('#mip-clean-style').length) {
            $('head').append(
                '<style id="mip-clean-style">' +
                    '@keyframes mipFadeInUp {' +
                        'from { opacity: 0; transform: translateY(15px); }' +
                        'to { opacity: 1; transform: translateY(0); }' +
                    '}' +
                    '#mip-empty-state-notice {' +
                        'display: block !important;' + /* Memaksa tampil di seluler/mobile */
                        'animation: mipFadeInUp 0.6s cubic-bezier(0.16, 1, 0.3, 1) forwards;' +
                    '}' +
                    '.mip-btn-container {' +
                        'display: flex;' +
                        'flex-wrap: wrap;' + /* Supaya otomatis turun ke bawah kalau di HP */
                        'justify-content: center;' +
                        'margin-bottom: 30px;' +
                        'padding-top: 5px;' +
                    '}' +
                    '.mip-action-btn {' +
                        'display: inline-flex; align-items: center; justify-content: center;' +
                        'padding: 10px 18px; margin: 6px; font-size: 0.88em; font-weight: 600;' +
                        'color: #6a5acd !important; background: #ffffff; border: 1.5px solid #6a5acd;' +
                        'border-radius: 30px; text-decoration: none !important; cursor: pointer;' +
                        'transition: all 0.25s ease-in-out; box-shadow: 0 2px 5px rgba(106,92,205,0.08);' +
                        'flex-grow: 1; max-width: 220px; min-width: 150px;' + /* Penyesuaian porsi tombol di HP */
                    '}' +
                    '.mip-action-btn:hover {' +
                        'color: #ffffff !important; background: #6a5acd;' +
                        'transform: translateY(-2px); box-shadow: 0 4px 12px rgba(106,92,205,0.2);' +
                    '}' +
                    '.mip-action-btn:active {' +
                        'transform: translateY(0);' +
                    '}' +
                '</style>'
            );
        }

        // --- FUNGSI TOOLS ---
        function applyAutoBold(text) { return text.replace(new RegExp('(' + pageTitle + ')', 'gi'), '<strong>$1</strong>'); }
        function cleanExtract(text) { return text.replace(/\[\d+\]/g, '').replace(/\{\{[^}]+\}\}/g, '').replace(/\(\s*\)/g, '').replace(/\s\s+/g, ' ').trim(); }
        
        function applyDynamicContext(text) {
            var date = new Date();
            var hari = ["Minggu", "Senin", "Selasa", "Rabu", "Kamis", "Jumat", "Sabtu"];
            var bulan = ["Januari", "Februari", "Maret", "April", "Mei", "Juni", "Juli", "Agustus", "September", "Oktober", "November", "Desember"];
            var tglSkrg = hari[date.getDay()] + ", " + date.getDate() + " " + bulan[date.getMonth()] + " " + date.getFullYear();
            return text.replace(/(hari ini|saat ini|sekarang)/gi, '$1 (' + tglSkrg + ')')
                .replace(/(\d{1,2}\s(?:Januari|Februari|Maret|April|Mei|Juni|Juli|Agustus|September|Oktober|November|Desember)\s(\d{4}))/gi, function(m, f, y) { 
                    return f + " <span style='color: #444; font-weight: bold;'>– usia " + (currentYear - parseInt(y)) + " tahun</span>"; 
                })
                .replace(/(sejak|tahun)\s(\d{4})/gi, function(m, k, y) {
                    var gap = currentYear - parseInt(y);
                    if (gap > 0 && gap < 100) return k + " " + y + " <small style='color: #888;'>(" + gap + " thn lalu)</small>";
                    return m;
                });
        }

        function applySummary(text) {
            var limit = 250;
            if (text.length <= limit) return '<span>' + text + '</span>';
            return '<span>' + text.substring(0, limit) + '</span><span class="mip-dots">... </span><span class="mip-more" style="display:none;">' + text.substring(limit) + '</span><span class="mip-read-btn" style="color: #6a5acd; cursor: pointer; font-weight: bold; margin-left: 5px;">Baca selengkapnya</span>';
        }

        // --- SMART LINKS PORTAL ---
        function buildSmartLinks(currentId, validatedEnTitle) {
            $portalLinks.empty();
            var validLinks = [];
            
            var checkRequests = projects.filter(p => p.id !== currentId).map(function(p) {
                var targetTitle = (p.id === 'en' && validatedEnTitle) ? validatedEnTitle : pageTitle;
                if (p.id === 'en' && !validatedEnTitle) return $.Deferred().resolve();

                return $.ajax({ url: p.url, data: { action: 'query', titles: targetTitle, format: 'json', origin: '*' }, dataType: 'json' })
                    .then(function(data) { 
                        if (data.query.pages["-1"] === undefined) { 
                            validLinks.push('<a href="' + p.base + encodeURIComponent(targetTitle) + '" target="_blank" style="color: #6a5acd; text-decoration: underline; font-weight: bold;">' + p.label + '</a>'); 
                        } 
                    });
            });

            $.when.apply($, checkRequests).done(function() {
                if (validLinks.length > 0) { $portalLinks.html(validLinks.join(' <span style="color:#ccc; margin: 0 5px;">•</span> ')); $projectPortal.fadeIn(); }
            });
        }

        // --- 🧠 RENDER EMPTY STATE + INTERACTIVE HUB ---
        function toggleMippediaLayout(isEmpty) {
            var $existingNotice = $('#mip-empty-state-notice');
            var userGroups = mw.config.get('wgUserGroups') || [];
            var isSysop = userGroups.indexOf('sysop') !== -1;

            var $wikiDataElements = $mainContent.children().not('#mip-empty-state-notice, #mip-desc-section, script, style, .printfooter');
            var $editElements = $('#ca-edit, .mw-editsection, .wb-editsection, .mip-edit-trigger, [id*="edit"], [class*="edit-pencil"]');
            var $metaRobots = $('meta[name="robots"]');

            if (isEmpty) {
                if (!$existingNotice.length) {
                    // Perbaikan Jalur URL tanpa sub-folder /w/ langsung menembak Short URL root parameter
                    var createUrlID = 'https://id.mippedia.org/index.php?title=' + encodeURIComponent(pageTitle) + '&action=edit';
                    var createUrlEN = 'https://en.mippedia.org/index.php?title=' + encodeURIComponent(pageTitle) + '&action=edit';
                    var createUrlConcise = 'https://concise.mippedia.org/index.php?title=' + encodeURIComponent(pageTitle) + '&action=edit';

                    var noticeHtml = 
                        '<div id="mip-empty-state-notice" style="text-align: center; max-width: 600px; margin: 40px auto; padding: 10px; font-family: -apple-system, BlinkMacSystemFont, \'Segoe UI\', Roboto, sans-serif;">' +
                            '<!-- Ikon Warning Besar -->' +
                            '<div style="margin-bottom: 22px; display: inline-block;">' +
                                '<svg width="64" height="64" viewBox="0 0 24 24" fill="none" stroke="#d9534f" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round">' +
                                    '<path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"></path>' +
                                    '<line x1="12" y1="9" x2="12" y2="13"></line>' +
                                    '<line x1="12" y1="17" x2="12.01" y2="17"></line>' +
                                '</' + 'svg>' +
                            '</div>' +
                            '<!-- Judul Utama -->' +
                            '<h4 style="color: #2c3e50; margin: 0 0 12px 0; font-size: 1.35em; font-weight: 700; letter-spacing: -0.3px;">Item Data Struktur Tidak Memiliki Sumber Artikel</h4>' +
                            '<!-- Deskripsi Utama -->' +
                            '<p style="color: #555; margin: 0 0 25px 0; font-size: 0.98em; line-height: 1.6;">' +
                                'Item data ini saat ini <strong>tidak memiliki artikel rujukan satu pun</strong> di Mippedia Indonesia, Mippedia Inggris, maupun Mippedia Indonesia Ringkas.' +
                            '</p>' +
                            
                            '<!-- 🚀 INSTANT ACTION HUB (Flexbox-Responsive Mobile & URL No /w/) -->' +
                            '<div class="mip-btn-container">' +
                                '<a href="' + createUrlID + '" target="_blank" class="mip-action-btn">' +
                                    '<span style="margin-right: 6px;"></span>Buat Artikel ID' +
                                '</a>' +
                                '<a href="' + createUrlEN + '" target="_blank" class="mip-action-btn">' +
                                    '<span style="margin-right: 6px;"></span>Buat Artikel EN' +
                                '</a>' +
                                '<a href="' + createUrlConcise + '" target="_blank" class="mip-action-btn">' +
                                    '<span style="margin-right: 6px;"></span>Buat Artikel Ringkas' +
                                '</a>' +
                            '</div>' +

                            '<!-- Catatan Kaki Info Kecil -->' +
                            '<div style="font-size: 0.85em; color: #a0a0a0; line-height: 1.5; font-style: italic; border-top: 1px solid #f0f0f0; padding-top: 15px;">' +
                                'Informasi: Item data yang tidak terikat dengan artikel ensiklopedia apa pun dalam ekosistem Mippedia akan dihapus secara otomatis oleh pengurus dalam waktu dekat.' +
                            '</div>' +
                        '</div>';
                    $mainContent.prepend(noticeHtml);
                }

                $wikiDataElements.hide();
                $descSection.hide();

                if (!isSysop) {
                    $editElements.css({ 'pointer-events': 'none', 'opacity': '0.3', 'cursor': 'not-allowed' }).hide();
                    $(document).on('keydown.miplock', function(e) {
                        if (e.key.toLowerCase() === 'e' && !$(e.target).is('input, textarea')) {
                            e.preventDefault();
                            return false;
                        }
                    });
                }

                mw.config.set('wgRobotsPolicies', { 'index': 'noindex', 'follow': 'nofollow' });
                if ($metaRobots.length) {
                    $metaRobots.attr('content', 'noindex, nofollow');
                } else {
                    $('head').append('<meta name="robots" content="noindex, nofollow">');
                }

            } else {
                if ($existingNotice.length) $existingNotice.remove();
                
                $wikiDataElements.show();
                $descSection.show();

                if (!isSysop) {
                    $(document).off('keydown.miplock');
                }

                mw.config.set('wgRobotsPolicies', { 'index': 'index', 'follow': 'follow' });
                if ($metaRobots.length) {
                    $metaRobots.attr('content', 'index, follow');
                }
            }
        }

        // --- SISTEM PRIORITAS ---
        var cached = JSON.parse(localStorage.getItem(cacheKey) || "{}");
        var globalEnTitle = cached.enTitle || ""; 

        function init() {
            var pPrimary = projects[0]; 
            $.ajax({
                url: pPrimary.url,
                data: { action: 'query', prop: 'revisions|pageimages|langlinks', lllang: 'en', rvprop: 'timestamp', piprop: 'thumbnail', pithumbsize: 150, titles: pageTitle, format: 'json', origin: '*' },
                dataType: 'json',
                success: function(res) {
                    var pg = res.query.pages, id = Object.keys(pg)[0];
                    var latestTS = (id != "-1") ? pg[id].revisions[0].timestamp : "0";
                    var thumbUrl = (id != "-1" && pg[id].thumbnail) ? pg[id].thumbnail.source : "";
                    
                    if (id != "-1" && pg[id].langlinks && pg[id].langlinks[0]) {
                        globalEnTitle = pg[id].langlinks[0]['*'];
                    }

                    if (cached.content && cached.ts === latestTS && latestTS !== "0" && !cached.isEmpty) {
                        toggleMippediaLayout(false);
                        renderAll(cached.p, cached.content, cached.isTrans, cached.orig, cached.img, cached.customUrl, cached.enTitle);
                    } else { 
                        fetchPriorityData(0, latestTS, thumbUrl); 
                    }
                },
                error: function() { 
                    if (cached.content) {
                        toggleMippediaLayout(cached.isEmpty || false);
                        if (!cached.isEmpty) renderAll(cached.p, cached.content, cached.isTrans, cached.orig, cached.img, cached.customUrl, cached.enTitle);
                    } 
                }
            });
        }

        function fetchPriorityData(index, newTS, img) {
            if (index >= projects.length) {
                localStorage.setItem(cacheKey, JSON.stringify({isEmpty: true, ts: newTS, content: ""}));
                toggleMippediaLayout(true);
                return;
            }

            var p = projects[index];

            if (p.id === 'en') {
                if (!globalEnTitle) {
                    $.ajax({
                        url: 'https://concise.mippedia.org/api.php',
                        data: { action: 'query', prop: 'langlinks', lllang: 'en', titles: pageTitle, format: 'json', origin: '*' },
                        dataType: 'json',
                        async: false, 
                        success: function(cRes) {
                            var cPg = cRes.query.pages, cId = Object.keys(cPg)[0];
                            if (cId != "-1" && cPg[cId].langlinks && cPg[cId].langlinks[0]) {
                                globalEnTitle = cPg[cId].langlinks[0]['*'];
                            }
                        }
                    });
                }

                if (globalEnTitle) {
                    $.ajax({
                        url: p.url,
                        data: { action: 'query', prop: 'extracts', exintro: 1, explaintext: 1, titles: globalEnTitle, format: 'json', origin: '*' },
                        dataType: 'json',
                        success: function(data) {
                            var pages = data.query.pages, pageId = Object.keys(pages)[0];
                            if (pageId != "-1" && pages[pageId].extract) {
                                var extract = cleanExtract(pages[pageId].extract);
                                finalize(p, extract, false, "", newTS, img, p.base + encodeURIComponent(globalEnTitle), globalEnTitle);
                            } else {
                                fetchPriorityData(index + 1, newTS, img);
                            }
                        },
                        error: function() { fetchPriorityData(index + 1, newTS, img); }
                    });
                } else {
                    fetchPriorityData(index + 1, newTS, img);
                }
            } else {
                $.ajax({
                    url: p.url,
                    data: { action: 'query', prop: 'extracts', exintro: 1, explaintext: 1, titles: pageTitle, format: 'json', origin: '*' },
                    dataType: 'json',
                    success: function(data) {
                        var pages = data.query.pages, pageId = Object.keys(pages)[0];
                        if (pageId != "-1" && pages[pageId].extract) {
                            var extract = cleanExtract(pages[pageId].extract);
                            finalize(p, extract, false, "", newTS, img, p.base + encodeURIComponent(pageTitle), globalEnTitle); 
                        } else {
                            fetchPriorityData(index + 1, newTS, img);
                        }
                    },
                    error: function() { fetchPriorityData(index + 1, newTS, img); }
                });
            }
        }

        function finalize(p, c, t, o, ts, img, customUrl, enTitle) {
            localStorage.setItem(cacheKey, JSON.stringify({isEmpty: false, p:p, content:c, isTrans:t, orig:o, ts:ts, img:img, customUrl: customUrl, enTitle: enTitle}));
            toggleMippediaLayout(false); 
            renderAll(p, c, t, o, img, customUrl, enTitle);
        }

        function renderAll(p, currentText, isTranslated, originalText, img, customUrl, enTitle) {
            var processedText = applyAutoBold(applyDynamicContext(currentText));
            var thumbHtml = img ? '<div style="float: right; margin-left: 15px; margin-bottom: 10px; border: 1px solid #ddd; padding: 3px; background: #fff; border-radius: 4px; box-shadow: 0 2px 4px rgba(0,0,0,0.1);"><img src="'+img+'" style="max-width: 100px; display: block; height: auto;"></div>' : '';

            if (!$mainContent.find('#mip-desc-section').length) {
                $mainContent.prepend($descSection);
            }

            $descSection.show();
            $descBox.show().html(thumbHtml + applySummary(processedText) + '<div style="clear:both;"></div>');
            
            var targetLink = customUrl ? customUrl : p.base + encodeURIComponent(pageTitle);
            var footer = '<div style="font-size: 0.9em; color: #777;">Sumber : <a href="' + targetLink + '" target="_blank" style="color: #6a5acd; font-weight: bold; text-decoration: none;">' + p.name + '.</a>';
            if (isTranslated) { footer += '<br><span style="font-size: 0.85em; font-style: italic;">(Diterjemahkan secara otomatis)</span> <span id="mip-toggle-orig" style="color: #6a5acd; cursor: pointer; text-decoration: underline; margin-left: 5px;">Tampilkan versi asli</span>'; }
            $sourceInfo.show().html(footer);
            
            buildSmartLinks(p.id, enTitle);
            
            $(document).off('click', '.mip-read-btn').on('click', '.mip-read-btn', function() { $(this).hide(); $('.mip-dots').hide(); $('.mip-more').fadeIn(); });
            $(document).off('click', '#mip-toggle-orig').on('click', '#mip-toggle-orig', function() {
                var isOrig = ($(this).text() === 'Tampilkan versi asli');
                var textToDisplay = applyAutoBold(applyDynamicContext(isOrig ? originalText : currentText));
                $descBox.html(thumbHtml + applySummary(textToDisplay) + '<div style="clear:both;"></div>');
                $(this).text(isOrig ? 'Tampilkan terjemahan' : 'Tampilkan versi asli');
            });
        }

        init();
    });
})();

/* ==========================================================
   🚀 MIPPEDIA DATA - CORE SYSTEM (ULTIMATE BUNDLE)
   Status: FINAL & REVISED (Visual Fix + Permission Logic)
   Fix: Mobile Responsive Notification Position
   ========================================================== */

(function() {
    $(document).ready(function() {
        // --- 1. FILTER GLOBAL (Namespace 0 & Bukan Halaman Utama) ---
        if (mw.config.get('wgNamespaceNumber') !== 0 || 
            mw.config.get('wgIsMainPage') || 
            mw.config.get('wgAction') !== 'view') return;

        var pageTitle = mw.config.get('wgPageName');
        var dataPage = 'MediaWiki:Sitelinks-Data.json';
        var userGroups = mw.config.get('wgUserGroups');
        var isAdmin = userGroups.includes('sysop') || userGroups.includes('interface-admin');

        var projects = {
            'id': { name: 'ID', url: 'https://id.mippedia.org/api.php', base: 'https://id.mippedia.org/wiki/', color: '#6a5acd' },
            'en': { name: 'EN', url: 'https://en.mippedia.org/api.php', base: 'https://en.mippedia.org/wiki/', color: '#4169e1' },
            'concise': { name: 'Concise', url: 'https://concise.mippedia.org/api.php', base: 'https://concise.mippedia.org/wiki/', color: '#20b2aa' }
        };

        // --- 2. KOTAK NOTIFIKASI INFORMASI MODERN (FIXED MOBILE POSITION) ---
        function showBoxNotif(title, msg, type) {
            $('.mip-box-notif').remove();
            var theme = type === 'success' ? {bg:'#e6fffa', border:'#38b2ac', text:'#234e52', icon:''} : 
                        {bg:'#fff5f5', border:'#f56565', text:'#742a2a', icon:''};
            
            // Logika CSS Responsif untuk posisi
            var isMobile = window.innerWidth <= 768;
            var desktopStyle = "top:25px; right:25px; width:350px;";
            var mobileStyle = "top:15px; left:50%; transform:translateX(-50%); width:90%; max-width:400px;";
            var finalPos = isMobile ? mobileStyle : desktopStyle;

            var $notif = $('<div class="mip-box-notif" style="position:fixed; ' + finalPos + ' background:'+theme.bg+'; border-left:6px solid '+theme.border+'; padding:18px; z-index:10001; border-radius:12px; box-shadow:0 15px 35px rgba(0,0,0,0.2); font-family:sans-serif; animation:mipSlideIn 0.4s ease-out;">' +
                '<div style="display:flex; align-items:center; gap:12px; margin-bottom:8px;">' +
                    '<span style="font-size:20px;">'+theme.icon+'</span>' +
                    '<strong style="color:'+theme.text+'; font-size:15px; letter-spacing:-0.3px;">'+title+'</strong>' +
                '</div>' +
                '<p style="margin:0; font-size:13px; color:'+theme.text+'; line-height:1.6; opacity:0.9;">'+msg+'</p>' +
            '</div>').appendTo('body');

            setTimeout(function() { $notif.fadeOut(function(){ $(this).remove(); }); }, 5500);
        }

        // --- 3. UI GENERATOR (DIPERTEBAL) ---

      // A. Header Pro
        var headerHtml = '<div id="mip-header" style="background:#f8f9fa; border:1px solid #ddd; border-left:6px solid #6a5acd; padding:18px; margin-bottom:25px; border-radius:6px; box-shadow:inset 0 0 10px rgba(0,0,0,0.02);">' +
            '<div style="display:flex; align-items:center; gap:10px; margin-bottom:8px;">' +
            '<span style="background:#6a5acd; color:white; padding:3px 10px; border-radius:4px; font-size:11px; font-weight:bold; text-transform:uppercase; letter-spacing:0.5px;">Basis Data Terstruktur</span>' +
            '<strong style="color:#111; font-size:16px;"></strong></div>' +
            '<p style="margin:0; font-size:13px; color:#444; line-height:1.6;">' +
            'Halaman ini adalah metadata entitas repositori pusat yang disinkronisasi secara otomatis lintas ekosistem. ' +
            'Informasi di bawah ini bersifat teknis dan bebas digunakan sebagai referensi data terbuka bagi semua orang di seluruh dunia berdasarkan lisensi atribusi yang sesuai.' +
            '</p></div>';

        // B. Connector Box
        var editBtn = '<span id="mip-open-editor" style="cursor:pointer; font-size:20px; color:#6a5acd; opacity:0.8; transition:0.3s;" onmouseover="this.style.opacity=1" onmouseout="this.style.opacity=0.8">✎</span>';
        var connectorHtml = '<div id="mip-connector" style="background:#fff; border:1px solid #e2e8f0; border-radius:16px; padding:22px; margin-top:30px; box-shadow:0 10px 25px rgba(0,0,0,0.04);">' +
            '<div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:20px;">' +
            '<strong style="font-size:15px; color:#1a202c; display:flex; align-items:center; gap:8px;">ID situs</strong>'+editBtn+'</div>' +
            '<div id="mip-display" style="display:flex; gap:12px; flex-wrap:wrap;"><small style="color:#a0aec0;">Mensinkronisasi basis data...</small></div>' +
            '<div id="mip-editor" style="display:none; margin-top:20px; border-top:2px solid #f7fafc; padding-top:20px;">' +
                Object.keys(projects).map(p => '<div style="margin-bottom:12px; display:flex; gap:10px;"><span style="width:75px; font-size:11px; font-weight:bold; background:#edf2f7; display:flex; align-items:center; justify-content:center; border-radius:8px; color:#4a5568;">'+projects[p].name+'</span><input type="text" id="in-'+p+'" placeholder="Judul artikel di '+projects[p].name+'..." style="flex:1; padding:10px; font-size:13px; border:1.5px solid #e2e8f0; border-radius:10px; outline:none; transition:0.2s;" onfocus="this.style.borderColor=\'#6a5acd\'"></div>').join('') +
                '<button id="mip-save" style="width:100%; padding:14px; background:#6a5acd; color:white; border:none; border-radius:12px; font-size:14px; font-weight:bold; cursor:pointer; box-shadow:0 4px 12px rgba(106,90,205,0.3); transition:0.3s;">Terbitkan</button>' +
            '</div></div>';

        // C. Footer Lisensi Lengkap
        var footerHtml = '<div id="mip-footer" style="background:#fafafa; border:1px solid #eee; border-radius:10px; padding:20px; margin-top:30px; text-align:center;">' +
            '<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;">' +
            'Seluruh data terstruktur yang tersaji dalam repositori ini merupakan milik publik dan tersedia di bawah lisensi resmi ' +
            '<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>.' +
            '</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>';

        // Injeksi
        $('#mw-content-text').prepend(headerHtml);
        $('#mw-content-text').append(connectorHtml).append(footerHtml);

        // --- 4. LOGIC ENGINE ---
        function loadLinks() {
            new mw.Api().get({ action: 'query', prop: 'revisions', titles: dataPage, rvprop: 'content', formatversion: 2 }).done(function(d) {
                var json = d.query.pages[0].revisions ? JSON.parse(d.query.pages[0].revisions[0].content) : {};
                var data = json[pageTitle] || {};
                var $box = $('#mip-display').empty();
                var found = false;
                Object.keys(projects).forEach(p => {
                    if (data[p]) {
                        found = true;
                        $box.append('<a style="background:'+projects[p].color+'; color:white; padding:8px 16px; border-radius:10px; font-size:12px; font-weight:bold; text-decoration:none; border-bottom:3px solid rgba(0,0,0,0.15);" href="'+projects[p].base+encodeURIComponent(data[p])+'" target="_blank">Mippedia '+projects[p].name+': '+data[p]+'</a>');
                        $('#in-' + p).val(data[p]);
                    }
                });
                if (!found) $box.html('<em style="color:#cbd5e0; font-size:13px;">Entitas ini belum terhubung ke cabang Mippedia manapun.</em>');
            });
        }

        $(document).on('click', '#mip-save', function() {
            // CEK IZIN: Tolak user biasa
            if (!isAdmin) {
                showBoxNotif('Suntingan anda tidak di terbitkan', 'Halaman ini dilindungi. Hanya <b>Pengurus</b> yang memiliki otoritas untuk memodifikasi metadata ekosistem secara langsung.', 'error');
                return;
            }

            var $btn = $(this).text('Sedang Memvalidasi...').prop('disabled', true);
            var api = new mw.Api();
            var newData = {}, promises = [], invalid = [], isDel = true;

            Object.keys(projects).forEach(p => {
                var v = $('#in-' + p).val().trim();
                if (v) {
                    isDel = false;
                    promises.push($.ajax({ url: projects[p].url, data: { action: 'query', titles: v, format: 'json', origin: '*' }, dataType: 'json' }).done(function(res){
                        if (res.query.pages["-1"]) invalid.push(projects[p].name); else newData[p] = v;
                    }));
                }
            });

            $.when.apply($, promises).then(function() {
                if (invalid.length > 0) {
                    showBoxNotif('Suntingan anda tidak di terbitkan', 'Artikel dengan judul tersebut tidak ditemukan di basis data Mippedia cabang: ' + invalid.join(', ') + '. Periksa kembali ejaan dan kapitalisasi.', 'error');
                    $btn.text('Terbitkan').prop('disabled', false); return;
                }
                
                api.get({ action: 'query', prop: 'revisions', titles: dataPage, rvprop: 'content', formatversion: 2 }).done(function(r) {
                    var full = r.query.pages[0].revisions ? JSON.parse(r.query.pages[0].revisions[0].content) : {};
                    if (isDel) delete full[pageTitle]; else full[pageTitle] = newData;
                    
                    api.postWithEditToken({ action: 'edit', title: dataPage, text: JSON.stringify(full, null, 2), summary: 'Sync Metadata: ' + pageTitle })
                    .done(function() {
                        showBoxNotif('Suntingan anda berhasil di terbitkan!', 'Metadata entitas berhasil disinkronisasi ke seluruh jaringan ekosistem Mippedia.', 'success');
                        setTimeout(function(){ location.reload(); }, 1500);
                    }).fail(function(c) {
                        showBoxNotif('Gagal Menyimpan', 'Terjadi kesalahan pada token API atau koneksi server. Kode: ' + c, 'error');
                        $btn.text('Simpan & Sinkronkan Data').prop('disabled', false);
                    });
                });
            });
        });

        $(document).on('click', '#mip-open-editor', function() { $('#mip-editor').slideToggle(); });
        loadLinks();
    });
})();

(function() {
    // Fungsi utama suntik teks
    function forcePreload() {
        var ns = mw.config.get('wgNamespaceNumber');
        var pageExists = mw.config.get('wgArticleId') > 0;
        
        // Cek Namespace Utama & Halaman Baru
        if (ns === 0 && !pageExists) {
            // Cari textarea secara spesifik (Desktop & Mobile punya selector beda)
            var $textbox = $('#wpTextbox1, textarea.mw-ui-input, .editor-container textarea');
            
            if ($textbox.length && $textbox.val().trim() === "") {
                var pageName = mw.config.get('wgTitle');
                $textbox.val('{{Infobox umum\n|nama = ' + pageName + '\n}}');
                console.log("Mippedia: Infobox injected!");
            }
        }
    }

    // 1. Jalankan pas halaman beres load
    $(document).ready(forcePreload);

    // 2. Jalankan tiap ada klik (karena mobile buka editor pake klik tanpa refresh)
    $(document).on('click', function() {
        setTimeout(forcePreload, 800); // Kasih delay dikit nunggu overlay muncul
    });

    // 3. Pake MutationObserver buat mantau elemen yang baru muncul secara gaib
    var observer = new MutationObserver(function() {
        forcePreload();
    });
    observer.observe(document.body, { childList: true, subtree: true });
})();

/* ==========================================================
   🚀 MIPPEDIA DATA - CONTENT GUARD (MODIFIED FOR RELATED)
   ========================================================== */
(function() {
    function handleBlock(e) {
        var ns = mw.config.get('wgNamespaceNumber');
        if (ns !== 0 || mw.config.get('wgIsMainPage')) return;

        var $el = $(e.currentTarget);
        
        if ($el.closest('.mw-parser-output').length && $el.text().toLowerCase().includes('buat item')) {
            return; 
        }

        var $textbox = $('#wpTextbox1, .editor-container textarea, textarea.mw-ui-input');
        
        if ($textbox.length) {
            var content = $textbox.val() || "";
            
            // Pengecekan: Harus ada {{Infobox ATAU setidaknya ada kode #related
            var hasInfobox = content.includes('{{Infobox');
            var hasRelated = content.includes('#related:');

            if (!hasInfobox && !hasRelated) {
                e.preventDefault();
                e.stopPropagation();
                e.stopImmediatePropagation();

                window.alert("SUNTINGAN ANDA TIDAK BISA DI TERBITKAN!\n\nMippedia Data bukan tempat untuk menulis artikel ensiklopedia, Jika anda ingin membuat artikel ensiklopedia bukan di sini tempat nya.\n");
                return false;
            }
        }
    }

    $(document).on('click mousedown touchstart', 
        '#wpSave, .editor-save, .mw-ui-button.primary, button[type="submit"], .save-button, .header-action button', 
        function(e) {
            handleBlock(e);
        }
    );

    window.addEventListener('submit', function(e) {
        handleBlock(e);
    }, true);
})();

/* ==========================================================
   🛡️ MIPPEDIA CORE SYSTEM - NEURAL ENGINE V12
   Update: Brain Upgrade - Semantic Search & Anti-Duplicate
   Semua fitur asli (Patroli, Promo, Kategori) tetap UTUH.
   ========================================================== */
mw.hook('postEdit').add(function() {
    var rawUser = mw.config.get('wgUserName');
    var userName = rawUser ? rawUser.replace(/_/g, ' ') : 'Anonim';
    var isPatroli = (userName === 'Admin');
    
    if (mw.config.get('wgNamespaceNumber') !== 0) return;

    var api = new mw.Api();
    var pageTitle = mw.config.get('wgPageName').replace(/_/g, ' ');

    api.get({
        action: 'query',
        titles: pageTitle,
        prop: 'revisions|categories|links',
        rvprop: 'content',
        clshow: '!hidden',
        pllimit: 'max'
    }).done(function(resData) {
        var page = resData.query.pages[Object.keys(resData.query.pages)[0]];
        if (!page || !page.revisions) return;

        var rawContent = page.revisions[0]['*'];
        var content = rawContent;
        var summaryParts = [];

        // --- 2. SUPER INTELLIGENCE RELATED (UPGRADE OTAK V12) ---
        // Cek jumlah related saat ini
        var currentRelatedMatch = content.match(/\{\{#related:.*?\}\}/g) || [];
        
        // Jika kurang dari 3, kita jalankan otak pencarian canggih
        if (currentRelatedMatch.length < 3) {
            // Hapus yang lama dulu agar tidak ada duplikat atau "pake yang bekas"
            content = content.replace(/\n*\{\{#related:.*?\}\}/g, '');

            // Langkah A: Ambil kandidat dari Search Engine (Ranking Skor)
            api.get({
                action: 'query',
                list: 'search',
                srsearch: pageTitle, // Gunakan judul sebagai basis pencarian semantic
                srlimit: 15,
                srprop: ''
            }).done(function(searchRes) {
                var candidates = {};

                // Masukkan hasil pencarian ke pool skor
                if (searchRes.query && searchRes.query.search) {
                    searchRes.query.search.forEach(function(item, index) {
                        if (item.title === pageTitle) return;
                        candidates[item.title] = (15 - index); // Skor berdasarkan urutan relevansi
                    });
                }

                // Langkah B: Tambah skor jika artikel ada di daftar Link Internal
                if (page.links) {
                    page.links.forEach(function(link) {
                        if (link.title === pageTitle) return;
                        candidates[link.title] = (candidates[link.title] || 0) + 5; // Bonus skor link
                    });
                }

                // Langkah C: Urutkan berdasarkan skor tertinggi (yang paling nyambung)
                var sortedTitles = Object.keys(candidates).sort(function(a, b) {
                    return candidates[b] - candidates[a];
                });

                // Ambil TOP 3
                var finalRelated = sortedTitles.filter(t => t.indexOf(':') === -1).slice(0, 3);

                if (finalRelated.length > 0) {
                    var relatedTags = '\n\n' + finalRelated.map(t => '{{#related: ' + t + '}}').join('\n');
                    content += relatedTags;
                    summaryParts.push('NeuralRelated');
                }
                
                runPatroliAndSave();
            });
        } else {
            runPatroliAndSave();
        }

        function runPatroliAndSave() {
            // --- 3. PATROLI ENGINE (FITUR ASLI - TETAP BERFUNGSI) ---
            if (isPatroli) {
                var placeholders = [];
                // Lindungi Brankas: Template, Header, Kategori, Ref, dan Kalimat Pembuka
                content = content.replace(/(\{\{[\s\S]*?\}\}|==+.*?==+|\[\[Kategori:.*?\]\]|<ref[\s\S]*?<\/ref>|^.*?adalah)/gi, function(match) {
                    placeholders.push(match);
                    return '___MIP_SKIP_' + (placeholders.length - 1) + '___';
                });

                // Proses Auto-Link (Wajib ambil daftar AllPages dulu)
                api.get({ action: 'query', list: 'allpages', apnamespace: 0, aplimit: 'max' }).done(function(apData) {
                    var allTitles = apData.query.allpages.map(p => p.title);
                    var lowerTitles = allTitles.map(t => t.toLowerCase());

                    var tokens = content.split(/(\s+|\[\[|\]\])/);
                    var inLink = false;
                    for (var i = 0; i < tokens.length; i++) {
                        if (tokens[i] === '[[' ) { inLink = true; continue; }
                        if (tokens[i] === ']]' ) { inLink = false; continue; }
                        if (inLink || tokens[i].trim().length < 3 || tokens[i].includes('___MIP_SKIP_')) continue;

                        var wordsInToken = tokens[i].match(/\b\w+\b/g);
                        if (wordsInToken) {
                            wordsInToken.forEach(function(word) {
                                var idx = lowerTitles.indexOf(word.toLowerCase());
                                if (idx !== -1 && allTitles[idx] !== pageTitle) {
                                    tokens[i] = tokens[i].replace(new RegExp('\\b' + word + '\\b', 'g'), '[[' + allTitles[idx] + '|' + word + ']]');
                                }
                            });
                        }
                    }
                    content = tokens.join('');
                    
                    // Kembalikan dari Brankas
                    content = content.replace(/___MIP_SKIP_(\d+)___/g, function(match, id) { return placeholders[id]; });

                    // Bersihkan Link Merah
                    content = content.replace(/\[\[([^|\]:]+)\]\]/g, function(match, p1) {
                        return lowerTitles.includes(p1.toLowerCase()) ? match : p1;
                    });

                    saveAction();
                });
            } else {
                saveAction();
            }
        }

        function saveAction() {
            // --- 4. EKSEKUSI ---
            if (content.trim() !== rawContent.trim()) {
                api.postWithToken('edit', {
                    action: 'edit',
                    title: pageTitle,
                    text: content,
                    summary: 'Mippedia Neural Engine V12: ' + summaryParts.join(', '),
                    bot: true, markasbot: true
                }).done(function() { location.reload(); });
            }
        }
    });
});

/* ==========================================================
   🌐 MIPPEDIA SHORTDESC - DATA CENTER (PREMIUM UI)
   Status: INDEPENDENT & REFINED VISUAL
   Storage: MediaWiki:ShortDesc-Data.json
   ========================================================== */
(function($, mw) {
    "use strict";
    $(document).ready(function() {
        if (mw.config.get('wgNamespaceNumber') !== 0 || mw.config.get('wgIsMainPage')) return;

        var pageTitle = mw.config.get('wgPageName');
        var storagePage = 'MediaWiki:ShortDesc-Data.json';
        var isAdmin = mw.config.get('wgUserGroups').some(g => ['sysop', 'interface-admin'].includes(g));

        var langs = {
            id: { label: 'Mippedia bahasa Indonesia', short: 'ID', color: '#6366f1' },
            en: { label: 'Mippedia bahasa Inggris', short: 'EN', color: '#3b82f6' },
            concise: { label: 'Mippedia bahasa Indonesia ringkas', short: 'CON', color: '#14b8a6' }
        };

        // UI Box dengan Spasi dan Desain Baru
        var html = `
            <div id="desc-manager" style="background:#ffffff; border:1px solid #f1f5f9; border-left:4px solid #6366f1; border-radius:12px; padding:20px; margin: 20px 0 25px 0; box-shadow:0 4px 12px rgba(0,0,0,0.03); font-family: -apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;">
                <div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:12px;">
                    <span style="font-size:13px; font-weight:700; color:#475569; text-transform:uppercase; letter-spacing:0.5px; display:flex; align-items:center; gap:6px;">
                        Label Deskripsi
                    </span>
                    <span id="desc-open-editor" style="cursor:pointer; padding:5px; transition:0.2s;" title="Edit Deskripsi">
                        <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#94a3b8" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><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>
                    </span>
                </div>
                
                <div id="desc-status-display" style="display:flex; flex-direction:column; gap:8px;">
                    <small style="color:#94a3b8; font-style:italic;">Sinkronisasi data...</small>
                </div>

                <div id="desc-editor" style="display:none; margin-top:18px; border-top:1px dashed #e2e8f0; padding-top:18px;">
                    ${Object.keys(langs).map(k => `
                        <div style="margin-bottom:12px;">
                            <label style="display:block; font-size:11px; font-weight:bold; color:#64748b; margin-bottom:4px;">${langs[k].label}</label>
                            <input type="text" id="desc-in-${k}" placeholder="Tulis deskripsi..." style="width:100%; padding:10px; font-size:13px; border:1px solid #e2e8f0; border-radius:8px; box-sizing:border-box; outline:none; focus:border-color:#6366f1;">
                        </div>
                    `).join('')}
                    <button id="desc-save" style="width:100%; padding:12px; background:#6366f1; color:white; border:none; border-radius:8px; font-size:13px; font-weight:600; cursor:pointer; margin-top:5px;">Terbitkan</button>
                </div>
            </div>`;

        $('.mw-parser-output').prepend(html);

        function loadDescStatus() {
            new mw.Api().get({ action: 'query', prop: 'revisions', titles: storagePage, rvprop: 'content', formatversion: 2 }).done(function(res) {
                var content = res.query.pages[0].revisions ? res.query.pages[0].revisions[0].content : "{}";
                var fullData = JSON.parse(content);
                var myData = fullData[pageTitle] || {};
                var $statusBox = $('#desc-status-display').empty();
                var foundAny = false;

                Object.keys(langs).forEach(k => {
                    var val = myData[k];
                    if (val && val.trim() !== "") {
                        foundAny = true;
                        $statusBox.append(`
                            <div style="display:flex; align-items:center; gap:10px;">
                                <span style="background:${langs[k].color}15; color:${langs[k].color}; padding:3px 10px; border-radius:20px; font-size:10px; font-weight:800; border:1px solid ${langs[k].color}30; min-width:35px; text-align:center;">${langs[k].short}</span>
                                <span style="font-size:13px; color:#334155; line-height:1.4;">${val}</span>
                            </div>
                        `);
                        $('#desc-in-' + k).val(val);
                    }
                });

                if (!foundAny) {
                    $statusBox.html('<div style="color:#cbd5e0; font-size:13px; background:#f8fafc; padding:10px; border-radius:8px; border:1px dashed #e2e8f0;">Belum ada metadata deskripsi yang dikaitkan dengan entitas ini.</div>');
                }
            });
        }

        $(document).on('click', '#desc-open-editor', function() { $('#desc-editor').slideToggle(); });

        $(document).on('click', '#desc-save', function() {
            if (!isAdmin) { alert('Akses ditolak. Anda memerlukan izin pengurus.'); return; }
            var $btn = $(this).text('Proses Sinkronisasi...').css('opacity','0.7');
            var api = new mw.Api();
            var newData = { id: $('#desc-in-id').val().trim(), en: $('#desc-in-en').val().trim(), concise: $('#desc-in-concise').val().trim() };

            api.get({ action: 'query', prop: 'revisions', titles: storagePage, rvprop: 'content', formatversion: 2 }).done(function(r) {
                var json = r.query.pages[0].revisions ? JSON.parse(r.query.pages[0].revisions[0].content) : {};
                if (!newData.id && !newData.en && !newData.concise) { delete json[pageTitle]; } else { json[pageTitle] = newData; }

                api.postWithEditToken({
                    action: 'edit',
                    title: storagePage,
                    text: JSON.stringify(json, null, 2),
                    summary: 'Update Entity Description: ' + pageTitle
                }).done(function() { location.reload(); });
            });
        });

        loadDescStatus();
    });
})(jQuery, mediaWiki);

/* ==========================================================
   📍 MIPPEDIA DATA - ULTIMATE TEXT-TO-MAP LOCATOR
   Fitur: Deteksi lokasi dari teks dengan database label lengkap
   ========================================================== */
(function() {
    $(document).ready(function() {
        var locationText = "";
        
        // --- DAFTAR LABEL SUPER LENGKAP & MASUK AKAL ---
        var locationLabels = [
            // Umum & Geografis
            'lokasi', 'tempat', 'wilayah', 'daerah', 'koordinat', 'alamat',
            // Orang (Biografi)
            'tempat lahir', 'asal', 'kediaman', 'domisili', 'negara asal',
            // Organisasi & Perusahaan
            'kantor pusat', 'markas', 'cabang utama', 'titik operasi',
            // Makanan & Budaya
            'asal wilayah', 'daerah asal', 'negara sumber', 'kawasan',
            // Sejarah & Bangunan
            'letak', 'posisi', 'titik temu', 'orbit'
        ];

        // Jalankan pencarian di tabel data (infobox atau wikitable)
        $('.wikitable tr, .infobox tr, .mip-data-table tr').each(function() {
            var label = $(this).find('th').text().toLowerCase().trim();
            // Hilangkan karakter spesial kayak titik dua biar matching-nya akurat
            label = label.replace(/[:]/g, '');

            var isMatch = locationLabels.some(function(target) {
                return label === target || label.includes(target);
            });

            if (isMatch) {
                var rawValue = $(this).find('td').text().trim();
                // Ambil bagian utama sebelum tanda koma, kurung, atau titik koma
                // Misal: "Bandung, Jawa Barat" -> ambil "Bandung"
                locationText = rawValue.split(/[,(\[;]/)[0].trim(); 
                
                if (locationText.length > 2) return false; // Stop jika sudah ketemu yang valid
            }
        });

        // Eksekusi Render Peta
        if (locationText && locationText.length > 2) {
            var $mapWrapper = $('<div>').css({
                'margin': '15px 0',
                'padding': '12px',
                'border': '1px solid #ddd',
                'background': '#ffffff',
                'border-radius': '10px',
                'box-shadow': '0 4px 12px rgba(0,0,0,0.08)'
            });

            $mapWrapper.append('<div style="font-weight:bold; font-size:0.9em; margin-bottom:10px; color:#444; display:flex; align-items:center;">' +
                               '<span style="margin-right:8px;">🗺️</span>Pratinjau Lokasi : ' + locationText + '</div>');

            // Embed URL dengan pencarian teks (Nominatim)
            var embedUrl = "https://www.openstreetmap.org/export/embed.html?layer=mapnik&q=" + encodeURIComponent(locationText);

            var $iframe = $('<iframe>').attr({
                'src': embedUrl,
                'width': '100%',
                'height': '280',
                'frameborder': '0',
                'style': 'border-radius: 8px; border: 1px solid #eee;'
            });

            $mapWrapper.append($iframe);
            
            // Link eksternal yang lebih rapi
            var gMapsUrl = "https://www.google.com/maps/search/" + encodeURIComponent(locationText);
            $mapWrapper.append('<div style="text-align:right; margin-top:8px;">' +
                               '<a href="' + gMapsUrl + '" target="_blank" style="font-size:0.75em; color:#6a5acd; font-weight:bold; text-decoration:none; text-transform:uppercase; letter-spacing:0.5px;">Buka di Google Maps →</a></div>');

            // Masukkan ke bawah section deskripsi otomatis
            if ($('#mip-desc-section').length) {
                $('#mip-desc-section').after($mapWrapper);
            }
        }
    });
})();