<!DOCTYPE html>
<html lang="id" class="dark">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Alat Modifikasi HTML v3.4 (Multi-JSON)</title>

    <link href="https://cdnjs.cloudflare.com/ajax/libs/tailwindcss/2.2.19/tailwind.min.css" rel="stylesheet">

    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.15/codemirror.min.css">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.15/theme/tokyo-night.min.css">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.15/codemirror.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.15/mode/xml/xml.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.15/mode/javascript/javascript.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.15/mode/css/css.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.15/mode/htmlmixed/htmlmixed.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.15/addon/search/searchcursor.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.15/addon/search/search.min.js"></script>

    <style>
        :root {
            --bg-color: #1a202c;
            --surface-color: #2d3748;
            --border-color: #4a5568;
            --text-color: #e2e8f0;
            --brand-color: #818cf8; /* indigo-400 */
        }
        body {
            background-color: var(--bg-color);
            color: var(--text-color);
            font-family: 'Inter', sans-serif;
        }
        .CodeMirror {
            border: 1px solid var(--border-color);
            border-radius: 0.375rem; /* rounded-md */
            height: 100%;
            font-size: 14px;
        }
        .CodeMirror-gutters {
            background-color: #1f2937 !important; /* bg-gray-800 */
            border-right: 1px solid var(--border-color);
        }
        .cm-editor-utama {
             display: none; /* Sembunyikan editor utama */
        }
        .form-textarea {
            background-color: var(--surface-color);
            border-color: var(--border-color);
            color: var(--text-color);
        }
        .form-textarea:focus {
            --tw-ring-color: var(--brand-color);
            border-color: var(--brand-color);
        }
        .modal-message-success { color: #4ade80; } /* text-green-400 */
        .modal-message-error { color: #f87171; } /* text-red-400 */
        .modal-message-info { color: #60a5fa; } /* text-blue-400 */
    </style>
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/js-beautify/1.14.7/beautify-html.min.js"></script>

</head>

<body class="bg-gray-900 text-gray-200">

    <div class="flex flex-col min-h-screen max-w-screen-xl mx-auto p-4 gap-4">

        <header class="text-center">
            <h1 class="text-3xl font-bold text-indigo-400">Alat Modifikasi HTML v3.4 (Multi-JSON)</h1>
        </header>

        <input type="file" id="fileUploader" accept=".html,.htm,.txt,.php" style="display: none;" onchange="handleFileSelect(event)">

        <div class="flex flex-col bg-gray-800 p-4 rounded-lg shadow-lg gap-3">

            <div class="flex items-center gap-3 self-start">
                <div id="mainIndicator" class="w-4 h-4 rounded-full bg-red-500 transition-colors flex-shrink-0"></div>
                <span id="versionIndicator" class="text-2xl font-mono font-bold text-gray-600 whitespace-nowrap">[ KOSONG ]</span>
            </div>

            <div class="flex gap-2 flex-shrink-0 self-end">
                <button onclick="triggerFileUpload()" title="Unggah file HTML" class="bg-gray-700 hover:bg-blue-600 text-white font-medium py-2 px-3 rounded-md transition-colors flex items-center gap-2">
                    <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                        <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path>
                        <polyline points="17 8 12 3 7 8"></polyline>
                        <line x1="12" y1="3" x2="12" y2="15"></line>
                    </svg>
                    <span>Upload</span>
                </button>
                <button onclick="pasteIntoMainEditor()" title="Tempel dari Clipboard" class="bg-gray-700 hover:bg-indigo-600 text-white font-medium py-2 px-3 rounded-md transition-colors flex items-center gap-2">
                    <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                        <path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"></path>
                        <rect x="8" y="2" width="8" height="4" rx="1" ry="1"></rect>
                    </svg>
                    <span>Tempel</span>
                </button>
                <button onclick="resetEditor()" title="Reset & Hapus Semua" class="bg-red-700 hover:bg-red-600 text-white font-medium py-2 px-3 rounded-md transition-colors flex items-center gap-2">
                    <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                        <polyline points="3 6 5 6 21 6"></polyline>
                        <path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path>
                    </svg>
                    <span>Reset</span>
                </button>
            </div>

            <div class="flex-1 relative min-h-0 cm-editor-utama">
                <textarea id="mainEditor" class="w-full h-full" placeholder="Tempel seluruh kode HTML Anda di sini..."></textarea>
            </div>
        </div>

        <div class="bg-gray-800 p-4 rounded-lg shadow-lg flex flex-col gap-3">
            <div class="flex justify-between items-center">
                <label for="quickCommandInput" class="block text-sm font-medium text-gray-300">2. Tempel Perintah Cepat Gemini (Bisa Multi-JSON)</label>
                <button onclick="pasteIntoQuickCommand()" title="Tempel Perintah Cepat" class="bg-gray-700 hover:bg-indigo-600 text-white font-medium py-1.5 px-3 rounded-md transition-colors flex items-center gap-2 text-sm">
                    <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                        <path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"></path>
                        <rect x="8" y="2" width="8" height="4" rx="1" ry="1"></rect>
                    </svg>
                    <span>Tempel</span>
                </button>
            </div>
            <textarea id="quickCommandInput" rows="7" class="form-textarea w-full rounded-md shadow-sm text-sm font-mono p-2" placeholder='Tempel JSON Objek TUNGGAL {...} atau JSON ARRAY [...]
[
  {
    "snippet": "...",
    "target": "...",
    "action": "replace",
    "regex": false,
    "global": false
  },
  {
    "snippet": "...",
    "target": "...",
    "action": "insertAfter",
    "regex": true,
    "global": true
  }
]'></textarea>
            <button onclick="applyAndExecute()" class="w-full bg-teal-600 hover:bg-teal-700 text-white font-bold py-3 px-4 rounded-lg shadow-md transition-transform transform hover:scale-105">
                Jalankan Perintah Cepat
            </button>
        </div>

        <div class="bg-gray-800 p-4 rounded-lg shadow-lg flex flex-col gap-3">

            <button onclick="beautifyCode()" title="Rapihkan Kode (Auto-Indent)" class="w-full sm:w-auto bg-gray-600 hover:bg-indigo-600 text-white font-medium py-3 px-4 rounded-md transition-colors flex items-center justify-center gap-2">
                <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                    <path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"></path>
                    <polyline points="3.27 6.96 12 12.01 20.73 6.96"></polyline>
                    <line x1="12" y1="22.08" x2="12" y2="12"></line>
                </svg>
                Rapihkan Kode
            </button>

            <button onclick="copyResult()" title="Salin Hasil" class="w-full sm:w-auto bg-gray-600 hover:bg-green-600 text-white font-medium py-3 px-4 rounded-md transition-colors flex items-center justify-center gap-2">
                <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                    <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>
                Salin Hasil
            </button>
            <div class="flex flex-col sm:flex-row gap-2 w-full sm:w-auto">
                <select id="downloadExtension" class="bg-gray-700 text-white font-medium py-3 px-4 rounded-md border border-gray-600 focus:outline-none focus:border-indigo-400">
                    <option value=".html">.html</option>
                    <option value=".php">.php</option>
                </select>
                <button onclick="downloadResult('index')" title="Download file index" class="flex-1 bg-gray-600 hover:bg-teal-600 text-white font-medium py-3 px-4 rounded-md transition-colors flex items-center justify-center gap-2">
                    <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                        <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>
                    Download Index
                </button>
                <button onclick="downloadResult('paneladmin')" title="Download file paneladmin" class="flex-1 bg-gray-600 hover:bg-teal-600 text-white font-medium py-3 px-4 rounded-md transition-colors flex items-center justify-center gap-2">
                    <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                        <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>
                    Download Panel
                </button>
            </div>
            <button onclick="copyPrompt()" title="Salin promp template" class="w-full sm:w-auto bg-gray-600 hover:bg-yellow-600 text-white font-medium py-3 px-4 rounded-md transition-colors flex items-center justify-center gap-2">
                <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                    <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>
                Salin Promp (WAJIB)
            </button>
        </div>


        <div class="bg-gray-800 p-4 rounded-lg shadow-lg flex flex-col gap-3">
            <h2 class="text-xl font-bold text-indigo-400">Pratinjau Layar (Mobile)</h2>

            <div class="mt-2 flex gap-2">
                <button onclick="openPreviewSettingsModal()" class="bg-gray-700 hover:bg-indigo-600 text-white font-medium py-2 px-4 rounded-md text-sm transition-colors flex items-center gap-2 border border-gray-600 shadow-sm">
                    <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                        <circle cx="12" cy="12" r="3"></circle>
                        <path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"></path>
                    </svg>
                    Pengaturan Pratinjau
                </button>
                <button id="btnLockPage" onclick="toggleLock()" class="bg-gray-700 hover:bg-rose-600 text-white font-medium py-2 px-4 rounded-md text-sm transition-colors flex items-center gap-2 border border-gray-600 shadow-sm">
                    <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                        <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>
                    Kunci Layar
                </button>
            </div>
            <div class="flex justify-center mt-4 w-full px-2">
                <div id="previewContainer" class="border-8 border-gray-900 overflow-hidden w-full bg-white relative shadow-2xl flex flex-col mx-auto" style="max-width: 360px; height: 760px; border-radius: 2.5rem; transform-origin: top center; transition: transform 0.3s ease;">

                    <div id="previewNotch" class="absolute top-0 inset-x-0 h-6 flex justify-center z-10 pointer-events-none">
                        <div class="h-5 bg-gray-900 rounded-b-xl" style="width: 100px;"></div>
                    </div>


                    <div class="flex-1 w-full bg-white relative mt-2 overflow-auto touch-pan-x touch-pan-y touch-pinch-zoom" id="iframeWrapper">
                        <iframe id="mobilePreview" class="w-full h-full border-none" style="transform-origin: top left;"></iframe>
                    </div>


                    <div id="previewNav" class="h-12 bg-gray-900 w-full flex justify-around items-center px-6 shrink-0 text-gray-400">
                        <button onclick="historyBackPreview()" title="Kembali" class="p-2 hover:text-white transition-colors">
                            <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">
                                <path d="M15 18l-6-6 6-6" />
                            </svg>
                        </button>
                        <button onclick="updatePreview()" title="Home (Reload)" class="p-2 hover:text-white transition-colors">
                            <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">
                                <circle cx="12" cy="12" r="10" />
                            </svg>
                        </button>
                        <button title="Recent" class="p-2 hover:text-white transition-colors cursor-default">
                            <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">
                                <rect x="3" y="3" width="18" height="18" rx="2" ry="2" />
                            </svg>
                        </button>
                    </div>
                </div>
            </div>
            <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mt-4">
                <div class="bg-gray-900 rounded-md border border-red-800 flex flex-col h-48">
                    <div class="bg-red-900 text-white text-xs font-bold p-2 px-3 flex justify-between items-center">
                        <span>Console: Deteksi Error</span>
                        <button onclick="document.getElementById('errorConsole').textContent=''" class="bg-red-700 hover:bg-red-600 text-white rounded px-2 py-0.5 transition-colors" title="Bersihkan Log">Clear</button>
                    </div>
                    <div id="errorConsole" class="p-3 font-mono text-xs text-red-400 overflow-y-auto flex-1 whitespace-pre-wrap break-all"></div>
                </div>
                <div class="bg-gray-900 rounded-md border border-green-800 flex flex-col h-48">
                    <div class="bg-green-900 text-white text-xs font-bold p-2 px-3">Console: Sistem Berjalan</div>
                    <div id="sysConsole" class="p-3 font-mono text-xs text-green-400 overflow-y-auto flex-1 whitespace-pre-wrap break-all"></div>
                </div>
            </div>
        </div>
    </div>

    <div id="previewSettingsModal" class="fixed inset-0 bg-black bg-opacity-70 flex items-center justify-center z-50 p-4 hidden">
        <div class="bg-gray-800 rounded-lg shadow-xl w-full max-w-sm mx-auto border border-gray-700 flex flex-col">
            <div class="flex justify-between items-center p-4 border-b border-gray-700">
                <h3 class="text-lg font-bold text-indigo-400">Pengaturan Pratinjau</h3>
                <button onclick="closePreviewSettingsModal()" class="text-gray-400 hover:text-white transition-colors">
                    <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                        <line x1="18" y1="6" x2="6" y2="18"></line>
                        <line x1="6" y1="6" x2="18" y2="18"></line>
                    </svg>
                </button>
            </div>
            <div class="p-5 flex flex-col gap-4">
                <div>
                    <label class="block text-xs font-medium text-gray-300 mb-2">Pilih Mode</label>
                    <div class="flex gap-2">
                        <button id="btnModeMobile" onclick="setDevicePreset('mobile')" class="flex-1 bg-indigo-600 hover:bg-indigo-500 text-white font-medium py-2 rounded-md transition-colors text-sm border border-indigo-500 flex items-center justify-center gap-2">
                            <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                                <rect x="5" y="2" width="14" height="20" rx="2" ry="2"></rect>
                                <line x1="12" y1="18" x2="12.01" y2="18"></line>
                            </svg> Mobile
                        </button>
                        <button id="btnModeDesktop" onclick="setDevicePreset('desktop')" class="flex-1 bg-gray-700 hover:bg-gray-600 text-white font-medium py-2 rounded-md transition-colors text-sm border border-gray-600 flex items-center justify-center gap-2">
                            <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                                <rect x="2" y="3" width="20" height="14" rx="2" ry="2"></rect>
                                <line x1="8" y1="21" x2="16" y2="21"></line>
                                <line x1="12" y1="17" x2="12" y2="21"></line>
                            </svg> Desktop
                        </button>
                    </div>
                </div>
                <input type="hidden" id="previewMode" value="mobile">
                <div class="grid grid-cols-2 gap-3">
                    <div class="flex flex-col">
                        <label class="text-xs text-gray-400 mb-1">Lebar (px)</label>
                        <input type="text" id="previewWidth" value="360" class="bg-gray-900 text-white border border-gray-600 rounded px-3 py-2 text-sm focus:outline-none focus:border-indigo-400 w-full">
                    </div>
                    <div class="flex flex-col">
                        <label class="text-xs text-gray-400 mb-1">Tinggi (px)</label>
                        <input type="text" id="previewHeight" value="760" class="bg-gray-900 text-white border border-gray-600 rounded px-3 py-2 text-sm focus:outline-none focus:border-indigo-400 w-full">
                    </div>
                </div>
                <div class="flex flex-col">
                    <label class="text-xs text-gray-400 mb-1">Skala/DPI (%)</label>
                    <input type="text" id="previewScale" value="100" class="bg-gray-900 text-white border border-gray-600 rounded px-3 py-2 text-sm focus:outline-none focus:border-indigo-400 w-full">
                </div>
            </div>
            <div class="p-4 border-t border-gray-700">
                <button onclick="applyAndCloseSettings()" class="w-full bg-teal-600 hover:bg-teal-500 text-white font-bold py-2 px-4 rounded-md shadow transition-colors">
                    Terapkan & Tutup
                </button>
            </div>
        </div>
    </div>


    <div id="alertModal" class="fixed inset-0 bg-black bg-opacity-70 flex items-center justify-center z-50 p-4 hidden">
        <div class="bg-gray-800 rounded-lg shadow-xl p-6 w-full max-w-sm mx-auto text-center border border-gray-700">
            <p id="modal-message" class="text-lg text-gray-200 mb-6"></p>
            <button id="modal-ok-btn" class="bg-indigo-600 hover:bg-indigo-700 text-white font-bold py-2 px-8 rounded-lg transition-colors w-full sm:w-auto">
                OK
            </button>
        </div>
    </div>

    <script>
        let editor;
        let versionCounter = 0;
        let currentFileName = 'index.html'; 
        
        // --- FUNGSI MODAL ---
        const alertModal = document.getElementById('alertModal');
        const modalMessage = document.getElementById('modal-message');
        const modalOkBtn = document.getElementById('modal-ok-btn');
        
        function showAlert(message, type = 'info') {
            modalMessage.classList.remove('modal-message-success', 'modal-message-error', 'modal-message-info');
            if (type === 'success') {
                modalMessage.classList.add('modal-message-success');
            } else if (type === 'error') {
                modalMessage.classList.add('modal-message-error');
            } else {
                modalMessage.classList.add('modal-message-info');
            }
            modalMessage.textContent = message;
            alertModal.classList.remove('hidden');
            modalOkBtn.focus();
        }
        modalOkBtn.addEventListener('click', () => {
            alertModal.classList.add('hidden');
        });
        // --- AKHIR FUNGSI MODAL ---
        
        // --- FUNGSI PRATINJAU & CONSOLE ---
        let previewHistory = [];
        let previewTimeout = null;
        
        function updatePreview() {
            const iframe = document.getElementById('mobilePreview');
            if (!iframe) return;
            const htmlContent = editor.getValue();
            
            const interceptScript = `
                <script>
                    window.onerror = function(msg, url, line, col, error) {
                        window.parent.postMessage({ type: 'error', msg: msg + ' (Baris: ' + line + ')' }, '*');
                        return false;
                    };
                    const origLog = console.log;
                    console.log = function(...args) {
                        window.parent.postMessage({ type: 'log', msg: args.join(' ') }, '*');
                        origLog.apply(console, args);
                    };
                    const origWarn = console.warn;
                    console.warn = function(...args) {
                        window.parent.postMessage({ type: 'log', msg: 'WARN: ' + args.join(' ') }, '*');
                        origWarn.apply(console, args);
                    };
                    const origError = console.error;
                    console.error = function(...args) {
                        window.parent.postMessage({ type: 'error', msg: 'ERR: ' + args.join(' ') }, '*');
                        origError.apply(console, args);
                    };
                    const origInfo = console.info;
                    console.info = function(...args) {
                        window.parent.postMessage({ type: 'log', msg: 'INFO: ' + args.join(' ') }, '*');
                        origInfo.apply(console, args);
                    };
                <\/script>
            `;
            
            const headIntercept = `
                <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0, user-scalable=yes">
                ${interceptScript}
            `;
            
            let injectedHtml = htmlContent;
            if (injectedHtml.includes('<head>')) {
                injectedHtml = injectedHtml.replace('<head>', '<head>\n' + headIntercept);
            } else {
                injectedHtml = headIntercept + '\n' + injectedHtml;
            }
            
            iframe.srcdoc = injectedHtml;
            
            if (previewHistory.length === 0 || previewHistory[previewHistory.length - 1] !== htmlContent) {
                previewHistory.push(htmlContent);
            }
        }
        
        function historyBackPreview() {
            if (previewHistory.length > 1) {
                previewHistory.pop(); 
                const previousHtml = previewHistory[previewHistory.length - 1];
                editor.setValue(previousHtml);
                updatePreview();
                showAlert("Kembali ke versi kode sebelumnya.", "info");
            } else {
                showAlert("Tidak ada riwayat halaman sebelumnya.", "error");
            }
        }
        
        function appendConsoleLine(containerId, message) {
            const container = document.getElementById(containerId);
            if (!container) return;
            const time = new Date().toLocaleTimeString();
            const line = document.createElement('div');
            line.textContent = `[${time}] ${String(message == null ? '' : message)}`;
            container.appendChild(line);
            container.scrollTop = container.scrollHeight;
        }
        
        window.addEventListener('message', function(e) {
            if (e.data && e.data.type) {
                if (e.data.type === 'error') {
                    appendConsoleLine('errorConsole', e.data.msg);
                } else if (e.data.type === 'log') {
                    appendConsoleLine('sysConsole', e.data.msg);
                }
            }
        });
        
        
        
                // --- FUNGSI BARU (RESET, BEAUTIFY, PREVIEW SETTINGS) ---
                let isPageLocked = false;
        
        function toggleLock() {
            const btn = document.getElementById('btnLockPage');
            isPageLocked = !isPageLocked;
            
            if (isPageLocked) {
                document.body.style.overflow = 'hidden';
                btn.classList.replace('bg-gray-700', 'bg-rose-600');
                btn.classList.replace('border-gray-600', 'border-rose-500');
                btn.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="11" width="18" height="11" rx="2" ry="2"></rect><path d="M7 11V7a5 5 0 0 1 9.9-1"></path></svg> Buka Kunci`;
                showAlert('Layar dikunci! Anda hanya dapat menggeser pratinjau sekarang.', 'info');
            } else {
                document.body.style.overflow = '';
                btn.classList.replace('bg-rose-600', 'bg-gray-700');
                btn.classList.replace('border-rose-500', 'border-gray-600');
                btn.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><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> Kunci Layar`;
                showAlert('Layar dibuka!', 'success');
            }
        }
        
        window.addEventListener('resize', () => {
            applyPreviewSettings();
        });
        
        
        function resetEditor() {
            if(confirm('Yakin ingin mereset editor? Semua kode akan dihapus dan LocalStorage akan dibersihkan!')) {
                editor.setValue('');
                localStorage.removeItem('autosave_html');
                versionCounter = 0;
                updateIndicators();
                const iframe = document.getElementById('mobilePreview');
                if(iframe) iframe.srcdoc = '';
                showAlert('Editor berhasil di-reset.', 'success');
            }
        }
        
        function beautifyCode() {
            const currentCode = editor.getValue();
            if(!currentCode) return;
            if(typeof html_beautify !== 'undefined') {
                const formattedCode = html_beautify(currentCode, { indent_size: 4, wrap_line_length: 0, preserve_newlines: true });
                editor.setValue(formattedCode);
                updatePreview();
                showAlert('Kode berhasil dirapikan!', 'success');
            } else {
                showAlert('Library js-beautify belum dimuat.', 'error');
            }
        }
        
                function openPreviewSettingsModal() {
            document.getElementById('previewSettingsModal').classList.remove('hidden');
        }
        
        function closePreviewSettingsModal() {
            document.getElementById('previewSettingsModal').classList.add('hidden');
        }
        
        function setDevicePreset(mode) {
            const w = document.getElementById('previewWidth');
            const h = document.getElementById('previewHeight');
            const btnMobile = document.getElementById('btnModeMobile');
            const btnDesktop = document.getElementById('btnModeDesktop');
            const modeInput = document.getElementById('previewMode');
            
            modeInput.value = mode;
            if(mode === 'mobile') {
                w.value = '360';
                h.value = '760';
                btnMobile.classList.replace('bg-gray-700', 'bg-indigo-600');
                btnMobile.classList.replace('border-gray-600', 'border-indigo-500');
                btnDesktop.classList.replace('bg-indigo-600', 'bg-gray-700');
                btnDesktop.classList.replace('border-indigo-500', 'border-gray-600');
            } else {
                w.value = '1280';
                h.value = '720';
                btnDesktop.classList.replace('bg-gray-700', 'bg-indigo-600');
                btnDesktop.classList.replace('border-gray-600', 'border-indigo-500');
                btnMobile.classList.replace('bg-indigo-600', 'bg-gray-700');
                btnMobile.classList.replace('border-indigo-500', 'border-gray-600');
            }
        }
        
        function applyAndCloseSettings() {
            applyPreviewSettings();
            closePreviewSettingsModal();
            showAlert('Pengaturan layar diterapkan!', 'success');
        }
        
        function applyPreviewSettings() {
            const w = parseFloat(document.getElementById('previewWidth').value) || 360;
            const h = parseFloat(document.getElementById('previewHeight').value) || 760;
            const s = parseFloat(document.getElementById('previewScale').value) || 100;
            const mode = document.getElementById('previewMode').value;
            
            const container = document.getElementById('previewContainer');
            const iframe = document.getElementById('mobilePreview');
            const notch = document.getElementById('previewNotch');
            const nav = document.getElementById('previewNav');
            
                        if(container && iframe) {
                // Dapatkan lebar batas maksimal dari layar perangkat user saat ini (dikurangi padding 40px)
                const screenMaxW = window.innerWidth - 40;
                
                let targetBaseWidth = mode === 'desktop' ? 800 : 360;
                // Jangan izinkan baseWidth lebih besar dari layar aktual HP agar tidak terpotong
                let baseContainerWidth = Math.min(targetBaseWidth, screenMaxW);
                
                if(mode === 'desktop') {
                    container.style.borderRadius = '0.5rem';
                    container.style.borderWidth = '2px';
                    if(notch) notch.style.display = 'none';
                    if(nav) nav.style.display = 'none';
                } else {
                    container.style.borderRadius = '2.5rem';
                    container.style.borderWidth = '8px';
                    if(notch) notch.style.display = 'flex';
                    if(nav) nav.style.display = 'flex';
                }
        
                const aspectRatio = h / w;
                const containerHeight = baseContainerWidth * aspectRatio;
                
                container.style.transform = 'none';
                container.style.maxWidth = baseContainerWidth + 'px';
                container.style.height = containerHeight + 'px';
                
                // Set iframe ke resolusi murni inputan Anda
                iframe.style.width = w + 'px';
                iframe.style.height = h + 'px';
                
                // Auto-skala resolusi besar agar pas ke bingkai yang responsif ini
                const autoScale = baseContainerWidth / w;
                const finalScale = autoScale * (s / 100);
                
                iframe.style.transform = 'scale(' + finalScale + ')';
            }
            localStorage.setItem('preview_settings', JSON.stringify({ w: w, h: h, s: s, m: mode }));
        }
        
        function loadPreviewSettings() {
            const settings = localStorage.getItem('preview_settings');
            if(settings) {
                const parsed = JSON.parse(settings);
                document.getElementById('previewWidth').value = parsed.w || 360;
                document.getElementById('previewHeight').value = parsed.h || 760;
                document.getElementById('previewScale').value = parsed.s || 100;
                if(parsed.m) setDevicePreset(parsed.m);
                applyPreviewSettings();
            }
        }
        
        
        // --- Inisialisasi Editor CodeMirror ---
        document.addEventListener('DOMContentLoaded', () => {
            // Editor Utama (Kotak 1)
            editor = CodeMirror.fromTextArea(document.getElementById('mainEditor'), {
                mode: 'htmlmixed',
                theme: 'tokyo-night',
                lineNumbers: true,
                lineWrapping: true,
                autoCloseTags: true,
                autoCloseBrackets: true,
                gutters: ["CodeMirror-linenumbers"]
            });
            editor.on('change', () => {
                updateIndicators();
                localStorage.setItem('autosave_html', editor.getValue());
            });
            editor.on('blur', () => {
                updatePreview();
            }); 
            editor.setSize(null, "100%");
        
            const savedHtml = localStorage.getItem('autosave_html');
            if(savedHtml) { editor.setValue(savedHtml); }
            loadPreviewSettings();
            
            updateIndicators(); 
        });
        
        // --- FUNGSI INDIKATOR (Disederhanakan) ---
        function updateIndicators() {
            if (!editor) return; 
        
            const mainIndicator = document.getElementById('mainIndicator');
            const versionIndicator = document.getElementById('versionIndicator');
            const mainContent = editor.getValue();
        
            // Cek Main Editor (Kotak 1)
            if (mainContent.length > 0) {
                mainIndicator.classList.remove('bg-red-500');
                mainIndicator.classList.add('bg-green-500');
                versionIndicator.textContent = 'Versi ' + versionCounter;
                versionIndicator.classList.remove('text-gray-600');
                versionIndicator.classList.add('text-indigo-400');
            } else {
                mainIndicator.classList.remove('bg-green-500');
                mainIndicator.classList.add('bg-red-500');
                versionIndicator.textContent = '[ KOSONG ]';
                versionIndicator.classList.remove('text-indigo-400');
                versionIndicator.classList.add('text-gray-600');
                versionCounter = 0;
            }
        }
        
        // --- FUNGSI UPLOAD FILE & PASTE ---
        function triggerFileUpload() {
            document.getElementById('fileUploader').click();
        }
        
        function handleFileSelect(event) {
            const file = event.target.files[0];
            if (!file) return;
            currentFileName = file.name.replace(/\s*\(\d+\)/g, '');
        
            const isHtml = file.type.startsWith('text/html') || file.name.endsWith('.html') || file.name.endsWith('.htm');
            const isText = file.type.startsWith('text/plain');
            const isPhp = file.name.endsWith('.php');
        
            if (!isHtml && !isText && !isPhp) {
                showAlert("Error: Harap pilih file .html, .txt, atau .php.", 'error');
                event.target.value = null; 
                return;
            }
        
            const reader = new FileReader();
            reader.onload = function(e) {
                editor.setValue(e.target.result);
                versionCounter = 1; // Set Versi ke 1
                updateIndicators();
                updatePreview();
                showAlert("File '" + file.name + "' berhasil dimuat!", 'success');
            };
            reader.onerror = function() { showAlert("Error: Gagal membaca file.", 'error'); };
            reader.readAsText(file);
            event.target.value = null;
        }
        
        async function pasteIntoMainEditor() {
            try {
                const text = await navigator.clipboard.readText();
                editor.setValue(text);
                versionCounter = 1; // Set versi ke 1
                updateIndicators(); // Update UI
                updatePreview();
                showAlert("Teks berhasil ditempel ke Editor Utama.", "info");
            } catch (err) {
                console.error('Gagal menempel:', err.message);
                showAlert("Tempel otomatis gagal. Silakan klik editor & gunakan Ctrl+V.", "error");
            }
        }
        
        async function pasteIntoQuickCommand() {
            try {
                const text = await navigator.clipboard.readText();
                document.getElementById('quickCommandInput').value = text;
                showAlert("Teks berhasil ditempel ke Perintah Cepat.", "info");
            } catch (err) {
                console.error('Gagal menempel:', err.message);
                showAlert("Tempel otomatis gagal. Silakan gunakan Ctrl+V.", "error");
            }
        }
        
        // --- FUNGSI REGEX & PARSER JSON HELPER ---
        function escapeRegExp(string) {
            return String(string).replace(/[.*+?^${}()|[\]\\]/g, function(match) {
                return '\\' + match;
            });
        }
        
        function findBalancedJson(text) {
            text = String(text || '');
            for (let start = 0; start < text.length; start++) {
                const firstChar = text[start];
                if (firstChar !== '[' && firstChar !== '{') continue;
        
                const stack = [];
                let inString = false;
                let isEscaped = false;
        
                for (let i = start; i < text.length; i++) {
                    const ch = text[i];
        
                    if (inString) {
                        if (isEscaped) {
                            isEscaped = false;
                        } else if (ch === '\\') {
                            isEscaped = true;
                        } else if (ch === '"') {
                            inString = false;
                        }
                        continue;
                    }
        
                    if (ch === '"') {
                        inString = true;
                        continue;
                    }
        
                    if (ch === '[' || ch === '{') {
                        stack.push(ch);
                        continue;
                    }
        
                    if (ch === ']' || ch === '}') {
                        const opener = stack.pop();
                        const validPair = (ch === ']' && opener === '[') || (ch === '}' && opener === '{');
                        if (!validPair) break;
                        if (stack.length === 0) {
                            return text.slice(start, i + 1).trim();
                        }
                    }
                }
            }
            return '';
        }
        
        function extractJsonCommand(rawInput) {
            const raw = String(rawInput || '').replace(/^\uFEFF/, '').trim();
            if (!raw) {
                throw new Error('Input kosong.');
            }
        
            const candidates = [];
            const codeBlockMatch = raw.match(/```(?:json|javascript|js)?\s*([\s\S]*?)```/i);
            if (codeBlockMatch && codeBlockMatch[1]) {
                candidates.push(codeBlockMatch[1].trim());
            }
            candidates.push(raw);
        
            for (const candidate of candidates) {
                const jsonText = findBalancedJson(candidate);
                if (jsonText) return jsonText;
            }
        
            throw new Error('JSON Array/Object tidak ditemukan di dalam teks.');
        }
        
        function parseJsonCommand(rawInput) {
            const jsonText = extractJsonCommand(rawInput);
            try {
                return JSON.parse(jsonText);
            } catch (e) {
                throw new Error(e.message + ' | JSON terdeteksi mulai dari: ' + jsonText.slice(0, 120));
            }
        }
        
        // --- FUNGSI INTI (Multi-Perintah JSON v3.4) ---
        function applyAndExecute() {
            let currentHtml = editor.getValue();
            const quickCommandTextarea = document.getElementById('quickCommandInput');
            const commandInput = quickCommandTextarea.value;
        
            try {
                if (!currentHtml) {
                    showAlert("Kesalahan: Status Kode Sumber (Kotak 1) masih kosong!", 'error');
                    return;
                }
                if (!commandInput.trim()) {
                    showAlert("Kesalahan: Kotak Perintah Cepat (Kotak 2) masih kosong.", 'error');
                    return;
                }
        
                let cmds;
                try {
                    cmds = parseJsonCommand(commandInput);
                } catch (e) {
                    showAlert("Error: Format JSON di Perintah Cepat tidak valid. " + e.message, 'error');
                    return;
                }
        
                if (!Array.isArray(cmds)) {
                    cmds = [cmds];
                }
        
                if (cmds.length === 0) {
                    showAlert("Peringatan: JSON Array kosong, tidak ada perintah untuk dijalankan.", 'error');
                    return;
                }
        
                let successCount = 0;
                let lastActionWasDelete = false;
        
                for (let i = 0; i < cmds.length; i++) {
                    const cmd = cmds[i] || {};
                    const snippet = typeof cmd.snippet === 'undefined' ? "" : String(cmd.snippet);
                    const target = cmd.target;
                    const action = cmd.action;
                    const isRegex = !!cmd.regex;
                    const isGlobal = !!cmd.global;
        
                    if (!target || !action) {
                        showAlert(`Error Perintah ${i + 1}/${cmds.length}: JSON harus berisi 'target' dan 'action'.`, 'error');
                        return;
                    }
                    if (typeof cmd.snippet === 'undefined' && (action === 'insertBefore' || action === 'insertAfter')) {
                        showAlert(`Error Perintah ${i + 1}/${cmds.length}: 'snippet' harus ada untuk aksi '${action}'!`, 'error');
                        return;
                    }
        
                    let searchPattern;
                    const flags = (isGlobal ? 'g' : '') + 'ms';
        
                    try {
                        if (isRegex) {
                            searchPattern = new RegExp(String(target), flags);
                        } else {
                            searchPattern = new RegExp(escapeRegExp(String(target)), flags);
                        }
                    } catch (e) {
                        showAlert(`Regex Error Perintah ${i + 1}/${cmds.length}: Pola 'target' tidak valid. ` + e.message, 'error');
                        return;
                    }
        
                    const isFound = searchPattern.test(currentHtml);
                    searchPattern.lastIndex = 0;
                    if (!isFound) {
                        showAlert(`Peringatan Perintah ${i + 1}/${cmds.length}: 'target' (Kode Patokan) tidak ditemukan. Proses dihentikan, tolong buat ulang seluruh Perintah.`, 'error');
                        return;
                    }
        
                    let modifiedHtml = '';
                    switch (action) {
                        case 'insertBefore':
                            modifiedHtml = currentHtml.replace(searchPattern, function(match) {
                                return snippet + '\n' + match;
                            });
                            break;
                        case 'insertAfter':
                            modifiedHtml = currentHtml.replace(searchPattern, function(match) {
                                return match + '\n' + snippet;
                            });
                            break;
                        case 'replace':
                            modifiedHtml = currentHtml.replace(searchPattern, snippet);
                            lastActionWasDelete = !snippet;
                            break;
                        default:
                            showAlert(`Error Perintah ${i + 1}/${cmds.length}: 'action' tidak valid. Gunakan 'insertBefore', 'insertAfter', atau 'replace'.`, 'error');
                            return;
                    }
        
                    currentHtml = modifiedHtml;
                    successCount++;
                }
        
                editor.setValue(currentHtml);
                versionCounter++;
                updateIndicators();
                updatePreview();
        
                if (successCount === cmds.length) {
                    let successMessage = `Perintah Cepat Selesai: ${successCount} dari ${cmds.length} perintah berhasil dijalankan!`;
                    if (lastActionWasDelete && successCount === 1) {
                        successMessage = "Perintah Cepat Dijalankan: Kode patokan berhasil dihapus!";
                    }
                    showAlert(successMessage, 'success');
                }
            } finally {
                quickCommandTextarea.value = '';
            }
        }
        
        // --- Fungsi Tombol Bawah ---
        function copyResult() {
            const editorContent = editor.getValue();
            if (!editorContent) {
                showAlert("Editor kosong, tidak ada yang bisa disalin.", 'error');
                return;
            }
            
            navigator.clipboard.writeText(editorContent).then(() => {
                showAlert("Hasil berhasil disalin ke clipboard!", 'info');
            }).catch(err => {
                 showAlert("Gagal menyalin. Coba salin manual.", 'error');
            });
        }
        
        function downloadResult(baseFilename) {
            const content = editor.getValue();
            if (!content) {
                showAlert("Editor kosong, tidak ada yang bisa di-download.", 'error');
                return;
            }
            try {
                const ext = document.getElementById('downloadExtension').value;
                const finalFilename = baseFilename + ext;
                const blob = new Blob([content], { type: 'text/plain;charset=utf-8' });
                const a = document.createElement('a');
                a.href = URL.createObjectURL(blob);
                a.download = finalFilename; 
                a.style.display = 'none'; 
                document.body.appendChild(a);
                a.click();
                document.body.removeChild(a);
                URL.revokeObjectURL(a.href);
            } catch (err) {
                showAlert("Gagal membuat file download: " + err.message, 'error');
            }
        }
        
        // --- FUNGSI PROMPT WAJIB ALAT MODIFIKATOR v3.4 ---
        function copyPrompt() {
            const promptText = [
                "Halo, saya akan memakai Alat Modifikator v3.4 untuk memodifikasi file HTML/PHP.",
                "",
                "WAJIB ikuti alur kerja ini:",
                "",
                "FASE 1 - ANALISIS",
                "1. Saat saya memberikan Tujuan dan Konteks Kode, jangan langsung membuat JSON.",
                "2. Berikan analisis singkat tetapi detail: bagian mana yang akan diubah, fungsi apa yang ditambah/diganti, dan risiko target tidak ditemukan.",
                "3. Jangan output JSON pada fase analisis.",
                "4. Setelah analisis, tunggu saya membalas: buatkan atau lanjut.",
                "",
                "FASE 2 - EKSEKUSI",
                "1. Setelah saya membalas buatkan atau lanjut, balas HANYA dengan satu blok kode JSON.",
                "2. Jangan menambah teks pembuka, penjelasan, catatan, atau penutup di luar blok JSON.",
                "3. Format wajib: JSON Array, walaupun hanya ada satu perintah.",
                "4. Satu blok saja: ```json lalu isi JSON Array lalu ```.",
                "",
                "STRUKTUR JSON WAJIB:",
                "- snippet: kode baru yang akan disisipkan atau kode pengganti. Jika ingin menghapus, isi dengan string kosong \"\".",
                "- target: kode patokan yang benar-benar ada di file.",
                "- action: hanya boleh insertBefore, insertAfter, atau replace.",
                "- regex: true jika target memakai regex, false jika target teks biasa.",
                "- global: true jika semua kemunculan target harus diubah, false jika hanya kemunculan pertama.",
                "",
                "ATURAN PENTING:",
                "1. Gunakan JSON Array valid.",
                "2. Escape semua tanda kutip dua di dalam snippet dan target.",
                "3. Gunakan \\n untuk baris baru di dalam string JSON.",
                "4. Jangan gunakan action selain insertBefore, insertAfter, replace.",
                "5. Jangan membuat target yang mengira-ngira. Target harus cocok dengan Konteks Kode.",
                "6. Untuk perubahan multi-file, kerjakan satu file dulu, lalu tunggu konfirmasi saya sebelum membuat JSON untuk file berikutnya.",
                "7. Jika target berisiko tidak ditemukan, gunakan regex yang aman dan spesifik.",
                "",
                "Contoh format jawaban saat fase eksekusi:",
                "```json",
                "[",
                "  {",
                "    \"snippet\": \"kode baru di sini\",",
                "    \"target\": \"kode patokan di sini\",",
                "    \"action\": \"replace\",",
                "    \"regex\": false,",
                "    \"global\": false",
                "  }",
                "]",
                "```",
                "",
                "Tujuan Saya:",
                "[saya akan menjelaskan tujuan modifikasi di pesan berikutnya]",
                "",
                "Konteks Kode:",
                "```html",
                "[tempelkan kode/file HTML atau PHP yang ingin dimodifikasi di sini]",
                "```"
            ].join('\n');
        
            navigator.clipboard.writeText(promptText).then(() => {
                showAlert("Prompt workflow Alat Modifikator v3.4 berhasil disalin!", 'success');
            }).catch(err => {
                showAlert("Gagal menyalin prompt. Coba salin manual.", 'error');
            });
        }
    </script>
</body>

</html>