MediaWiki:Common.js: Perbedaan antara revisi

Tidak ada ringkasan suntingan
Tidak ada ringkasan suntingan
Tanda: Suntingan perangkat seluler Suntingan peramban seluler
Baris 1: Baris 1:
/**
/**
  * ====================================================================
  * ====================================================================
  * MIPPEDIA DATA - ADVANCED STRUCTURED DATA SYSTEM (V7.0 ULTIMATE)
  * MIPPEDIA DATA - ADVANCED STRUCTURED DATA SYSTEM (V8.0 TITANIUM)
  * Fitur: Complete Music & Socials, Explicit Ref Labels, Preset Templates,
  * Fitur: 25+ Fitur Baru, Collapsible References, Direct Link Button,
  * JSON Export/Import, Mobile Perfect, Auto-Domain & Instant Validation
  * Dark Mode, Toast Notifications, Drag & Drop, Export CSV, Auto-Fill
  * ====================================================================
  * ====================================================================
  */
  */
Baris 19: Baris 19:
         var isLocked = false;
         var isLocked = false;
         var api = new mw.Api();
         var api = new mw.Api();
        var isDarkMode = localStorage.getItem('md-dark-mode') === 'true';


         // 1. DATA MASTER PLATFORM MEDIA SOSIAL & MUSIK
         // 1. DATA MASTER PLATFORM MEDIA SOSIAL & MUSIK (+5 Baru)
         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', 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>' },
Baris 26: Baris 27:
             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', 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>' },
             bandcamp: { name: 'Bandcamp', base: 'https://bandcamp.com/', color: '#1da0c3', icon: '<svg width="13" height="13" viewBox="0 0 24 24" fill="currentColor"><path d="M0 18.75l7.437-13.5H24l-7.438 13.5H0z"/></svg>' },
             bandcamp: { name: 'Bandcamp', base: 'https://bandcamp.com/', color: '#1da0c3', icon: '<svg width="13" height="13" viewBox="0 0 24 24" fill="currentColor"><path d="M0 18.75l7.437-13.5H24l-7.438 13.5H0z"/></svg>' },
             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', 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></svg>' },
             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', 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>' },
             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', 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>' },
Baris 34: Baris 35:
             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>' },
             linkedin: { name: 'LinkedIn', base: 'https://linkedin.com/in/', color: '#0a66c2', icon: '<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M16 8a6 6 0 0 1 6 6v7h-4v-7a2 2 0 0 0-2-2 2 2 0 0 0-2 2v7h-4v-7a6 6 0 0 1 6-6z"></path><rect x="2" y="9" width="4" height="12"></rect><circle cx="4" cy="4" r="2"></circle></svg>' },
             github: { name: 'GitHub', base: 'https://github.com/', color: '#24292e', icon: '<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22"></path></svg>' },
             github: { name: 'GitHub', base: 'https://github.com/', color: '#24292e', icon: '<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22"></path></svg>' },
             pinterest: { name: 'Pinterest', base: 'https://pinterest.com/', color: '#e60023', icon: '<svg width="13" height="13" viewBox="0 0 24 24" fill="currentColor"><path d="M12 0C5.373 0 0 5.372 0 12c0 5.084 3.163 9.426 7.627 11.174-.105-.949-.2-2.405.042-3.441.218-.937 1.407-5.965 1.407-5.965s-.359-.719-.359-1.782c0-1.668.967-2.914 2.171-2.914 1.023 0 1.518.769 1.518 1.69 0 1.029-.655 2.568-.994 3.995-.283 1.194.599 2.169 1.777 2.169 2.133 0 3.772-2.249 3.772-5.495 0-2.873-2.064-4.882-5.012-4.882-3.414 0-5.418 2.561-5.418 5.207 0 1.031.397 2.138.893 2.738.098.119.112.224.083.345l-.333 1.36c-.053.22-.174.267-.402.161-1.499-.698-2.436-2.889-2.436-4.649 0-3.785 2.75-7.262 7.929-7.262 4.163 0 7.398 2.967 7.398 6.931 0 4.136-2.607 7.464-6.227 7.464-1.216 0-2.359-.631-2.75-1.378l-.748 2.853c-.271 1.043-1.002 2.35-1.492 3.146C9.57 23.812 10.763 24 12 24c6.627 0 12-5.373 12-12 0-6.628-5.373-12-12-12z"/></svg>' }
             pinterest: { name: 'Pinterest', base: 'https://pinterest.com/', color: '#e60023', icon: '<svg width="13" height="13" viewBox="0 0 24 24" fill="currentColor"><path d="M12 0C5.373 0 0 5.372 0 12c0 5.084 3.163 9.426 7.627 11.174-.105-.949-.2-2.405.042-3.441.218-.937 1.407-5.965 1.407-5.965s-.359-.719-.359-1.782c0-1.668.967-2.914 2.171-2.914 1.023 0 1.518.769 1.518 1.69 0 1.029-.655 2.568-.994 3.995-.283 1.194.599 2.169 1.777 2.169 2.133 0 3.772-2.249 3.772-5.495 0-2.873-2.064-4.882-5.012-4.882-3.414 0-5.418 2.561-5.418 5.207 0 1.031.397 2.138.893 2.738.098.119.112.224.083.345l-.333 1.36c-.053.22-.174.267-.402.161-1.499-.698-2.436-2.889-2.436-4.649 0-3.785 2.75-7.262 7.929-7.262 4.163 0 7.398 2.967 7.398 6.931 0 4.136-2.607 7.464-6.227 7.464-1.216 0-2.359-.631-2.75-1.378l-.748 2.853c-.271 1.043-1.002 2.35-1.492 3.146C9.57 23.812 10.763 24 12 24c6.627 0 12-5.373 12-12 0-6.628-5.373-12-12-12z"/></svg>' },
            twitch: { name: 'Twitch', base: 'https://twitch.tv/', color: '#9146ff', icon: '<svg width="13" height="13" viewBox="0 0 24 24" fill="currentColor"><path d="M11.571 4.714h1.715v5.143H11.57zm4.715 0H18v5.143h-1.714zM6 0L1.714 4.286v15.428h5.143V24l4.286-4.286h3.428L22.286 12V0zm14.571 11.143l-3.428 3.428h-3.429l-3 3v-3H6.857V1.714h13.714Z"/></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.779c0-1.459-1.192-2.645-2.657-2.645-.715 0-1.363.275-1.84.734-1.605-1.056-3.868-1.739-6.38-1.815l1.341-4.218 3.238.683c.038 1.168 1.002 2.1 2.189 2.1 1.212 0 2.193-.984 2.193-2.2s-.981-2.2-2.193-2.2c-1.01 0-1.868.682-2.131 1.606l-3.619-.763c-.156-.033-.311.042-.366.19l-1.547 4.86c-2.61.037-4.978.711-6.643 1.785-.477-.47-1.135-.754-1.861-.754-1.465 0-2.656 1.187-2.656 2.646 0 .97.533 1.811 1.317 2.271-.052.282-.086.567-.086.857 0 3.911 4.808 7.093 10.719 7.093s10.72-3.182 10.72-7.093c0-.274-.029-.544-.075-.81.832-.447 1.405-1.312 1.405-2.318zm-17.224 1.816c0-.868.71-1.575 1.582-1.575.872 0 1.581.707 1.581 1.575s-.709 1.574-1.581 1.574-1.582-.706-1.582-1.574zm9.014 4.597c-1.233 1.234-3.535 1.294-5.068 1.294-1.531 0-3.834-.06-5.068-1.294-.216-.216-.216-.566 0-.783.216-.217.567-.217.784 0 1.019 1.018 3.033 1.109 4.284 1.109 1.253 0 3.266-.09 4.284-1.109.217-.217.568-.217.784 0 .216.217.216.566 0 .783zm.18-2.923c-.872 0-1.582-.706-1.582-1.574 0-.868.71-1.575 1.582-1.575.871 0 1.581.707 1.581 1.575s-.71 1.574-1.581 1.574z"/></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>' },
            wikipedia: { name: 'Wikipedia', base: 'https://id.wikipedia.org/wiki/', color: '#000000', icon: '<svg width="13" height="13" viewBox="0 0 24 24" fill="currentColor"><path d="M11.964 1.488C5.467 1.488.2 6.756.2 13.253s5.267 11.765 11.764 11.765 11.765-5.268 11.765-11.765S18.461 1.488 11.964 1.488zm-2.003 18.06l-4.706-9.412h1.412l2.353 5.378 1.954-5.378h1.41l2.42 5.513 2.164-5.513h1.365l-4.47 9.412h-1.554l-1.954-5.464-2.046 5.464h-1.348z"/></svg>' }
         };
         };


Baris 41: Baris 46:
             "Nama Lahir", "Tanggal Lahir", "Tempat Lahir", "Pekerjaan",  
             "Nama Lahir", "Tanggal Lahir", "Tempat Lahir", "Pekerjaan",  
             "Kebangsaan", "Genre", "Instrumen", "Label Rekaman",  
             "Kebangsaan", "Genre", "Instrumen", "Label Rekaman",  
             "Tahun Aktif", "Situs Web Resmi", "Pasangan", "Orang Tua"
             "Tahun Aktif", "Situs Web Resmi", "Pasangan", "Orang Tua", "Agama", "Pendidikan"
         ];
         ];


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


         // 4. IKON SISTEM
         // 4. IKON SISTEM (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 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 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>';
         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>';
Baris 68: Baris 73:
         var svgSearch = '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line></svg>';
         var svgSearch = '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line></svg>';
         var svgCode = '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="16 18 22 12 16 6"></polyline><polyline points="8 6 2 12 8 18"></polyline></svg>';
         var svgCode = '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="16 18 22 12 16 6"></polyline><polyline points="8 6 2 12 8 18"></polyline></svg>';
        var svgExternal = '<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 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 svgSun = '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="5"></circle><line x1="12" y1="1" x2="12" y2="3"></line><line x1="12" y1="21" x2="12" y2="23"></line><line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line><line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line><line x1="1" y1="12" x2="3" y2="12"></line><line x1="21" y1="12" x2="23" y2="12"></line><line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line><line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line></svg>';
        var svgDownload = '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path><polyline points="7 10 12 15 17 10"></polyline><line x1="12" y1="15" x2="12" y2="3"></line></svg>';
        var svgClone = '<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 svgDrag = '<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="cursor:grab; color:#94a3b8;"><line x1="8" y1="6" x2="21" y2="6"></line><line x1="8" y1="12" x2="21" y2="12"></line><line x1="8" y1="18" x2="21" y2="18"></line><line x1="3" y1="6" x2="3.01" y2="6"></line><line x1="3" y1="12" x2="3.01" y2="12"></line><line x1="3" y1="18" x2="3.01" y2="18"></line></svg>';


         // 5. HELPER UTILITY
         // 5. HELPER UTILITY
        function showToast(msg, type) {
            var bg = type === 'error' ? '#ef4444' : '#10b981';
            var $toast = $('<div style="position:fixed; bottom:20px; right:20px; background:'+bg+'; color:white; padding:12px 20px; border-radius:8px; box-shadow:0 10px 25px rgba(0,0,0,0.2); z-index:9999; font-weight:600; font-size:0.9rem; transform:translateY(100px); opacity:0; transition:all 0.3s ease;">' + msg + '</div>');
            $('body').append($toast);
            setTimeout(function() { $toast.css({transform: 'translateY(0)', opacity: 1}); }, 50);
            setTimeout(function() { $toast.css({transform: 'translateY(100px)', opacity: 0}); setTimeout(function(){ $toast.remove(); }, 300); }, 3000);
        }
         function formatIndonesianDate(dateStr) {
         function formatIndonesianDate(dateStr) {
             if (!dateStr) return '';
             if (!dateStr) return '';
             var parts = dateStr.split('-');
             var parts = dateStr.split('-');
             if (parts.length !== 3) return dateStr;
             if (parts.length !== 3) return dateStr;
             var months = ['Januari', 'Februari', 'Maret', 'April', 'Mei', 'Juni', 'Juli', 'Agustus', 'September', 'Oktober', 'November', 'Desember'];
             var months = ['Jan', 'Feb', 'Mar', 'Apr', 'Mei', 'Jun', 'Jul', 'Agu', 'Sep', 'Okt', 'Nov', 'Des'];
             var day = parseInt(parts[2], 10);
             var day = parseInt(parts[2], 10);
             var monthIdx = parseInt(parts[1], 10) - 1;
             var monthIdx = parseInt(parts[1], 10) - 1;
Baris 85: Baris 104:
             try {
             try {
                 if (!urlStr.match(/^https?:\/\//i)) urlStr = 'https://' + urlStr;
                 if (!urlStr.match(/^https?:\/\//i)) urlStr = 'https://' + urlStr;
                 var parsed = new URL(urlStr);
                 return new URL(urlStr).hostname.replace(/^www\./, '');
                return parsed.hostname.replace(/^www\./, '');
             } catch(e) { return urlStr.replace(/^https?:\/\/(www\.)?/, '').split('/')[0]; }
             } catch(e) {
                return urlStr.replace(/^https?:\/\/(www\.)?/, '').split('/')[0];
            }
         }
         }


Baris 95: Baris 111:
             if (!urlStr) return '';
             if (!urlStr) return '';
             urlStr = urlStr.trim();
             urlStr = urlStr.trim();
             if (urlStr && !urlStr.match(/^https?:\/\//i)) {
             if (urlStr && !urlStr.match(/^https?:\/\//i)) return 'https://' + urlStr;
                return 'https://' + urlStr;
            }
             return urlStr;
             return urlStr;
         }
         }
Baris 107: Baris 121:
             var d = String(now.getDate()).padStart(2, '0');
             var d = String(now.getDate()).padStart(2, '0');
             return y + '-' + m + '-' + d;
             return y + '-' + m + '-' + d;
        }
       
        function toTitleCase(str) {
            return str.replace(/\w\S*/g, function(txt){ return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase(); });
         }
         }


         // 6. STYLESHEET MODERN V7.0
        function getRefQuality(ref) {
            if (!ref || (!ref.url && !ref.title)) return 0;
            var score = 0;
            if(ref.url) score++; if(ref.title) score++; if(ref.publisher || ref.site) score++;
            if(ref.date) score++; if(ref.author) score++;
            return score;
        }
 
         // 6. STYLESHEET MODERN V8.0 TITANIUM (Dark Mode Ready & Animations)
         var css = `
         var css = `
            :root {
                --md-bg: #ffffff; --md-surface: #f8fafc; --md-border: #e2e8f0;
                --md-text-main: #0f172a; --md-text-sub: #64748b; --md-primary: #4f46e5;
                --md-primary-hover: #4338ca; --md-shadow: rgba(0,0,0,0.06);
                --md-glass: rgba(255, 255, 255, 0.8);
            }
            .md-dark {
                --md-bg: #1e1e2f; --md-surface: #2a2a40; --md-border: #3b3b5c;
                --md-text-main: #f1f5f9; --md-text-sub: #94a3b8; --md-primary: #6366f1;
                --md-primary-hover: #818cf8; --md-shadow: rgba(0,0,0,0.3);
                --md-glass: rgba(30, 30, 47, 0.8);
            }
             #mippedia-data-app {
             #mippedia-data-app {
                 background: #ffffff; border-radius: 16px; box-shadow: 0 4px 24px rgba(0,0,0,0.06);
                 background: var(--md-bg); border-radius: 16px; box-shadow: 0 4px 24px var(--md-shadow);
                 padding: 20px; margin: 20px 0; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
                 padding: 20px; margin: 20px 0; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
                 border: 1px solid #e2e8f0; max-width: 100%; box-sizing: border-box; overflow: hidden;
                 border: 1px solid var(--md-border); max-width: 100%; box-sizing: border-box; overflow: hidden;
                color: var(--md-text-main); transition: background 0.3s, color 0.3s;
             }
             }
              
              
            /* Sticky Header */
             .md-header {
             .md-header {
                 display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center;
                 display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center;
                 gap: 12px; margin-bottom: 16px; padding-bottom: 14px; border-bottom: 1px solid #f1f5f9;
                 gap: 12px; margin-bottom: 16px; padding-bottom: 14px; border-bottom: 1px solid var(--md-border);
                position: sticky; top: 0; background: var(--md-glass); backdrop-filter: blur(10px); z-index: 10;
             }
             }
             .md-title-container { display: flex; align-items: center; gap: 8px; flex: 1 1 auto; min-width: 180px; }
             .md-title-container { display: flex; align-items: center; gap: 8px; flex: 1 1 auto; min-width: 180px; }
             .md-title { font-size: 1.25rem; font-weight: 800; color: #0f172a; margin: 0; white-space: nowrap; letter-spacing: -0.3px; }
             .md-title { font-size: 1.25rem; font-weight: 800; margin: 0; white-space: nowrap; letter-spacing: -0.3px; }
             .md-actions { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
             .md-actions { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; }
              
              
             .md-btn-icon {
             .md-btn-icon {
                 background: #f8fafc; border: 1px solid #cbd5e1; cursor: pointer; color: #4f46e5;
                 background: var(--md-surface); border: 1px solid var(--md-border); cursor: pointer; color: var(--md-primary);
                 padding: 8px 14px; border-radius: 8px; transition: all 0.2s ease;
                 padding: 8px 12px; border-radius: 8px; transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
                 display: inline-flex; align-items: center; gap: 6px; font-size: 0.85rem; font-weight: 600; white-space: nowrap;
                 display: inline-flex; align-items: center; gap: 6px; font-size: 0.8rem; font-weight: 600; white-space: nowrap;
             }
             }
             .md-btn-icon:hover:not(:disabled) { background: #f1f5f9; border-color: #94a3b8; transform: translateY(-1px); }
             .md-btn-icon:hover:not(:disabled) { background: var(--md-border); transform: translateY(-2px); box-shadow: 0 4px 10px var(--md-shadow); }
             .md-btn-lock { color: #dc2626; background: #fef2f2; border-color: #fca5a5; }
 
            /* Tab Filters */
             .md-tabs { display: flex; gap: 10px; margin-bottom: 15px; border-bottom: 2px solid var(--md-surface); padding-bottom: 5px; }
            .md-tab { background: none; border: none; font-weight: 700; color: var(--md-text-sub); cursor: pointer; padding: 5px 10px; border-bottom: 2px solid transparent; transition: 0.2s; font-size: 0.85rem;}
            .md-tab.active { color: var(--md-primary); border-bottom-color: var(--md-primary); }
            .md-tab:hover { color: var(--md-primary); }


             .md-search-box { position: relative; margin-bottom: 16px; width: 100%; box-sizing: border-box; }
             .md-search-box { position: relative; margin-bottom: 16px; width: 100%; box-sizing: border-box; }
             .md-search-input {
             .md-search-input {
                 width: 100%; padding: 8px 12px 8px 34px; border: 1px solid #cbd5e1; border-radius: 8px;
                 width: 100%; padding: 10px 12px 10px 34px; border: 1px solid var(--md-border); border-radius: 8px;
                 font-size: 0.85rem; box-sizing: border-box; background: #f8fafc; transition: 0.2s;
                 font-size: 0.9rem; box-sizing: border-box; background: var(--md-surface); color: var(--md-text-main); transition: 0.2s;
             }
             }
             .md-search-input:focus { background: #fff; border-color: #4f46e5; outline: none; }
             .md-search-input:focus { background: var(--md-bg); border-color: var(--md-primary); outline: none; box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.2); }
             .md-search-icon { position: absolute; left: 10px; top: 50%; transform: translateY(-50%); color: #94a3b8; }
             .md-search-icon { position: absolute; left: 10px; top: 50%; transform: translateY(-50%); color: var(--md-text-sub); }


             /* Row Display Fix */
             /* Row Display & Drag */
             .md-row-display {
             .md-row-display {
                 display: flex; justify-content: space-between; align-items: flex-start;
                 display: flex; justify-content: space-between; align-items: flex-start;
                 padding: 16px 12px; border-bottom: 1px solid #f1f5f9; transition: all 0.2s;
                 padding: 14px 12px; border-bottom: 1px solid var(--md-border); transition: all 0.3s;
                 border-radius: 12px; gap: 12px; margin-bottom: 8px; background: #fff;
                 border-radius: 12px; gap: 12px; margin-bottom: 8px; background: var(--md-bg);
             }
             }
             .md-row-display:hover { background: #faf5ff; box-shadow: inset 4px 0 0 #6366f1; }
            .md-row-display.dragging { opacity: 0.5; background: var(--md-surface); }
             .md-row-display:hover { background: var(--md-surface); box-shadow: inset 4px 0 0 var(--md-primary); }
              
              
            .md-drag-handle { cursor: grab; padding-top: 5px; color: var(--md-text-sub); display:flex; align-items:center;}
             .md-data-group { display: flex; flex-direction: column; gap: 6px; flex: 1; min-width: 0; }
             .md-data-group { display: flex; flex-direction: column; gap: 6px; flex: 1; min-width: 0; }
             .md-data-label { font-size: 0.72rem; color: #64748b; font-weight: 800; text-transform: uppercase; letter-spacing: 0.6px; }
             .md-data-label { font-size: 0.72rem; color: var(--md-text-sub); font-weight: 800; text-transform: uppercase; letter-spacing: 0.6px; }
             .md-data-value-wrap { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
             .md-data-value-wrap { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
             .md-data-value { font-size: 1.02rem; color: #0f172a; line-height: 1.4; font-weight: 600; word-break: break-word; }
             .md-data-value { font-size: 1.05rem; font-weight: 600; word-break: break-word; color: var(--md-text-main); }
           
             .md-data-value a { color: var(--md-primary); text-decoration: none; }
             .md-btn-copy {
             .md-data-value a:hover { text-decoration: underline; }
                background: none; border: none; color: #94a3b8; cursor: pointer; padding: 2px 4px;
                border-radius: 4px; transition: 0.2s; display: inline-flex; align-items: center;
            }
             .md-btn-copy:hover { color: #4f46e5; background: #e0e7ff; }


             /* Tampilan Referensi V7.0 (Eksplisit & Elegan) */
             /* AKORDEON REFERENSI V8.0 */
             .md-ref-container { margin-top: 10px; width: 100%; box-sizing: border-box; }
             .md-ref-container { margin-top: 6px; width: 100%; box-sizing: border-box; }
             .md-ref-card {
             .md-ref-toggle {
                 background: #f8fafc; padding: 12px 14px; border-radius: 10px;
                 background: var(--md-surface); border: 1px solid var(--md-border); padding: 6px 12px; border-radius: 20px;
                 border-left: 4px solid #4f46e5; font-size: 0.85rem; display: flex; flex-direction: column; gap: 6px;
                 font-size: 0.78rem; font-weight: 700; color: var(--md-text-sub); cursor: pointer; display: inline-flex; align-items: center; gap: 6px;
                 box-sizing: border-box; border-top: 1px solid #f1f5f9; border-right: 1px solid #f1f5f9; border-bottom: 1px solid #f1f5f9;
                 transition: 0.2s; user-select: none;
             }
             }
             .md-ref-tag-header {
             .md-ref-toggle:hover { background: var(--md-border); color: var(--md-primary); }
                 font-size: 0.73rem; font-weight: 800; text-transform: uppercase; letter-spacing: 0.5px;
            .md-ref-toggle.open { background: var(--md-primary); color: white; border-color: var(--md-primary); }
                color: #4f46e5; display: flex; align-items: center; gap: 5px; margin-bottom: 2px;
           
            .md-ref-panel {
                 display: none; /* Disembunyikan by default */
                background: var(--md-surface); padding: 12px 14px; border-radius: 10px; margin-top: 8px;
                border-left: 4px solid var(--md-primary); font-size: 0.85rem; flex-direction: column; gap: 8px;
                border-top: 1px solid var(--md-border); border-right: 1px solid var(--md-border); border-bottom: 1px solid var(--md-border);
                animation: mdFadeIn 0.3s ease-out;
             }
             }
             .md-ref-header { font-weight: 700; color: #2563eb; display: inline-flex; align-items: center; gap: 6px; text-decoration: none; word-break: break-word; }
            @keyframes mdFadeIn { from { opacity: 0; transform: translateY(-5px); } to { opacity: 1; transform: translateY(0); } }
             .md-ref-header:hover { text-decoration: underline; }
           
             .md-ref-header { font-weight: 800; font-size: 0.9rem; color: var(--md-text-main); word-break: break-word; }
            .md-ref-details-grid { display: flex; flex-direction: column; gap: 4px; }
            .md-ref-detail-row { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 6px; font-size: 0.82rem; }
            .md-ref-lbl { font-weight: 700; color: var(--md-text-sub); white-space: nowrap; flex-shrink: 0; }
             .md-ref-val { color: var(--md-text-main); font-weight: 500; }
              
              
             .md-ref-details-grid { display: flex; flex-direction: column; gap: 3px; margin-top: 4px; }
             .md-ref-bottom { display: flex; justify-content: space-between; align-items: center; margin-top: 8px; border-top: 1px dashed var(--md-border); padding-top: 8px; }
            .md-ref-detail-row { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 6px; font-size: 0.82rem; color: #334155; }
             .md-ref-badge { display: inline-block; background: var(--md-border); color: var(--md-text-main); padding: 3px 8px; border-radius: 6px; font-weight: 700; font-size: 0.72rem; }
             .md-ref-lbl { font-weight: 700; color: #64748b; white-space: nowrap; flex-shrink: 0; }
             .md-btn-direct {
            .md-ref-val { color: #0f172a; font-weight: 500; word-break: break-word; }
                 background: var(--md-primary); color: white !important; text-decoration: none; padding: 5px 12px; border-radius: 6px;
             .md-ref-badge {
                font-weight: 700; font-size: 0.78rem; display: inline-flex; align-items: center; gap: 5px; transition: 0.2s;
                 display: inline-block; background: #e2e8f0; color: #334155; padding: 2px 8px;
                border-radius: 6px; font-weight: 700; font-size: 0.72rem; margin-top: 4px; width: fit-content;
             }
             }
            .md-btn-direct:hover { background: var(--md-primary-hover); transform: scale(1.05); text-decoration: none; }
            .md-q-indicator { display:inline-block; width:8px; height:8px; border-radius:50%; margin-left:5px; }


             /* Media Sosial Badges V7 */
             /* Media Sosial Badges */
             .md-social-group { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
             .md-social-group { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
             .md-social-badge {
             .md-social-badge {
                 display: inline-flex; align-items: center; gap: 6px; padding: 5px 11px; border-radius: 18px;
                 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;
                 font-size: 0.78rem; font-weight: 600; color: white !important; text-decoration: none; transition: transform 0.2s, opacity 0.2s;
                 box-shadow: 0 2px 4px rgba(0,0,0,0.05);
                 box-shadow: 0 2px 4px rgba(0,0,0,0.1);
            }
            .md-social-badge:hover { transform: translateY(-2px); opacity: 0.92; color: white; text-decoration: none; }
 
            /* Preset Pill Badges */
            .md-preset-wrapper { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
            .md-preset-pill {
                background: #f1f5f9; border: 1px solid #cbd5e1; padding: 4px 10px; border-radius: 12px;
                font-size: 0.75rem; font-weight: 600; color: #475569; cursor: pointer; transition: 0.2s;
             }
             }
             .md-preset-pill:hover { background: #e0e7ff; color: #3730a3; border-color: #a5b4fc; }
             .md-social-badge:hover { transform: translateY(-2px); opacity: 0.9; text-decoration: none; }


             /* Form Elements Responsif */
             /* Form Elements */
             .md-form-box { background: #ffffff; border-radius: 12px; padding: 18px; margin-top: 16px; border: 1px solid #cbd5e1; box-shadow: 0 4px 16px rgba(0,0,0,0.05); }
             .md-form-box { background: var(--md-bg); border-radius: 12px; padding: 18px; margin-top: 16px; border: 1px solid var(--md-border); box-shadow: 0 8px 30px var(--md-shadow); animation: mdFadeIn 0.3s; }
             .md-form-title { font-size: 1.05rem; font-weight: 800; color: #0f172a; margin: 0 0 16px 0; border-bottom: 2px solid #e2e8f0; padding-bottom: 8px; }
             .md-form-title { font-size: 1.1rem; font-weight: 800; margin: 0 0 16px 0; border-bottom: 2px solid var(--md-border); padding-bottom: 8px; display:flex; justify-content:space-between;}
             .md-form-group { margin-bottom: 14px; }
             .md-form-group { margin-bottom: 14px; position:relative;}
             .md-form-group label { display: block; font-size: 0.82rem; font-weight: 700; margin-bottom: 6px; color: #334155; }
             .md-form-group label { display: block; font-size: 0.82rem; font-weight: 700; margin-bottom: 6px; color: var(--md-text-sub); }
             .md-input, .md-select, .md-textarea {
             .md-input, .md-select, .md-textarea {
                 width: 100%; padding: 9px 12px; border: 1px solid #cbd5e1; border-radius: 8px;
                 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: #fff;
                 box-sizing: border-box; font-family: inherit; font-size: 0.9rem; transition: 0.2s; background: var(--md-surface); color: var(--md-text-main);
             }
             }
             .md-input:focus, .md-select:focus, .md-textarea:focus { border-color: #4f46e5; outline: none; box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.15); }
             .md-input:focus, .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); }
            .md-input.error { border-color: #ef4444; background: #fef2f2; }
            .md-dark .md-input.error { background: #3f1a1a; }
              
              
             .md-ref-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; background: #f8fafc; padding: 12px; border-radius: 8px; border: 1px dashed #cbd5e1; }
            .md-preset-pill { background: var(--md-surface); border: 1px solid var(--md-border); padding: 4px 10px; border-radius: 12px; font-size: 0.75rem; font-weight: 600; cursor: pointer; transition: 0.2s; display:inline-block; margin:2px;}
             .md-social-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; background: #f1f5f9; padding: 12px; border-radius: 8px; border: 1px solid #cbd5e1; max-height: 280px; overflow-y: auto; }
            .md-preset-pill:hover { background: var(--md-primary); color:white; border-color:var(--md-primary);}
           
             .md-ref-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; background: var(--md-surface); 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-surface); 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-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 #e2e8f0; flex-wrap: wrap; }
             .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 {
             .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; }
                padding: 10px 18px; border: none; border-radius: 8px; font-weight: 700; cursor: pointer;
             .md-btn:hover:not(:disabled) { transform: translateY(-2px); box-shadow: 0 4px 10px rgba(0,0,0,0.15); }
                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); }
             .md-btn-save { background: linear-gradient(135deg, #4f46e5, #4338ca); flex: 1; min-width: 140px; }
             .md-btn-save { background: linear-gradient(135deg, #4f46e5, #4338ca); flex: 1; min-width: 140px; }
             .md-btn-cancel { background: #64748b; }
             .md-btn-cancel { background: #64748b; }
             .md-btn-delete { background: #dc2626; margin-left: auto; }
             .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; }
             .md-char-count { position:absolute; right:10px; top:35px; font-size:0.7rem; color:var(--md-text-sub); }
            .is-loading .md-spinner { display: inline-block; }
            @keyframes md-spin { to { transform: rotate(360deg); } }


             @media (max-width: 600px) {
             @media (max-width: 600px) {
                 #mippedia-data-app { padding: 14px; margin: 14px 0; border-radius: 12px; }
                 #mippedia-data-app { padding: 14px; margin: 10px 0; border-radius: 12px; }
                 .md-header { flex-direction: column; align-items: flex-start; gap: 10px; }
                 .md-header { position: relative; backdrop-filter: none; }
                 .md-actions { width: 100%; justify-content: flex-start; }
                 .md-actions { width: 100%; justify-content: flex-start; overflow-x: auto; padding-bottom: 5px;}
                 .md-btn-icon { padding: 7px 12px; font-size: 0.8rem; }
                 .md-btn-icon { padding: 7px 10px; font-size: 0.75rem; }
                 .md-ref-grid, .md-social-grid { grid-template-columns: 1fr; }
                 .md-ref-grid, .md-social-grid { grid-template-columns: 1fr; }
                 .md-grid-full { grid-column: span 1; }
                 .md-grid-full { grid-column: span 1; }
                 .md-form-actions { flex-direction: column; width: 100%; }
                 .md-form-actions { flex-direction: column; width: 100%; }
                 .md-btn { width: 100%; margin: 0 !important; }
                 .md-btn { width: 100%; margin: 0 !important; }
                 .md-row-display { padding: 12px 8px; }
                 .md-row-display { padding: 12px 8px; gap: 8px; }
                .md-data-value { font-size: 0.95rem; }
                .md-drag-handle { display:none; } /* Hide drag on mobile to prevent scrolling issues */
             }
             }
             .md-native-render { display: none; }
             .md-native-render { display: none; }
         `;
         `;
         $('<style>').text(css).appendTo('head');
         $('<style id="md-styles">').text(css).appendTo('head');
        if(isDarkMode) $('body').addClass('md-dark');


         // 7. PARSER & PENYIMPANAN DATA
         // 7. PARSER & PENYIMPANAN DATA
Baris 264: Baris 315:
         function buildWikitextVal(item) {
         function buildWikitextVal(item) {
             var val = item.val;
             var val = item.val;
             if (item.linkTarget && item.linkTarget.trim() !== '') {
             if (item.linkTarget && item.linkTarget.trim() !== '') return "[[" + item.linkTarget.trim() + "|" + val + "]]";
                return "[[" + item.linkTarget.trim() + "|" + val + "]]";
            }
             if (item.linkSplit) {
             if (item.linkSplit) {
                 return val.replace(/([a-zA-Z0-9_À-ÿ\- ]+)/g, function(match) {
                 return val.replace(/([a-zA-Z0-9_À-ÿ\- ]+)/g, function(match) {
                     var trimmed = match.trim();
                     var trimmed = match.trim();
                     if (trimmed.length > 2 && trimmed.toLowerCase() !== 'dan' && trimmed.toLowerCase() !== 'atau') {
                     if (trimmed.length > 2 && trimmed.toLowerCase() !== 'dan' && trimmed.toLowerCase() !== 'atau') return "[[" + trimmed + "]]";
                        return "[[" + trimmed + "]]";
                    }
                     return match;
                     return match;
                 });
                 });
             }
             }
             if (item.link) {
             if (item.link) return "[[" + val + "]]";
                return "[[" + val + "]]";
            }
             return val;
             return val;
         }
         }
Baris 284: Baris 329:
         function buildWikitextRef(refObj) {
         function buildWikitextRef(refObj) {
             if (!refObj) return "";
             if (!refObj) return "";
             var title = refObj.title || "Rujukan";
             var title = refObj.title || extractDomain(refObj.url) || "Rujukan";
             var text = refObj.url ? "[" + ensureHttps(refObj.url) + " " + title + "]" : "'''" + title + "'''";
             var text = refObj.url ? "[" + ensureHttps(refObj.url) + " " + title + "]" : "'''" + title + "'''";
             var details = [];
             var details = [];
Baris 297: Baris 342:
         }
         }


         function saveData(actionType, $btnEl, originalContent) {
         function saveData(actionMsg, $btnEl, originalContent, isMinor) {
             if ($btnEl) $btnEl.addClass('is-loading').prop('disabled', true);
             if ($btnEl) { $btnEl.prop('disabled', true).html('Menyimpan...⏳'); }
              
              
             var jsonStr = JSON.stringify({ locked: isLocked, items: dataItems });
             var jsonStr = JSON.stringify({ locked: isLocked, items: dataItems });
             var wt = "<!-- MIPPEDIA_DATA_START | " + jsonStr + " -->\n";
             var wt = "<!-- MIPPEDIA_DATA_START | " + jsonStr + " -->\n<div class=\"md-native-render\">\n{| class=\"wikitable\"\n! Data !! Nilai !! Referensi\n";
            wt += "<div class=\"md-native-render\">\n{| class=\"wikitable\"\n! Data !! Nilai !! Referensi\n";
              
              
             dataItems.forEach(function(item) {
             dataItems.forEach(function(item) {
                var valTxt = buildWikitextVal(item);
                 wt += "|-\n| " + item.prop + " || " + buildWikitextVal(item) + " || " + buildWikitextRef(item.ref) + "\n";
                var refTxt = buildWikitextRef(item.ref);
                 wt += "|-\n| " + item.prop + " || " + valTxt + " || " + refTxt + "\n";
             });
             });
             wt += "|}\n</div>\n<!-- MIPPEDIA_DATA_END -->";
             wt += "|}\n</div>\n<!-- MIPPEDIA_DATA_END -->";
Baris 313: Baris 355:
             var newContent;
             var newContent;
             var regex = /<!-- MIPPEDIA_DATA_START \| .*? -->[\s\S]*?<!-- MIPPEDIA_DATA_END -->/;
             var regex = /<!-- MIPPEDIA_DATA_START \| .*? -->[\s\S]*?<!-- MIPPEDIA_DATA_END -->/;
             if (regex.test(originalContent)) {
             if (regex.test(originalContent)) newContent = originalContent.replace(regex, wt);
                newContent = originalContent.replace(regex, wt);
             else newContent = originalContent.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 Data V7: ' + actionType, minor: false
                 action: 'edit', title: pageName, text: newContent,  
                summary: 'Mippedia V8: ' + actionMsg, minor: isMinor || false
             }).done(function() {
             }).done(function() {
                 var nocacheUrl = location.pathname + "?refresh=" + new Date().getTime();
                 showToast('Berhasil disimpan! Memuat ulang...', 'success');
                 window.location.href = nocacheUrl;
                 setTimeout(function(){ window.location.reload(true); }, 1000);
             }).fail(function(err) {
             }).fail(function(err) {
                 if ($btnEl) $btnEl.removeClass('is-loading').prop('disabled', false);
                 if ($btnEl) $btnEl.prop('disabled', false).html('Coba Lagi');
                 alert("Gagal menyimpan! Error: " + err);
                 showToast("Gagal menyimpan: " + err, 'error');
             });
             });
         }
         }
Baris 334: Baris 374:
             var $app = $('<div id="mippedia-data-app"></div>');
             var $app = $('<div id="mippedia-data-app"></div>');
              
              
             // HEADER
             // HEADER & ACTION BAR
             var $header = $('<div class="md-header"></div>');
             var $header = $('<div class="md-header"></div>');
             var $titleContainer = $('<div class="md-title-container"><h3 class="md-title">' + svgEdit + ' Data Terstruktur</h3></div>');
             var $titleContainer = $('<div class="md-title-container"><h3 class="md-title">' + svgEdit + ' Data Terstruktur V8</h3></div>');
             var $actions = $('<div class="md-actions"></div>');
             var $actions = $('<div class="md-actions"></div>');
              
              
             // Tombol Ekspor JSON
             // Toggle Dark Mode
             var $jsonBtn = $('<button class="md-btn-icon" title="Ekspor/Impor JSON">' + svgCode + ' JSON</button>');
            var $darkBtn = $('<button class="md-btn-icon" title="Mode Gelap">' + (isDarkMode ? svgSun : svgMoon) + '</button>');
            $darkBtn.on('click', function() {
                isDarkMode = !isDarkMode;
                localStorage.setItem('md-dark-mode', isDarkMode);
                $('body').toggleClass('md-dark', isDarkMode);
                $(this).html(isDarkMode ? svgSun : svgMoon);
            });
            $actions.append($darkBtn);
 
            // Export CSV
            var $csvBtn = $('<button class="md-btn-icon" title="Ekspor CSV">' + svgDownload + ' CSV</button>');
            $csvBtn.on('click', function() { exportCSV(); });
            $actions.append($csvBtn);
 
             var $jsonBtn = $('<button class="md-btn-icon" title="JSON Tool">' + svgCode + ' JSON</button>');
             $jsonBtn.on('click', function() { showJsonModal(rawContent); });
             $jsonBtn.on('click', function() { showJsonModal(rawContent); });
             $actions.append($jsonBtn);
             $actions.append($jsonBtn);


             if (isSysop) {
             if (isSysop) {
                 var $lockBtn = $('<button class="md-btn-icon ' + (isLocked ? 'md-btn-unlock' : 'md-btn-lock') + '">' + (isLocked ? svgUnlock + ' Buka Kunci' : svgLock + ' Kunci') + ' <span class="md-spinner"></span></button>');
                 var $lockBtn = $('<button class="md-btn-icon">' + (isLocked ? svgUnlock + ' Buka Kunci' : svgLock + ' Kunci') + '</button>');
                 $lockBtn.on('click', function() {
                 $lockBtn.on('click', function() {
                     isLocked = !isLocked;
                     isLocked = !isLocked;
                     saveData(isLocked ? 'Mengunci data' : 'Membuka kunci data', $(this), rawContent);
                     saveData(isLocked ? 'Mengunci data' : 'Membuka kunci data', $(this), rawContent, true);
                 });
                 });
                 $actions.append($lockBtn);
                 $actions.append($lockBtn);
Baris 354: Baris 408:


             if (!isLocked || isSysop) {
             if (!isLocked || isSysop) {
                 var $addBtn = $('<button class="md-btn-icon" title="Tambah Data Baru">' + svgEdit + ' Tambah</button>');
                 var $addBtn = $('<button class="md-btn-icon" style="background:var(--md-primary); color:white; border-color:var(--md-primary);">' + svgEdit + ' Tambah</button>');
                 $addBtn.on('click', function() { showForm(-1, rawContent); });
                 $addBtn.on('click', function() { showForm(-1, rawContent); });
                 $actions.append($addBtn);
                 $actions.append($addBtn);
Baris 362: Baris 416:
             $app.append($header);
             $app.append($header);


             // SEARCH BAR
             // FILTER TABS & SEARCH
             if (dataItems.length > 2) {
             if (dataItems.length > 1) {
                 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>');
                var $tabArea = $('<div class="md-tabs"><button class="md-tab active" data-filter="all">Semua Data</button><button class="md-tab" data-filter="social">Punya Sosmed</button><button class="md-tab" data-filter="ref">Ada Referensi</button></div>');
                 $searchBox.find('input').on('keyup input', function() {
                 var $searchBox = $('<div class="md-search-box"><span class="md-search-icon">' + svgSearch + '</span><input type="text" class="md-search-input" placeholder="Cari data (label/nilai)..."></div>');
                     var q = $(this).val().toLowerCase();
               
                $tabArea.find('.md-tab').on('click', function() {
                    $tabArea.find('.md-tab').removeClass('active'); $(this).addClass('active');
                    filterList();
                });
                 $searchBox.find('input').on('keyup input', filterList);
               
                $app.append($tabArea).append($searchBox);
 
                function filterList() {
                     var q = $searchBox.find('input').val().toLowerCase();
                    var filter = $tabArea.find('.active').data('filter');
                   
                     $app.find('.md-row-display').each(function() {
                     $app.find('.md-row-display').each(function() {
                         var text = $(this).text().toLowerCase();
                         var $r = $(this);
                         $(this).toggle(text.indexOf(q) !== -1);
                        var text = $r.text().toLowerCase();
                         var hasSocial = $r.find('.md-social-group').length > 0;
                        var hasRef = $r.find('.md-ref-container').length > 0;
                       
                        var matchSearch = text.indexOf(q) !== -1;
                        var matchTab = filter === 'all' ? true : (filter === 'social' ? hasSocial : hasRef);
                       
                        $r.toggle(matchSearch && matchTab);
                     });
                     });
                 });
                 }
                $app.append($searchBox);
             }
             }


             // DAFTAR BARIS DATA
             // DAFTAR BARIS DATA (List)
             var $list = $('<div class="md-list"></div>');
             var $list = $('<div class="md-list"></div>');
             if (dataItems.length === 0) {
             if (dataItems.length === 0) {
                 $list.append('<div style="color:#64748b; text-align:center; padding: 25px 10px; background:#f8fafc; border-radius:10px; border:1px dashed #cbd5e1; font-size:0.88rem;">Belum ada data terstruktur. Klik <b>Tambah</b> untuk membuat baru.</div>');
                 $list.append('<div style="text-align:center; padding: 30px 10px; color:var(--md-text-sub); border:2px dashed var(--md-border); border-radius:12px; margin-top:10px;">Belum ada data. Klik <b>Tambah</b> untuk mulai menyusun mahakarya.</div>');
             } else {
             } else {
                 dataItems.forEach(function(item, index) {
                 dataItems.forEach(function(item, index) {
                     var $row = $('<div class="md-row-display"></div>');
                     var $row = $('<div class="md-row-display" draggable="true" data-index="'+index+'"></div>');
                    var $dragHandle = $('<div class="md-drag-handle" title="Tahan & Geser">' + svgDrag + '</div>');
                   
                     var $info = $('<div class="md-data-group"></div>');
                     var $info = $('<div class="md-data-group"></div>');
                     $info.append('<span class="md-data-label">' + item.prop + '</span>');
                     $info.append('<span class="md-data-label">' + item.prop + '</span>');
                      
                      
                     // RENDER NILAI DATA
                     // Render Nilai Data
                    var displayValHtml = '';
                     var rawVal = item.val || '';
                     var rawVal = item.val || '';
 
                    var displayValHtml = rawVal;
                     if (rawVal.match(/^https?:\/\//i)) {
                     if (rawVal.match(/^https?:\/\//i)) {
                        var domain = extractDomain(rawVal);
                         displayValHtml = '<a href="' + rawVal + '" target="_blank">' + extractDomain(rawVal) + ' ' + svgExternal + '</a>';
                         displayValHtml = '<a href="' + rawVal + '" target="_blank" style="color:#2563eb; font-weight:700; text-decoration:none;">' + domain + '</a>';
                     } else if (item.linkTarget && item.linkTarget.trim() !== '') {
                     } else if (item.linkTarget && item.linkTarget.trim() !== '') {
                         displayValHtml = '<a href="' + mw.util.getUrl(item.linkTarget.trim()) + '" style="color:#2563eb; font-weight:700; text-decoration:none;">' + rawVal + '</a>';
                         displayValHtml = '<a href="' + mw.util.getUrl(item.linkTarget.trim()) + '">' + rawVal + '</a>';
                     } else if (item.linkSplit) {
                     } else if (item.linkSplit) {
                         var parts = rawVal.split(/([,/\s]+dan\s+|[,/\s]+atau\s+|[,/]+)/gi);
                         var parts = rawVal.split(/([,/\s]+dan\s+|[,/\s]+atau\s+|[,/]+)/gi);
                         displayValHtml = parts.map(function(p) {
                         displayValHtml = parts.map(function(p) {
                             var trimmed = p.trim();
                             var trimmed = p.trim();
                             if (trimmed && !p.match(/^[,/\s]+$/) && trimmed.toLowerCase() !== 'dan' && trimmed.toLowerCase() !== 'atau') {
                             if (trimmed && !p.match(/^[,/\s]+$/) && !/^(dan|atau)$/i.test(trimmed)) {
                                 return '<a href="' + mw.util.getUrl(trimmed) + '" style="color:#2563eb; font-weight:700; text-decoration:none;">' + trimmed + '</a>';
                                 return '<a href="' + mw.util.getUrl(trimmed) + '">' + trimmed + '</a>';
                             }
                             }
                             return p;
                             return p;
                         }).join('');
                         }).join('');
                     } else if (item.link) {
                     } else if (item.link) {
                         displayValHtml = '<a href="' + mw.util.getUrl(rawVal) + '" style="color:#2563eb; font-weight:700; text-decoration:none;">' + rawVal + '</a>';
                         displayValHtml = '<a href="' + mw.util.getUrl(rawVal) + '">' + rawVal + '</a>';
                    } else {
                        displayValHtml = rawVal;
                     }
                     }


Baris 412: Baris 482:
                     $valWrap.append('<span class="md-data-value">' + displayValHtml + '</span>');
                     $valWrap.append('<span class="md-data-value">' + displayValHtml + '</span>');
                      
                      
                     var $copyBtn = $('<button class="md-btn-copy" title="Salin teks">' + svgCopy + '</button>');
                     var $copyBtn = $('<button class="md-btn-icon" style="padding:4px; border:none; background:transparent;" title="Salin teks">' + svgCopy + '</button>');
                     $copyBtn.on('click', function() {
                     $copyBtn.on('click', function() { navigator.clipboard.writeText(rawVal); showToast('Teks disalin: ' + rawVal, 'success'); });
                        navigator.clipboard.writeText(rawVal);
                        $(this).css('color', '#16a34a');
                        setTimeout(function(){ $copyBtn.css('color', '#94a3b8'); }, 1200);
                    });
                     $valWrap.append($copyBtn);
                     $valWrap.append($copyBtn);
                     $info.append($valWrap);
                     $info.append($valWrap);


                     // RENDER MEDIA SOSIAL & MUSIK
                     // Render Media Sosial (+ Twitch dll)
                     if (item.isPersonOrg && item.socials) {
                     if (item.isPersonOrg && item.socials) {
                         var $socialGroup = $('<div class="md-social-group"></div>');
                         var $socialGroup = $('<div class="md-social-group"></div>');
Baris 428: Baris 494:
                             var uname = item.socials[key];
                             var uname = item.socials[key];
                             if (uname) {
                             if (uname) {
                                 hasSocial = true;
                                 hasSocial = true; var platform = SOCIAL_PLATFORMS[key];
                                var platform = SOCIAL_PLATFORMS[key];
                                 var fullUrl = platform.base + uname.replace(/^@/, '');
                                 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('<a class="md-social-badge" href="'+fullUrl+'" target="_blank" style="background:'+platform.color+';">'+platform.icon+' '+platform.name+'</a>');
                                $socialGroup.append($badge);
                             }
                             }
                         });
                         });
Baris 438: Baris 502:
                     }
                     }
                      
                      
                     // RENDER REFERENSI EKSPLISIT (V7)
                     // Render FITUR AKORDEON REFERENSI
                     if (item.ref && (item.ref.url || item.ref.title)) {
                     if (item.ref && (item.ref.url || item.ref.title)) {
                         var ref = item.ref;
                         var ref = item.ref;
                         var $refContainer = $('<div class="md-ref-container"></div>');
                         var $refContainer = $('<div class="md-ref-container"></div>');
                         var $refCard = $('<div class="md-ref-card"></div>');
                         var refTitle = ref.title || extractDomain(ref.url) || "Rujukan Eksternal";
                          
                          
                         // Header Penjelas Referensi
                         // Toggle Button
                         $refCard.append('<div class="md-ref-tag-header">' + svgRef + ' Referensi:</div>');
                        var qScore = getRefQuality(ref);
                        var qColor = qScore >= 4 ? '#10b981' : (qScore >= 2 ? '#f59e0b' : '#ef4444');
                        var $toggleBtn = $('<button class="md-ref-toggle">' + svgRef + ' Lihat Referensi <span class="md-q-indicator" style="background:'+qColor+';" title="Kualitas Ref: '+qScore+'/5"></span></button>');
                       
                        // Panel Detail
                         var $refPanel = $('<div class="md-ref-panel"></div>');
                        $refPanel.append('<div class="md-ref-header">' + refTitle + '</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">Akses:</span><span class="md-ref-val">'+formatIndonesianDate(ref.date)+'</span></div>');
                        $refPanel.append($detailsGrid);


                         var refTitle = ref.title || "Sumber Rujukan";
                         var $refBottom = $('<div class="md-ref-bottom"></div>');
                         if (ref.url) {
                         if (ref.type) {
                             var safeUrl = ensureHttps(ref.url);
                             var tLbl = ref.type + (ref.subType ? ' • ' + ref.subType : '');
                             $refCard.append('<a href="' + safeUrl + '" target="_blank" class="md-ref-header">' + refTitle + '</a>');
                             $refBottom.append('<span class="md-ref-badge">' + tLbl + '</span>');
                         } else {
                         } else {
                             $refCard.append('<span class="md-ref-header" style="color:#0f172a;">' + refTitle + '</span>');
                             $refBottom.append('<span></span>'); // spacer
                         }
                         }


                         var $detailsGrid = $('<div class="md-ref-details-grid"></div>');
                         // Tombol Kunjungi Tautan Langsung
                         if (ref.author) {
                         if (ref.url) {
                             $detailsGrid.append('<div class="md-ref-detail-row"><span class="md-ref-lbl">Penulis:</span><span class="md-ref-val">' + ref.author + '</span></div>');
                            var safeUrl = ensureHttps(ref.url);
                             $refBottom.append('<a href="' + safeUrl + '" target="_blank" class="md-btn-direct">' + svgExternal + ' Kunjungi</a>');
                         }
                         }
                        if (ref.site) {
                         $refPanel.append($refBottom);
                            $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">Tanggal Akses:</span><span class="md-ref-val">' + formatIndonesianDate(ref.date) + '</span></div>');
                        }
                       
                         $refCard.append($detailsGrid);


                         if (ref.type) {
                         // Logic Buka-Tutup (Akordeon)
                             var typeLabel = ref.type + (ref.subType ? ' &bull; ' + ref.subType : '');
                        $toggleBtn.on('click', function() {
                             $refCard.append('<span class="md-ref-badge">' + typeLabel + '</span>');
                             var isOpen = $(this).hasClass('open');
                         }
                            $(this).toggleClass('open');
                             if(isOpen) {
                                $refPanel.slideUp(200);
                                $(this).html(svgRef + ' Lihat Referensi <span class="md-q-indicator" style="background:'+qColor+';"></span>');
                            } else {
                                $refPanel.slideDown(200).css('display', 'flex');
                                $(this).html(svgRef + ' Tutup Detail');
                            }
                         });


                         $refContainer.append($refCard);
                         $refContainer.append($toggleBtn).append($refPanel);
                         $info.append($refContainer);
                         $info.append($refContainer);
                     }
                     }
                      
                      
                     $row.append($info);
                     $row.append($dragHandle).append($info);


                     if (!isLocked || isSysop) {
                     if (!isLocked || isSysop) {
                         var $editIcon = $('<button class="md-btn-icon edit-btn" style="padding:6px 10px;">' + svgEdit + ' Edit</button>');
                        var $actionGroup = $('<div style="display:flex; flex-direction:column; gap:4px; align-items:flex-end;"></div>');
                         var $editIcon = $('<button class="md-btn-icon" style="padding:6px;">' + svgEdit + ' Edit</button>');
                         $editIcon.on('click', function() { showForm(index, rawContent); });
                         $editIcon.on('click', function() { showForm(index, rawContent); });
                         $row.append($editIcon);
                       
                        var $cloneIcon = $('<button class="md-btn-icon" style="padding:6px; background:transparent; border:none; color:var(--md-text-sub);" title="Duplikasi Data">' + svgClone + '</button>');
                        $cloneIcon.on('click', function() {
                            var cloned = JSON.parse(JSON.stringify(item));
                            dataItems.splice(index+1, 0, cloned);
                            saveData('Menduplikasi baris', null, rawContent, true);
                        });
 
                        $actionGroup.append($editIcon).append($cloneIcon);
                         $row.append($actionGroup);
                     }
                     }
                    // Simple Drag and Drop Event Binding
                    $row.on('dragstart', function(e) { $(this).addClass('dragging'); e.originalEvent.dataTransfer.setData('text/plain', index); });
                    $row.on('dragend', function() { $(this).removeClass('dragging'); });
                    $row.on('dragover', function(e) { e.preventDefault(); $(this).css('border-top', '3px solid var(--md-primary)'); });
                    $row.on('dragleave', function() { $(this).css('border-top', ''); });
                    $row.on('drop', function(e) {
                        e.preventDefault(); $(this).css('border-top', '');
                        var oldIdx = parseInt(e.originalEvent.dataTransfer.getData('text/plain'), 10);
                        var newIdx = parseInt($(this).data('index'), 10);
                        if (oldIdx === newIdx) return;
                        var movedItem = dataItems.splice(oldIdx, 1)[0];
                        dataItems.splice(newIdx, 0, movedItem);
                        saveData('Mengubah urutan baris', null, rawContent, true);
                    });
                     $list.append($row);
                     $list.append($row);
                 });
                 });
Baris 499: Baris 601:
         }
         }


         // 9. FORM EDIT DENGAN PRESET & PLATFORM LENGKAP
        // Ekspor ke CSV Generator
        function exportCSV() {
            if(dataItems.length === 0) return showToast('Tidak ada data untuk diekspor', 'error');
            var csv = 'Label,Nilai,Tipe Referensi,URL Referensi\n';
            dataItems.forEach(function(item) {
                var l = '"'+(item.prop||'').replace(/"/g,'""')+'"';
                var v = '"'+(item.val||'').replace(/"/g,'""')+'"';
                var rt = '"'+((item.ref && item.ref.type) ? item.ref.type : '')+'"';
                var ru = '"'+((item.ref && item.ref.url) ? item.ref.url : '')+'"';
                csv += [l, v, rt, ru].join(',') + '\n';
            });
            var blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' });
            var link = document.createElement('a');
            var url = URL.createObjectURL(blob);
            link.setAttribute('href', url); link.setAttribute('download', 'Data_Mippedia_' + getTodayString() + '.csv');
            link.style.visibility = 'hidden'; document.body.appendChild(link); link.click(); document.body.removeChild(link);
            showToast('File CSV berhasil diunduh!', 'success');
        }
 
         // 9. FORM EDIT V8
         function showForm(index, rawContent) {
         function showForm(index, rawContent) {
             var $container = $('#md-form-container');
             var $container = $('#md-form-container');
Baris 510: Baris 631:


             var $form = $('<div class="md-form-box"></div>');
             var $form = $('<div class="md-form-box"></div>');
             $form.append('<h4 class="md-form-title">' + (isNew ? 'Tambah Data Baru' : 'Edit Data Terstruktur') + '</h4>');
             var $closeIcon = $('<button style="background:none;border:none;cursor:pointer;color:var(--md-text-sub);font-size:1.2rem;line-height:1;">&times;</button>');
            $closeIcon.on('click', function(){ $container.empty(); });
           
            var $titleWrap = $('<div class="md-form-title"></div>').append('<span>' + (isNew ? 'Tambah Data Baru' : 'Edit Data Terstruktur') + '</span>').append($closeIcon);
            $form.append($titleWrap);
           
            // Label Data + Auto Capitalize + Presets
            var $propGroup = $('<div class="md-form-group"><label>Label Data (Kategori)</label></div>');
            var $propInp = $('<input type="text" id="md-inp-prop" class="md-input" placeholder="Misal: Tanggal Lahir" value="' + (currentData.prop || '') + '">');
            $propInp.on('blur', function() { $(this).val(toTitleCase($(this).val())); }); // Auto Format
            $propGroup.append($propInp);
              
              
            // Label Data + Preset Fast Selector
             var $presetWrap = $('<div style="margin-top:6px;"></div>');
             var $propGroup = $('<div class="md-form-group"><label>Label Data (Contoh: Pekerjaan, Sutradara, Tempat Lahir)</label><input type="text" id="md-inp-prop" class="md-input" value="' + (currentData.prop || '') + '"></div>');
            var $presetWrap = $('<div class="md-preset-wrapper"></div>');
             PRESET_LABELS.forEach(function(lbl) {
             PRESET_LABELS.forEach(function(lbl) {
                 var $pill = $('<span class="md-preset-pill">' + lbl + '</span>');
                 var $pill = $('<span class="md-preset-pill">' + lbl + '</span>');
                 $pill.on('click', function() { $('#md-inp-prop').val(lbl); });
                 $pill.on('click', function() { $propInp.val(lbl); $propInp.removeClass('error'); });
                 $presetWrap.append($pill);
                 $presetWrap.append($pill);
             });
             });
Baris 523: Baris 652:
             $form.append($propGroup);
             $form.append($propGroup);
              
              
             // Nilai Data & Wikilink Options
             // Nilai Data & Char Counter
             var $valBox = $('<div class="md-form-group"></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 || '') + '">');
             $valBox.append('<label>Nilai Data Utama</label>');
            var $valInp = $('<input type="text" id="md-inp-val" class="md-input" value="' + (currentData.val || '') + '">');
            var $charCount = $('<span class="md-char-count">0</span>');
            $valInp.on('input', function() { $charCount.text($(this).val().length); }).trigger('input');
              
              
             var $wikilinkOpts = $('<div style="margin-top:8px; display:flex; flex-direction:column; gap:8px; background:#f8fafc; padding:10px; border-radius:8px; border:1px solid #e2e8f0;"></div>');
             $valBox.append($valInp).append($charCount);
           
            var chkLink = currentData.link ? 'checked' : '';
            var chkSplit = currentData.linkSplit ? 'checked' : '';
           
            $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>');
            $wikilinkOpts.append('<label style="display:flex; align-items:center; gap:8px; font-size:0.82rem; font-weight:700; cursor:pointer;"><input type="checkbox" id="md-inp-split" ' + chkSplit + '> Smart Split Wikilink</label>');
           
            var $pipedGroup = $('<div style="margin-top:4px;"><label style="font-size:0.78rem; color:#475569;">Target Halaman Khusus (Opsional):</label><input type="text" id="md-inp-target" class="md-input" style="padding:6px 10px; font-size:0.85rem;" placeholder="Contoh: Diskografi Rumi Haitami" value="' + (currentData.linkTarget || '') + '"></div>');
            $wikilinkOpts.append($pipedGroup);
              
              
            var $wikilinkOpts = $('<div style="margin-top:8px; display:flex; flex-direction:column; gap:8px; background:var(--md-surface); padding:10px; border-radius:8px; border:1px solid var(--md-border);"></div>');
            $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" ' + (currentData.link?'checked':'') + '> Buat Wikilink Standar</label>');
            $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" ' + (currentData.linkSplit?'checked':'') + '> Pisah Otomatis (Dan/Atau/Koma)</label>');
            $wikilinkOpts.append('<div style="margin-top:4px;"><label style="font-size:0.75rem; color:var(--md-text-sub);">Halaman Target (Opsional):</label><input type="text" id="md-inp-target" class="md-input" style="padding:6px; font-size:0.8rem;" value="' + (currentData.linkTarget || '') + '"></div>');
             $valBox.append($wikilinkOpts);
             $valBox.append($wikilinkOpts);
             $form.append($valBox);
             $form.append($valBox);


             // MEDIA SOSIAL & MUSIK LENGKAP
             // SOSIAL MEDIA
             var $socialSec = $('<div class="md-form-group" style="margin-top:16px;"></div>');
             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);"><input type="checkbox" id="md-chk-person" ' + (currentData.isPersonOrg?'checked':'') + '> Aktifkan Profil Sosial / Musik</label>');
             $socialSec.append('<label style="display:flex; align-items:center; gap:8px; cursor:pointer; background:#e0e7ff; padding:10px; border-radius:8px; font-weight:700; color:#3730a3; font-size:0.85rem;"><input type="checkbox" id="md-chk-person" ' + chkPerson + '> Aktifkan Profil Media Sosial</label>');
              
              
             var $socialGrid = $('<div class="md-social-grid" id="md-social-box" style="display:' + (currentData.isPersonOrg ? 'grid' : 'none') + '; margin-top:8px;"></div>');
             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) {
             Object.keys(SOCIAL_PLATFORMS).forEach(function(key) {
                 var p = SOCIAL_PLATFORMS[key];
                 var p = SOCIAL_PLATFORMS[key];
                var valUname = currentSocials[key] || '';
                 $socialGrid.append('<div><label style="font-size:0.75rem; color:var(--md-text-sub);">' + p.name + '</label><input type="text" id="md-soc-' + key + '" class="md-input" placeholder="@username" value="' + (currentSocials[key]||'') + '"></div>');
                 $socialGrid.append('<div><label style="font-size:0.78rem; color:#334155; font-weight:700;">' + p.name + '</label><input type="text" id="md-soc-' + key + '" class="md-input" placeholder="ID / Username" value="' + valUname + '"></div>');
             });
             });
             $socialSec.append($socialGrid);
             $socialSec.append($socialGrid);
             $form.append($socialSec);
             $form.append($socialSec);


             // GRID DETAIL RUJUKAN LENGKAP
             // REFERENSI
             var $refArea = $('<div class="md-form-group" style="margin-top:20px;"></div>');
             var $refArea = $('<div class="md-form-group" style="margin-top:20px;"></div>');
             $refArea.append('<label style="font-size:0.95rem; font-weight:800; color:#0f172a;">Sumber Referensi</label>');
             $refArea.append('<label style="font-size:0.95rem; font-weight:800; color:var(--md-text-main); border-bottom:1px solid var(--md-border); padding-bottom:5px;">Sumber Referensi</label>');
              
              
             var $refGrid = $('<div class="md-ref-grid"></div>');
             var $refGrid = $('<div class="md-ref-grid" style="margin-top:10px;"></div>');
           
             var $typeSel = $('<select id="md-ref-type" class="md-select"><option value="">-- Tipe Utama --</option></select>');
             var $typeSel = $('<select id="md-ref-type" class="md-select"><option value="">-- Pilih Tipe Utama --</option></select>');
             Object.keys(REF_TYPES).forEach(function(t) { $typeSel.append('<option value="'+t+'" '+(currentRef.type===t?'selected':'')+'>'+t+'</option>'); });
             Object.keys(REF_TYPES).forEach(function(t) {
             var $subTypeSel = $('<select id="md-ref-subtype" class="md-select"><option value="">-- Sub-Tipe --</option></select>');
                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="">-- Pilih Sub-Tipe Spesifik --</option></select>');
              
              
             function updateSubTypes(mainType, selectedSub) {
             function updateSubTypes(mainType, selectedSub) {
                 $subTypeSel.empty().append('<option value="">-- Pilih Sub-Tipe Spesifik --</option>');
                 $subTypeSel.empty().append('<option value="">-- Sub-Tipe --</option>');
                 if (mainType && REF_TYPES[mainType]) {
                 if (mainType && REF_TYPES[mainType]) {
                     REF_TYPES[mainType].forEach(function(st) {
                     REF_TYPES[mainType].forEach(function(st) { $subTypeSel.append('<option value="'+st+'" '+(selectedSub===st?'selected':'')+'>'+st+'</option>'); });
                        var sel = selectedSub === st ? 'selected' : '';
                        $subTypeSel.append('<option value="' + st + '" ' + sel + '>' + st + '</option>');
                    });
                 }
                 }
             }
             }
             $typeSel.on('change', function() { updateSubTypes($(this).val(), ''); });
             $typeSel.on('change', function() { updateSubTypes($(this).val(), ''); });
             updateSubTypes(currentRef.type, currentRef.subType);
             updateSubTypes(currentRef.type, currentRef.subType);


             $refGrid.append('<div><label style="font-size:0.78rem;">Tipe Utama</label></div>').find('div').last().append($typeSel);
             $refGrid.append('<div><label style="font-size:0.75rem;">Tipe Utama</label></div>').find('div').last().append($typeSel);
             $refGrid.append('<div><label style="font-size:0.78rem;">Sub-Tipe</label></div>').find('div').last().append($subTypeSel);
             $refGrid.append('<div><label style="font-size:0.75rem;">Sub-Tipe</label></div>').find('div').last().append($subTypeSel);


             var $urlInput = $('<input type="url" id="md-ref-url" class="md-input" placeholder="https://...." value="' + (currentRef.url || '') + '">');
            // Auto-Fill URL Logic
             var $urlInput = $('<input type="url" id="md-ref-url" class="md-input" placeholder="https://..." value="' + (currentRef.url || '') + '">');
            var $siteInp = $('<input type="text" id="md-ref-site" class="md-input" placeholder="Nama Situs" value="' + (currentRef.site || '') + '">');
            var $titleInp = $('<input type="text" id="md-ref-title" class="md-input" placeholder="Judul Halaman" value="' + (currentRef.title || '') + '">');
           
             $urlInput.on('blur', function() {
             $urlInput.on('blur', function() {
                 var u = ensureHttps($(this).val());
                 var u = ensureHttps($(this).val()); $(this).val(u);
                $(this).val(u);
                 if (u) {
                 var $siteInp = $('#md-ref-site');
                    var domain = extractDomain(u);
                if (u && !$siteInp.val().trim()) {
                    if (!$siteInp.val().trim()) $siteInp.val(domain);
                     $siteInp.val(extractDomain(u));
                    if (!$titleInp.val().trim()) $titleInp.val(domain);
                    // Auto Select Tipe
                     if(u.indexOf('youtube.com') !== -1 || u.indexOf('youtu.be') !== -1) $typeSel.val('Video').trigger('change');
                    else if(u.indexOf('instagram.com') !== -1 || u.indexOf('twitter.com') !== -1 || u.indexOf('x.com') !== -1) $typeSel.val('Media Sosial').trigger('change');
                 }
                 }
             });
             });


             $refGrid.append('<div class="md-grid-full"><label style="font-size:0.78rem;">URL Rujukan</label></div>').find('div').last().append($urlInput);
             $refGrid.append('<div class="md-grid-full"><label style="font-size:0.75rem;">URL Rujukan</label></div>').find('div').last().append($urlInput);
             $refGrid.append('<div><label style="font-size:0.78rem;">Judul Halaman</label><input type="text" id="md-ref-title" class="md-input" placeholder="Judul Rujukan" value="' + (currentRef.title || '') + '"></div>');
             $refGrid.append('<div><label style="font-size:0.75rem;">Judul Halaman</label></div>').find('div').last().append($titleInp);
             $refGrid.append('<div><label style="font-size:0.78rem;">Nama Situs</label><input type="text" id="md-ref-site" class="md-input" placeholder="Situs" value="' + (currentRef.site || '') + '"></div>');
             $refGrid.append('<div><label style="font-size:0.75rem;">Nama Situs</label></div>').find('div').last().append($siteInp);
             $refGrid.append('<div><label style="font-size:0.78rem;">Penulis</label><input type="text" id="md-ref-author" class="md-input" placeholder="Penulis" value="' + (currentRef.author || '') + '"></div>');
             $refGrid.append('<div><label style="font-size:0.75rem;">Penulis/Kreator</label><input type="text" id="md-ref-author" class="md-input" value="' + (currentRef.author || '') + '"></div>');
             $refGrid.append('<div><label style="font-size:0.78rem;">Penerbit</label><input type="text" id="md-ref-publisher" class="md-input" placeholder="Penerbit" value="' + (currentRef.publisher || '') + '"></div>');
             $refGrid.append('<div><label style="font-size:0.75rem;">Penerbit (Opsional)</label><input type="text" id="md-ref-publisher" class="md-input" value="' + (currentRef.publisher || '') + '"></div>');
              
              
            // Tanggal Akses + Hari Ini
             var $dateBox = $('<div><label style="font-size:0.75rem;">Tgl Akses</label></div>');
             var $dateBox = $('<div><label style="font-size:0.78rem;">Tanggal Akses</label></div>');
             var $dateInpWrap = $('<div style="display:flex; gap:4px;"></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 $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">Hari Ini</button>');
             var $todayBtn = $('<button type="button" class="md-btn-icon" style="padding:4px 6px;" title="Set Hari Ini">Cetak H.Ini</button>');
             $todayBtn.on('click', function() { $dateInp.val(getTodayString()); });
             $todayBtn.on('click', function() { $dateInp.val(getTodayString()); });
             $dateInpWrap.append($dateInp).append($todayBtn);
             $dateInpWrap.append($dateInp).append($todayBtn);
Baris 614: Baris 736:
             $form.append($refArea);
             $form.append($refArea);


             // TOMBOL AKSI FORM
             // Edit Summary & Actions
            var $summaryBox = $('<div class="md-form-group" style="margin-top:10px;"><input type="text" id="md-edit-summary" class="md-input" placeholder="Ringkasan suntingan (opsional)..." style="font-size:0.8rem; background:var(--md-bg);"></div>');
            var $minorChk = $('<label style="font-size:0.75rem; margin-left:10px;"><input type="checkbox" id="md-edit-minor"> Suntingan Kecil</label>');
            $summaryBox.append($minorChk);
            $form.append($summaryBox);
 
             var $actions = $('<div class="md-form-actions"></div>');
             var $actions = $('<div class="md-form-actions"></div>');
             var $btnSave = $('<button class="md-btn md-btn-save">Terbitkan<span class="md-spinner"></span></button>');
             var $btnSave = $('<button class="md-btn md-btn-save">Simpan Perubahan</button>');
             var $btnCancel = $('<button class="md-btn md-btn-cancel">Batal</button>');
             var $btnCancel = $('<button class="md-btn md-btn-cancel">Batal</button>');
           
             $actions.append($btnSave).append($btnCancel);
             $actions.append($btnSave).append($btnCancel);
              
              
             if (!isNew) {
             if (!isNew) {
                 var $btnDelete = $('<button class="md-btn md-btn-delete">Hapus Data<span class="md-spinner"></span></button>');
                 var $btnDelete = $('<button class="md-btn md-btn-delete">Hapus Baris</button>');
                 $btnDelete.on('click', function() {
                 $btnDelete.on('click', function() {
                     if(confirm('Yakin ingin menghapus item data ini?')) {
                     if(confirm('Yakin ingin membuang data ini ke tong sampah?')) {
                         dataItems.splice(index, 1);
                         dataItems.splice(index, 1);
                         saveData('Menghapus data', $(this), rawContent);
                         saveData('Menghapus data (' + currentData.prop + ')', $(this), rawContent, false);
                     }
                     }
                 });
                 });
Baris 635: Baris 761:
             $container.append($form);
             $container.append($form);


            // Interaksi Form
             $('#md-chk-person').on('change', function() {
             $('#md-chk-person').on('change', function() {
                 if($(this).is(':checked')) $('#md-social-box').css('display', 'grid');
                 if($(this).is(':checked')) $('#md-social-box').slideDown(200).css('display', 'grid');
                 else $('#md-social-box').hide();
                 else $('#md-social-box').slideUp(200);
             });
             });


             $('html, body').animate({ scrollTop: $form.offset().top - 60 }, 250);
             $('html, body').animate({ scrollTop: $form.offset().top - 80 }, 300);
             $btnCancel.on('click', function() { $container.empty(); });
             $btnCancel.on('click', function() { $container.empty(); });
           
            // Hotkeys (Ctrl+S & Esc)
            $form.on('keydown', function(e) {
                if (e.ctrlKey && e.key === 's') { e.preventDefault(); $btnSave.click(); }
                if (e.key === 'Escape') $btnCancel.click();
            });
            $propInp.focus(); // Auto focus


             $btnSave.on('click', function() {
             $btnSave.on('click', function() {
                 var newProp = $('#md-inp-prop').val().trim();
                 // Validation
                 var newVal = $('#md-inp-val').val().trim();
                $propInp.removeClass('error'); $valInp.removeClass('error');
 
                var newProp = $propInp.val().trim();
                 var newVal = $valInp.val().trim();
               
                 if (!newProp || !newVal) {
                 if (!newProp || !newVal) {
                     alert("Label Data dan Nilai wajib diisi!"); return;
                     if(!newProp) $propInp.addClass('error');
                    if(!newVal) $valInp.addClass('error');
                    showToast("Label dan Nilai wajib diisi!", "error");
                    return;
                 }
                 }


Baris 661: Baris 800:


                 var refObj = {
                 var refObj = {
                     type: $('#md-ref-type').val(),
                     type: $typeSel.val(), subType: $subTypeSel.val(),
                    subType: $('#md-ref-subtype').val(),
                     url: ensureHttps($urlInput.val()), title: $titleInp.val().trim(),
                     url: ensureHttps($('#md-ref-url').val()),
                     site: $siteInp.val().trim(), author: $('#md-ref-author').val().trim(),
                    title: $('#md-ref-title').val().trim(),
                     publisher: $('#md-ref-publisher').val().trim(), date: $dateInp.val()
                     site: $('#md-ref-site').val().trim(),
                    author: $('#md-ref-author').val().trim(),
                     publisher: $('#md-ref-publisher').val().trim(),
                    date: $('#md-ref-date').val()
                 };
                 };


                // Clean empty refs
                 Object.keys(refObj).forEach(function(key) { if (!refObj[key]) delete refObj[key]; });
                 Object.keys(refObj).forEach(function(key) { if (!refObj[key]) delete refObj[key]; });
                 if (Object.keys(refObj).length === 0) refObj = null;
                 if (Object.keys(refObj).length === 0) refObj = null;


                 var newItem = {
                 var newItem = {
                     prop: newProp,
                     prop: newProp, val: newVal,
                    val: newVal,
                     link: $('#md-inp-link').is(':checked'), linkSplit: $('#md-inp-split').is(':checked'),
                     link: $('#md-inp-link').is(':checked'),
                    linkSplit: $('#md-inp-split').is(':checked'),
                     linkTarget: $('#md-inp-target').val().trim(),
                     linkTarget: $('#md-inp-target').val().trim(),
                     isPersonOrg: isPerson,
                     isPersonOrg: isPerson, socials: socObj, ref: refObj
                    socials: socObj,
                    ref: refObj
                 };
                 };


Baris 688: Baris 820:
                 else dataItems[index] = newItem;  
                 else dataItems[index] = newItem;  


                 saveData(isNew ? 'Tambah data' : 'Edit data', $(this), rawContent);
                 var cSum = $('#md-edit-summary').val().trim();
                var sumMsg = cSum ? cSum : (isNew ? 'Tambah data ' + newProp : 'Edit data ' + newProp);
                var isMin = $('#md-edit-minor').is(':checked');
               
                saveData(sumMsg, $(this), rawContent, isMin);
             });
             });
         }
         }


         // 10. JSON EXPORT & IMPORT MODAL
         // 10. JSON EXPORT & IMPORT (MODAL V8)
         function showJsonModal(rawContent) {
         function showJsonModal(rawContent) {
             var $container = $('#md-form-container');
             var $container = $('#md-form-container');
Baris 699: Baris 835:
             var jsonStr = JSON.stringify(dataItems, null, 2);
             var jsonStr = JSON.stringify(dataItems, null, 2);
             var $box = $('<div class="md-form-box"></div>');
             var $box = $('<div class="md-form-box"></div>');
             $box.append('<h4 class="md-form-title">Ekspor / Impor JSON Data</h4>');
             $box.append('<h4 class="md-form-title">Console Data (JSON)</h4>');
             $box.append('<p style="font-size:0.82rem; color:#64748b; margin-bottom:10px;">Anda dapat menyalin struktur JSON di bawah untuk cadangan atau menempelkan JSON dari artikel lain.</p>');
             $box.append('<p style="font-size:0.8rem; color:var(--md-text-sub); margin-bottom:10px;">Gunakan ini untuk backup data atau migrasi cepat antar halaman.</p>');
              
              
             var $txt = $('<textarea class="md-textarea" rows="10" style="font-family:monospace; font-size:0.8rem;"></textarea>').val(jsonStr);
             var $txt = $('<textarea class="md-textarea" rows="12" style="font-family:monospace; font-size:0.8rem; background:#1e1e1e; color:#d4d4d4;"></textarea>').val(jsonStr);
             $box.append($txt);
             $box.append($txt);


             var $actions = $('<div class="md-form-actions"></div>');
             var $actions = $('<div class="md-form-actions"></div>');
             var $btnImport = $('<button class="md-btn md-btn-save">Impor JSON & Simpan <span class="md-spinner"></span></button>');
             var $btnImport = $('<button class="md-btn md-btn-save">Timpa Data dengan JSON di Atas</button>');
            var $btnCopy = $('<button class="md-btn" style="background:#10b981;">Salin Kode</button>');
             var $btnCancel = $('<button class="md-btn md-btn-cancel">Tutup</button>');
             var $btnCancel = $('<button class="md-btn md-btn-cancel">Tutup</button>');


             $actions.append($btnImport).append($btnCancel);
             $actions.append($btnImport).append($btnCopy).append($btnCancel);
             $box.append($actions);
             $box.append($actions);
             $container.append($box);
             $container.append($box);


             $btnCancel.on('click', function() { $container.empty(); });
             $btnCancel.on('click', function() { $container.empty(); });
            $btnCopy.on('click', function() { navigator.clipboard.writeText($txt.val()); showToast('JSON Disalin!', 'success'); });
           
             $btnImport.on('click', function() {
             $btnImport.on('click', function() {
                 try {
                 try {
Baris 719: Baris 858:
                     if (Array.isArray(parsed)) {
                     if (Array.isArray(parsed)) {
                         dataItems = parsed;
                         dataItems = parsed;
                         saveData('Impor data dari JSON', $(this), rawContent);
                         saveData('Impor massal dari JSON', $(this), rawContent, false);
                     } else {
                     } else showToast("Format JSON salah! Harus berawal [ dan berakhir ]", "error");
                        alert("Format JSON harus berupa Array items!");
                 } catch(e) { showToast("Error JSON: " + e.message, "error"); }
                    }
                 } catch(e) {
                    alert("Format JSON tidak valid: " + e.message);
                }
             });
             });
         }
         }


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


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


/* ==========================================================
/* ==========================================================