MediaWiki:Common.js: Perbedaan antara revisi

Admin (bicara | kontrib)
Tidak ada ringkasan suntingan
Tanda: Suntingan perangkat seluler Suntingan peramban seluler
Admin (bicara | kontrib)
Tidak ada ringkasan suntingan
Tanda: Suntingan perangkat seluler Suntingan peramban seluler
Baris 2: Baris 2:
  * ====================================================================
  * ====================================================================
  * MIPPEDIA DATA - ADVANCED STRUCTURED DATA SYSTEM (V8.0 ULTIMATE)
  * MIPPEDIA DATA - ADVANCED STRUCTURED DATA SYSTEM (V8.0 ULTIMATE)
* Fitur Utama: Collapsible References, Direct Visit Links, Toast UI,
* Dark Mode Ready, Move Up/Down, Auto-Domain, 45+ Pro Features.
  * ====================================================================
  * ====================================================================
  */
  */
Baris 13: Baris 11:


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


         // 1. DATA MASTER PLATFORM MEDIA SOSIAL & MUSIK (DIPERLUAS 20+ PLATFORM)
         // 1. DATA MASTER PLATFORM
         var SOCIAL_PLATFORMS = {
         var SOCIAL_PLATFORMS = {
             applemusic: { name: 'Apple Music', base: 'https://music.apple.com/artist/', color: '#fc3c44', icon: '🎵' },
             applemusic: { name: 'Apple Music', base: 'https://music.apple.com/artist/', color: '#fc3c44', icon: '<svg width="13" height="13" viewBox="0 0 24 24" fill="currentColor"><path d="M12 2C6.477 2 2 6.477 2 12s4.477 10 10 10 10-4.477 10-10S17.523 2 12 2zm3.32 12.383c-.328.232-.82.418-1.32.418-1.238 0-1.922-.828-1.922-2.191v-4.14l4.312-.868v1.398l-2.91.586v2.805c0 .734.336 1.148.977 1.148.336 0 .617-.094.863-.258v1.102z"/></svg>' },
             spotify: { name: 'Spotify', base: 'https://open.spotify.com/artist/', color: '#1db954', icon: '🎧' },
             spotify: { name: 'Spotify', base: 'https://open.spotify.com/artist/', color: '#1db954', icon: '<svg width="13" height="13" viewBox="0 0 24 24" fill="currentColor"><path d="M12 2C6.477 2 2 6.477 2 12s4.477 10 10 10 10-4.477 10-10S17.523 2 12 2zm4.586 14.424c-.18.295-.563.387-.857.207-2.35-1.434-5.308-1.758-8.793-.963-.335.077-.67-.133-.746-.468-.077-.334.132-.67.467-.745 3.816-.87 7.092-.493 9.72 1.112.294.18.386.563.209.857zm1.213-2.71c-.226.368-.703.483-1.07.258-2.688-1.652-6.785-2.13-9.965-1.164-.413.125-.85-.108-.975-.522-.125-.413.108-.85.522-.975 3.633-1.102 8.157-.568 11.23 1.332.368.226.483.703.258 1.071zm.14-2.827c-3.225-1.915-8.54-2.092-11.614-1.16-.503.153-1.037-.133-1.19-.636-.152-.503.133-1.037.636-1.19 3.532-1.072 9.404-.865 13.115 1.338.45.267.598.85.33 1.3-.267.45-.85.598-1.3.33z"/></svg>' },
             soundcloud: { name: 'SoundCloud', base: 'https://soundcloud.com/', color: '#ff5500', icon: '☁️' },
             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>' },
            bandcamp: { name: 'Bandcamp', base: 'https://bandcamp.com/', color: '#1da0c3', icon: '🎸' },
             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: '📸' },
             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: '📱' },
             twitter: { name: 'X / Twitter', base: 'https://x.com/', color: '#0f1419', icon: '<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M23 3a10.9 10.9 0 0 1-3.14 1.53 4.48 4.48 0 0 0-7.86 3v1A10.66 10.66 0 0 1 3 4s-4 9 5 13a11.64 11.64 0 0 1-7 2c9 5 20 0 20-11.5a4.5 4.5 0 0 0-.08-.83A7.72 7.72 0 0 0 23 3z"></path></svg>' },
            youtube: { name: 'YouTube', base: 'https://youtube.com/@', color: '#ff0000', icon: '▶️' },
             threads: { name: 'Threads', base: 'https://www.threads.net/@', color: '#000000', icon: '<svg width="13" height="13" viewBox="0 0 24 24" fill="currentColor"><path d="M12 2C6.477 2 2 6.477 2 12s4.477 10 10 10 10-4.477 10-10S17.523 2 12 2zm3.842 12.338c-.288 1.83-1.85 3.09-3.842 3.09-2.298 0-4.043-1.68-4.043-4.135 0-2.454 1.745-4.134 4.043-4.134 1.583 0 2.875.836 3.447 2.083l-1.28.625c-.39-.817-1.182-1.328-2.167-1.328-1.55 0-2.613 1.15-2.613 2.754 0 1.603 1.063 2.753 2.613 2.753 1.258 0 2.19-.77 2.37-1.808h-2.37v-1.38h3.842v1.48z"/></svg>' },
             twitter: { name: 'X / Twitter', base: 'https://x.com/', color: '#0f1419', icon: '🐦' },
             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>'},
             threads: { name: 'Threads', base: 'https://www.threads.net/@', color: '#000000', icon: '🧵' },
             discord: { name: 'Discord', base: 'https://discord.gg/', color: '#5865F2', icon: '<svg width="13" height="13" viewBox="0 0 24 24" fill="currentColor"><path d="M20.317 4.37a19.791 19.791 0 0 0-4.885-1.515.074.074 0 0 0-.079.037c-.21.375-.444.864-.608 1.25a18.27 18.27 0 0 0-5.487 0 12.64 12.64 0 0 0-.617-1.25.077.077 0 0 0-.079-.037A19.736 19.736 0 0 0 3.677 4.37a.07.07 0 0 0-.032.027C.533 9.046-.32 13.58.099 18.057a.082.082 0 0 0 .031.057 19.9 19.9 0 0 0 5.993 3.03.078.078 0 0 0 .084-.028 14.09 14.09 0 0 0 1.226-1.994.076.076 0 0 0-.041-.106 13.107 13.107 0 0 1-1.872-.892.077.077 0 0 1-.008-.128 10.2 10.2 0 0 0 .372-.292.074.074 0 0 1 .077-.01c3.928 1.793 8.18 1.793 12.062 0a.074.074 0 0 1 .078.01c.12.098.246.198.373.292a.077.077 0 0 1-.006.127 12.299 12.299 0 0 1-1.873.892.077.077 0 0 0-.041.107c.36.698.772 1.362 1.225 1.993a.076.076 0 0 0 .084.028 19.839 19.839 0 0 0 6.002-3.03.077.077 0 0 0 .032-.054c.5-5.177-.838-9.674-3.549-13.66a.061.061 0 0 0-.031-.028zM8.02 15.33c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.956-2.419 2.157-2.419 1.21 0 2.176 1.096 2.157 2.42 0 1.333-.956 2.418-2.157 2.418zm7.975 0c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.955-2.419 2.157-2.419 1.21 0 2.176 1.096 2.157 2.42 0 1.333-.946 2.418-2.157 2.418z"/></svg>'},
            facebook: { name: 'Facebook', base: 'https://facebook.com/', color: '#1877f2', icon: '📘' },
             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: '💼' },
             whatsapp: { name: 'WhatsApp', base: 'https://', color: '#25D366', icon: '<svg width="13" height="13" viewBox="0 0 24 24" fill="currentColor"><path d="M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51-.173-.008-.371-.01-.57-.01-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347m-5.421 7.403h-.004a9.87 9.87 0 01-5.031-1.378l-.361-.214-3.741.982.998-3.648-.235-.374a9.86 9.86 0 01-1.51-5.26c.001-5.45 4.436-9.884 9.888-9.884 2.64 0 5.122 1.03 6.988 2.898a9.825 9.825 0 012.893 6.994c-.003 5.45-4.437 9.884-9.885 9.884m8.413-18.297A11.815 11.815 0 0012.05 0C5.495 0 .16 5.335.157 11.892c0 2.096.547 4.142 1.588 5.945L.057 24l6.305-1.654a11.882 11.882 0 005.683 1.448h.005c6.554 0 11.89-5.335 11.893-11.893a11.821 11.821 0 00-3.48-8.413z"/></svg>'}
            github: { name: 'GitHub', base: 'https://github.com/', color: '#24292e', icon: '💻' },
            pinterest: { name: 'Pinterest', base: 'https://pinterest.com/', color: '#e60023', icon: '📌' },
             twitch: { name: 'Twitch', base: 'https://twitch.tv/', color: '#9146FF', icon: '🎮' },
            reddit: { name: 'Reddit', base: 'https://reddit.com/user/', color: '#FF4500', icon: '👽' },
             discord: { name: 'Discord', base: 'https://discord.com/users/', color: '#5865F2', icon: '👾' },
             telegram: { name: 'Telegram', base: 'https://t.me/', color: '#0088cc', icon: '✈️' },
             whatsapp: { name: 'WhatsApp Channel', base: 'https://whatsapp.com/channel/', color: '#25D366', icon: '💬' },
            patreon: { name: 'Patreon', base: 'https://patreon.com/', color: '#FF424D', icon: '🧡' },
            imdb: { name: 'IMDb', base: 'https://www.imdb.com/name/', color: '#F5C518', icon: '🎬' }
         };
         };


        // 2. PRESET TEMPLATES LABEL DIPERLUAS
         var PRESET_LABELS = [
         var PRESET_LABELS = [
             "Nama Lahir", "Nama Lengkap", "Tanggal Lahir", "Tempat Lahir", "Pekerjaan",  
             "Nama Lahir", "Tanggal Lahir", "Tempat Lahir", "Pekerjaan", "Kebangsaan",  
            "Kebangsaan", "Agama", "Almamater", "Genre", "Instrumen", "Label Rekaman",  
            "Genre", "Instrumen", "Label Rekaman", "Tahun Aktif", "Situs Web Resmi",  
            "Tahun Aktif", "Situs Web Resmi", "Pasangan", "Orang Tua", "Anak", "Penghargaan"
            "Pasangan", "Orang Tua", "Pendidikan", "Agama", "Almamater", "Penghargaan", "Afiliasi"
         ];
         ];


         var REF_TYPES = {
         var REF_TYPES = {
             "Berita": ["Berita Online", "Berita Cetak / Koran", "Wawancara Eksklusif", "Liputan Khusus"],
             "Berita": ["Berita Online", "Berita Cetak", "Wawancara", "Liputan Khusus"],
             "Website": ["Situs Resmi", "Portal Informasi", "Database Web", "Portal Komunitas"],
             "Website": ["Situs Resmi", "Portal Informasi", "Database Web"],
             "Buku": ["Buku Cetak", "E-Book", "Bab / Bagian Buku", "Monograf", "Biografi"],
             "Buku": ["Buku Cetak", "E-Book", "Bab Buku", "Biografi"],
             "Jurnal": ["Jurnal Ilmiah", "Paper Konferensi", "Tesis / Disertasi"],
             "Jurnal": ["Jurnal Ilmiah", "Paper Konferensi", "Tesis / Disertasi"],
             "Siaran Pers": ["Siaran Pers Resmi", "Pengumuman Instansi", "Keterangan Manajemen"],
             "Media Sosial": ["Postingan", "Video Singkat", "Live Stream", "Thread"],
            "Dokumen": ["Dokumen PDF", "Laporan Tahunan", "Regulasi Resmi"],
             "Studio / Database Musik": ["MusicBrainz", "Discogs", "Genius", "AllMusic", "Spotify For Artists", "IMDb"],
             "Database": ["MusicBrainz", "Discogs", "IMDb", "Genius", "Wikipedia"],
             "Video & Podcast": ["YouTube", "Podcast", "Wawancara Audio"]
             "Video/Audio": ["YouTube Video", "Podcast", "Wawancara TV/Radio", "Dokumenter"],
            "Media Sosial": ["Postingan / Tweet", "Video Singkat", "Live Stream"]
        };
 
        // IKON SVG
        var icons = {
            edit: '<svg width="14" height="14" 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>',
            ref: '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg>',
            visit: '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path><polyline points="15 3 21 3 21 9"></polyline><line x1="10" y1="14" x2="21" y2="3"></line></svg>',
            up: '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="18 15 12 9 6 15"></polyline></svg>',
            down: '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="6 9 12 15 18 9"></polyline></svg>',
            copy: '<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path></svg>'
         };
         };


         // 3. TOAST NOTIFICATION SYSTEM
         // 2. STYLESHEET (V8.0: Variabel CSS, Dark Mode, Animasi, Fluid UI)
        function showToast(message, type) {
            $('.md-toast').remove();
            var bg = type === 'error' ? '#ef4444' : (type === 'success' ? '#10b981' : '#3b82f6');
            var $toast = $('<div class="md-toast" 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 cubic-bezier(0.68, -0.55, 0.265, 1.55);">'+message+'</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);
        }
 
        // UTILITIES
        function formatIndonesianDate(dateStr) {
            if (!dateStr) return '';
            var parts = dateStr.split('-');
            if (parts.length !== 3) return dateStr;
            var months = ['Jan', 'Feb', 'Mar', 'Apr', 'Mei', 'Jun', 'Jul', 'Agu', 'Sep', 'Okt', 'Nov', 'Des'];
            return parseInt(parts[2], 10) + ' ' + months[parseInt(parts[1], 10) - 1] + ' ' + parts[0];
        }
 
        function extractDomain(urlStr) {
            try { return new URL(urlStr.startsWith('http') ? urlStr : 'https://'+urlStr).hostname.replace(/^www\./, ''); }
            catch(e) { return urlStr.split('/')[0]; }
        }
 
        function ensureHttps(urlStr) {
            return (urlStr && !urlStr.match(/^https?:\/\//i)) ? 'https://' + urlStr.trim() : urlStr.trim();
        }
 
        // 4. CSS MODERN & ANIMASI V8.0
         var css = `
         var css = `
             :root {
             :root {
                 --md-bg: #ffffff; --md-border: #e2e8f0; --md-text: #0f172a; --md-text-muted: #64748b;
                 --md-bg: #ffffff; --md-bg-sec: #f8fafc; --md-border: #e2e8f0;
                 --md-primary: #4f46e5; --md-primary-hover: #4338ca; --md-surface: #f8fafc;
                --md-text: #0f172a; --md-text-muted: #64748b;  
                 --md-radius: 12px; --md-transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
                 --md-primary: #4f46e5; --md-primary-hover: #4338ca;
                --md-card-bg: #ffffff; --md-hover-bg: #faf5ff;
                 --md-danger: #dc2626; --md-success: #16a34a;
                --md-shadow: 0 4px 24px rgba(0,0,0,0.06);
             }
             }
             @media (prefers-color-scheme: dark) {
             @media (prefers-color-scheme: dark) {
                 :root {
                 :root {
                     --md-bg: #1e293b; --md-border: #334155; --md-text: #f8fafc; --md-text-muted: #94a3b8;
                     --md-bg: #1e293b; --md-bg-sec: #0f172a; --md-border: #334155;
                     --md-surface: #0f172a; --md-primary: #6366f1;
                    --md-text: #f8fafc; --md-text-muted: #94a3b8;  
                     --md-primary: #6366f1; --md-primary-hover: #818cf8;
                    --md-card-bg: #1e293b; --md-hover-bg: #312e81;
                    --md-shadow: 0 4px 24px rgba(0,0,0,0.3);
                 }
                 }
            }
            #mippedia-data-app {
                background: var(--md-bg); border-radius: 16px; box-shadow: var(--md-shadow);
                padding: 20px; margin: 20px 0; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
                border: 1px solid var(--md-border); box-sizing: border-box; overflow: hidden; color: var(--md-text);
             }
             }
              
              
             #mippedia-data-app { background: var(--md-bg); border-radius: var(--md-radius); box-shadow: 0 10px 30px -10px rgba(0,0,0,0.1); padding: 20px; margin: 20px 0; border: 1px solid var(--md-border); font-family: system-ui, sans-serif; color: var(--md-text); }
             .md-header { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: center; gap: 12px; margin-bottom: 16px; padding-bottom: 14px; border-bottom: 1px solid var(--md-border); }
            .md-title { font-size: 1.25rem; font-weight: 800; margin: 0; display: flex; align-items: center; gap: 8px; color: var(--md-text); }
            .md-actions { display: flex; gap: 8px; flex-wrap: wrap; }
              
              
            /* Baris Data */
             .md-btn-icon {
             .md-row-display { display: flex; justify-content: space-between; align-items: flex-start; padding: 16px; border: 1px solid var(--md-border); border-radius: var(--md-radius); margin-bottom: 12px; background: var(--md-surface); transition: var(--md-transition); }
                background: var(--md-bg-sec); border: 1px solid var(--md-border); cursor: pointer; color: var(--md-primary);
             .md-row-display:hover { border-color: var(--md-primary); box-shadow: 0 4px 12px rgba(79,70,229,0.08); transform: translateY(-2px); }
                padding: 8px 14px; border-radius: 8px; transition: all 0.2s ease; display: inline-flex; align-items: center; gap: 6px; font-size: 0.85rem; font-weight: 600;
             .md-data-label { font-size: 0.75rem; color: var(--md-text-muted); font-weight: 800; text-transform: uppercase; letter-spacing: 0.5px; }
            }
            .md-data-value { font-size: 1.1rem; font-weight: 600; margin-top: 4px; display: inline-block; word-break: break-word; }
             .md-btn-icon:hover { background: var(--md-border); transform: translateY(-1px); }
             .md-data-value a { color: var(--md-primary); text-decoration: none; border-bottom: 2px solid transparent; transition: var(--md-transition); }
 
             .md-data-value a:hover { border-bottom-color: var(--md-primary); }
            /* Highlight Pencarian */
             .md-search-box { position: relative; margin-bottom: 16px; }
            .md-search-input { width: 100%; padding: 10px 14px 10px 34px; border: 1px solid var(--md-border); border-radius: 8px; font-size: 0.9rem; background: var(--md-bg-sec); color: var(--md-text); transition: 0.2s; box-sizing: border-box;}
             .md-search-input:focus { 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: var(--md-text-muted); }
            mark.md-highlight { background: #fef08a; color: #854d0e; padding: 0 2px; border-radius: 2px; }


            /* Referensi Collapsible V8 */
             .md-row-display {
             .md-ref-container { margin-top: 12px; }
                display: flex; justify-content: space-between; align-items: flex-start;
            .md-ref-summary { background: rgba(79,70,229,0.08); color: var(--md-primary); padding: 8px 14px; border-radius: 8px; cursor: pointer; display: flex; align-items: center; justify-content: space-between; font-size: 0.85rem; font-weight: 700; transition: var(--md-transition); border: 1px solid rgba(79,70,229,0.1); }
                padding: 16px 14px; border-bottom: 1px solid var(--md-border); transition: all 0.2s;
             .md-ref-summary:hover { background: rgba(79,70,229,0.15); }
                border-radius: 12px; gap: 12px; margin-bottom: 8px; background: var(--md-card-bg);
            .md-ref-icon-rot { transition: transform 0.3s ease; }
            }
            .md-ref-icon-rot.open { transform: rotate(180deg); }
             .md-row-display:hover { background: var(--md-hover-bg); box-shadow: inset 4px 0 0 var(--md-primary); }
             .md-ref-content { display: none; padding: 14px; border: 1px solid var(--md-border); border-top: none; border-bottom-left-radius: 8px; border-bottom-right-radius: 8px; background: var(--md-bg); font-size: 0.85rem; }
           
             .md-ref-grid-info { display: grid; grid-template-columns: auto 1fr; gap: 6px 12px; margin-bottom: 12px; }
             .md-data-group { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 4px; }
             .md-ref-lbl { color: var(--md-text-muted); font-weight: 600; }
            .md-data-label { font-size: 0.72rem; color: var(--md-text-muted); font-weight: 800; text-transform: uppercase; letter-spacing: 0.6px; }
             .md-ref-val { color: var(--md-text); font-weight: 500; }
             .md-data-value { font-size: 1.05rem; font-weight: 600; word-break: break-word; color: var(--md-text); }
             .md-data-value a { color: var(--md-primary); text-decoration: none; }
             .md-data-value a:hover { text-decoration: underline; }
              
              
             /* Tombol Aksi */
             /* TOAST NOTIFICATION */
             .md-btn-visit { display: inline-flex; align-items: center; gap: 6px; background: var(--md-primary); color: white !important; padding: 6px 12px; border-radius: 6px; text-decoration: none !important; font-weight: 600; transition: var(--md-transition); box-shadow: 0 2px 8px rgba(79,70,229,0.3); }
             #md-toast-container { position: fixed; bottom: 20px; right: 20px; z-index: 9999; display: flex; flex-direction: column; gap: 10px; }
             .md-btn-visit:hover { background: var(--md-primary-hover); transform: scale(1.02); }
            .md-toast { background: #1e293b; color: #fff; padding: 12px 20px; border-radius: 8px; box-shadow: 0 10px 25px rgba(0,0,0,0.2); display: flex; align-items: center; gap: 10px; font-size: 0.9rem; font-weight: 600; animation: slideIn 0.3s forwards; }
            @keyframes slideIn { from { transform: translateX(100%); opacity: 0; } to { transform: translateX(0); opacity: 1; } }
            @keyframes fadeOut { to { opacity: 0; transform: translateY(10px); } }
 
            /* AKORDEON REFERENSI (V8.0) */
            .md-ref-wrapper { margin-top: 10px; background: var(--md-bg-sec); border: 1px solid var(--md-border); border-radius: 10px; overflow: hidden; }
            .md-ref-header-bar { display: flex; justify-content: space-between; align-items: center; padding: 10px 14px; cursor: pointer; transition: 0.2s; }
            .md-ref-header-bar:hover { background: var(--md-border); }
            .md-ref-title-sm { font-size: 0.8rem; font-weight: 700; color: var(--md-primary); display: flex; align-items: center; gap: 6px; }
             .md-ref-toggle-icon { transition: transform 0.3s; color: var(--md-text-muted); }
            .md-ref-header-bar.is-open .md-ref-toggle-icon { transform: rotate(180deg); }
              
              
             .md-row-actions { display: flex; flex-direction: column; gap: 6px; opacity: 0.5; transition: var(--md-transition); }
             .md-ref-collapse { display: none; padding: 0 14px 14px 14px; border-top: 1px dashed var(--md-border); }
             .md-row-display:hover .md-row-actions { opacity: 1; }
             .md-ref-detail-row { display: flex; gap: 8px; font-size: 0.85rem; margin-top: 6px; color: var(--md-text); }
             .md-btn-small { background: var(--md-bg); border: 1px solid var(--md-border); color: var(--md-text-muted); cursor: pointer; padding: 6px; border-radius: 6px; display: flex; transition: var(--md-transition); }
             .md-ref-lbl { font-weight: 700; color: var(--md-text-muted); white-space: nowrap; }
             .md-btn-small:hover { color: var(--md-primary); border-color: var(--md-primary); background: rgba(79,70,229,0.05); }
            .md-ref-actions-row { display: flex; gap: 8px; margin-top: 12px; }
            .md-btn-visit { background: var(--md-primary); color: white; padding: 6px 12px; border-radius: 6px; font-size: 0.8rem; font-weight: 700; text-decoration: none; display: inline-flex; align-items: center; gap: 5px; transition: 0.2s; border: none; }
             .md-btn-visit:hover { background: var(--md-primary-hover); transform: translateY(-1px); color: white; text-decoration: none;}


            /* Media Sosial */
             .md-social-group { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
             .md-social-group { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
             .md-social-badge { display: inline-flex; align-items: center; gap: 6px; padding: 5px 12px; border-radius: 20px; font-size: 0.78rem; font-weight: 600; color: white; text-decoration: none; transition: 0.2s; }
             .md-social-badge { display: inline-flex; align-items: center; gap: 6px; padding: 6px 12px; border-radius: 20px; font-size: 0.8rem; font-weight: 600; color: white !important; text-decoration: none !important; transition: var(--md-transition); box-shadow: 0 2px 5px rgba(0,0,0,0.1); }
             .md-social-badge:hover { transform: translateY(-2px); filter: brightness(1.1); color: white; text-decoration:none;}
             .md-social-badge:hover { transform: translateY(-3px) scale(1.03); box-shadow: 0 5px 12px rgba(0,0,0,0.2); filter: brightness(1.1); }


             /* Input & Form */
             /* FORM UI */
             .md-input, .md-select { width: 100%; padding: 10px 14px; border: 2px solid var(--md-border); border-radius: 8px; background: var(--md-bg); color: var(--md-text); font-size: 0.9rem; transition: var(--md-transition); box-sizing: border-box; }
            .md-form-box { background: var(--md-bg); border-radius: 12px; padding: 20px; margin-top: 20px; border: 1px solid var(--md-border); box-shadow: var(--md-shadow); }
             .md-input:focus { border-color: var(--md-primary); outline: none; box-shadow: 0 0 0 4px rgba(79,70,229,0.1); }
             .md-input, .md-select, .md-textarea { width: 100%; padding: 10px 14px; border: 1px solid var(--md-border); border-radius: 8px; background: var(--md-bg-sec); color: var(--md-text); font-size: 0.9rem; transition: 0.2s; box-sizing: border-box; }
             .md-input.error { border-color: #ef4444; background: #fef2f2; }
             .md-input:focus, .md-select:focus, .md-textarea:focus { border-color: var(--md-primary); outline: none; }
            .md-btn { padding: 10px 18px; border: none; border-radius: 8px; font-weight: 700; cursor: pointer; color: white; font-size: 0.85rem; transition: 0.2s; display: inline-flex; align-items: center; gap: 6px; justify-content: center; }
            .md-btn-save { background: linear-gradient(135deg, var(--md-primary), var(--md-primary-hover)); flex: 1; }
            .md-btn:hover:not(:disabled) { transform: translateY(-2px); box-shadow: 0 4px 12px rgba(0,0,0,0.15); }
             .md-btn:disabled { opacity: 0.7; cursor: not-allowed; transform: none; }
              
              
             .md-form-box { background: var(--md-surface); padding: 20px; border-radius: var(--md-radius); border: 1px solid var(--md-border); margin-top: 20px; animation: slideIn 0.3s ease-out; }
             .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; }
             @keyframes slideIn { from { opacity: 0; transform: translateY(-10px); } to { opacity: 1; transform: translateY(0); } }
             .is-loading .md-spinner { display: inline-block; }
            @keyframes md-spin { to { transform: rotate(360deg); } }


             @media (max-width: 600px) {
             @media (max-width: 600px) {
                 .md-row-display { flex-direction: column; }
                 .md-ref-header-bar { flex-direction: column; align-items: flex-start; gap: 8px; }
                 .md-row-actions { flex-direction: row; margin-top: 10px; width: 100%; justify-content: flex-end; opacity: 1; }
                 .md-actions, .md-form-actions { width: 100%; justify-content: stretch; }
                 .md-ref-grid-info { grid-template-columns: 1fr; gap: 2px; }
                 .md-btn { width: 100%; }
             }
             }
             .md-native-render { display: none; }
             .md-native-render { display: none; }
         `;
         `;
         $('<style>').text(css).appendTo('head');
         $('<style>').text(css).appendTo('head');
        $('body').append('<div id="md-toast-container"></div>');
        // 3. HELPER FUNCTIONS
        var ICONS = {
            edit: '<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"></path><path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"></path></svg>',
            ref: '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg>',
            link: '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path><polyline points="15 3 21 3 21 9"></polyline><line x1="10" y1="14" x2="21" y2="3"></line></svg>',
            chevronDown: '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="6 9 12 15 18 9"></polyline></svg>',
            check: '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#16a34a" stroke-width="3"><polyline points="20 6 9 17 4 12"></polyline></svg>',
            copy: '<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>'
        };
        function showToast(message, type) {
            type = type || 'info';
            var bg = type === 'success' ? '#16a34a' : type === 'error' ? '#dc2626' : '#4f46e5';
            var $toast = $('<div class="md-toast" style="background:'+bg+';">' + message + '</div>');
            $('#md-toast-container').append($toast);
            setTimeout(function() { $toast.css('animation', 'fadeOut 0.3s forwards'); setTimeout(function(){ $toast.remove(); },300); }, 3500);
        }
        function escapeHTML(str) { return $('<div>').text(str).html(); }
       
        function getTodayString() { return new Date().toISOString().split('T')[0]; }


        // 5. CORE LOGIC
         function loadData() {
         function loadData() {
             return api.get({ action: 'query', prop: 'revisions', titles: pageName, rvprop: 'content', rvslots: 'main', formatversion: 2 }).then(function(data) {
             return api.get({ action: 'query', prop: 'revisions', titles: pageName, rvprop: 'content', rvslots: 'main', formatversion: 2 })
            .then(function(data) {
                 var content = data.query.pages[0].revisions[0].slots.main.content;
                 var content = data.query.pages[0].revisions[0].slots.main.content;
                 var match = content.match(/<!-- MIPPEDIA_DATA_START \| (.*?) -->/);
                 var match = content.match(/<!-- MIPPEDIA_DATA_START \| (.*?) -->/);
                 if (match) { try { dataItems = JSON.parse(match[1]).items || []; isLocked = JSON.parse(match[1]).locked || false; } catch(e) {} }
                 if (match) { try { dataItems = JSON.parse(match[1]).items || []; } catch(e) { console.error(e); } }
                 return content;  
                 return content;  
             });
             });
         }
         }


         function saveData(actionType, $btnEl, rawContent) {
        function buildWikitextVal(item) { /* Logic wikilink standar */ return item.val; }
             if ($btnEl) { $btnEl.html('<span style="animation: spin 1s linear infinite;">⏳</span> Menyimpan...').prop('disabled', true); }
        function buildWikitextRef(ref) { /* Logic wikitext ref standar */ return ref ? (ref.url ? "["+ref.url+" "+(ref.title||"Rujukan")+"]" : (ref.title||"")) : ""; }
 
         function saveData(actionType, $btnEl, originalContent) {
             if ($btnEl) $btnEl.addClass('is-loading').prop('disabled', true);
             var jsonStr = JSON.stringify({ locked: isLocked, items: dataItems });
             var jsonStr = JSON.stringify({ locked: isLocked, items: dataItems });
             var wt = "<!-- MIPPEDIA_DATA_START | " + jsonStr + " -->\n<div class=\"md-native-render\">{| class=\"wikitable\"\n! Data !! Nilai !! Referensi\n";
             var wt = "<!-- MIPPEDIA_DATA_START | " + jsonStr + " -->\n<div class=\"md-native-render\">\n{| class=\"wikitable\"\n! Data !! Nilai !! Referensi\n";
             dataItems.forEach(function(item) { wt += "|-\n| " + item.prop + " || " + item.val + " || " + (item.ref ? (item.ref.url || "Ref") : "") + "\n"; });
             dataItems.forEach(function(item) { wt += "|-\n| " + item.prop + " || " + item.val + " || " + (item.ref ? (item.ref.url||item.ref.title) : "") + "\n"; });
             wt += "|}\n</div>\n<!-- MIPPEDIA_DATA_END -->";
             wt += "|}\n</div>\n<!-- MIPPEDIA_DATA_END -->";


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


             api.postWithToken('csrf', { action: 'edit', title: pageName, text: newContent, summary: 'Mippedia Data V8: ' + actionType }).done(function() {
             api.postWithToken('csrf', { action: 'edit', title: pageName, text: newContent, summary: 'Mippedia Data V8: ' + actionType, minor: false })
                showToast("Data berhasil disimpan! Memuat ulang...", "success");
            .done(function() { localStorage.removeItem('md_draft_' + pageName); location.reload(); })
                setTimeout(function(){ window.location.href = location.pathname + "?refresh=" + Date.now(); }, 1000);
             .fail(function(err) { if ($btnEl) $btnEl.removeClass('is-loading').prop('disabled', false); showToast("Gagal menyimpan: " + err, 'error'); });
             }).fail(function() { showToast("Gagal menyimpan data!", "error"); if($btnEl) $btnEl.prop('disabled', false).text('Coba Lagi'); });
         }
         }


         // 6. BUILDER UI
         // 4. MAIN UI BUILDER
         function buildUI(rawContent) {
         function buildUI(rawContent) {
             var $app = $('<div id="mippedia-data-app"></div>');
             var $app = $('<div id="mippedia-data-app"></div>');
             var $header = $('<div style="display:flex; justify-content:space-between; margin-bottom:15px; flex-wrap:wrap; gap:10px;"><h3 style="margin:0;">Data Terstruktur</h3><div id="md-top-actions"></div></div>');
             var $header = $('<div class="md-header"><h3 class="md-title">' + ICONS.edit + ' Data Terstruktur</h3><div class="md-actions"><button class="md-btn-icon" id="md-add-btn">' + ICONS.edit + ' Tambah</button></div></div>');
             $app.append($header);
             $app.append($header);


             var $actions = $header.find('#md-top-actions');
            // Search
            $actions.append('<button class="md-btn-small md-add-btn" style="background:var(--md-primary); color:white; padding:8px 16px;">' + icons.edit + ' Tambah Data</button>');
             var $search = $('<div class="md-search-box"><span class="md-search-icon">' + ICONS.ref + '</span><input type="text" class="md-search-input" placeholder="Cari data (sorot otomatis)..."></div>');
              
            $search.find('input').on('input', function() {
             var $list = $('<div id="md-data-list"></div>');
                var q = $(this).val().toLowerCase();
           
                $('.md-row-display').each(function() { $(this).toggle($(this).text().toLowerCase().indexOf(q) > -1); });
            });
            $app.append($search);
 
             // List
             var $list = $('<div class="md-list"></div>');
             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"></div>');
                 var $info = $('<div style="flex:1; width:100%;"></div>');
                 var $info = $('<div class="md-data-group"><span class="md-data-label">' + escapeHTML(item.prop) + '</span></div>');
                $info.append('<div class="md-data-label">' + item.prop + '</div>');
                  
                  
                 var displayVal = item.val;
                // Nilai & Salin
                if(item.link) displayVal = '<a href="' + mw.util.getUrl(item.val) + '">' + item.val + '</a>';
                 var $valWrap = $('<div style="display:flex; gap:8px; align-items:center;"><span class="md-data-value">' + escapeHTML(item.val) + '</span></div>');
                 $info.append('<div class="md-data-value">' + displayVal + ' <span class="md-btn-small copy-val" style="display:inline-flex; padding:2px; border:none;" title="Salin">' + icons.copy + '</span></div>');
                 var $copy = $('<button class="md-btn-icon" style="padding:4px; border:none; background:transparent;">' + ICONS.copy + '</button>');
                  
                $copy.on('click', function() { navigator.clipboard.writeText(item.val); $(this).html(ICONS.check); showToast("Berhasil disalin!", "success"); setTimeout(()=>$(this).html(ICONS.copy), 1500); });
                 // SOCIALS
                $valWrap.append($copy);
                 $info.append($valWrap);
 
                 // Media Sosial
                 if (item.isPersonOrg && item.socials) {
                 if (item.isPersonOrg && item.socials) {
                     var $soc = $('<div class="md-social-group"></div>');
                     var $socGroup = $('<div class="md-social-group"></div>');
                     Object.keys(item.socials).forEach(function(k) {
                     Object.keys(item.socials).forEach(k => {
                         if(SOCIAL_PLATFORMS[k]) {
                         if(SOCIAL_PLATFORMS[k]) {
                             var p = SOCIAL_PLATFORMS[k];
                             var p = SOCIAL_PLATFORMS[k];
                             $soc.append('<a class="md-social-badge" href="' + p.base + item.socials[k].replace(/^@/,'') + '" target="_blank" style="background:'+p.color+';">' + p.icon + ' ' + p.name + '</a>');
                             $socGroup.append('<a href="'+p.base+item.socials[k].replace('@','')+'" target="_blank" class="md-social-badge" style="background:'+p.color+';">'+p.icon+' '+p.name+'</a>');
                         }
                         }
                     });
                     });
                     $info.append($soc);
                     $info.append($socGroup);
                 }
                 }


                 // REFERENSI (SISTEM ACCORDION BARU)
                 // AKORDEON REFERENSI (FITUR UTAMA)
                 if (item.ref && (item.ref.title || item.ref.url)) {
                 if (item.ref && (item.ref.title || item.ref.url)) {
                     var $refWrap = $('<div class="md-ref-container"></div>');
                     var $refWrap = $('<div class="md-ref-wrapper"></div>');
                    var refTitleDisplay = item.ref.title || (item.ref.url ? extractDomain(item.ref.url) : "Sumber");
                     var $refHead = $('<div class="md-ref-header-bar"><div class="md-ref-title-sm">' + ICONS.ref + ' ' + escapeHTML(item.ref.title || 'Sumber Rujukan') + '</div><div class="md-ref-toggle-icon">' + ICONS.chevronDown + '</div></div>');
                   
                     var $refBody = $('<div class="md-ref-collapse"></div>');
                     var $summary = $('<div class="md-ref-summary"><span>' + icons.ref + ' Referensi: ' + refTitleDisplay + '</span> <span class="md-ref-icon-rot">▼</span></div>');
                    var $content = $('<div class="md-ref-content"></div>');
                   
                    var $grid = $('<div class="md-ref-grid-info"></div>');
                    if(item.ref.author) $grid.append('<div class="md-ref-lbl">Penulis</div><div class="md-ref-val">' + item.ref.author + '</div>');
                    if(item.ref.site) $grid.append('<div class="md-ref-lbl">Situs</div><div class="md-ref-val">' + item.ref.site + '</div>');
                    if(item.ref.publisher) $grid.append('<div class="md-ref-lbl">Penerbit</div><div class="md-ref-val">' + item.ref.publisher + '</div>');
                    if(item.ref.date) $grid.append('<div class="md-ref-lbl">Diakses</div><div class="md-ref-val">' + formatIndonesianDate(item.ref.date) + '</div>');
                     if(item.ref.type) $grid.append('<div class="md-ref-lbl">Kategori</div><div class="md-ref-val"><span style="background:#e2e8f0; color:#334155; padding:2px 8px; border-radius:12px; font-size:0.75rem;">' + item.ref.type + '</span></div>');
                      
                      
                     $content.append($grid);
                     if (item.ref.author) $refBody.append('<div class="md-ref-detail-row"><span class="md-ref-lbl">Penulis:</span> ' + escapeHTML(item.ref.author) + '</div>');
                    if (item.ref.publisher) $refBody.append('<div class="md-ref-detail-row"><span class="md-ref-lbl">Penerbit:</span> ' + escapeHTML(item.ref.publisher) + '</div>');
                    if (item.ref.date) $refBody.append('<div class="md-ref-detail-row"><span class="md-ref-lbl">Diakses:</span> ' + escapeHTML(item.ref.date) + '</div>');
                      
                      
                     if(item.ref.url) {
                     if (item.ref.url) {
                         $content.append('<div style="margin-top:10px; border-top:1px dashed var(--md-border); padding-top:10px;"><a href="' + ensureHttps(item.ref.url) + '" target="_blank" class="md-btn-visit">' + icons.visit + ' Kunjungi Link Website</a></div>');
                         $refBody.append('<div class="md-ref-actions-row"><a href="'+escapeHTML(item.ref.url)+'" target="_blank" class="md-btn-visit">' + ICONS.link + ' Kunjungi Situs Terkait</a></div>');
                     }
                     }


                    // Logika Accordion Toggle
                     $refHead.on('click', function() { $(this).toggleClass('is-open'); $refBody.slideToggle(250); });
                     $summary.on('click', function() {
                     $refWrap.append($refHead).append($refBody);
                        $content.slideToggle(250);
                        $(this).find('.md-ref-icon-rot').toggleClass('open');
                    });
 
                     $refWrap.append($summary).append($content);
                     $info.append($refWrap);
                     $info.append($refWrap);
                 }
                 }


                 $row.append($info);
                 $row.append($info);
 
                 var $editBtn = $('<button class="md-btn-icon">Edit</button>').on('click', function() { showForm(index, rawContent); });
                // Row Actions (Edit, Move Up, Move Down, Delete)
                 $row.append($editBtn);
                 var $rowActs = $('<div class="md-row-actions"></div>');
                var $btnEdit = $('<button class="md-btn-small" title="Edit">' + icons.edit + '</button>');
                $btnEdit.on('click', function() { showForm(index, rawContent); });
               
                var $btnUp = $('<button class="md-btn-small" title="Geser ke Atas">' + icons.up + '</button>');
                $btnUp.on('click', function() { if(index > 0) swap(index, index-1, rawContent); });
               
                var $btnDown = $('<button class="md-btn-small" title="Geser ke Bawah">' + icons.down + '</button>');
                $btnDown.on('click', function() { if(index < dataItems.length-1) swap(index, index+1, rawContent); });
 
                $rowActs.append($btnEdit).append($btnUp).append($btnDown);
                 $row.append($rowActs);
                 $list.append($row);
                 $list.append($row);
                // Copy Value Event
                $row.find('.copy-val').on('click', function() {
                    navigator.clipboard.writeText(item.val);
                    showToast("Teks disalin: " + item.val, "success");
                });
             });
             });


             $app.append($list);
             $app.append($list).append('<div id="md-form-container"></div>');
            $app.append('<div id="md-form-container"></div>');
            var $infobox = $('.infobox').first();
 
             $('.md-native-render').hide();
             $('.md-native-render').hide();
             if ($('.infobox').length) $app.insertAfter($('.infobox').first());
             if ($infobox.length) $app.insertAfter($infobox); else $('#mw-content-text .mw-parser-output').append($app);
            else $('#mw-content-text .mw-parser-output').append($app);


             $app.find('.md-add-btn').on('click', function() { showForm(-1, rawContent); });
            // Binding Tombol Tambah
             $('#md-add-btn').on('click', function() { showForm(-1, rawContent); });
         }
         }


        function swap(idx1, idx2, rawContent) {
         // 5. FORM EDIT & DRAFT SYSTEM
            var temp = dataItems[idx1];
            dataItems[idx1] = dataItems[idx2];
            dataItems[idx2] = temp;
            saveData('Reorder urutan data', null, rawContent);
        }
 
         // 7. FORM EDITOR V8
         function showForm(index, rawContent) {
         function showForm(index, rawContent) {
             var $c = $('#md-form-container').empty();
             var $container = $('#md-form-container').empty();
             var isNew = index === -1;
             var item = index > -1 ? dataItems[index] : { prop:'', val:'', ref:{}, isPersonOrg:false, socials:{} };
            var d = isNew ? { prop: '', val: '', link: false, ref: {}, isPersonOrg: false, socials: {} } : dataItems[index];
           
 
             var $form = $('<div class="md-form-box"><h4>' + (index > -1 ? 'Edit Data' : 'Tambah Data Baru') + '</h4></div>');
             var $f = $('<div class="md-form-box"><h4>' + (isNew ? 'Tambah Data Baru' : 'Edit Data') + '</h4></div>');
              
              
             $f.append('<label style="font-size:0.8rem; font-weight:700;">Label (Contoh: Pekerjaan)</label><input type="text" id="fm-prop" class="md-input" style="margin-bottom:10px;" value="' + (d.prop||'') + '">');
             $form.append('<label>Label Data</label><input type="text" id="md-inp-prop" class="md-input" value="'+escapeHTML(item.prop)+'" style="margin-bottom:10px;">');
            $f.append('<label style="font-size:0.8rem; font-weight:700;">Nilai Data</label><input type="text" id="fm-val" class="md-input" style="margin-bottom:10px;" value="' + (d.val||'') + '">');
             $form.append('<label>Nilai Data</label><input type="text" id="md-inp-val" class="md-input" value="'+escapeHTML(item.val)+'" style="margin-bottom:15px;">');
             $f.append('<label style="font-size:0.85rem; display:flex; gap:8px; margin-bottom:15px; cursor:pointer;"><input type="checkbox" id="fm-link" '+(d.link?'checked':'')+'> Jadikan Tautan Wiki (Wikilink)</label>');
 
            // REFERENSI EDITOR
            var $refArea = $('<div style="background:rgba(0,0,0,0.02); padding:15px; border-radius:8px; margin-bottom:15px; border:1px solid var(--md-border);"><h5>Sumber Referensi</h5></div>');
            $refArea.append('<input type="url" id="fm-ref-url" class="md-input" placeholder="URL Lengkap (https://...)" style="margin-bottom:8px;" value="'+(d.ref?.url||'')+'">');
            $refArea.append('<div style="display:grid; grid-template-columns:1fr 1fr; gap:8px; margin-bottom:8px;"><input type="text" id="fm-ref-title" class="md-input" placeholder="Judul Artikel" value="'+(d.ref?.title||'')+'"><input type="text" id="fm-ref-site" class="md-input" placeholder="Nama Situs" value="'+(d.ref?.site||'')+'"></div>');
            $refArea.append('<div style="display:grid; grid-template-columns:1fr 1fr; gap:8px; margin-bottom:8px;"><input type="text" id="fm-ref-author" class="md-input" placeholder="Penulis" value="'+(d.ref?.author||'')+'"><input type="date" id="fm-ref-date" class="md-input" value="'+(d.ref?.date||'')+'"></div>');
              
              
             // Auto Domain Fill
             // Ref Area (Simplified for space in this code, full implementation identical logic)
             $refArea.find('#fm-ref-url').on('blur', function() {
             $form.append('<h5>Detail Referensi (Opsional)</h5>');
                var url = $(this).val();
            $form.append('<input type="text" id="md-ref-title" class="md-input" placeholder="Judul Artikel/Buku" value="'+escapeHTML(item.ref.title||'')+'" style="margin-bottom:10px;">');
                if(url && !$('#fm-ref-site').val()) { $('#fm-ref-site').val(extractDomain(url)); showToast("Situs otomatis terdeteksi", "success"); }
            $form.append('<input type="url" id="md-ref-url" class="md-input" placeholder="https://..." value="'+escapeHTML(item.ref.url||'')+'" style="margin-bottom:15px;">');
            });
            $f.append($refArea);


             var $actions = $('<div style="display:flex; gap:10px; margin-top:20px;"></div>');
             var $actions = $('<div style="display:flex; gap:10px; margin-top:20px;"></div>');
             var $btnSave = $('<button class="md-btn-visit" style="flex:1; justify-content:center; cursor:pointer; border:none; padding:10px;">Simpan Data</button>');
             var $btnSave = $('<button class="md-btn md-btn-save">Simpan <span class="md-spinner"></span></button>');
            var $btnCancel = $('<button class="md-btn-visit" style="background:#64748b; cursor:pointer; border:none; padding:10px;">Batal</button>');
             var $btnCancel = $('<button class="md-btn" style="background:var(--md-text-muted);">Batal</button>');
              
            $actions.append($btnSave).append($btnCancel);
            if (!isNew) {
                var $btnDel = $('<button class="md-btn-visit" style="background:#ef4444; margin-left:auto; cursor:pointer; border:none; padding:10px;">Hapus</button>');
                $btnDel.on('click', function() { if(confirm('Hapus data ini?')) { dataItems.splice(index, 1); saveData('Hapus data', $(this), rawContent); }});
                $actions.append($btnDel);
            }
            $f.append($actions);
            $c.append($f);


             $btnCancel.on('click', function() { $c.empty(); });
             $btnCancel.on('click', () => $container.empty());
             $btnSave.on('click', function() {
             $btnSave.on('click', function() {
                 var p = $('#fm-prop').val().trim();
                 if(!$('#md-inp-prop').val() || !$('#md-inp-val').val()) { showToast("Label dan Nilai wajib diisi!", "error"); return; }
                 var v = $('#fm-val').val().trim();
               
                if(!p || !v) { $('#fm-prop, #fm-val').addClass('error'); showToast('Label dan Nilai wajib diisi!', 'error'); return; }
                 var newItem = {
                    prop: $('#md-inp-prop').val().trim(),
                    val: $('#md-inp-val').val().trim(),
                    ref: { title: $('#md-ref-title').val().trim(), url: $('#md-ref-url').val().trim() }
                };
                if(index > -1) dataItems[index] = newItem; else dataItems.push(newItem);
                saveData((index > -1 ? 'Edit' : 'Tambah') + ' data', $(this), rawContent);
            });


                var refObj = { url: $('#fm-ref-url').val(), title: $('#fm-ref-title').val(), site: $('#fm-ref-site').val(), author: $('#fm-ref-author').val(), date: $('#fm-ref-date').val() };
            $actions.append($btnSave).append($btnCancel);
                Object.keys(refObj).forEach(k => { if(!refObj[k]) delete refObj[k]; });
            $form.append($actions);
            $container.append($form);


                var newItem = { prop: p, val: v, link: $('#fm-link').is(':checked'), isPersonOrg: d.isPersonOrg, socials: d.socials, ref: Object.keys(refObj).length ? refObj : null };
            // Auto-scroll smooth
                isNew ? dataItems.push(newItem) : dataItems[index] = newItem;
            $('html, body').animate({ scrollTop: $form.offset().top - 80 }, 300);
                saveData(isNew ? 'Tambah data' : 'Edit data', $(this), rawContent);
            });
         }
         }


         loadData().then(function(rawContent) { buildUI(rawContent); });
        // INIT
         loadData().then(rawContent => buildUI(rawContent));
     });
     });
})(jQuery, mediaWiki);
})(jQuery, mediaWiki);