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

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Admin Panel - Pandawa-Digital</title>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
    <style>
        :root {
            --primary: #2563eb;
            --primary-dark: #1d4ed8;
            --primary-soft: #dbeafe;
            --dark: #0f172a;
            --light: #f4f7fb;
            --surface: rgba(255,255,255,0.92);
            --surface-solid: #ffffff;
            --muted: #64748b;
            --line: #e2e8f0;
            --success: #10b981;
            --warning: #f59e0b;
            --danger: #ef4444;
            --grad-main: linear-gradient(135deg, #2563eb 0%, #4f46e5 55%, #7c3aed 100%);
            --grad-dark: linear-gradient(180deg, #0f172a 0%, #111827 48%, #1e1b4b 100%);
            --sidebar-width: 268px;
            --radius-xl: 22px;
            --shadow-soft: 0 14px 40px rgba(15, 23, 42, 0.08);
            --shadow-card: 0 18px 45px rgba(37, 99, 235, 0.10);
        }
        * { box-sizing: border-box; }
        body {
            font-family: 'Segoe UI', system-ui, -apple-system, BlinkMacSystemFont, sans-serif;
            background:
                radial-gradient(circle at top left, rgba(37,99,235,.14), transparent 28%),
                radial-gradient(circle at bottom right, rgba(124,58,237,.12), transparent 28%),
                var(--light);
            margin: 0;
            display: flex;
            flex-direction: column;
            height: 100vh;
            overflow: hidden;
            color: #1e293b;
        }
        body::before {
            content: "";
            position: fixed;
            inset: 0;
            pointer-events: none;
            background-image: linear-gradient(rgba(255,255,255,.35) 1px, transparent 1px), linear-gradient(90deg, rgba(255,255,255,.35) 1px, transparent 1px);
            background-size: 34px 34px;
            opacity: .35;
            z-index: -1;
        }
        
        /* LOGIN STYLE */
        .login-container {
            display: flex;
            min-height: 100%;
            width: 100%;
            align-items: center;
            justify-content: center;
            position: absolute;
            top: 0;
            left: 0;
            padding: 22px;
            background:
                linear-gradient(135deg, rgba(15,23,42,.94), rgba(29,78,216,.90)),
                radial-gradient(circle at 15% 20%, rgba(56,189,248,.55), transparent 32%),
                radial-gradient(circle at 85% 75%, rgba(168,85,247,.42), transparent 34%);
            z-index: 9999;
            overflow: hidden;
        }
        .login-container::before,
        .login-container::after {
            content: "";
            position: absolute;
            width: 340px;
            height: 340px;
            border-radius: 999px;
            filter: blur(5px);
            opacity: .5;
            background: radial-gradient(circle, rgba(255,255,255,.22), transparent 68%);
            animation: adminFloat 8s ease-in-out infinite;
        }
        .login-container::before { top: -110px; left: -80px; }
        .login-container::after { bottom: -130px; right: -90px; animation-delay: -3s; }
        .card {
            position: relative;
            z-index: 1;
            background: rgba(255,255,255,.92);
            backdrop-filter: blur(18px);
            -webkit-backdrop-filter: blur(18px);
            padding: 32px;
            border-radius: 28px;
            border: 1px solid rgba(255,255,255,.50);
            box-shadow: 0 25px 70px rgba(2, 6, 23, .32);
            width: 100%;
            max-width: 430px;
        }
        .login-brand-icon {
            width: 62px;
            height: 62px;
            margin: 0 auto 14px;
            border-radius: 20px;
            display: flex;
            align-items: center;
            justify-content: center;
            background: var(--grad-main);
            color: #fff;
            box-shadow: 0 14px 30px rgba(37, 99, 235, .32);
            font-size: 26px;
        }
        .login-title { text-align:center; margin:0; color:#0f172a; font-size:24px; letter-spacing:-.4px; }
        .login-subtitle { text-align:center; color:#64748b; font-size:12px; margin:8px 0 22px; line-height:1.5; }
        .form-group { margin-bottom: 15px; }
        .form-group label { display: block; margin-bottom: 7px; font-weight: 700; font-size: 12px; color: #334155; }
        input, select {
            width: 100%;
            padding: 12px 13px;
            border: 1px solid #dbe3ef;
            border-radius: 14px;
            box-sizing: border-box;
            background: rgba(255,255,255,.92);
            color: #0f172a;
            outline: none;
            transition: .2s ease;
        }
        input:focus, select:focus {
            border-color: rgba(37,99,235,.65);
            box-shadow: 0 0 0 4px rgba(37,99,235,.10);
            background: #fff;
        }
        button {
            width: 100%;
            padding: 12px;
            background: var(--grad-main);
            color: white;
            border: none;
            border-radius: 14px;
            cursor: pointer;
            font-weight: 800;
            transition: 0.22s ease;
            box-shadow: 0 12px 26px rgba(37, 99, 235, 0.24);
        }
        button:hover { transform: translateY(-1px); box-shadow: 0 16px 32px rgba(37, 99, 235, 0.30); }
        button:active { transform: scale(0.98); box-shadow: 0 6px 14px rgba(37, 99, 235, 0.22); }
        
        /* DASHBOARD LAYOUT */
        #adminDashboard { display: none; width: 100%; height: 100%; }
        
        /* SIDEBAR */
        .sidebar {
            width: var(--sidebar-width);
            background: var(--grad-dark);
            color: white;
            height: 100vh;
            position: fixed;
            left: 0;
            top: 0;
            z-index: 100;
            transition: 0.3s;
            display: flex;
            flex-direction: column;
            box-shadow: 18px 0 55px rgba(15,23,42,.20);
            border-right: 1px solid rgba(255,255,255,.10);
        }
        .sidebar::before {
            content: "";
            position: absolute;
            inset: 0;
            background: radial-gradient(circle at 30% 0%, rgba(59,130,246,.30), transparent 35%);
            pointer-events: none;
        }
        .sidebar-header {
            position: relative;
            padding: 22px 18px;
            font-size: 20px;
            font-weight: 900;
            border-bottom: 1px solid rgba(255,255,255,0.10);
            display: flex;
            justify-content: space-between;
            align-items: center;
        }
        .brand-wrap { display:flex; align-items:center; gap:12px; min-width:0; }
        .brand-logo {
            width: 42px;
            height: 42px;
            border-radius: 15px;
            display:flex;
            align-items:center;
            justify-content:center;
            background: rgba(255,255,255,.14);
            border: 1px solid rgba(255,255,255,.22);
            box-shadow: inset 0 1px 0 rgba(255,255,255,.16);
        }
        .brand-text { line-height:1.05; min-width:0; }
        .brand-title { display:block; font-size:15px; letter-spacing:.2px; white-space:nowrap; }
        .brand-subtitle { display:block; margin-top:4px; font-size:10px; color:#93c5fd; letter-spacing:1.2px; text-transform:uppercase; }
        .sidebar-menu { position:relative; list-style: none; padding: 12px; margin: 0; flex: 1; overflow-y: auto; }
        .sidebar-menu::-webkit-scrollbar, .content-body::-webkit-scrollbar { width: 7px; }
        .sidebar-menu::-webkit-scrollbar-thumb, .content-body::-webkit-scrollbar-thumb { background: rgba(148,163,184,.55); border-radius:999px; }
        .sidebar-menu li {
            padding: 13px 14px;
            cursor: pointer;
            border-left: 0;
            border-radius: 15px;
            transition: 0.22s ease;
            display: flex;
            align-items: center;
            gap: 11px;
            font-size: 13px;
            color: rgba(226,232,240,.84);
            margin-bottom: 5px;
            position: relative;
        }
        .sidebar-menu li:hover, .sidebar-menu li.active {
            background: rgba(255,255,255,0.12);
            color: #ffffff;
            font-weight: 800;
            transform: translateX(3px);
            box-shadow: inset 0 0 0 1px rgba(255,255,255,.09);
        }
        .sidebar-menu li.active::before {
            content: "";
            width: 4px;
            height: 22px;
            border-radius: 999px;
            background: #60a5fa;
            position: absolute;
            left: -6px;
        }
        .sidebar-menu li i {
            width: 28px;
            height: 28px;
            border-radius: 10px;
            display:flex;
            align-items:center;
            justify-content:center;
            text-align: center;
            color: #bfdbfe;
            background: rgba(255,255,255,.08);
        }
        
        /* MAIN CONTENT */
        .main-content { margin-left: var(--sidebar-width); height: 100vh; overflow: hidden; display: flex; flex-direction: column; transition: 0.3s; width: calc(100% - var(--sidebar-width)); }
        .top-header {
            background: rgba(255,255,255,.86);
            backdrop-filter: blur(14px);
            -webkit-backdrop-filter: blur(14px);
            padding: 16px 26px;
            box-shadow: 0 8px 28px rgba(15,23,42,0.06);
            display: flex;
            align-items: center;
            justify-content: space-between;
            z-index: 90;
            flex-shrink: 0;
            border-bottom: 1px solid rgba(226,232,240,.78);
        }
        .top-header h3 { letter-spacing:-.35px; color:#0f172a; }
        .admin-chip {
            display:inline-flex;
            align-items:center;
            gap:7px;
            padding:8px 12px;
            border-radius:999px;
            background:#eff6ff;
            color:#1d4ed8;
            border:1px solid #bfdbfe;
            font-size:12px;
            font-weight:800;
        }
        .content-body { padding: 26px; flex: 1; overflow-y: auto; position: relative; }
        
        /* VIEWS & SECTIONS */
        .page-section { display: none; animation: fadeIn 0.3s; }
        .page-section.active { display: block; }
        @keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }
        @keyframes adminFloat { 0%,100% { transform: translate3d(0,0,0) scale(1); } 50% { transform: translate3d(18px,16px,0) scale(1.04); } }
        
        .section {
            background: var(--surface);
            padding: 25px;
            border-radius: var(--radius-xl);
            box-shadow: var(--shadow-soft);
            margin-bottom: 22px;
            border: 1px solid rgba(226,232,240,.86);
            backdrop-filter: blur(10px);
            -webkit-backdrop-filter: blur(10px);
        }
        .section h4 {
            margin-top: 0;
            border-bottom: 1px solid #e2e8f0;
            padding-bottom: 15px;
            color: var(--dark);
            letter-spacing: -.2px;
            display:flex;
            align-items:center;
            gap:8px;
        }
        .section h4 i { color: var(--primary); }
        
        /* COMPONENTS */
        .stats-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: 18px; margin-bottom: 22px; }
        .stat-card {
            position: relative;
            overflow: hidden;
            background: linear-gradient(145deg, rgba(255,255,255,.98), rgba(248,250,252,.92));
            padding: 22px;
            border-radius: 22px;
            box-shadow: var(--shadow-card);
            border: 1px solid rgba(226,232,240,.82);
            border-left: 0 !important;
            min-height: 118px;
            transition: .24s ease;
        }
        .stat-card::after {
            content: "";
            position: absolute;
            right: -38px;
            top: -38px;
            width: 122px;
            height: 122px;
            border-radius: 999px;
            background: rgba(37,99,235,.10);
        }
        .stat-card:hover { transform: translateY(-3px); box-shadow: 0 22px 55px rgba(37,99,235,.14); }
        .stat-card p { font-size: 11px; color: #64748b; margin: 0 0 9px 0; font-weight: 900; text-transform: uppercase; letter-spacing:.45px; position:relative; z-index:1; }
        .stat-card h2 { margin: 0; font-size: 25px; color: var(--dark); letter-spacing:-.6px; position:relative; z-index:1; }
        
        table { width: 100%; border-collapse: separate; border-spacing: 0; font-size: 13px; margin-top: 10px; overflow:hidden; }
        th { background: linear-gradient(180deg, #f8fafc, #eef2ff); font-weight: 800; color: #334155; font-size:12px; text-transform:uppercase; letter-spacing:.25px; }
        th:first-child { border-top-left-radius: 14px; }
        th:last-child { border-top-right-radius: 14px; }
        th, td { text-align: left; padding: 13px 15px; border-bottom: 1px solid #e2e8f0; }
        tbody tr { transition:.18s ease; }
        tbody tr:hover { background:#f8fbff; }
        .status-badge { padding: 5px 10px; border-radius: 20px; color: white; font-size: 10px; font-weight: 900; letter-spacing:.25px; }
        
        
        /* USER CARD MODERN */
        .users-toolbar-admin { display:flex; align-items:center; justify-content:space-between; gap:14px; flex-wrap:wrap; margin-bottom:16px; }
        .users-toolbar-admin .search-box { flex:1; min-width:240px; margin-bottom:0; }
        .users-total-chip { display:flex; align-items:center; gap:8px; padding:11px 14px; border-radius:999px; background:linear-gradient(135deg,#eef2ff,#f8fafc); border:1px solid #dbeafe; color:#1e3a8a; font-size:12px; font-weight:900; box-shadow:0 8px 22px rgba(37,99,235,.08); }
        .user-card-grid-admin { display:grid; grid-template-columns:repeat(auto-fit,minmax(285px,1fr)); gap:16px; margin-top:8px; }
        .user-card-admin { position:relative; overflow:hidden; background:linear-gradient(145deg,rgba(255,255,255,.98),rgba(248,250,252,.96)); border:1px solid rgba(226,232,240,.9); border-radius:22px; padding:16px; box-shadow:0 15px 42px rgba(15,23,42,.08); transition:.22s ease; }
        .user-card-admin::before { content:""; position:absolute; inset:0 0 auto 0; height:5px; background:linear-gradient(90deg,#2563eb,#7c3aed,#06b6d4); }
        .user-card-admin::after { content:""; position:absolute; width:115px; height:115px; right:-48px; top:-48px; border-radius:999px; background:rgba(37,99,235,.09); pointer-events:none; }
        .user-card-admin:hover { transform:translateY(-3px); box-shadow:0 22px 55px rgba(37,99,235,.14); border-color:#bfdbfe; }
        .user-card-top-admin { position:relative; z-index:1; display:flex; align-items:flex-start; gap:12px; }
        .user-avatar-admin { width:48px; height:48px; border-radius:18px; display:flex; align-items:center; justify-content:center; color:white; font-weight:900; font-size:18px; background:linear-gradient(135deg,#2563eb,#7c3aed); box-shadow:0 10px 24px rgba(37,99,235,.25); flex-shrink:0; text-transform:uppercase; }
        .user-main-admin { flex:1; min-width:0; }
        .user-name-admin { display:flex; align-items:center; gap:7px; flex-wrap:wrap; font-size:15px; font-weight:900; color:#0f172a; line-height:1.25; word-break:break-word; }
        .user-email-admin { margin-top:3px; font-size:11px; color:#64748b; word-break:break-all; line-height:1.35; }
        .user-badge-admin { display:inline-flex; align-items:center; gap:5px; padding:4px 8px; border-radius:999px; font-size:9px; font-weight:900; letter-spacing:.25px; text-transform:uppercase; }
        .user-badge-admin.role-user { color:#1d4ed8; background:#dbeafe; }
        .user-badge-admin.role-pelapak { color:#7c2d12; background:#ffedd5; }
        .user-badge-admin.warn { color:#991b1b; background:#fee2e2; }
        .user-badge-admin.chat-off { color:#92400e; background:#fef3c7; }
        .user-badge-admin.chat-on { color:#065f46; background:#d1fae5; }
        .user-meta-grid-admin { position:relative; z-index:1; display:grid; grid-template-columns:1fr 1fr; gap:10px; margin-top:14px; }
        .user-meta-admin { background:#f8fafc; border:1px solid #e2e8f0; border-radius:16px; padding:10px; min-width:0; }
        .user-meta-admin span { display:block; font-size:9px; color:#64748b; font-weight:900; text-transform:uppercase; letter-spacing:.35px; margin-bottom:4px; }
        .user-meta-admin b { display:block; font-size:12px; color:#0f172a; word-break:break-word; }
        .user-meta-admin.saldo b { color:#2563eb; font-size:14px; }
        .uid-row-admin { display:flex; align-items:center; gap:7px; }
        .uid-row-admin code { flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; font-size:11px; color:#334155; background:#eef2ff; border:1px solid #dbeafe; padding:5px 7px; border-radius:10px; }
        .copy-uid-admin { width:28px; height:28px; border:none; border-radius:10px; display:flex; align-items:center; justify-content:center; background:#2563eb; color:white; cursor:pointer; box-shadow:0 7px 16px rgba(37,99,235,.22); }
        .user-action-grid-admin { position:relative; z-index:1; display:grid; grid-template-columns:repeat(2,1fr); gap:8px; margin-top:14px; }
        .user-action-grid-admin button { border:none; border-radius:13px; padding:10px 9px; font-size:11px; font-weight:900; cursor:pointer; display:flex; align-items:center; justify-content:center; gap:7px; color:white; transition:.18s ease; width:100%; }
        .user-action-grid-admin button:hover { transform:translateY(-1px); filter:brightness(.98); }
        .btn-user-store { background:linear-gradient(135deg,#8b5cf6,#6d28d9); }
        .btn-user-history { background:linear-gradient(135deg,#334155,#0f172a); }
        .btn-user-edit { background:linear-gradient(135deg,#2563eb,#1d4ed8); }
        .btn-user-chat { background:linear-gradient(135deg,#06b6d4,#0284c7); }
        .btn-user-chat.off { background:linear-gradient(135deg,#f59e0b,#d97706); }
        .btn-user-delete { background:linear-gradient(135deg,#ef4444,#b91c1c); grid-column:1 / -1; }
        .empty-user-card-admin { text-align:center; padding:30px 15px; border-radius:20px; border:1px dashed #cbd5e1; background:#f8fafc; color:#64748b; font-weight:800; }
        @media (max-width:768px) {
            .users-toolbar-admin { gap:10px; }
            .users-toolbar-admin .search-box { min-width:100%; }
            .users-total-chip { width:100%; justify-content:center; padding:9px 12px; font-size:11px; }
            .user-card-grid-admin { grid-template-columns:1fr; gap:12px; }
            .user-card-admin { padding:14px; border-radius:18px; }
            .user-avatar-admin { width:42px; height:42px; border-radius:15px; font-size:16px; }
            .user-meta-grid-admin { grid-template-columns:1fr; gap:8px; }
            .user-action-grid-admin { grid-template-columns:1fr 1fr; }
            .user-action-grid-admin button { padding:9px 8px; font-size:10px; }
        }
        
        
        /* CHAT SYSTEM STYLES */
        .chat-bubble { max-width: 80%; padding: 10px 14px; border-radius: 12px; position: relative; font-size: 13px; line-height: 1.4; word-wrap: break-word; margin-bottom: 5px; box-shadow: 0 1px 2px rgba(0,0,0,0.1); }
        .chat-bubble.user { align-self: flex-start; background: white; border: 1px solid #ddd; border-bottom-left-radius: 0; }
        .chat-bubble.admin { align-self: flex-end; background: #dcf8c6; border: 1px solid #c3e6cb; border-bottom-right-radius: 0; }
        .chat-info { font-size: 10px; color: #999; margin-bottom: 4px; display: flex; justify-content: space-between; gap: 15px; }
        .chat-actions { position: absolute; top: -8px; right: -8px; display: none; background: white; padding: 3px; border-radius: 5px; box-shadow: 0 2px 5px rgba(0,0,0,0.2); border: 1px solid #ccc; }
        .chat-bubble:hover .chat-actions { display: flex; gap: 4px; }
        .chat-btn-act { cursor: pointer; font-size: 11px; padding: 5px; color: #555; transition: 0.2s; border-radius: 3px; background:#f9f9f9; }
        .chat-btn-act:hover { background: #eee; }
        .chat-btn-act.del:hover { background: #ffebee; color: red; }
        
        /* MODAL */
        .modal { display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.5); z-index: 1000; align-items: center; justify-content: center; }
        .modal-content { background: white; padding: 25px; border-radius: 12px; width: 90%; max-width: 400px; }
        .btn-save { background: var(--grad-main); color: white; border: none; padding: 10px; border-radius: 8px; width: 100%; cursor: pointer; margin-top: 10px; box-shadow: 0 4px 15px rgba(37, 99, 235, 0.2); }
        .btn-close { background: #eee; color: #333; border: none; padding: 10px; border-radius: 8px; width: 100%; cursor: pointer; margin-top: 5px; }
        .search-box { position: relative; margin-bottom: 15px; }
        .search-box i { position: absolute; left: 12px; top: 13px; color: #999; }
        .search-box input { padding-left: 35px; }
        
        /* DETAIL MODAL STYLE */
        .detail-row { display: flex; justify-content: space-between; padding: 10px 0; border-bottom: 1px dashed #eee; font-size: 13px; }
        .detail-label { color: #888; }
        .detail-value { font-weight: bold; color: #333; text-align: right; }
        .sn-box-admin { background: #f9f9f9; padding: 10px; border-radius: 8px; border: 1px solid #ddd; font-family: monospace; font-size: 12px; margin-top: 10px; word-break: break-all; }
        
        /* Floating Save Button */
        .fab-container { position: fixed; bottom: 0; left: 0; width: 100%; padding: 15px 20px; background: white; box-shadow: 0 -5px 15px rgba(0,0,0,0.1); z-index: 999; display: flex; justify-content: center; box-sizing: border-box; }
        .btn-fab { background: var(--grad-main); color: white; padding: 12px 30px; border-radius: 50px; font-weight: bold; border: none; font-size: 16px; width: 100%; max-width: 500px; cursor: pointer; display: flex; align-items: center; justify-content: center; gap: 10px; box-shadow: 0 4px 15px rgba(37, 99, 235, 0.3); transition: 0.2s; }
        .btn-fab:active { transform: scale(0.98); }
        
        /* Markup Row Styling */
        .markup-item-row { background: #f9f9f9; padding: 10px; border-radius: 10px; border: 1px solid #eee; display: flex; align-items: center; gap: 12px; transition: 0.2s; }
        .markup-item-row:hover { border-color: var(--primary); background: #f0f7ff; }
        .markup-info { flex: 1; overflow: hidden; }
        .markup-check-box { display: flex; align-items: center; justify-content: center; border-left: 1px dashed #ccc; padding-left: 10px; }
        .markup-checkbox { width: 22px; height: 22px; cursor: pointer; accent-color: var(--primary); }
        
        /* QUICK MENU & FILTER & PAGINATION */
        .quick-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 15px; margin-bottom: 20px; }
        .btn-quick { background: white; border: none; padding: 20px; border-radius: 12px; box-shadow: 0 4px 10px rgba(0,0,0,0.03); cursor: pointer; transition: 0.2s; text-align: center; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px; font-weight: bold; color: #555; }
        .btn-quick:hover { transform: translateY(-3px); box-shadow: 0 8px 20px rgba(0,0,0,0.1); color: var(--primary); }
        .btn-quick i { font-size: 24px; color: var(--primary); }
        
        .filter-group { display: flex; gap: 10px; margin-bottom: 15px; flex-wrap: wrap; }
        .filter-btn { background: white; border: 1px solid #ddd; padding: 8px 15px; border-radius: 20px; cursor: pointer; font-size: 12px; font-weight: bold; color: #555; transition: 0.2s; }
        .filter-btn.active { background: var(--primary); color: white; border-color: var(--primary); }
        
        .pagination { display: flex; justify-content: center; gap: 5px; margin-top: 15px; }
        .page-btn { width: 30px; height: 30px; display: flex; align-items: center; justify-content: center; background: white; border: 1px solid #ddd; border-radius: 5px; cursor: pointer; font-size: 12px; font-weight: bold; }
        .page-btn.active { background: var(--primary); color: white; border-color: var(--primary); }
        
        /* === MOBILE RESPONSIVE (50% SMALLER / CONDENSED VIEW) === */
        .burger-btn { display: none; font-size: 20px; cursor: pointer; color: var(--dark); }
        
        @media (max-width: 768px) {
            :root { --sidebar-width: 250px; }
            body { font-size: 12px; /* Perkecil font base */ } 
            
            /* Sidebar & Overlay */
            .sidebar { left: -250px; width: 220px; }
            .sidebar.active { left: 0; box-shadow: 5px 0 15px rgba(0,0,0,0.1); }
            .main-content { margin-left: 0; width: 100%; }
            .burger-btn { display: block; margin-right: 15px; font-size: 18px; flex-shrink: 0; }
            .overlay-mobile { display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.5); z-index: 99; }
            .overlay-mobile.active { display: block; }
        
            /* Header Condensed */
            .top-header { padding: 10px 15px; height: auto; min-height: 50px; box-sizing: border-box; }
            .top-header h3 { font-size: 16px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 50vw; }
            
            /* Content Padding Smaller */
            .content-body { padding: 15px; }
            .section { padding: 15px; border-radius: 8px; margin-bottom: 15px; }
            .section h4 { font-size: 14px; padding-bottom: 10px; margin-bottom: 10px; }
        
            /* Grid Smaller Gap */
            .stats-grid { gap: 10px; grid-template-columns: repeat(2, 1fr); } 
            .stat-card { padding: 15px; }
            .stat-card p { font-size: 10px; margin-bottom: 3px; }
            .stat-card h2 { font-size: 18px; }
        
            /* Quick Grid 2 Kolom */
            .quick-grid { grid-template-columns: repeat(2, 1fr); gap: 10px; }
            .btn-quick { padding: 15px; gap: 8px; font-size: 11px; }
            .btn-quick i { font-size: 20px; }
        
            /* Table Condensed */
            table, thead, tbody, th, td, tr { display: block; }
            thead { display: none; }
            tr { margin-bottom: 10px; border: 1px solid #eee; border-radius: 8px; padding: 10px; background: white; }
            td { padding: 5px 0; border: none; font-size: 11px; display: flex; justify-content: space-between; align-items: center; text-align: right; }
            td::before { content: attr(data-label); font-weight: bold; float: left; text-align: left; margin-right: 10px; color: #777; }
            #adminTrxList td, #listUserHist td { display: block; text-align: left; padding: 0; }
            #adminTrxList td::before, #listUserHist td::before { content: none; }
        
            /* Form Elements Smaller */
            input, select, button { padding: 8px; font-size: 11px; border-radius: 6px; }
            .form-group { margin-bottom: 10px; }
            .form-group label { font-size: 11px; margin-bottom: 3px; }
        
            /* Modal Smaller */
            .modal-content { padding: 15px; width: 95%; max-height: 90vh; overflow-y: auto; }
            
            /* Tombol Paginasi Kecil */
            .pagination button, #adminTrxPagin button, #paginUserHist button { 
                min-width: 26px !important; 
                height: 26px !important; 
                font-size: 10px !important; 
                margin: 0 1px !important;
            }
        }
            
        /* CHAT V2 (REPLY & MOBILE OPTIMIZED) */
        .chat-reply-bar { background: #f0f4f8; padding: 8px 12px; border-left: 4px solid var(--primary); display: flex; justify-content: space-between; align-items: center; font-size: 11px; border-top: 1px solid #eee; width: 100%; box-sizing: border-box; animation: slideUp 0.2s; }
        .reply-content { flex: 1; overflow: hidden; margin-right: 10px; }
        .reply-name { font-weight: bold; color: var(--primary); margin-bottom: 2px; font-size: 10px; }
        .reply-text { color: #666; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-size: 10px; }
        .quoted-msg { background: rgba(0,0,0,0.05); border-left: 3px solid var(--primary); padding: 5px 8px; border-radius: 4px; margin-bottom: 6px; font-size: 11px; display: block; color: #555; }
        .chat-bubble.admin .quoted-msg { background: rgba(0,0,0,0.05); border-left-color: #0f5132; }
        
        /* MOBILE CHAT COMPACT (60% DENSITY) */
        @media (max-width: 768px) {
            #adminChatBox { padding: 10px !important; gap: 4px !important; }
            .chat-bubble { font-size: 10px !important; padding: 6px 10px !important; max-width: 85% !important; border-radius: 8px !important; margin-bottom: 3px !important; }
            .chat-info { font-size: 9px !important; margin-bottom: 2px !important; gap: 5px !important; }
            .chat-actions { top: auto !important; bottom: -25px !important; right: 0 !important; background: white; padding: 2px !important; border: 1px solid #eee; box-shadow: 0 2px 5px rgba(0,0,0,0.1); z-index: 99; }
            .chat-btn-act { font-size: 12px !important; padding: 6px !important; }
            .quoted-msg { font-size: 9px !important; padding: 4px !important; margin-bottom: 3px !important; }
            #chatReplyPreview { padding: 5px 10px !important; }
            #adminChatInput { font-size: 11px !important; padding: 8px 12px !important; height: auto !important; }
            /* FIX SCROLL MOBILE: Sesuaikan tinggi dengan sisa layar tanpa mengganggu body */
            #view-chat .section { height: calc(100vh - 120px) !important; margin-bottom: 0 !important; padding: 0 !important; border-radius: 8px !important; }
        }
            
            /* CONTEXT MENU CHAT */
            .chat-popup-menu { position: fixed; background: white; border: 1px solid #ddd; border-radius: 8px; box-shadow: 0 4px 15px rgba(0,0,0,0.15); z-index: 99999; display: flex; flex-direction: column; overflow: hidden; min-width: 140px; }
            .chat-popup-menu button { background: none; border: none; padding: 12px 15px; text-align: left; font-size: 13px; cursor: pointer; display: flex; align-items: center; gap: 10px; color: #333; transition: 0.2s; width: 100%; font-family: 'Segoe UI', sans-serif; }
            .chat-popup-menu button:hover { background: #f0f4f8; color: var(--primary); }
            .chat-popup-menu button.del-btn { color: #ef4444; border-top: 1px solid #eee; }
            .chat-popup-menu button.del-btn:hover { background: #fee2e2; }
            .chat-popup-overlay { position: fixed; top: 0; left: 0; width: 100%; height: 100%; z-index: 99998; display: none; }
            
            
        
        /* SWITCH MAINTENANCE MODERN */
        .maintenance-switch-grid {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
            gap: 12px;
            margin: 10px 0 18px;
        }
        .maintenance-switch-card {
            position: relative;
            background: #ffffff;
            border: 1px solid #e5e7eb;
            border-radius: 16px;
            padding: 14px;
            box-shadow: 0 8px 24px rgba(15, 23, 42, 0.06);
            transition: .25s ease;
        }
        .maintenance-switch-card.is-on {
            border-color: #fecaca;
            background: linear-gradient(135deg, #fff7f7, #fff1f2);
            box-shadow: 0 12px 30px rgba(220, 38, 38, 0.12);
        }
        .maintenance-switch-head {
            display: flex;
            align-items: center;
            justify-content: space-between;
            gap: 12px;
        }
        .maintenance-switch-title {
            font-size: 13px;
            font-weight: 800;
            color: #111827;
            line-height: 1.35;
        }
        .maintenance-switch-desc {
            margin-top: 7px;
            font-size: 11px;
            color: #6b7280;
            line-height: 1.45;
        }
        .maintenance-switch-status {
            display: inline-flex;
            align-items: center;
            gap: 5px;
            margin-top: 10px;
            padding: 5px 8px;
            border-radius: 999px;
            background: #f3f4f6;
            color: #4b5563;
            font-size: 10px;
            font-weight: 900;
            letter-spacing: .3px;
            transition: .25s ease;
        }
        .maintenance-switch-card.is-on .maintenance-switch-status {
            background: #fee2e2;
            color: #b91c1c;
        }
        .maintenance-switch {
            position: relative;
            width: 58px;
            height: 32px;
            flex: 0 0 auto;
        }
        .maintenance-switch input {
            opacity: 0;
            width: 0;
            height: 0;
        }
        .maintenance-slider {
            position: absolute;
            inset: 0;
            cursor: pointer;
            background: #d1d5db;
            border-radius: 999px;
            transition: .28s cubic-bezier(.4, 0, .2, 1);
            box-shadow: inset 0 2px 4px rgba(0,0,0,.12);
        }
        .maintenance-slider:before {
            content: "";
            position: absolute;
            width: 26px;
            height: 26px;
            left: 3px;
            top: 3px;
            background: white;
            border-radius: 50%;
            transition: .28s cubic-bezier(.4, 0, .2, 1);
            box-shadow: 0 4px 10px rgba(0,0,0,.18);
        }
        .maintenance-switch input:checked + .maintenance-slider {
            background: linear-gradient(135deg, #ef4444, #b91c1c);
        }
        .maintenance-switch input:checked + .maintenance-slider:before {
            transform: translateX(26px);
        }
        .maintenance-switch input:active + .maintenance-slider:before {
            width: 31px;
        }
        
        
        /* PATCH DONI: Panel Admin Running Text */
        .running-admin-card {
            background: linear-gradient(135deg, #ffffff 0%, #f8fafc 100%);
            border: 1px solid #e2e8f0;
            border-radius: 18px;
            padding: 16px;
            margin: 18px 0;
            box-shadow: 0 14px 35px rgba(15, 23, 42, 0.08);
        }
        .running-admin-head {
            display: flex;
            justify-content: space-between;
            align-items: center;
            gap: 12px;
            margin-bottom: 14px;
            padding-bottom: 12px;
            border-bottom: 1px dashed #cbd5e1;
        }
        .running-admin-title {
            font-weight: 900;
            color: #0f172a;
            font-size: 15px;
            display: flex;
            align-items: center;
            gap: 8px;
        }
        .running-admin-subtitle {
            font-size: 11px;
            color: #64748b;
            margin-top: 4px;
            line-height: 1.4;
        }
        .running-admin-grid {
            display: grid;
            grid-template-columns: repeat(2, minmax(0, 1fr));
            gap: 12px;
        }
        .running-admin-grid .form-group { margin-bottom: 0; }
        .running-admin-grid label {
            font-size: 12px;
            font-weight: 800;
            color: #334155;
            margin-bottom: 6px;
            display: block;
        }
        .running-admin-grid input,
        .running-admin-grid select,
        .running-admin-grid textarea {
            width: 100%;
            box-sizing: border-box;
            padding: 10px 11px;
            border: 1px solid #cbd5e1;
            border-radius: 11px;
            outline: none;
            font-size: 12px;
            background: #fff;
            transition: .2s;
        }
        .running-admin-grid input:focus,
        .running-admin-grid select:focus,
        .running-admin-grid textarea:focus {
            border-color: var(--primary);
            box-shadow: 0 0 0 3px rgba(37, 99, 235, .10);
        }
        .running-admin-wide { grid-column: 1 / -1; }
        .running-toggle-row {
            display: flex;
            align-items: center;
            gap: 10px;
            background: #f1f5f9;
            border-radius: 14px;
            padding: 10px;
            border: 1px solid #e2e8f0;
        }
        .running-preview-box {
            --rt-preview-color: #ffffff;
            --rt-preview-bg: #0f172a;
            --rt-preview-speed: 14s;
            --rt-preview-dot-off: rgba(203, 213, 225, .15);
            --rt-preview-dot-off-soft: rgba(148, 163, 184, .09);
            background:
                linear-gradient(180deg, rgba(255,255,255,.04), rgba(2,6,23,.10)),
                var(--rt-preview-bg);
            color: var(--rt-preview-color);
            border-radius: 15px;
            min-height: 44px;
            overflow: hidden;
            position: relative;
            display: flex;
            align-items: center;
            margin-top: 10px;
            border: 1px solid rgba(148, 163, 184, .25);
            box-shadow: inset 0 1px 0 rgba(255,255,255,.04), inset 0 -8px 18px rgba(2,6,23,.18);
        }
        .running-preview-box::before {
            content: "";
            position: absolute;
            inset: 0;
            pointer-events: none;
            background-image:
                radial-gradient(circle at center, var(--rt-preview-dot-off) 0 1.05px, transparent 1.45px),
                radial-gradient(circle at center, var(--rt-preview-dot-off-soft) 0 .65px, transparent .95px);
            background-size: 10px 10px, 20px 20px;
            background-position: 0 0, 5px 5px;
            opacity: .95;
        }
        .running-preview-box.preview-transparent {
            background: transparent !important;
            color: var(--rt-preview-color);
            box-shadow: none;
        }
        .running-preview-box.preview-transparent::before { opacity: .28; }
        .running-preview-content {
            position: relative;
            z-index: 1;
            display: inline-flex;
            flex-direction: column;
            gap: 3px;
            white-space: nowrap;
            font-size: 12px;
            font-weight: 900;
            padding-left: 100%;
            text-shadow: 0 2px 9px rgba(0,0,0,.35);
            animation: adminRtLeft var(--rt-preview-speed) linear infinite;
        }
        .running-preview-box.preview-led .running-preview-content,
        .running-preview-box.preview-rgb .running-preview-content {
            font-family: 'Courier New', monospace;
            letter-spacing: 3px;
            text-transform: uppercase;
            text-shadow: none;
        }
        .running-preview-box.preview-led .running-preview-content span,
        .running-preview-box.preview-rgb .running-preview-content span {
            display: block;
            color: transparent !important;
            -webkit-text-fill-color: transparent;
            background-image: radial-gradient(circle, var(--rt-preview-color) 0 48%, rgba(255,255,255,0) 58%);
            background-size: 8px 8px;
            background-position: center center;
            -webkit-background-clip: text;
            background-clip: text;
            filter: drop-shadow(0 0 4px var(--rt-preview-color)) drop-shadow(0 0 10px var(--rt-preview-color));
        }
        .running-preview-box.preview-rainbow:not(.preview-led):not(.preview-rgb) .running-preview-content {
            background: linear-gradient(90deg, #ef4444, #f59e0b, #22c55e, #06b6d4, #3b82f6, #a855f7, #ec4899, #ef4444);
            background-size: 350% 100%;
            -webkit-background-clip: text;
            background-clip: text;
            color: transparent !important;
            animation: adminRtLeft var(--rt-preview-speed) linear infinite, adminRtRainbow 3s linear infinite;
        }
        .running-preview-box.preview-rainbow.preview-led .running-preview-content span,
        .running-preview-box.preview-rainbow.preview-rgb .running-preview-content span {
            background-image:
                linear-gradient(90deg, #ef4444, #f59e0b, #22c55e, #06b6d4, #3b82f6, #a855f7, #ec4899, #ef4444),
                radial-gradient(circle, rgba(255,255,255,.98) 0 48%, rgba(255,255,255,0) 58%);
            background-size: 350% 100%, 8px 8px;
            background-position: 0% 50%, center center;
            background-blend-mode: screen;
            animation: adminRtRainbow 3s linear infinite;
        }
        .running-preview-box.preview-right .running-preview-content { padding-left: 0; padding-right: 100%; animation-name: adminRtRight; }
        .running-preview-box.preview-bounce .running-preview-content { padding-left: 0; min-width: 100%; animation-name: adminRtBounce; animation-timing-function: ease-in-out; }
        .running-preview-box.preview-blink .running-preview-content { padding-left: 0; width: 100%; text-align: center; animation-name: adminRtBlink; animation-timing-function: steps(2, end); }
        .running-preview-box.preview-wave .running-preview-content { animation: adminRtLeft var(--rt-preview-speed) linear infinite, adminRtWave 1.5s ease-in-out infinite; }
        .running-preview-box.preview-bus .running-preview-content { animation-name: adminRtBus; animation-timing-function: cubic-bezier(.28,.02,.08,1); }
        .running-preview-box.preview-neon .running-preview-content { animation: adminRtLeft var(--rt-preview-speed) linear infinite, adminRtNeon 1.2s ease-in-out infinite; }
        .running-preview-box.preview-fade .running-preview-content { padding-left: 0; width: 100%; text-align: center; animation-name: adminRtFade; animation-timing-function: ease-in-out; }
        @keyframes adminRtLeft { 0% { transform: translateX(0); } 100% { transform: translateX(-120%); } }
        @keyframes adminRtRight { 0% { transform: translateX(-100%); } 100% { transform: translateX(120%); } }
        @keyframes adminRtBounce { 0%,100% { transform: translateX(6%); } 50% { transform: translateX(-6%); } }
        @keyframes adminRtBlink { 0%,45% { opacity:1; } 46%,70% { opacity:.16; } 71%,100% { opacity:1; } }
        @keyframes adminRtWave { 0%,100% { filter:hue-rotate(0deg) brightness(1); } 50% { filter:hue-rotate(80deg) brightness(1.25); } }
        @keyframes adminRtBus { 0% { transform:translateX(0) skewX(-8deg) scale(1); } 8% { transform:translateX(-8%) skewX(8deg) scale(1.03); } 18% { transform:translateX(-20%) skewX(-5deg) scale(.98); } 100% { transform:translateX(-130%) skewX(-8deg) scale(1); } }
        @keyframes adminRtNeon { 0%,100% { text-shadow:0 0 4px currentColor, 0 0 10px currentColor; } 50% { text-shadow:0 0 8px currentColor, 0 0 18px currentColor, 0 0 28px currentColor; } }
        @keyframes adminRtFade { 0%,100% { opacity:0; transform:scale(.96); } 18%,82% { opacity:1; transform:scale(1); } }
        @keyframes adminRtRainbow { 0% { background-position:0% 50%; } 100% { background-position:350% 50%; } }
        @media (max-width: 768px) {
            .running-admin-grid { grid-template-columns: 1fr; }
            .running-admin-head { align-items: flex-start; flex-direction: column; }
        }
        
        /* === TRADING STYLE STATISTIC CHART === */
        .trading-chart-panel {
            position: relative;
            margin: 18px 0 24px;
            padding: 18px;
            border-radius: 24px;
            overflow: hidden;
            background:
                radial-gradient(circle at top left, rgba(34,197,94,.18), transparent 30%),
                radial-gradient(circle at bottom right, rgba(59,130,246,.18), transparent 34%),
                linear-gradient(135deg, #06111f 0%, #0f172a 50%, #111827 100%);
            border: 1px solid rgba(148,163,184,.20);
            box-shadow: 0 24px 60px rgba(15,23,42,.22);
        }
        .trading-chart-panel::before {
            content: "";
            position: absolute;
            inset: 0;
            background-image:
                linear-gradient(rgba(148,163,184,.06) 1px, transparent 1px),
                linear-gradient(90deg, rgba(148,163,184,.06) 1px, transparent 1px);
            background-size: 38px 38px;
            pointer-events: none;
        }
        .trading-chart-head {
            position: relative;
            z-index: 1;
            display: flex;
            justify-content: space-between;
            align-items: flex-start;
            gap: 14px;
            flex-wrap: wrap;
            margin-bottom: 14px;
        }
        .trading-title {
            display: flex;
            align-items: center;
            gap: 11px;
            color: #f8fafc;
            margin: 0;
            font-size: 17px;
            letter-spacing: -.3px;
        }
        .trading-title-icon {
            width: 40px;
            height: 40px;
            border-radius: 14px;
            display: inline-flex;
            align-items: center;
            justify-content: center;
            background: rgba(34,197,94,.14);
            color: #4ade80;
            border: 1px solid rgba(74,222,128,.24);
        }
        .trading-subtitle {
            margin: 6px 0 0 51px;
            font-size: 11px;
            color: #94a3b8;
        }
        .trading-controls {
            position: relative;
            z-index: 1;
            display: flex;
            gap: 8px;
            flex-wrap: wrap;
            justify-content: flex-end;
        }
        .trading-controls .chart-btn {
            width: auto;
            padding: 8px 11px;
            border-radius: 12px;
            font-size: 11px;
            font-weight: 900;
            color: #dbeafe;
            background: rgba(15,23,42,.72);
            border: 1px solid rgba(148,163,184,.24);
            box-shadow: none;
            cursor: pointer;
        }
        .trading-controls .chart-btn:hover,
        .trading-controls .chart-btn.active {
            color: #ffffff;
            background: rgba(37,99,235,.88);
            border-color: rgba(147,197,253,.45);
            transform: translateY(-1px);
        }
        .trading-mini-stats {
            position: relative;
            z-index: 1;
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(135px, 1fr));
            gap: 10px;
            margin: 12px 0 14px;
        }
        .trading-mini-card {
            padding: 11px 12px;
            border-radius: 16px;
            background: rgba(15,23,42,.62);
            border: 1px solid rgba(148,163,184,.18);
        }
        .trading-mini-card span {
            display:block;
            font-size:10px;
            color:#94a3b8;
            font-weight:900;
            text-transform:uppercase;
            letter-spacing:.45px;
        }
        .trading-mini-card b {
            display:block;
            margin-top:5px;
            font-size:18px;
            color:#f8fafc;
            letter-spacing:-.35px;
        }
        .trading-chart-wrap {
            position: relative;
            z-index: 1;
            height: 390px;
            width: 100%;
            border-radius: 18px;
            padding: 10px;
            background: rgba(2,6,23,.32);
            border: 1px solid rgba(148,163,184,.14);
        }
        .trading-help {
            position: relative;
            z-index: 1;
            margin-top: 10px;
            color: #94a3b8;
            font-size: 11px;
            display: flex;
            align-items: center;
            gap: 7px;
            flex-wrap: wrap;
        }
        @media (max-width: 720px) {
            .trading-chart-panel { padding: 14px; border-radius: 20px; }
            .trading-chart-head { align-items: stretch; }
            .trading-controls { justify-content: flex-start; }
            .trading-controls .chart-btn { padding: 7px 9px; }
            .trading-chart-wrap { height: 330px; }
            .trading-subtitle { margin-left: 0; }
        }
        
        
        /* === EXTRA POLISH CHART RESPONSIVE MOBILE === */
        .trading-chart-panel {
            padding: clamp(12px, 2.4vw, 22px) !important;
            border-radius: clamp(18px, 3vw, 28px) !important;
            background:
                radial-gradient(circle at 12% 10%, rgba(34,197,94,.26), transparent 28%),
                radial-gradient(circle at 88% 8%, rgba(59,130,246,.22), transparent 30%),
                radial-gradient(circle at 80% 82%, rgba(168,85,247,.18), transparent 35%),
                linear-gradient(135deg, #020617 0%, #07111f 42%, #111827 100%) !important;
            box-shadow: 0 26px 70px rgba(2, 6, 23, .34) !important;
        }
        .trading-chart-panel::after {
            content: "";
            position: absolute;
            inset: 0;
            pointer-events: none;
            background: linear-gradient(120deg, transparent 0%, rgba(255,255,255,.055) 35%, transparent 65%);
            opacity: .85;
        }
        .trading-chart-head {
            align-items: center !important;
        }
        .trading-title {
            font-size: clamp(14px, 2.8vw, 18px) !important;
        }
        .trading-title-icon {
            width: clamp(34px, 8vw, 42px) !important;
            height: clamp(34px, 8vw, 42px) !important;
            border-radius: 14px !important;
            background: linear-gradient(135deg, rgba(34,197,94,.26), rgba(59,130,246,.18)) !important;
            box-shadow: 0 0 26px rgba(34,197,94,.20) !important;
        }
        .trading-subtitle {
            max-width: 520px;
            color: #a7b7d4 !important;
        }
        .trading-controls {
            background: rgba(2,6,23,.38);
            padding: 7px;
            border-radius: 17px;
            border: 1px solid rgba(148,163,184,.16);
        }
        .trading-controls .chart-btn {
            min-width: 42px;
            min-height: 34px;
            border-radius: 12px !important;
            white-space: nowrap;
            background: rgba(15,23,42,.78) !important;
        }
        .trading-controls .chart-btn.active {
            background: linear-gradient(135deg, #2563eb, #16a34a) !important;
            border-color: rgba(187,247,208,.38) !important;
            box-shadow: 0 9px 22px rgba(37,99,235,.22) !important;
        }
        .trading-mini-stats {
            grid-template-columns: repeat(4, minmax(0, 1fr)) !important;
        }
        .trading-mini-card {
            background: linear-gradient(145deg, rgba(15,23,42,.82), rgba(30,41,59,.58)) !important;
            box-shadow: inset 0 1px 0 rgba(255,255,255,.05);
        }
        .trading-mini-card b {
            font-size: clamp(14px, 2.6vw, 19px) !important;
        }
        .trading-chart-wrap {
            height: clamp(280px, 48vh, 430px) !important;
            padding: clamp(6px, 1.8vw, 12px) !important;
            background:
                linear-gradient(180deg, rgba(2,6,23,.48), rgba(15,23,42,.28)),
                rgba(2,6,23,.32) !important;
            box-shadow: inset 0 0 0 1px rgba(255,255,255,.035), inset 0 18px 40px rgba(15,23,42,.28);
        }
        @media (max-width: 820px) {
            .trading-chart-head {
                display: block !important;
            }
            .trading-controls {
                margin-top: 12px;
                justify-content: flex-start !important;
                flex-wrap: nowrap !important;
                overflow-x: auto;
                -webkit-overflow-scrolling: touch;
                scrollbar-width: none;
                padding-bottom: 8px;
            }
            .trading-controls::-webkit-scrollbar { display: none; }
            .trading-mini-stats {
                grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
                gap: 8px !important;
            }
        }
        @media (max-width: 480px) {
            .trading-chart-panel {
                margin-left: -8px !important;
                margin-right: -8px !important;
            }
            .trading-subtitle {
                display: none !important;
            }
            .trading-mini-card {
                padding: 9px 10px !important;
                border-radius: 14px !important;
            }
            .trading-mini-card span {
                font-size: 9px !important;
            }
            .trading-chart-wrap {
                height: 300px !important;
                border-radius: 16px !important;
            }
        }
        
        
    </style>
    <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/hammerjs@2.0.8"></script>
    <script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-zoom@2.0.1/dist/chartjs-plugin-zoom.min.js"></script>


</head>

<body>

    <div id="loginPage" class="login-container">
        <div class="card">
            <div class="login-brand-icon"><i class="fas fa-shield-halved"></i></div>
            <h2 class="login-title">Pandawa Admin</h2>
            <p class="login-subtitle">Control Center profesional untuk mengelola user, transaksi, audit, produk, topup, dan pengaturan sistem.</p>
            <div class="form-group">
                <label><i class="fas fa-envelope"></i> Email Admin</label>
                <input type="email" id="email" placeholder="Masukkan email admin">
            </div>
            <div class="form-group">
                <label><i class="fas fa-lock"></i> Password</label>
                <input type="password" id="pass" placeholder="Masukkan password">
            </div>
            <button onclick="login()"><i class="fas fa-right-to-bracket"></i> MASUK PANEL</button>
            <div style="text-align:center; font-size:11px; color:#64748b; margin-top:16px;">Pandawa-Digital Admin Control Center</div>
        </div>
    </div>

    <div id="adminDashboard">

        <div class="overlay-mobile" id="mobileOverlay" onclick="toggleSidebar()"></div>

        <div class="sidebar" id="sidebar">
            <div class="sidebar-header">
                <div class="brand-wrap">
                    <div class="brand-logo"><i class="fas fa-bolt"></i></div>
                    <div class="brand-text">
                        <span class="brand-title">Pandawa-Digital</span>
                        <span class="brand-subtitle">Admin Panel</span>
                    </div>
                </div>
                <i class="fas fa-times" onclick="toggleSidebar()" style="cursor:pointer; font-size:16px; display:none;" id="closeSidebar"></i>
            </div>
            <ul class="sidebar-menu">
                <li onclick="showPage('view-home', this)" class="active"><i class="fas fa-home"></i> Dashboard</li>
                <li onclick="showPage('view-chat', this)"><i class="fas fa-comments"></i> Live Chat</li>
                <li onclick="showPage('view-doniguard', this)"><i class="fas fa-shield-alt"></i> Audit DoniGuard</li>
                <li onclick="showPage('view-settings', this)"><i class="fas fa-cog"></i> Pengaturan</li>

                <li onclick="showPage('view-bank-manual', this)"><i class="fas fa-university"></i> Metode Bank</li>
                <li onclick="showPage('view-markup', this)"><i class="fas fa-tags"></i> Atur Markup</li>
                <li onclick="showPage('view-upload', this)"><i class="fas fa-images"></i> Upload Icon</li>
                <li onclick="showPage('view-users', this)"><i class="fas fa-users"></i> Pengguna</li>
                <li onclick="showPage('view-history', this)"><i class="fas fa-history"></i> Riwayat</li>
                <li onclick="showPage('view-broadcast', this)"><i class="fas fa-bullhorn"></i> Siaran Masal</li>
                <li onclick="showPage('view-version', this)"><i class="fas fa-code-branch"></i> Versi Sistem</li>


                <li onclick="showPage('view-po-akrab', this)"><i class="fas fa-clock"></i> Antrian Pre-Order</li>
                <li onclick="logout()" style="color:#ff6b6b; margin-top:20px; border-top:1px solid rgba(255,255,255,0.1)"><i class="fas fa-sign-out-alt"></i> Keluar</li>
            </ul>
        </div>

        <div class="main-content">

            <div class="top-header">
                <div style="display:flex; align-items:center;">
                    <i class="fas fa-bars burger-btn" onclick="toggleSidebar()"></i>
                    <h3 style="margin:0; font-size:18px;" id="pageTitle">Dashboard</h3>
                </div>
                <div class="admin-chip"><i class="fas fa-user-shield"></i> Admin Panel</div>
            </div>

            <div class="content-body">

                <div id="view-home" class="page-section active">
                    <div class="stats-grid">
                        <div class="stat-card" style="cursor:pointer;" onclick="showPage('view-users', document.querySelector('.sidebar-menu li[onclick*=\" view-users\"]'))">
                            <p>TOTAL PENGGUNA</p>
                            <h2 id="statTotalUser">0</h2>
                        </div>
                        <div class="stat-card">
                            <p>LIABILITAS SALDO</p>
                            <h2 id="statTotalSaldo">Rp 0</h2>
                        </div>

                        <div class="stat-card" style="border-left-color: #10b981;">
                            <p>TOTAL TOPUP (BERHASIL)</p>
                            <h2 id="statTotalTopup">Rp 0</h2>
                        </div>
                        <div class="stat-card" style="border-left-color: #ef4444; cursor:pointer;" onclick="window.cekSaldoAdmin()" title="Klik untuk refresh saldo server">
                            <p>Saldo OrKut</p>
                            <h2 id="statSaldoAdmin" style="color:#ef4444">
                                <i class="fas fa-sync"></i> Cek
                            </h2>
                        </div>
                    </div>
                    <div class="section">
                        <div class="quick-grid">

                            <div class="btn-quick" onclick="showPage('view-po-akrab', document.querySelector('.sidebar-menu li:nth-child(12)'))">
                                <i class="fas fa-clock"></i> Antrian PO Akrab
                            </div>
                            <div class="btn-quick" onclick="showPage('view-settings', document.querySelector('.sidebar-menu li:nth-child(4)'))">
                                <i class="fas fa-cogs"></i> Pengaturan
                            </div>
                        </div>

                        <div class="trading-chart-panel">
                            <div class="trading-chart-head">
                                <div>
                                    <h4 class="trading-title">
                                        <span class="trading-title-icon"><i class="fas fa-chart-line"></i></span>
                                        Statistik Transaksi Trading View (<span id="chartMonthLabel">Bulan Ini</span>)
                                    </h4>
                                    <p class="trading-subtitle">Kontrol grafik lewat tombol 7D, 14D, Full, zoom, reset, atau geser grafik di layar HP.</p>
                                </div>
                                <div class="trading-controls">
                                    <button class="chart-btn" onclick="changeChartMonth(-1)"><i class="fas fa-chevron-left"></i> Prev</button>
                                    <button class="chart-btn" onclick="changeChartMonth(1)">Next <i class="fas fa-chevron-right"></i></button>
                                    <button class="chart-btn active" data-range-btn="7" onclick="setChartRange(7)">7D</button>
                                    <button class="chart-btn" data-range-btn="14" onclick="setChartRange(14)">14D</button>
                                    <button class="chart-btn" data-range-btn="all" onclick="setChartRange('all')">Full</button>
                                    <button class="chart-btn active" data-mode-btn="trading" onclick="setChartMode('trading')"><i class="fas fa-wave-square"></i></button>
                                    <button class="chart-btn" data-mode-btn="bar" onclick="setChartMode('bar')"><i class="fas fa-chart-column"></i></button>
                                    <button class="chart-btn" onclick="zoomChart(1.35)" title="Zoom In"><i class="fas fa-search-plus"></i></button>
                                    <button class="chart-btn" onclick="zoomChart(0.75)" title="Zoom Out"><i class="fas fa-search-minus"></i></button>
                                    <button class="chart-btn" onclick="resetZoomChart()" title="Reset"><i class="fas fa-rotate-right"></i></button>
                                </div>
                            </div>
                            <div class="trading-mini-stats">
                                <div class="trading-mini-card"><span>Berhasil</span><b id="chartSuccessTotal">0</b></div>
                                <div class="trading-mini-card"><span>Gagal</span><b id="chartFailedTotal">0</b></div>
                                <div class="trading-mini-card"><span>Total Transaksi</span><b id="chartAllTotal">0</b></div>
                                <div class="trading-mini-card"><span>Hari Tersibuk</span><b id="chartBestDay">-</b></div>
                            </div>
                            <div class="trading-chart-wrap">
                                <canvas id="trxChart"></canvas>
                            </div>

                        </div>
                    </div>

                    <div class="section" style="border: 2px solid #f59e0b; background: #fffdf7;">
                        <h4 style="color: #d35400; border-bottom-color: #f59e0b;"><i class="fas fa-bell"></i> Antrean Topup Manual (PENDING)</h4>
                        <div id="listPendingTopup" style="max-height: 350px; overflow-y: auto;">
                            <div style="text-align:center; padding:20px; color:#999;"><i class="fas fa-circle-notch fa-spin"></i> Memuat antrean...</div>
                        </div>
                    </div>
                </div>

                <div id="view-chat" class="page-section">
                    <style>
                        .chat-container-layout { height: calc(100vh - 110px); display: flex; padding: 0; background: white; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.05); overflow: hidden; }
                        .chat-sidebar-layout { width: 250px; border-right: 1px solid #eee; display: flex; flex-direction: column; background: #f8f9fa; }
                        .chat-main-layout { flex: 1; display: flex; flex-direction: column; background: #e5ddd5; }
                        .chat-header-style { padding: 10px 15px; background: white; border-bottom: 1px solid #ddd; font-weight: bold; font-size: 13px; color: var(--primary); box-shadow: 0 2px 5px rgba(0,0,0,0.02); }
                        .chat-input-style { flex: 1; padding: 10px 12px; border-radius: 20px; border: 1px solid #ccc; outline: none; font-size: 12px; }
                        .chat-btn-style { width: 38px; height: 38px; border-radius: 50%; background: var(--primary); color: white; border: none; cursor: pointer; display: flex; align-items: center; justify-content: center; font-size: 13px; }
                        
                        @media (max-width: 768px) {
                            .chat-container-layout { flex-direction: column; height: calc(100vh - 130px) !important; }
                            .chat-sidebar-layout { width: 100%; height: 35%; border-right: none; border-bottom: 2px solid #ddd; }
                            .chat-main-layout { height: 65%; }
                            .chat-header-style { font-size: 11px; padding: 8px 10px; }
                            .chat-input-style { font-size: 10px; padding: 8px 10px; }
                            .chat-btn-style { width: 30px; height: 30px; font-size: 11px; }
                            #listChatUsers { padding: 0; }
                            #listChatUsers > div { padding: 6px 10px !important; }
                            #listChatUsers > div > div:first-child { font-size: 11px !important; margin-bottom: 1px !important; }
                            #listChatUsers > div > div:last-child { font-size: 9px !important; }
                            #adminChatBox { padding: 8px !important; gap: 4px !important; }
                            #adminChatBox > div { padding: 6px 10px !important; font-size: 10px !important; max-width: 85% !important; margin-bottom: 3px !important; }
                            #adminChatBox > div > div:first-child { font-size: 8px !important; margin-bottom: 2px !important; }
                            #adminChatBox > div > div:last-child { font-size: 7px !important; margin-top: 2px !important; }
                            #chatInputAreaAdmin { padding: 6px 10px !important; gap: 6px !important; }
                        }
                    </style>
                    <div class="section chat-container-layout">
                        <div class="chat-sidebar-layout">
                            <div class="chat-header-style" style="background: #eee; color:var(--dark);">
                                <i class="fas fa-users"></i> DAFTAR USER CHAT
                            </div>
                            <div id="listChatUsers" style="flex: 1; overflow-y: auto;">
                                <div style="text-align:center; padding:20px; color:#999; font-size:11px;">Memuat...</div>
                            </div>
                        </div>
                        <div class="chat-main-layout">
                            <div id="chatHeaderAdmin" class="chat-header-style">
                                Pilih User untuk Membalas
                            </div>
                            <div id="adminChatBox" style="flex: 1; overflow-y: auto; padding: 15px; display: flex; flex-direction: column; gap: 8px;"></div>
                            <div id="chatInputAreaAdmin" style="padding: 10px 15px; background: #f0f0f0; border-top: 1px solid #ddd; display: none; gap: 10px; align-items: center;">
                                <input type="text" id="adminChatInputPribadi" placeholder="Ketik balasan Anda di sini..." class="chat-input-style">
                                <button onclick="kirimChatAdminPribadi()" class="chat-btn-style"><i class="fas fa-paper-plane"></i></button>
                            </div>
                        </div>
                    </div>
                </div>
                <div id="view-doniguard" class="page-section">
                    <div class="section">
                        <h4><i class="fas fa-shield-alt"></i> Audit DoniGuard</h4>
                        <p style="font-size:12px; color:#666; margin-bottom:15px;">Audit rantai saldo seluruh user: saldo awal admin/reset, topup/transfer, refund, saldo digunakan, dan saldo sekarang.</p>

                        <div style="display:grid; grid-template-columns:repeat(auto-fit,minmax(180px,1fr)); gap:10px; margin-bottom:15px;">
                            <div style="background:#eff6ff; border:1px solid #bfdbfe; border-radius:12px; padding:12px;">
                                <div style="font-size:11px; color:#1d4ed8; font-weight:bold;">TOTAL USER DIAUDIT</div>
                                <div id="dgAuditTotalUser" style="font-size:22px; font-weight:900; color:#1e3a8a;">0</div>
                            </div>
                            <div style="background:#f0fdf4; border:1px solid #bbf7d0; border-radius:12px; padding:12px;">
                                <div style="font-size:11px; color:#15803d; font-weight:bold;">USER AMAN</div>
                                <div id="dgAuditAman" style="font-size:22px; font-weight:900; color:#166534;">0</div>
                            </div>
                            <div style="background:#fff7ed; border:1px solid #fed7aa; border-radius:12px; padding:12px;">
                                <div style="font-size:11px; color:#c2410c; font-weight:bold;">USER BERMASALAH</div>
                                <div id="dgAuditMasalah" style="font-size:22px; font-weight:900; color:#9a3412;">0</div>
                            </div>
                            <div style="background:#fef2f2; border:1px solid #fecaca; border-radius:12px; padding:12px;">
                                <div style="font-size:11px; color:#b91c1c; font-weight:bold;">TOTAL TEMUAN</div>
                                <div id="dgAuditTemuan" style="font-size:22px; font-weight:900; color:#991b1b;">0</div>
                            </div>
                        </div>

                        <div style="background:white; padding:15px; border-radius:10px; border:1px solid #eee; margin-bottom:20px;">
                            <div style="display:flex; justify-content:space-between; align-items:center; gap:10px; margin-bottom:10px; flex-wrap:wrap;">
                                <div>
                                    <h5 style="margin:0; color:#555;">Pilih User / Jalankan Audit:</h5>
                                    <div style="font-size:11px; color:#777; margin-top:3px;">Audit membaca file <b>user/uidUSER.txt</b>. Jika ada INITIAL_PUSH_ADMIN/RESET, audit dimulai dari reset terakhir.</div>
                                </div>
                                <div style="display:flex; gap:8px; flex-wrap:wrap;">
                                    <input type="text" placeholder="Filter Nama/Email..." oninput="renderAuditUserList(this.value)" style="padding:8px; font-size:12px; border:1px solid #ddd; border-radius:5px; width:200px;">
                                    <button onclick="runDoniGuardGlobalAudit()" style="background:#111827; color:white; border:none; border-radius:8px; padding:8px 12px; font-weight:bold; cursor:pointer;"><i class="fas fa-search-dollar"></i> Audit Semua User</button>
                                </div>
                            </div>

                            <div id="containerUserAudit" style="display:grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap:10px; max-height:250px; overflow-y:auto; padding:5px; background:#f9f9f9; border-radius:8px; border:1px solid #eee;">
                                <div style="text-align:center; color:#999; padding:20px; grid-column:1/-1;">Memuat data user...</div>
                            </div>
                        </div>

                        <div id="dgGlobalAuditPanel" style="display:none; background:#fff; border:1px solid #ddd; border-radius:10px; overflow:hidden; margin-bottom:20px;">
                            <div style="padding:10px 15px; background:#111827; color:white; font-weight:bold; font-size:13px; display:flex; justify-content:space-between; align-items:center; gap:10px; flex-wrap:wrap;">
                                <span><i class="fas fa-sitemap"></i> Hasil Audit Seluruh User</span>
                                <span id="dgGlobalAuditStatus" style="font-size:11px; opacity:.9;">-</span>
                            </div>
                            <div id="dgGlobalAuditResult" style="padding:12px; overflow-x:auto;">
                                <div style="text-align:center; color:#999; padding:20px;">Belum dijalankan.</div>
                            </div>
                        </div>

                        <div style="background:#fff; border:1px solid #ddd; border-radius:10px; overflow:hidden;">
                            <div style="padding:10px 15px; background:#f1f2f6; border-bottom:1px solid #ddd; font-weight:bold; font-size:13px; color:#2c3e50; display:flex; justify-content:space-between; align-items:center; gap:10px; flex-wrap:wrap;">
                                <span><i class="fas fa-file-alt"></i> Log & Audit User: <span id="auditTargetName" style="color:var(--primary);">-</span></span>
                                <span id="auditTargetSummary" style="font-size:11px; color:#64748b; font-weight:normal;"></span>
                            </div>
                            <div id="auditLogContainer" style="overflow-x:auto">
                                <div style="text-align:center; padding:30px; color:#ccc;">Pilih user di atas atau tekan Detail dari hasil audit.</div>
                            </div>
                        </div>
                    </div>
                </div>

                <div id="dgDetailSheetOverlay" onclick="closeDoniGuardDetailSheet(event)" style="display:none; position:fixed; inset:0; background:rgba(15,23,42,.55); z-index:99999; align-items:flex-end; justify-content:center; backdrop-filter:blur(3px);">
                    <div id="dgDetailSheetBox" onclick="event.stopPropagation()" style="width:100%; max-width:980px; height:86vh; background:#f8fafc; border-radius:24px 24px 0 0; box-shadow:0 -15px 45px rgba(0,0,0,.28); overflow:hidden; transform:translateY(100%); transition:.28s ease; display:flex; flex-direction:column;">
                        <div style="padding:10px 14px 6px; display:flex; justify-content:center; background:#f8fafc;">
                            <div style="width:48px; height:5px; border-radius:99px; background:#cbd5e1;"></div>
                        </div>
                        <div style="padding:12px 16px; background:#111827; color:white; display:flex; justify-content:space-between; align-items:center; gap:10px; flex-wrap:wrap;">
                            <div style="min-width:0;">
                                <div style="font-size:11px; opacity:.75; font-weight:700; letter-spacing:.4px;">DETAIL AUDIT DONIGUARD USER</div>
                                <div id="dgDetailSheetTitle" style="font-size:16px; font-weight:900; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; max-width:680px;">-</div>
                                <div id="dgDetailSheetSummary" style="font-size:11px; color:#cbd5e1; margin-top:3px;"></div>
                            </div>
                            <button onclick="closeDoniGuardDetailSheet()" style="border:none; background:#ef4444; color:white; border-radius:12px; padding:9px 12px; font-weight:800; cursor:pointer;"><i class="fas fa-times"></i> Tutup</button>
                        </div>
                        <div id="dgDetailSheetContent" style="flex:1; overflow-y:auto; padding:12px; background:#f4f7f6; -webkit-overflow-scrolling:touch;">
                            <div style="text-align:center; color:#64748b; padding:30px;">Belum ada data.</div>
                        </div>
                    </div>
                </div>




                <div id="view-settings" class="page-section">
                    <div class="section" style="max-width:600px;">
                        <h4><i class="fas fa-cog"></i> Pengaturan Global</h4>
                        <div class="form-group">
                            <label>WhatsApp Admin (62xxx)</label>
                            <input type="text" id="setWA" placeholder="628xxx">
                        </div>
                        <div class="form-group">
                            <label>Sembunyikan Menu Paket Akrab All</label>
                            <select id="cfgHideAkrab" style="padding:10px; border-radius:8px; border:1px solid #ddd; width:100%;">
                                <option value="false">Tidak (Tampilkan)</option>
                                <option value="true">Ya (Sembunyikan)</option>
                            </select>
                        </div>
                        <div class="form-group">
                            <label>Sembunyikan Menu PO Akrab</label>
                            <select id="cfgHidePoAkrab" style="padding:10px; border-radius:8px; border:1px solid #ddd; width:100%;">
                                <option value="false">Tidak (Tampilkan)</option>
                                <option value="true">Ya (Sembunyikan)</option>
                            </select>
                        </div>

                        <div class="form-group">
                            <label style="font-weight:900; color:#111827; margin-bottom:10px; display:block;"><i class="fas fa-tools"></i> Kontrol Maintenance</label>
                            <div class="maintenance-switch-grid">
                                <div class="maintenance-switch-card" data-switch-card="cfgMaintenanceAkrabSpesial">
                                    <div class="maintenance-switch-head">
                                        <div class="maintenance-switch-title">Maintenance Akrab Spesial</div>
                                        <label class="maintenance-switch">
                                            <input type="checkbox" id="cfgMaintenanceAkrabSpesial" onchange="window.updateMaintenanceSwitchUi(this)">
                                            <span class="maintenance-slider"></span>
                                        </label>
                                    </div>
                                    <div class="maintenance-switch-desc">Jika ON, produk Akrab Spesial ditutup sementara.</div>
                                    <div class="maintenance-switch-status" data-switch-status="cfgMaintenanceAkrabSpesial">OFF • Aktif Normal</div>
                                </div>

                                <div class="maintenance-switch-card" data-switch-card="cfgMaintenanceQris">
                                    <div class="maintenance-switch-head">
                                        <div class="maintenance-switch-title">Maintenance Topup QRIS</div>
                                        <label class="maintenance-switch">
                                            <input type="checkbox" id="cfgMaintenanceQris" onchange="window.updateMaintenanceSwitchUi(this)">
                                            <span class="maintenance-slider"></span>
                                        </label>
                                    </div>
                                    <div class="maintenance-switch-desc">Jika ON, metode QRIS ditutup sementara.</div>
                                    <div class="maintenance-switch-status" data-switch-status="cfgMaintenanceQris">OFF • Aktif Normal</div>
                                </div>

                                <div class="maintenance-switch-card" data-switch-card="cfgMaintenanceQrisGopay">
                                    <div class="maintenance-switch-head">
                                        <div class="maintenance-switch-title">Maintenance QRIS GoPay Otomatis</div>
                                        <label class="maintenance-switch">
                                            <input type="checkbox" id="cfgMaintenanceQrisGopay" onchange="window.updateMaintenanceSwitchUi(this)">
                                            <span class="maintenance-slider"></span>
                                        </label>
                                    </div>
                                    <div class="maintenance-switch-desc">Jika ON, QRIS GoPay otomatis tidak bisa dipilih user.</div>
                                    <div class="maintenance-switch-status" data-switch-status="cfgMaintenanceQrisGopay">OFF • Aktif Normal</div>
                                </div>

                                <div class="maintenance-switch-card" data-switch-card="cfgMaintenanceGopayTf">
                                    <div class="maintenance-switch-head">
                                        <div class="maintenance-switch-title">Maintenance Transfer GoPay Otomatis</div>
                                        <label class="maintenance-switch">
                                            <input type="checkbox" id="cfgMaintenanceGopayTf" onchange="window.updateMaintenanceSwitchUi(this)">
                                            <span class="maintenance-slider"></span>
                                        </label>
                                    </div>
                                    <div class="maintenance-switch-desc">Jika ON, Transfer GoPay otomatis tidak bisa dipilih user.</div>
                                    <div class="maintenance-switch-status" data-switch-status="cfgMaintenanceGopayTf">OFF • Aktif Normal</div>
                                </div>

                                <div class="maintenance-switch-card" data-switch-card="cfgMaintenanceTotal" style="border-color:#fecaca;">
                                    <div class="maintenance-switch-head">
                                        <div class="maintenance-switch-title" style="color:#b91c1c;">Maintenance Total Website</div>
                                        <label class="maintenance-switch">
                                            <input type="checkbox" id="cfgMaintenanceTotal" onchange="window.updateMaintenanceSwitchUi(this)">
                                            <span class="maintenance-slider"></span>
                                        </label>
                                    </div>
                                    <div class="maintenance-switch-desc">Jika ON, user yang sampai menu utama akan melihat layar maintenance dan website tidak dapat digunakan.</div>
                                    <div class="maintenance-switch-status" data-switch-status="cfgMaintenanceTotal">OFF • Website Aktif</div>
                                </div>
                            </div>
                        </div>


                        <div class="running-admin-card">
                            <div class="running-admin-head">
                                <div>
                                    <div class="running-admin-title"><i class="fas fa-bus"></i> Running Text Halaman Utama</div>
                                    <div class="running-admin-subtitle">Setting disimpan ke <b>public_html/runingtex/apiruning.php</b>, jadi index membaca dari JSON lokal tanpa memakai kuota Firebase.</div>
                                </div>
                                <button type="button" onclick="window.simpanRunningTextSetting(event)" style="width:auto; padding:9px 14px; border-radius:999px; background:#0f172a; color:white; border:none; font-size:12px; font-weight:900; cursor:pointer;"><i class="fas fa-save"></i> Simpan Running Text</button>
                            </div>

                            <div class="running-toggle-row running-admin-wide" style="margin-bottom:12px;">
                                <label class="maintenance-switch" style="margin:0;">
                                    <input type="checkbox" id="rtAktif" onchange="window.updateRunningTextPreview()">
                                    <span class="maintenance-slider"></span>
                                </label>
                                <div>
                                    <div style="font-weight:900; color:#0f172a; font-size:13px;">Aktifkan Running Text</div>
                                    <div style="font-size:11px; color:#64748b;">Jika ON, running text otomatis muncul di atas menu utama user.</div>
                                </div>
                            </div>

                            <div class="running-admin-grid">
                                <div class="form-group running-admin-wide">
                                    <label>Isi Text Baris 1</label>
                                    <input type="text" id="rtText1" placeholder="Contoh: Selamat datang di Pandawa Digital" oninput="window.updateRunningTextPreview()">
                                </div>
                                <div class="form-group running-admin-wide">
                                    <label>Isi Text Baris 2</label>
                                    <input type="text" id="rtText2" placeholder="Kosongkan jika hanya ingin 1 baris" oninput="window.updateRunningTextPreview()">
                                </div>
                                <div class="form-group">
                                    <label>Baris Text Dalam Sekali Jalan</label>
                                    <select id="rtBaris" onchange="window.updateRunningTextPreview()">
                                        <option value="1">1 Baris</option>
                                        <option value="2">2 Baris</option>
                                    </select>
                                </div>
                                <div class="form-group">
                                    <label>Model Text</label>
                                    <select id="rtModel" onchange="window.updateRunningTextPreview()">
                                        <option value="biasa">Text Biasa</option>
                                        <option value="led">Text Titik-Titik LED</option>
                                        <option value="rgb">RGB Dot Matrix + Background LED</option>
                                    </select>
                                </div>
                                <div class="form-group">
                                    <label>Warna Text</label>
                                    <input type="color" id="rtWarnaText" value="#ffffff" oninput="window.updateRunningTextPreview()">
                                </div>
                                <div class="form-group">
                                    <label>Warna Text Pelangi</label>
                                    <select id="rtWarnaPelangi" onchange="window.updateRunningTextPreview()">
                                        <option value="false">Tidak</option>
                                        <option value="true">Ya, Pelangi Bergerak</option>
                                    </select>
                                </div>
                                <div class="form-group">
                                    <label>Background Transparan</label>
                                    <select id="rtBackgroundTransparan" onchange="window.updateRunningTextPreview()">
                                        <option value="false">Tidak</option>
                                        <option value="true">Ya, Transparan</option>
                                    </select>
                                </div>
                                <div class="form-group">
                                    <label>Warna Background</label>
                                    <input type="color" id="rtWarnaBackground" value="#0f172a" oninput="window.updateRunningTextPreview()">
                                </div>
                                <div class="form-group">
                                    <label>Animasi</label>
                                    <select id="rtAnimasi" onchange="window.updateRunningTextPreview()">
                                        <option value="left">Jalan ke Kiri</option>
                                        <option value="right">Jalan ke Kanan</option>
                                        <option value="bounce">Bolak-Balik</option>
                                        <option value="blink">Kedip LED</option>
                                        <option value="wave">Gelombang Warna</option>
                                        <option value="bus">Ala Running Text Bus Indonesia</option>
                                        <option value="neon">Neon Glow</option>
                                        <option value="fade">Fade Diam Tengah</option>
                                    </select>
                                </div>
                                <div class="form-group">
                                    <label>Kecepatan Berjalan</label>
                                    <input type="number" id="rtKecepatan" min="3" max="60" step="1" value="14" oninput="window.updateRunningTextPreview()">
                                </div>
                                <div class="form-group">
                                    <label>Jeda Setelah Selesai</label>
                                    <input type="number" id="rtJeda" min="0" max="20" step="1" value="1" oninput="window.updateRunningTextPreview()">
                                </div>
                                <div class="form-group">
                                    <label>Status File JSON</label>
                                    <input type="text" id="rtStatus" value="Belum dimuat" readonly>
                                </div>
                                <div class="form-group running-admin-wide">
                                    <label>Preview Running Text</label>
                                    <div id="rtPreviewBox" class="running-preview-box">
                                        <div id="rtPreviewContent" class="running-preview-content">
                                            <span id="rtPreviewLine1">Selamat datang di Pandawa Digital</span>
                                            <span id="rtPreviewLine2" style="display:none;"></span>
                                        </div>
                                    </div>
                                </div>
                            </div>
                        </div>



                        <button onclick="simpanSetting()">Simpan Perubahan</button>

                        <hr style="margin:25px 0; border:0; border-top:1px dashed #ddd;">
                        <h4><i class="fas fa-satellite-dish"></i> Cek Respon Server API</h4>
                        <p style="font-size:12px; color:#666; margin-top:-10px;">Alat untuk mengecek respon mentah (JSON) dari server guna memastikan koneksi API berjalan normal.</p>
                        <div class="form-group">
                            <select id="testApiServer" class="form-input">
                                <option value="khfy">KHFY (Paket Akrab)</option>
                                <option value="ics">ICS Store</option>
                                <option value="paydisini">Paydisini (Profile)</option>
                                <option value="saldo_pusat">OkeConnect (Cek Saldo)</option>
                            </select>
                        </div>
                        <button onclick="window.testApiServer(event)" style="background:#8e44ad; margin-bottom:10px;"><i class="fas fa-bug"></i> Test Respon Server</button>
                        <textarea id="testApiResult" style="width:100%; height:150px; font-family:monospace; font-size:11px; background:#f4f4f4; border:1px solid #ddd; border-radius:8px; padding:10px; box-sizing:border-box;" readonly placeholder="Hasil JSON mentah akan muncul di sini..."></textarea>
                    </div>
                </div>

                <div id="view-bank-manual" class="page-section">
                    <div class="section">
                        <div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:15px; border-bottom:1px solid #eee; padding-bottom:15px;">
                            <h4 style="margin:0; border:none;"><i class="fas fa-university"></i> Kelola Bank Manual</h4>
                            <button onclick="window.bukaModalBank()" style="width:auto; padding:8px 15px; background:var(--primary); font-size:12px; color:white; border:none; border-radius:5px; cursor:pointer;"><i class="fas fa-plus"></i> Tambah Bank</button>
                        </div>
                        <div style="overflow-y:auto; max-height:calc(100vh - 280px); border:1px solid #eee; border-radius:10px; padding:5px; background:#fcfcfc;">
                            <table>
                                <thead>
                                    <tr>
                                        <th>Logo</th>
                                        <th>Nama Bank</th>
                                        <th>No. Rekening</th>
                                        <th>Atas Nama</th>
                                        <th>Fee (Rp)</th>
                                        <th>Aksi</th>
                                    </tr>
                                </thead>
                                <tbody id="listBankManual"></tbody>
                            </table>
                        </div>
                    </div>
                </div>


                <div id="view-markup" class="page-section">
                    <div class="section" style="max-width:800px; padding-bottom: 80px;">
                        <div style="display:flex; justify-content:space-between; align-items:center; border-bottom:1px solid #eee; padding-bottom:15px; margin-bottom:15px;">
                            <h4 style="margin:0; border:none;"><i class="fas fa-tags"></i> Atur Markup (Keuntungan)</h4>
                            <button onclick="loadMarkupConfig()" style="width:auto; padding:8px 15px; background:var(--primary); font-size:12px; color:white; border:none; border-radius:5px; cursor:pointer;"><i class="fas fa-sync"></i> Refresh Data</button>
                        </div>

                        <div style="background:#e3f2fd; padding:15px; border-radius:12px; margin-bottom:20px; border:1px solid #bbdefb;">
                            <label style="font-weight:bold; font-size:13px; color:#0066b2;"><i class="fas fa-layer-group"></i> Markup Masal (Bulk Action)</label>
                            <div style="display:flex; gap:10px; margin-top:5px;">
                                <input type="text" id="markupMasal" style="flex:2; padding:10px; border:1px solid #90caf9; border-radius:8px; font-weight:bold;" placeholder="Contoh: 1000 atau 0.5%"><select id="tipeMarkupMasal" style="flex:1; padding:10px; border:1px solid #90caf9; border-radius:8px; font-weight:bold; background:white;">
                                    <option value="flat">Rp</option>
                                    <option value="percent">%</option>
                                </select>
                            </div>
                            <div style="font-size:11px; color:#555; margin-top:5px;">
                                <i class="fas fa-info-circle"></i> Masukkan nominal, lalu <b>centang</b> provider di bawah yang ingin diubah. Klik Simpan untuk menerapkan.
                            </div>
                            <div style="margin-top:10px; border-top:1px dashed #bbdefb; padding-top:10px; display:flex; gap:10px;">
                                <button onclick="toggleAllCheckboxes(true)" style="background:#2563eb; color:white; border:none; padding:6px 12px; border-radius:6px; font-size:11px; cursor:pointer; font-weight:bold;"><i class="fas fa-check-double"></i> Tandai Semua</button>
                                <button onclick="toggleAllCheckboxes(false)" style="background:#ef4444; color:white; border:none; padding:6px 12px; border-radius:6px; font-size:11px; cursor:pointer; font-weight:bold;"><i class="fas fa-times"></i> Hapus Tanda</button>
                            </div>
                        </div>

                        <div style="display:flex; gap:10px; margin-bottom:15px;">
                            <div style="flex:1;">
                                <label style="font-weight:bold; font-size:12px; color:#555;">Markup Paket Akrab</label>
                                <div style="display:flex; gap:5px; margin-top:5px;">
                                    <input type="number" id="markupAkrab" placeholder="0" style="flex:2; font-weight:bold; color:#2563eb;">
                                    <select id="unitAkrab" style="flex:1; padding:5px; border-radius:8px; border:1px solid #ddd; font-size:11px;">
                                        <option value="flat">Rp</option>
                                        <option value="percent">%</option>
                                    </select>
                                </div>
                            </div>
                            <div style="flex:1;">
                                <label style="font-weight:bold; font-size:12px; color:#555;">Markup Paket Akrab v2</label>
                                <div style="display:flex; gap:5px; margin-top:5px;">
                                    <input type="number" id="markupAkrabV2" placeholder="0" style="flex:2; font-weight:bold; color:#9b59b6;">
                                    <select id="unitAkrabV2" style="flex:1; padding:5px; border-radius:8px; border:1px solid #ddd; font-size:11px;">
                                        <option value="flat">Rp</option>
                                        <option value="percent">%</option>
                                    </select>
                                </div>
                            </div>

                            <div style="flex:1;">
                                <label style="font-weight:bold; font-size:12px; color:#555;">Markup KDA (Promo)</label>
                                <div style="display:flex; gap:5px; margin-top:5px;">
                                    <input type="number" id="markupKdaPromo" placeholder="0" style="flex:2; font-weight:bold; color:#e67e22;">
                                    <select id="unitKdaPromo" style="flex:1; padding:5px; border-radius:8px; border:1px solid #ddd; font-size:11px;">
                                        <option value="flat">Rp</option>
                                        <option value="percent">%</option>
                                    </select>
                                </div>
                            </div>
                        </div>
                        <div class="search-box" style="margin-bottom: 15px;">
                            <i class="fas fa-search"></i>
                            <input type="text" id="searchMarkup" placeholder="Cari Provider (Contoh: Telkomsel)..." oninput="window.filterMarkupUI()">
                        </div>
                        <div id="loaderMarkup" style="text-align:center; padding:20px; display:none;"><i class="fas fa-spinner fa-spin"></i> Sedang mengambil filter produk...</div>

                        <div id="containerMarkupList" style="display:grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); gap:10px;"></div>

                        <div class="fab-container">
                            <button class="btn-fab" onclick="simpanMarkup()">
                                <i class="fas fa-save"></i> SIMPAN PERUBAHAN
                            </button>
                        </div>
                    </div>
                </div>

                <div id="view-upload" class="page-section">
                    <div class="section" style="max-width:600px;">
                        <h4><i class="fas fa-cloud-upload-alt"></i> Upload Icon Provider (Masal)</h4>

                        <div style="background:#f8f9fa; border:2px dashed #2563eb; border-radius:10px; padding:30px; text-align:center; margin-bottom:20px;">
                            <i class="fas fa-images" style="font-size:50px; color:#ccc; margin-bottom:15px;"></i>
                            <p style="color:#555; font-size:14px; margin:0 0 10px 0; font-weight:bold;">Pilih Gambar Icon (PNG/JPG)</p>
                            <p style="font-size:12px; color:#777; margin-bottom:15px;">
                                Bisa pilih banyak sekaligus. <br>
                                <span style="color:#ef4444">*PENTING:</span> Nama file harus sesuai provider (Contoh: <b>Telkomsel.png</b>, <b>Indosat.png</b>)
                            </p>

                            <input type="file" id="filesIcon" multiple accept="image/*" style="display:block; margin:0 auto; width:80%; padding:10px; border:1px solid #ddd; border-radius:5px; background:white;">
                        </div>

                        <button class="btn-action" onclick="uploadKeHosting()" style="width:100%; background:#2563eb; color:white; padding:12px; border:none; border-radius:8px; font-weight:bold; cursor:pointer; font-size:14px;">
                            <i class="fas fa-paper-plane"></i> MULAI UPLOAD
                        </button>

                        <div id="hasilUpload" style="margin-top:20px; font-size:13px; max-height:300px; overflow-y:auto;"></div>
                    </div>
                </div>

                <div id="view-products" class="page-section">
                    <div class="section" style="max-width:600px;">
                        <h4><i class="fas fa-plus-circle"></i> Tambah Produk Baru</h4>
                        <div class="form-group"><label>Nama Produk</label><input type="text" id="pNama" placeholder="Contoh: Telkomsel 10GB"></div>
                        <div class="form-group"><label>Harga Jual (Rp)</label><input type="number" id="pHarga" placeholder="0"></div>
                        <div class="form-group">
                            <label>Gambar Produk</label>
                            <div style="display:flex; gap:5px;">
                                <input type="file" id="filePImg" accept="image/*" style="padding:8px; border:1px solid #ddd; border-radius:5px; width:100%;">
                            </div>
                            <input type="text" id="pImg" placeholder="URL akan muncul otomatis setelah upload" readonly style="margin-top:5px; background:#f4f4f4; color:#555;">
                        </div>
                        <button onclick="tambahProduk()" style="background:#28a745">Tambah Produk</button>
                    </div>

                    <div class="section">
                        <h4><i class="fas fa-list"></i> Daftar Semua Produk</h4>
                        <div class="search-box">
                            <input type="text" id="searchProdAdmin" placeholder="Cari Produk..." oninput="filterProdukAdmin()">
                            <i class="fas fa-search"></i>
                        </div>
                        <div style="overflow-x:auto; max-height:500px;">
                            <table>
                                <thead>
                                    <tr>
                                        <th>Gambar</th>
                                        <th>Nama Produk</th>
                                        <th>Harga</th>
                                        <th>Aksi</th>
                                    </tr>
                                </thead>
                                <tbody id="listAllProdukAdmin"></tbody>
                            </table>
                        </div>
                        <div id="histPagination" class="pagination"></div>
                    </div>
                </div>

                <div id="view-users" class="page-section">
                    <div class="section">
                        <div class="users-toolbar-admin">
                            <div>
                                <h4 style="margin-bottom:6px;"><i class="fas fa-users"></i> Data Pengguna</h4>
                                <div style="font-size:12px; color:#64748b; font-weight:700;">Setiap pengguna tampil dalam kartu agar lebih mudah dibaca dan dikelola.</div>
                            </div>
                            <div class="users-total-chip"><i class="fas fa-id-card"></i> <span id="userCardCounter">0 User</span></div>
                        </div>
                        <div class="users-toolbar-admin">
                            <div class="search-box">
                                <i class="fas fa-search"></i>
                                <input type="text" id="searchUser" placeholder="Cari username atau email..." oninput="filterUserTable()">
                            </div>
                        </div>
                        <div id="listUserBody" class="user-card-grid-admin"></div>
                    </div>
                </div>

                <div id="view-topup" class="page-section">
                    <div class="section">
                        <h4><i class="fas fa-wallet"></i> Riwayat Topup (Paydisini)</h4>
                        <div style="overflow-x:auto">
                            <table>
                                <thead>
                                    <tr>
                                        <th>Waktu</th>
                                        <th>User</th>
                                        <th>Nominal</th>
                                        <th>Metode</th>
                                        <th>Status</th>
                                        <th>Aksi</th>
                                    </tr>
                                </thead>
                                <tbody id="listTopupBody"></tbody>
                            </table>
                        </div>
                        <div id="topupPagination" class="pagination"></div>
                    </div>
                </div>
                <div id="view-po-akrab" class="page-section">
                    <div class="section">
                        <div style="display:flex; justify-content:space-between; align-items:center; border-bottom:1px solid #eee; padding-bottom:15px; margin-bottom:15px;">
                            <h4 style="margin:0; border:none;"><i class="fas fa-clock"></i> Antrian PO</h4>
                            <div style="display:flex; gap:10px; flex-wrap:wrap;">
                                <button onclick="window.bukaModalInjeksiPO()" style="width:auto; padding:8px 15px; background:#8e44ad; font-size:12px; color:white; border:none; border-radius:5px; cursor:pointer; font-weight:bold;"><i class="fas fa-syringe"></i> Injeksi PO</button>
                                <button onclick="window.fixStuckPO()" style="width:auto; padding:8px 15px; background:#f59e0b; font-size:12px; color:white; border:none; border-radius:5px; cursor:pointer; font-weight:bold;"><i class="fas fa-tools"></i> Sinkronkan PO Lama</button>
                                <div style="display:inline-block; vertical-align:top; text-align:center;"><button onclick="window.runPoMasal()" style="width:auto; padding:8px 15px; background:#10b981; font-size:12px; color:white; border:none; border-radius:5px; cursor:pointer; font-weight:bold;"><i class="fas fa-play-circle"></i> RUN MASAL</button>
                                    <div id="runMasalStatus" style="font-size:10px; color:#10b981; font-weight:bold; margin-top:4px;"></div>
                                </div>
                                <button onclick="window.loadPoAkrab()" style="width:auto; padding:8px 15px; background:var(--primary); font-size:12px; color:white; border:none; border-radius:5px; cursor:pointer;"><i class="fas fa-sync"></i> Refresh Data</button>
                            </div>
                        </div>
                        <p style="font-size:12px; color:#666;">Daftar pesanan Pre-Order. Eksekusi manual dengan klik tombol RUN. Sistem akan mendeteksi Provider secara otomatis dan akurat.</p>

                        <div style="display:flex; gap:8px; margin-bottom:15px; border-bottom:1px solid #f0f0f0; padding-bottom:10px;">
                            <button onclick="window.setPoFilter('ANTREAN', this)" class="filter-btn active" style="background:#e1effe; color:#2563eb; border:none; padding:8px 15px; border-radius:20px; font-size:11px; font-weight:bold; cursor:pointer;">Antrean</button>
                            <button onclick="window.setPoFilter('DIBATALKAN', this)" class="filter-btn" style="background:#f1f5f9; color:#64748b; border:none; padding:8px 15px; border-radius:20px; font-size:11px; font-weight:bold; cursor:pointer;">Dibatalkan</button>
                            <button onclick="window.setPoFilter('SUKSES', this)" class="filter-btn" style="background:#f1f5f9; color:#64748b; border:none; padding:8px 15px; border-radius:20px; font-size:11px; font-weight:bold; cursor:pointer;">Sukses</button>
                        </div>
                        <div style="overflow-x:auto">
                            <table>
                                <thead>
                                    <tr>
                                        <th>Waktu & Status</th>
                                        <th>User UID</th>
                                        <th>Produk & Tujuan</th>
                                        <th>Provider</th>
                                        <th>Aksi</th>
                                    </tr>
                                </thead>
                                <tbody id="listPoAkrab"></tbody>
                            </table>
                        </div>
                    </div>
                </div>



                <div id="view-broadcast" class="page-section">
                    <div class="section" style="max-width:600px;">
                        <h4><i class="fas fa-bullhorn"></i> Kelola Siaran Masal (Single Slot)</h4>
                        <p style="font-size:12px; color:#666;">Hanya ada 1 siaran yang aktif. Membuat baru akan menimpa/menghapus yang lama.</p>

                        <div class="form-group">
                            <label>Judul Siaran</label>
                            <input type="text" id="bcTitle" placeholder="Contoh: Maintenance Server">
                        </div>

                        <div class="form-group">
                            <label>Isi Pesan (Teks)</label>
                            <textarea id="bcMessage" style="width:100%; padding:10px; border:1px solid #ddd; border-radius:8px; height:100px;" placeholder="Isi pesan broadcast..."></textarea>
                        </div>

                        <div class="form-group">
                            <label>Gambar Lampiran (Opsional)</label>

                            <div id="currentBcImgArea" style="display:none; margin-bottom:10px; background:#f9f9f9; padding:10px; border-radius:5px;">
                                <span style="font-size:11px; color:#555;">Gambar Aktif:</span><br>
                                <img id="previewBcImg" src="" style="height:80px; margin-top:5px; border-radius:5px;">
                                <input type="hidden" id="bcOldImgName">
                            </div>

                            <div style="display:flex; gap:10px;">
                                <input type="file" id="bcFile" accept="image/*" style="padding:8px; border:1px solid #ddd; width:100%;">
                                <button onclick="uploadBroadcastImg()" style="width:auto; background:#6c5ce7; padding:8px 15px; color:white; border:none; border-radius:5px;"><i class="fas fa-upload"></i></button>
                            </div>
                            <input type="text" id="bcNewImgName" placeholder="Nama file baru muncul di sini..." readonly style="background:#eee; color:#555; margin-top:5px;">
                        </div>

                        <div class="form-group">
                            <label>Batas Tampil per User</label>
                            <select id="bcMaxShow">
                                <option value="1">1 Kali Saja</option>
                                <option value="3">3 Kali</option>
                                <option value="5">5 Kali</option>
                                <option value="9999">Selalu Tampil</option>
                            </select>
                        </div>

                        <div style="display:flex; gap:10px; margin-top:20px;">
                            <button onclick="publishBroadcast()" style="flex:2; background:var(--primary); font-weight:bold; padding:12px;"><i class="fas fa-paper-plane"></i> PUBLIKASIKAN & TIMPA LAMA</button>
                            <button onclick="hapusSiaranTotal()" style="flex:1; background:#ff4757; font-weight:bold; padding:12px;"><i class="fas fa-trash"></i> HAPUS</button>
                        </div>
                    </div>
                </div>



                <div id="view-version" class="page-section">
                    <div class="section" style="max-width:600px;">
                        <h4><i class="fas fa-code-branch"></i> Pengaturan Versi Sistem</h4>
                        <p style="font-size:12px; color:#666;">Setel versi aplikasi. Jika versi di sini berbeda dengan di device user, aplikasi akan otomatis me-refresh dan membuang cache.</p>
                        <div class="form-group">
                            <label>Versi Saat Ini</label>
                            <input type="text" id="appVersion" placeholder="Contoh: 1.0.5" style="font-weight:bold; color:var(--primary);">
                        </div>
                        <button onclick="simpanVersiAplikasi()" style="background:#8e44ad; font-weight:bold; padding:12px;"><i class="fas fa-save"></i> SIMPAN VERSI</button>
                    </div>
                </div>


                <div id="view-history" class="page-section">
                    <div class="section">
                        <h4><i class="fas fa-history"></i> Riwayat Transaksi (Semua User)</h4>
                        <div style="display:flex; gap:5px; margin-bottom:10px; overflow-x:auto; padding-bottom:5px;">
                            <button onclick="window.filterRiwayatStatus('SEMUA', this)" class="filter-btn active">Semua</button>
                            <button onclick="window.filterRiwayatStatus('BERHASIL', this)" class="filter-btn">Berhasil</button>
                            <button onclick="window.filterRiwayatStatus('PENDING', this)" class="filter-btn">Pending</button>
                            <button onclick="window.filterRiwayatStatus('GAGAL', this)" class="filter-btn">Gagal</button>
                            <button onclick="window.filterRiwayatStatus('TOPUP', this)" class="filter-btn">Topup</button>
                        </div>

                        <div style="background:#f8f9fa; padding:15px; border-radius:10px; margin-bottom:15px; border:1px solid #eee; display:flex; gap:10px; align-items:center; flex-wrap:wrap;">
                            <div style="flex:1; min-width:200px;">
                                <label style="font-size:12px; font-weight:bold; color:#666; display:block; margin-bottom:5px;">Pilih Tanggal</label>
                                <input type="date" id="adminTrxDate" class="form-input" style="padding:8px; border:1px solid #ddd; border-radius:5px; width:100%;">
                            </div>
                            <button onclick="window.loadRiwayat()" style="padding:10px 20px; background:var(--primary); color:white; border:none; border-radius:8px; cursor:pointer; height:fit-content; align-self:flex-end;"><i class="fas fa-filter"></i> Tampilkan</button>
                        </div>

                        <div id="adminTrxPagin" style="display:flex; justify-content:center; gap:3px; margin-bottom:15px;"></div>
                        <div id="adminTrxList" style="display:grid; gap:10px;"></div>
                    </div>
                </div>
            </div>
        </div>




        <div id="modalEditChat" class="modal">
            <div class="modal-content">
                <h4>Edit Pesan Chat</h4>
                <input type="hidden" id="editChatId">
                <textarea id="editChatText" style="width: 100%; height: 100px; padding: 10px; border: 1px solid #ddd; border-radius: 8px; margin-bottom: 10px; font-family:sans-serif;"></textarea>
                <button class="btn-save" onclick="simpanEditChat()">Simpan Perubahan</button>
                <button class="btn-close" onclick="document.getElementById('modalEditChat').style.display='none'">Batal</button>
            </div>
        </div>

        <div id="modalMarkupH2H" class="modal">
            <div class="modal-content" style="max-width:800px; max-height:90vh; overflow-y:auto;">
                <div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:15px; border-bottom:1px solid #eee; padding-bottom:10px;">
                    <h4 style="margin:0;"><i class="fas fa-tags"></i> Markup H2H: <span id="titleMarkupH2H" style="color:var(--primary);"></span></h4>
                    <i class="fas fa-times" onclick="document.getElementById('modalMarkupH2H').style.display='none'" style="cursor:pointer;"></i>
                </div>
                <input type="hidden" id="markupH2H_uid">

                <div style="background:#fff3cd; padding:15px; border-radius:12px; margin-bottom:15px; border:1px solid #ffeeba;">
                    <label style="font-weight:bold; font-size:12px; color:#856404;"><i class="fas fa-layer-group"></i> Setel Markup Masal H2H</label>
                    <div style="display:flex; gap:10px; margin-top:5px;">
                        <input type="number" id="markupMasalH2H" style="flex:1; padding:8px; border:1px solid #ffdf7e; border-radius:6px; font-weight:bold;" placeholder="Contoh: 100">
                    </div>
                    <div style="font-size:11px; color:#666; margin-top:5px;">Catatan: Jika dikosongkan, sistem akan otomatis menggunakan Harga <b>Markup Global</b>.</div>
                    <div style="margin-top:10px; border-top:1px dashed #ffeeba; padding-top:10px; display:flex; gap:10px;">
                        <button onclick="toggleAllCheckboxesH2H(true)" style="background:#f59e0b; color:white; border:none; padding:6px 12px; border-radius:6px; font-size:11px; cursor:pointer; font-weight:bold;"><i class="fas fa-check-double"></i> Tandai Semua</button>
                        <button onclick="toggleAllCheckboxesH2H(false)" style="background:#ef4444; color:white; border:none; padding:6px 12px; border-radius:6px; font-size:11px; cursor:pointer; font-weight:bold;"><i class="fas fa-times"></i> Hapus Tanda</button>
                    </div>
                </div>

                <div class="search-box" style="margin-bottom:15px;">
                    <i class="fas fa-search"></i>
                    <input type="text" id="searchMarkupH2H" placeholder="Cari Provider..." oninput="window.filterMarkupH2H()">
                </div>
                <div id="loaderMarkupH2H" style="text-align:center; padding:20px; display:none;"><i class="fas fa-spinner fa-spin"></i> Mengambil data produk...</div>

                <div id="containerMarkupListH2H" style="display:grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap:10px; margin-bottom:20px;"></div>

                <button class="btn-save" onclick="simpanMarkupH2H()">Simpan Markup H2H</button>
                <button class="btn-close" onclick="document.getElementById('modalMarkupH2H').style.display='none'">Batal</button>
            </div>
        </div>


        <div id="modalBankManual" class="modal">
            <div class="modal-content">
                <h4 id="titleModalBank">Tambah Bank Manual</h4>
                <input type="hidden" id="bankId">
                <div class="form-group"><label>Nama Bank (Misal: BCA, DANA)</label><input type="text" id="bankNama"></div>
                <div class="form-group"><label>Nomor Rekening</label><input type="text" id="bankRek"></div>
                <div class="form-group"><label>Atas Nama Pemilik</label><input type="text" id="bankAN"></div>
                <div class="form-group"><label>Biaya Admin / Fee (Rp)</label><input type="number" id="bankFee" value="0"></div>
                <div class="form-group">
                    <label>Logo Bank (Upload dari perangkat)</label>
                    <div style="display:flex; gap:5px; margin-bottom:5px;">
                        <input type="file" id="fileLogoBank" accept="image/*" style="padding:8px; border:1px solid #ddd; border-radius:5px; width:100%;">
                        <button onclick="window.uploadLogoBank(event)" style="width:auto; padding:8px 15px; background:#6c5ce7; color:white; border:none; border-radius:5px; cursor:pointer;" title="Upload ke Hosting"><i class="fas fa-upload"></i></button>
                    </div>
                    <input type="text" id="bankLogo" placeholder="URL akan otomatis terisi setelah upload..." style="background:#f9f9f9; color:#555;">
                </div>
                <button class="btn-save" onclick="window.simpanBankManual()">Simpan Bank</button>
                <button class="btn-close" onclick="document.getElementById('modalBankManual').style.display='none'">Batal</button>
            </div>
        </div>


        <div id="modalEditUser" class="modal">
            <div class="modal-content">
                <h4>Edit Pengguna</h4>
                <input type="hidden" id="editUid">
                <div class="form-group"><label>Nama Lengkap</label><input type="text" id="editNama"></div>
                <div class="form-group"><label>Username</label><input type="text" id="editUsername"></div>
                <div class="form-group"><label>WhatsApp</label><input type="text" id="editWA"></div>
                <div class="form-group"><label>Saldo (Rp)</label><input type="number" id="editSaldo"></div><input type="hidden" id="editOldRole" value="user"><input type="hidden" id="editRole" value="user"><input type="hidden" id="editApiKey" value="">
                <button class="btn-save" onclick="updateUser()">Simpan Perubahan</button>
                <button class="btn-close" onclick="tutupModalUser()">Batal</button>
            </div>
        </div>

        <div id="modalLapakUser" class="modal">
            <div class="modal-content" style="max-width:600px;">
                <div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:15px;">
                    <h4 id="judulLapakUser" style="margin:0;">Lapak User</h4>
                    <i class="fas fa-times" onclick="document.getElementById('modalLapakUser').style.display='none'" style="cursor:pointer;"></i>
                </div>
                <div style="background:#f8f9fa; padding:15px; border-radius:10px; margin-bottom:15px; border:1px dashed #ccc;">
                    <h5 style="margin:0 0 10px 0; font-size:13px;"><i class="fas fa-plus"></i> Tambah Produk</h5>
                    <div style="display:grid; grid-template-columns: 2fr 1fr; gap:10px; margin-bottom:10px;">
                        <input type="text" id="addLapakNama" placeholder="Nama Produk" style="padding:8px; border-radius:5px; border:1px solid #ddd;">
                        <input type="number" id="addLapakHarga" placeholder="Harga" style="padding:8px; border-radius:5px; border:1px solid #ddd;">
                    </div>
                    <div style="margin-bottom:10px;">
                        <div style="display:flex; gap:5px;">
                            <input type="file" id="fileLapakImg" accept="image/*" style="padding:5px; border:1px solid #ddd; border-radius:5px; width:100%;">
                            <button onclick="uploadGambarEtalase('fileLapakImg', 'addLapakImg')" style="width:auto; padding:5px 12px; background:#6c5ce7; color:white; border:none; border-radius:5px; cursor:pointer;"><i class="fas fa-upload"></i></button>
                        </div>
                        <input type="text" id="addLapakImg" placeholder="URL Gambar (Upload dulu)" readonly style="width:100%; padding:8px; border-radius:5px; border:1px solid #ddd; margin-top:5px; background:#eee; box-sizing:border-box;">
                    </div>
                    <button onclick="tambahProdukUserIni()" style="width:100%; padding:8px; background:var(--primary); color:white; border:none; border-radius:5px; cursor:pointer;">Posting</button>
                </div>
                <div style="overflow-y:auto; max-height:300px;">
                    <table style="width:100%; border-collapse:collapse; font-size:12px;">
                        <thead style="position:sticky; top:0; background:white;">
                            <tr style="border-bottom:2px solid #eee;">
                                <th style="padding:10px;">Produk</th>
                                <th>Harga</th>
                                <th>Aksi</th>
                            </tr>
                        </thead>
                        <tbody id="bodyLapakUser"></tbody>
                    </table>
                </div>
            </div>
        </div>

        <div id="modalEditLapak" class="modal">
            <div class="modal-content">
                <h3>Edit Barang</h3>
                <input type="hidden" id="editLapakId">
                <div class="input-group"><input type="text" id="editLapakNama" class="form-input" placeholder="Nama"></div>
                <div class="input-group"><input type="number" id="editLapakHarga" class="form-input" placeholder="Harga"></div>
                <div class="input-group"><input type="text" id="editLapakImg" class="form-input" placeholder="URL Gambar" readonly style="background:#eee;"></div>
                <div style="margin-bottom:15px; text-align:center;">
                    <input type="file" id="fileEditLapak" accept="image/*" style="font-size:12px;">
                    <button onclick="uploadGambarEtalase('fileEditLapak', 'editLapakImg')" style="padding:5px 10px; background:var(--primary); color:white; border:none; border-radius:5px;">Upload Baru</button>
                </div>
                <button class="btn-save" onclick="simpanEditLapak()">Simpan Perubahan</button>
                <button class="btn-close" onclick="document.getElementById('modalEditLapak').style.display='none'">Batal</button>
            </div>
        </div>

        <div id="modalInjeksiPO" class="modal">
            <div class="modal-content">
                <h4 style="margin-top:0;"><i class="fas fa-syringe"></i> Injeksi Pre-Order</h4>
                <div class="form-group"><label>UID User Tujuan</label><input type="text" id="injUid" placeholder="Masukkan UID User"></div>
                <div class="form-group"><label>Nomor HP Tujuan</label><input type="text" id="injTujuan" placeholder="Contoh: 08123456789"></div>
                <div class="form-group"><label>Kode Produk</label><input type="text" id="injKode" placeholder="Contoh: TSEL10"></div>
                <div class="form-group"><label>Provider</label><select id="injProvider" style="width:100%; padding:10px; border-radius:8px; border:1px solid #ddd;">
                        <option value="KHFY">KHFY (Paket Akrab)</option>
                        <option value="ICS">ICS Store (Reguler)</option>
                        <option value="KAJE">KAJE Store (All)</option>
                    </select></div>
                <div class="form-group"><label>Harga Transaksi (Rp)</label><input type="number" id="injHarga" placeholder="0"></div>
                <button class="btn-save" onclick="window.simpanInjeksiPO()">Injeksi Sekarang</button>
                <button class="btn-close" onclick="document.getElementById('modalInjeksiPO').style.display='none'">Batal</button>
            </div>
        </div>

        <div id="modalDetailTrx" class="modal">
            <div class="modal-content" style="max-width: 500px;">
                <h4 style="margin-bottom:20px; text-align:center; border:none;">Detail Transaksi</h4>
                <div id="contentDetailTrx"></div>
                <div id="areaRawJson" style="display:none; margin-top:10px;">
                    <textarea id="textRawJson" style="width:100%; height:80px; font-family:monospace; font-size:10px; border:1px solid #ccc; border-radius:5px; padding:5px; background:#eee;" readonly></textarea>
                </div>
                <button class="btn-close" onclick="tutupModalDetail()" style="margin-top:20px;">Tutup</button>
            </div>
        </div>
        <button class="btn-close" onclick="document.getElementById('modalPaydisini').style.display='none'" style="margin-top:15px;">Tutup</button>
    </div>
    </div>

    <div id="modalUserHistory" style="display:none; position:fixed; top:0; left:0; width:100%; height:100%; background:rgba(0,0,0,0.5); align-items:center; justify-content:center; z-index:10001;">
        <div style="background:white; width:90%; max-width:500px; max-height:85vh; border-radius:15px; display:flex; flex-direction:column; padding:20px; box-shadow:0 10px 30px rgba(0,0,0,0.3);">
            <div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:15px; border-bottom:1px solid #eee; padding-bottom:10px;">
                <h3 style="margin:0; font-size:16px;">Riwayat: <span id="histUserTitle" style="color:var(--primary);">User</span></h3>
                <i class="fas fa-times" onclick="document.getElementById('modalUserHistory').style.display='none'" style="cursor:pointer; font-size:20px; color:#999;"></i>
            </div>
            <div id="paginUserHist" style="display:flex; justify-content:center; gap:3px; margin-bottom:15px;"></div>
            <div id="listUserHist" style="flex:1; overflow-y:auto; padding-right:5px;"></div>
        </div>
    </div>

    </div>

    <script type="module">
        import { initializeApp } from "https://www.gstatic.com/firebasejs/10.7.1/firebase-app.js";
        import { getAuth, signInWithEmailAndPassword, onAuthStateChanged, signOut } from "https://www.gstatic.com/firebasejs/10.7.1/firebase-auth.js";
        import { getFirestore, doc, setDoc, getDoc, collection, collectionGroup, addDoc, onSnapshot, query, orderBy, limit, updateDoc, getDocs, deleteDoc, where, serverTimestamp } from "https://www.gstatic.com/firebasejs/10.7.1/firebase-firestore.js";
        
        const firebaseConfig = {
          apiKey: "AIzaSyDYj0BA6cZDUxNBA7lmxBoXzah7H4y8yu4",
          authDomain: "pandawa-store.firebaseapp.com",
          projectId: "pandawa-store",
          storageBucket: "pandawa-store.firebasestorage.app",
          messagingSenderId: "974440930132",
          appId: "1:974440930132:web:57fcb857cfd5ac51b386c1"
        };
        
        // INISIALISASI KHUSUS ADMIN (Agar Sesi Terpisah dari index.html)
        const app = initializeApp(firebaseConfig, "AdminPanelApp");
        const auth = getAuth(app);
        const db = getFirestore(app);
        window.poIntervals = {}; // Tracker untuk auto-check PO
        window.currentChartDate = new Date();
        window.chartVisibleDays = 7;
        window.chartMode = 'trading';
        let trxChartInstance = null;
        
        function setChartButtonState(group, value) {
            document.querySelectorAll(`[data-${group}-btn]`).forEach(btn => btn.classList.remove('active'));
            const target = document.querySelector(`[data-${group}-btn="${value}"]`);
            if (target) target.classList.add('active');
        }
        
        window.changeChartMonth = (offset) => {
            window.currentChartDate.setMonth(window.currentChartDate.getMonth() + offset);
            window.loadChartData();
        };
        
        window.setChartRange = (days) => {
            window.chartVisibleDays = days;
            setChartButtonState('range', days);
            window.applyChartRange();
        };
        
        window.setChartMode = (mode) => {
            window.chartMode = mode;
            setChartButtonState('mode', mode);
            window.loadChartData();
        };
        
        window.applyChartRange = () => {
            if (!trxChartInstance) return;
            const maxIndex = trxChartInstance.data.labels.length - 1;
        
            if (window.chartVisibleDays === 'all') {
                trxChartInstance.options.scales.x.min = 0;
                trxChartInstance.options.scales.x.max = maxIndex;
            } else {
                const now = new Date();
                const isCurrentMonth = now.getMonth() === window.currentChartDate.getMonth() && now.getFullYear() === window.currentChartDate.getFullYear();
                const endIndex = isCurrentMonth ? Math.min(now.getDate() - 1, maxIndex) : maxIndex;
                const startIndex = Math.max(0, endIndex - Number(window.chartVisibleDays) + 1);
                trxChartInstance.options.scales.x.min = startIndex;
                trxChartInstance.options.scales.x.max = endIndex;
            }
            trxChartInstance.update();
        };
        
        window.zoomChart = (factor) => {
            if (!trxChartInstance) return;
            trxChartInstance.zoom(factor);
        };
        
        window.resetZoomChart = () => {
            if (!trxChartInstance) return;
            trxChartInstance.resetZoom();
            window.applyChartRange();
        };
        
        window.loadChartData = async () => {
            const year = window.currentChartDate.getFullYear();
            const month = window.currentChartDate.getMonth();
            const monthNames = ["Januari", "Februari", "Maret", "April", "Mei", "Juni", "Juli", "Agustus", "September", "Oktober", "November", "Desember"];
            const labelEl = document.getElementById('chartMonthLabel');
            if (labelEl) labelEl.innerText = monthNames[month] + " " + year;
        
            const startDate = new Date(year, month, 1);
            const endDate = new Date(year, month + 1, 0, 23, 59, 59, 999);
            const daysInMonth = endDate.getDate();
        
            const labels = Array.from({ length: daysInMonth }, (_, i) => String(i + 1).padStart(2, '0'));
            const dataBerhasil = new Array(daysInMonth).fill(0);
            const dataGagal = new Array(daysInMonth).fill(0);
        
            try {
                const q = query(
                    collectionGroup(db, 'riwayat_transaksi'),
                    where('timestamp', '>=', startDate),
                    where('timestamp', '<=', endDate)
                );
                const snap = await getDocs(q);
        
                snap.forEach(doc => {
                    const data = doc.data();
                    if (data.timestamp && data.status) {
                        let dateObj;
                        if (data.timestamp.toDate) {
                            dateObj = data.timestamp.toDate();
                        } else if (data.timestamp.seconds) {
                            dateObj = new Date(data.timestamp.seconds * 1000);
                        } else {
                            dateObj = new Date(data.timestamp);
                        }
        
                        const dayIndex = dateObj.getDate() - 1;
                        const status = String(data.status || '').toUpperCase();
                        if (status === 'BERHASIL' || status === 'SUKSES') {
                            dataBerhasil[dayIndex]++;
                        } else if (status === 'GAGAL') {
                            dataGagal[dayIndex]++;
                        }
                    }
                });
        
                const totalVolume = dataBerhasil.map((v, i) => v + dataGagal[i]);
                const totalSuccess = dataBerhasil.reduce((a, b) => a + b, 0);
                const totalFailed = dataGagal.reduce((a, b) => a + b, 0);
                const totalAll = totalSuccess + totalFailed;
                const bestIndex = totalVolume.indexOf(Math.max(...totalVolume));
        
                const successEl = document.getElementById('chartSuccessTotal');
                const failedEl = document.getElementById('chartFailedTotal');
                const allEl = document.getElementById('chartAllTotal');
                const bestEl = document.getElementById('chartBestDay');
                if (successEl) successEl.innerText = totalSuccess.toLocaleString('id-ID');
                if (failedEl) failedEl.innerText = totalFailed.toLocaleString('id-ID');
                if (allEl) allEl.innerText = totalAll.toLocaleString('id-ID');
                if (bestEl) bestEl.innerText = totalAll > 0 ? `${bestIndex + 1} ${monthNames[month]}` : '-';
        
                if (trxChartInstance) trxChartInstance.destroy();
        
                const canvas = document.getElementById('trxChart');
                if (!canvas) return;
        
                const ctx = canvas.getContext('2d');
                const successGradient = ctx.createLinearGradient(0, 0, 0, 360);
                successGradient.addColorStop(0, 'rgba(34,197,94,.36)');
                successGradient.addColorStop(1, 'rgba(34,197,94,0)');
                const failedGradient = ctx.createLinearGradient(0, 0, 0, 360);
                failedGradient.addColorStop(0, 'rgba(239,68,68,.30)');
                failedGradient.addColorStop(1, 'rgba(239,68,68,0)');
        
                const isBarMode = window.chartMode === 'bar';
                const datasets = isBarMode
                    ? [
                        { type: 'bar', label: 'Berhasil', data: dataBerhasil, backgroundColor: 'rgba(34,197,94,.78)', borderColor: '#22c55e', borderWidth: 1, borderRadius: 6, barPercentage: .72, categoryPercentage: .72 },
                        { type: 'bar', label: 'Gagal', data: dataGagal, backgroundColor: 'rgba(239,68,68,.72)', borderColor: '#ef4444', borderWidth: 1, borderRadius: 6, barPercentage: .72, categoryPercentage: .72 }
                    ]
                    : [
                        { type: 'bar', label: 'Volume', data: totalVolume, yAxisID: 'y1', backgroundColor: 'rgba(59,130,246,.22)', borderColor: 'rgba(96,165,250,.34)', borderWidth: 1, borderRadius: 8, barPercentage: .64, categoryPercentage: .74, order: 3 },
                        { type: 'line', label: 'Berhasil', data: dataBerhasil, borderColor: '#22c55e', backgroundColor: successGradient, fill: true, tension: .44, cubicInterpolationMode: 'monotone', pointRadius: 0, pointHoverRadius: 7, pointHitRadius: 16, pointBackgroundColor: '#22c55e', pointBorderColor: '#dcfce7', pointBorderWidth: 2, borderWidth: window.innerWidth <= 480 ? 2.2 : 3.2, order: 1 },
                        { type: 'line', label: 'Gagal', data: dataGagal, borderColor: '#fb7185', backgroundColor: failedGradient, fill: true, tension: .44, cubicInterpolationMode: 'monotone', pointRadius: 0, pointHoverRadius: 7, pointHitRadius: 16, pointBackgroundColor: '#fb7185', pointBorderColor: '#ffe4e6', pointBorderWidth: 2, borderWidth: window.innerWidth <= 480 ? 2 : 2.8, borderDash: [6, 5], order: 2 }
                    ];
        
                trxChartInstance = new Chart(ctx, {
                    data: { labels, datasets },
                    options: {
                        responsive: true,
                        maintainAspectRatio: false,
                        interaction: { mode: 'index', intersect: false },
                        animation: { duration: 650, easing: 'easeOutQuart' },
                        layout: { padding: window.innerWidth <= 480 ? 4 : 10 },
                        plugins: {
                            legend: {
                                position: window.innerWidth <= 520 ? 'bottom' : 'top',
                                labels: { color: '#cbd5e1', usePointStyle: true, boxWidth: 8, padding: window.innerWidth <= 480 ? 10 : 16, font: { size: window.innerWidth <= 480 ? 10 : 12, weight: 'bold' } }
                            },
                            tooltip: {
                                backgroundColor: 'rgba(2,6,23,.92)',
                                titleColor: '#f8fafc',
                                bodyColor: '#cbd5e1',
                                borderColor: 'rgba(148,163,184,.30)',
                                borderWidth: 1,
                                padding: 12,
                                displayColors: true,
                                callbacks: {
                                    title: items => `${items[0].label} ${monthNames[month]} ${year}`,
                                    label: item => `${item.dataset.label}: ${Number(item.raw || 0).toLocaleString('id-ID')} transaksi`
                                }
                            },
                            zoom: {
                                pan: { enabled: true, mode: 'x', modifierKey: null },
                                zoom: { wheel: { enabled: true }, pinch: { enabled: true }, mode: 'x' },
                                limits: { x: { min: 0, max: daysInMonth - 1, minRange: 3 } }
                            }
                        },
                        scales: {
                            x: {
                                min: 0,
                                max: daysInMonth - 1,
                                grid: { color: 'rgba(148,163,184,.09)', drawBorder: false },
                                ticks: { color: '#94a3b8', font: { size: window.innerWidth <= 480 ? 9 : 11, weight: 'bold' }, maxRotation: 0, autoSkip: true, maxTicksLimit: window.innerWidth <= 480 ? 7 : 12 }
                            },
                            y: {
                                beginAtZero: true,
                                grid: { color: 'rgba(148,163,184,.10)', drawBorder: false },
                                ticks: { color: '#94a3b8', precision: 0, font: { size: window.innerWidth <= 480 ? 9 : 11 } }
                            },
                            y1: {
                                display: !isBarMode && window.innerWidth > 520,
                                position: 'right',
                                beginAtZero: true,
                                grid: { drawOnChartArea: false },
                                ticks: { color: '#64748b', precision: 0, font: { size: 10 } }
                            }
                        }
                    }
                });
        
                window.applyChartRange();
            } catch (e) {
                console.error("Error loading chart data:", e);
                window.showNotice && window.showNotice('error', 'Grafik Gagal Dimuat', 'Data statistik transaksi gagal dimuat. Cek koneksi Firebase atau index koleksi transaksi.');
            }
        };
        
        setTimeout(() => { if (document.getElementById('trxChart')) window.loadChartData(); }, 1500);
        // --- POLYFILL NOTICE ADMIN ---
        window.showNotice = function(type, title, msg) {
            let modal = document.getElementById('adminNoticeModal');
            if (!modal) {
                modal = document.createElement('div');
                modal.id = 'adminNoticeModal';
                modal.style.cssText = 'display:none; position:fixed; top:0; left:0; width:100%; height:100%; background:rgba(0,0,0,0.5); z-index:99999; align-items:center; justify-content:center;';
                modal.innerHTML = `
                    <div style="background:white; padding:25px; border-radius:12px; width:90%; max-width:320px; text-align:center; box-shadow:0 10px 30px rgba(0,0,0,0.2);">
                        <div id="adminNoticeIcon" style="font-size:40px; margin-bottom:15px;"></div>
                        <div id="adminNoticeTitle" style="font-weight:bold; font-size:18px; margin-bottom:10px; color:#333;"></div>
                        <div id="adminNoticeMsg" style="font-size:13px; color:#666; line-height:1.4;"></div>
                        <button id="adminNoticeBtn" onclick="document.getElementById('adminNoticeModal').style.display='none'" style="margin-top:20px; width:100%; padding:10px; background:#2563eb; color:white; border:none; border-radius:8px; font-weight:bold; cursor:pointer;">OKE</button>
                    </div>
                `;
                document.body.appendChild(modal);
            }
            
            const icon = document.getElementById('adminNoticeIcon');
            const t = document.getElementById('adminNoticeTitle');
            const m = document.getElementById('adminNoticeMsg');
            const btn = document.getElementById('adminNoticeBtn');
            
            modal.style.display = 'flex';
            t.innerText = title;
            m.innerText = msg;
            
            if (type === 'loading') {
                icon.innerHTML = '<i class="fas fa-circle-notch fa-spin" style="color:#2563eb;"></i>';
                btn.style.display = 'none';
            } else if (type === 'success') {
                icon.innerHTML = '<i class="fas fa-check-circle" style="color:#10b981;"></i>';
                btn.style.display = 'block';
                btn.style.background = '#2563eb';
            } else {
                icon.innerHTML = '<i class="fas fa-times-circle" style="color:#ef4444;"></i>';
                btn.style.display = 'block';
                btn.style.background = '#ef4444';
            }
        };
        
        // UI & NAVIGATION
        window.toggleSidebar = () => {
            const sb = document.getElementById('sidebar');
            const overlay = document.getElementById('mobileOverlay');
            const closeBtn = document.getElementById('closeSidebar');
            
            sb.classList.toggle('active');
            overlay.classList.toggle('active');
            
            if(window.innerWidth <= 768) {
                closeBtn.style.display = sb.classList.contains('active') ? 'block' : 'none';
            }
        };
        
        let targetLapakUid = '';
        window.bukaLapakUser = (uid, username) => {
            targetLapakUid = uid;
            document.getElementById('judulLapakUser').innerText = "Lapak: " + username;
            document.getElementById('modalLapakUser').style.display = 'flex';
            loadProdukUserIni(uid);
        };
        
        window.loadProdukUserIni = (uid) => {
            document.getElementById('bodyLapakUser').innerHTML = "<tr><td colspan='3' style='text-align:center'>Memuat...</td></tr>";
            const q = query(collection(db, "produk"), where("seller_uid", "==", uid));
            onSnapshot(q, (snap) => {
                let html = "";
                snap.forEach(d => {
                    const data = d.data();
                    const date = data.timestamp ? data.timestamp.toDate().toLocaleString('id-ID') : '-';
                    let btnAksi = "";
                    if(data.status === 'DIKEMAS') {
                        btnAksi = `<button onclick="inputResi('${d.id}')" style="background:#e67e22; color:white; padding:6px 12px; border-radius:6px; border:none; cursor:pointer; font-size:11px; font-weight:bold;"><i class="fas fa-barcode"></i> Input Resi</button>`;
                    } else if (data.status === 'DIKIRIM') {
                        btnAksi = `<div style="font-size:11px; margin-bottom:5px; color:#555;">Resi: <b style="color:#2563eb; background:#e1f5fe; padding:2px 5px; border-radius:4px;">${data.resi}</b></div><button onclick="selesaikanPesanan('${d.id}')" style="background:#10b981; color:white; padding:6px 12px; border-radius:6px; border:none; cursor:pointer; font-size:11px; font-weight:bold;"><i class="fas fa-check"></i> Selesai</button>`;
                    } else {
                        btnAksi = `<span style="color:#10b981; font-weight:bold; font-size:11px; background:#e8f5e9; padding:5px 10px; border-radius:15px; border:1px solid #c8e6c9;"><i class="fas fa-check-circle"></i> Selesai</span>`;
                    }
                    html += `<tr>
                        <td style="font-size:11px; color:#666;" data-label="Tanggal">${date}</td>
                        <td data-label="Produk"><b style="font-size:13px; color:#2c3e50">${data.produk}</b><br><small style="color:var(--primary); font-weight:bold;">Rp ${new Intl.NumberFormat('id-ID').format(data.total)}</small></td>
                        <td data-label="Aksi">${btnAksi}</td>
                    </tr>`;
                });
                document.getElementById('bodyLapakUser').innerHTML = html || "<tr><td colspan='3' style='text-align:center'>Kosong</td></tr>";
            });
        };
        
        window.tambahProdukUserIni = async () => {
            const nama = document.getElementById('addLapakNama').value;
            const harga = document.getElementById('addLapakHarga').value;
            const img = document.getElementById('addLapakImg').value;
            if(!nama || !harga || !img) return alert("Wajib diisi semua!");
            try {
                await addDoc(collection(db, "produk"), { nama: nama, harga: parseInt(harga), img: img, seller_uid: targetLapakUid, kategori: "FISIK_USER", tipe: "fisik" });
                alert("Berhasil!");
                document.getElementById('addLapakNama').value=""; document.getElementById('addLapakHarga').value=""; document.getElementById('addLapakImg').value="";
            } catch(e) { alert("Gagal: "+e.message); }
        };
        
        window.hapusProdukLapakAdmin = async (id) => {
            if(confirm("Hapus produk ini?")) {
                try { await deleteDoc(doc(db, "produk", id)); } catch(e) { alert("Gagal menghapus: " + e.message); }
            }
        };
        
        window.simpanEditLapak = async () => {
            const id = document.getElementById('editLapakId').value;
            try {
                await updateDoc(doc(db, "produk", id), {
                    nama: document.getElementById('editLapakNama').value,
                    harga: parseInt(document.getElementById('editLapakHarga').value),
                    img: document.getElementById('editLapakImg').value
                });
                alert("Berhasil diupdate!");
                document.getElementById('modalEditLapak').style.display = 'none';
            } catch(e) { alert("Gagal: " + e.message); }
        };
        
        window.uploadGambarEtalase = async (inputId, outputId) => {
            const fileInput = document.getElementById(inputId);
            const output = document.getElementById(outputId);
            if(fileInput.files.length === 0) return alert("Pilih gambar terlebih dahulu!");
            const file = fileInput.files[0];
            if(file.size > 2 * 1024 * 1024) return alert("Gagal: Ukuran file terlalu besar! Maksimal 2MB.");
            
            const formData = new FormData();
            formData.append('file_etalase', file);
            
            const btn = event.currentTarget;
            const oriHtml = btn.innerHTML;
            btn.innerHTML = '<i class="fas fa-spinner fa-spin"></i>';
            btn.disabled = true;
        
            try {
                const req = await fetch('upload_etalase.php', { method: 'POST', body: formData });
                const rawText = await req.text();
                let res; try { res = JSON.parse(rawText); } catch (e) { throw new Error("Format respon server tidak valid."); }
                
                if(res.status === 'success') { output.value = res.url; alert("Upload Berhasil!"); } 
                else { alert("Gagal: " + (res.message || 'Error server')); }
            } catch(e) { alert("Error Upload: " + e.message); } 
            finally { btn.innerHTML = oriHtml; btn.disabled = false; }
        };
        
        window.uploadKeHosting = async () => {
            const input = document.getElementById('filesIcon');
            const resArea = document.getElementById('hasilUpload');
            if(input.files.length === 0) return alert("Pilih minimal 1 gambar!");
            
            const btn = event.currentTarget;
            const oriText = btn.innerHTML;
            btn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Mengupload...';
            btn.disabled = true;
        
            const formData = new FormData();
            for(let i=0; i<input.files.length; i++) formData.append('file_icon[]', input.files[i]);
        
            resArea.innerHTML = '<div style="color:#2563eb; padding:10px; background:#e3f2fd; border-radius:5px;"><i class="fas fa-spinner fa-spin"></i> Sedang mengupload ke folder icons...</div>';
        
            try {
                const req = await fetch('upload_handler.php', { method: 'POST', body: formData });
                const json = await req.json();
                if(json.status === 'success') {
                    let list = '<div style="color:green; font-weight:bold; margin-bottom:10px;"><i class="fas fa-check-circle"></i> Upload Berhasil!</div><div style="display:grid; grid-template-columns:repeat(auto-fill, minmax(150px, 1fr)); gap:10px;">';
                    if(json.files) json.files.forEach(f => list += `<div style="background:#fff; border:1px solid #eee; padding:8px; border-radius:5px; display:flex; flex-direction:column; align-items:center; text-align:center;"><img src="icons/${f}" style="width:40px; height:40px; object-fit:contain; margin-bottom:5px;"><div style="font-family:monospace; font-size:10px; word-break:break-all;">icons/${f}</div></div>`);
                    list += '</div>';
                    if(json.errors && json.errors.length > 0) { list += '<div style="color:red; margin-top:10px; font-weight:bold;">Beberapa Gagal:</div><ul>'; json.errors.forEach(e => list += `<li>${e}</li>`); list += '</ul>'; }
                    resArea.innerHTML = list; input.value = '';
                } else { resArea.innerHTML = '<div style="color:red; font-weight:bold;">Gagal: ' + (json.message || 'Error tidak diketahui') + '</div>'; }
            } catch(e) { resArea.innerHTML = '<div style="color:red; background:#ffeaea; padding:10px; border-radius:5px;"><b>Koneksi Gagal!</b><br>Pastikan file <b>upload_handler.php</b> ada.</div>'; } 
            finally { btn.innerHTML = oriText; btn.disabled = false; }
        };
        
        /* --- LOGIKA SIARAN MASAL (SINGLE) --- */
        
        // Helper: Hapus file fisik di server (Wajib ada file delete_handler.php)
        async function deleteServerFile(filename) {
            if(!filename) return;
            try {
                let fd = new FormData(); fd.append('filename', filename); fd.append('folder', 'icons');
                // Pastikan Anda memiliki file delete_handler.php untuk menghapus file fisik
                await fetch('delete_handler.php', { method: 'POST', body: fd });
                console.log("Request hapus file dikirim:", filename);
            } catch(e) { console.warn("Gagal request hapus file:", e); }
        }
        
        window.uploadBroadcastImg = async () => {
            const fileInput = document.getElementById('bcFile');
            const output = document.getElementById('bcNewImgName');
            if(fileInput.files.length === 0) return alert("Pilih file dulu!");
            
            const btn = event.currentTarget; const oriHtml = btn.innerHTML;
            btn.innerHTML = '<i class="fas fa-spinner fa-spin"></i>'; btn.disabled = true;
            
            const formData = new FormData();
            formData.append('file_icon[]', fileInput.files[0]);
            
            try {
                const req = await fetch('upload_handler.php', { method: 'POST', body: formData });
                const res = await req.json();
        if(res.msg && res.msg.toLowerCase().includes("akan di proses")) { console.log("MENUNGGU RESPON FINAL, TIDAK DISIMPAN"); return; }
                if(res.status === 'success' && res.files.length > 0) {
                    output.value = res.files[0]; 
                    alert("Gambar Terupload! Klik PUBLIKASIKAN untuk menyimpan.");
                } else { alert("Gagal: " + (res.message || 'Error')); }
            } catch(e) { alert("Error upload: " + e.message); }
            finally { btn.innerHTML = oriHtml; btn.disabled = false; }
        };
        
        window.loadBroadcastSettings = async () => {
            try {
                const snap = await getDoc(doc(db, "pengaturan", "broadcast"));
                if(snap.exists()) {
                    const d = snap.data();
                    document.getElementById('bcTitle').value = d.judul || '';
                    document.getElementById('bcMessage').value = d.pesan || '';
                    document.getElementById('bcMaxShow').value = d.max_show || 1;
                    
                    // Tampilkan gambar aktif jika ada
                    if(d.img) {
                        document.getElementById('currentBcImgArea').style.display = 'block';
                        document.getElementById('previewBcImg').src = 'icons/' + d.img;
                        document.getElementById('bcOldImgName').value = d.img;
                    } else {
                        document.getElementById('currentBcImgArea').style.display = 'none';
                        document.getElementById('bcOldImgName').value = '';
                    }
                } else {
                    // Reset form jika kosong
                    document.getElementById('bcTitle').value = '';
                    document.getElementById('bcMessage').value = '';
                    document.getElementById('currentBcImgArea').style.display = 'none';
                    document.getElementById('bcOldImgName').value = '';
                }
                // Reset input upload baru
                document.getElementById('bcNewImgName').value = '';
                document.getElementById('bcFile').value = '';
            } catch(e) { console.log("Load BC Error", e); }
        };
        
        window.publishBroadcast = async () => {
            if(!confirm("Publikasikan siaran ini? Siaran lama akan ditimpa.")) return;
            
            const btn = event.currentTarget; const oriHtml = btn.innerHTML;
            btn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> PROSES...'; btn.disabled = true;
            
            try {
                const oldImg = document.getElementById('bcOldImgName').value;
                const newImg = document.getElementById('bcNewImgName').value;
                
                // 1. Logika Hapus Gambar Lama
                // Jika ada gambar baru, hapus yang lama. ATAU jika user ingin menghapus gambar (bisa ditambahkan logika checkbox nanti, tapi ini default replace)
                if(newImg && oldImg && newImg !== oldImg) {
                    await deleteServerFile(oldImg);
                }
        
                // 2. Tentukan Gambar Final
                let finalImg = oldImg;
                if(newImg) finalImg = newImg;
        
                // 3. Simpan Data & Generate ID Baru (Supaya muncul lagi di user)
                const data = {
                    judul: document.getElementById('bcTitle').value,
                    pesan: document.getElementById('bcMessage').value,
                    img: finalImg,
                    max_show: parseInt(document.getElementById('bcMaxShow').value),
                    broadcast_id: 'BC-' + Date.now(), // ID BARU
                    active: true
                };
                
                await setDoc(doc(db, "pengaturan", "broadcast"), data);
                alert("Sukses! Siaran baru telah dipublikasikan.");
                loadBroadcastSettings(); // Reload tampilan
                
            } catch(e) { alert("Gagal: " + e.message); }
            finally { btn.innerHTML = oriHtml; btn.disabled = false; }
        };
        
        window.hapusSiaranTotal = async () => {
            if(!confirm("Yakin hapus siaran? Data dan gambar akan dihapus permanen.")) return;
             
            const btn = event.currentTarget; btn.innerHTML = '...'; btn.disabled = true;
            try {
                const oldImg = document.getElementById('bcOldImgName').value;
                // 1. Hapus Fisik Gambar
                if(oldImg) await deleteServerFile(oldImg);
        
                // 2. Hapus Data DB
                await deleteDoc(doc(db, "pengaturan", "broadcast"));
                
                alert("Siaran dihapus total.");
                loadBroadcastSettings();
            } catch(e) { alert("Error: " + e.message); }
            finally { btn.innerHTML = '<i class="fas fa-trash"></i> HAPUS'; btn.disabled = false; }
        };
        
        window.showPage = (pageId, el) => {
            document.querySelectorAll('.page-section').forEach(p => p.classList.remove('active'));
            document.getElementById(pageId).classList.add('active');
            if (pageId === 'view-chat') window.loadChatUsers();
            if (pageId === 'view-bank-manual') window.loadBankManual();
            
        if (pageId === 'view-markup') loadMarkupConfig();
            if (pageId === 'view-products') loadSemuaProdukAdmin();
            if (pageId === 'view-orders-fisik') loadOrdersFisik('DIKEMAS');
            if (pageId === 'view-history') window.loadRiwayat();
            window.loadPoAkrab();
        
            if (pageId === 'view-broadcast') loadBroadcastSettings();
            if (pageId === 'view-doniguard') renderAuditUserList();
        
            if(el) {
                document.querySelectorAll('.sidebar-menu li').forEach(li => li.classList.remove('active'));
                el.classList.add('active');
            }
        
            if(window.innerWidth <= 768) {
                document.getElementById('sidebar').classList.remove('active');
                document.getElementById('mobileOverlay').classList.remove('active');
            }
        };
        
        window.login = () => signInWithEmailAndPassword(auth, email.value, pass.value).catch(e => alert("Login Gagal: " + e.message));
        window.logout = () => signOut(auth);
        
        const allowedEmails = ['doni888855519@gmail.com', 'suwarno8797@gmail.com'];
        
        onAuthStateChanged(auth, user => {
            if(user) {
                if (user.email && allowedEmails.includes(user.email)) {
                    loginPage.style.display = "none";
                    adminDashboard.style.display = "block";
                    loadSettings();
                    if(window.loadRunningTextSetting) window.loadRunningTextSetting();
                    loadUsers(); 
                    loadTopup();
                    if(window.loadPendingTopup) window.loadPendingTopup();
                } else { alert("Akses Ditolak!"); signOut(auth); }
            } else {
                loginPage.style.display = "flex";
                adminDashboard.style.display = "none";
            }
        });
        
        
        // PATCH DONI: Setting Running Text memakai file JSON lokal via runingtex/apiruning.php
        const RUNNING_TEXT_ADMIN_API = 'runingtex/apiruning.php';
        const runningTextDefaultSetting = {
            aktif: false,
            text1: 'Selamat datang di Pandawa Digital',
            text2: '',
            baris: 1,
            model: 'biasa',
            warnaText: '#ffffff',
            warnaPelangi: false,
            backgroundTransparan: false,
            warnaBackground: '#0f172a',
            animasi: 'left',
            kecepatan: 14,
            jeda: 1
        };
        
        window.getRunningTextFormData = function() {
            return {
                aktif: document.getElementById('rtAktif') ? document.getElementById('rtAktif').checked : false,
                text1: document.getElementById('rtText1') ? document.getElementById('rtText1').value : '',
                text2: document.getElementById('rtText2') ? document.getElementById('rtText2').value : '',
                baris: document.getElementById('rtBaris') ? parseInt(document.getElementById('rtBaris').value || '1') : 1,
                model: document.getElementById('rtModel') ? document.getElementById('rtModel').value : 'biasa',
                warnaText: document.getElementById('rtWarnaText') ? document.getElementById('rtWarnaText').value : '#ffffff',
                warnaPelangi: document.getElementById('rtWarnaPelangi') ? document.getElementById('rtWarnaPelangi').value === 'true' : false,
                backgroundTransparan: document.getElementById('rtBackgroundTransparan') ? document.getElementById('rtBackgroundTransparan').value === 'true' : false,
                warnaBackground: document.getElementById('rtWarnaBackground') ? document.getElementById('rtWarnaBackground').value : '#0f172a',
                animasi: document.getElementById('rtAnimasi') ? document.getElementById('rtAnimasi').value : 'left',
                kecepatan: document.getElementById('rtKecepatan') ? Math.max(3, Math.min(60, parseFloat(document.getElementById('rtKecepatan').value) || 14)) : 14,
                jeda: document.getElementById('rtJeda') ? Math.max(0, Math.min(20, parseFloat(document.getElementById('rtJeda').value) || 1)) : 1
            };
        };
        
        window.setRunningTextFormData = function(data) {
            const cfg = Object.assign({}, runningTextDefaultSetting, data || {});
            const rawModel = String(cfg.model || 'biasa').toLowerCase();
            const normalizedModel = ['rgb', 'rgb-led', 'rgbdot', 'dotmatrix', 'matrix', 'rgbmatrix', 'rgn'].includes(rawModel)
                ? 'rgb'
                : (['led', 'dot', 'dotled', 'titik', 'titik-led'].includes(rawModel) ? 'led' : 'biasa');
            if(document.getElementById('rtAktif')) document.getElementById('rtAktif').checked = cfg.aktif === true || cfg.aktif === 'true' || cfg.aktif === 1 || cfg.aktif === '1';
            if(document.getElementById('rtText1')) document.getElementById('rtText1').value = cfg.text1 || cfg.isiText || cfg.text || '';
            if(document.getElementById('rtText2')) document.getElementById('rtText2').value = cfg.text2 || '';
            if(document.getElementById('rtBaris')) document.getElementById('rtBaris').value = String(cfg.baris) === '2' ? '2' : '1';
            if(document.getElementById('rtModel')) document.getElementById('rtModel').value = normalizedModel;
            if(document.getElementById('rtWarnaText')) document.getElementById('rtWarnaText').value = cfg.warnaText || '#ffffff';
            if(document.getElementById('rtWarnaPelangi')) document.getElementById('rtWarnaPelangi').value = (cfg.warnaPelangi === true || cfg.warnaPelangi === 'true' || cfg.warnaPelangi === 1 || cfg.warnaPelangi === '1') ? 'true' : 'false';
            if(document.getElementById('rtBackgroundTransparan')) document.getElementById('rtBackgroundTransparan').value = (cfg.backgroundTransparan === true || cfg.backgroundTransparan === 'true' || cfg.backgroundTransparan === 1 || cfg.backgroundTransparan === '1') ? 'true' : 'false';
            if(document.getElementById('rtWarnaBackground')) document.getElementById('rtWarnaBackground').value = cfg.warnaBackground || '#0f172a';
            if(document.getElementById('rtAnimasi')) document.getElementById('rtAnimasi').value = cfg.animasi || 'left';
            if(document.getElementById('rtKecepatan')) document.getElementById('rtKecepatan').value = cfg.kecepatan || 14;
            if(document.getElementById('rtJeda')) document.getElementById('rtJeda').value = cfg.jeda || 1;
            window.updateRunningTextPreview();
        };
        
        window.updateRunningTextPreview = function() {
            const cfg = window.getRunningTextFormData ? window.getRunningTextFormData() : runningTextDefaultSetting;
            const box = document.getElementById('rtPreviewBox');
            const content = document.getElementById('rtPreviewContent');
            const line1 = document.getElementById('rtPreviewLine1');
            const line2 = document.getElementById('rtPreviewLine2');
            if(!box || !content || !line1 || !line2) return;
            const rawModel = String(cfg.model || 'biasa').toLowerCase();
            const normalizedModel = ['rgb', 'rgb-led', 'rgbdot', 'dotmatrix', 'matrix', 'rgbmatrix', 'rgn'].includes(rawModel)
                ? 'rgb'
                : (['led', 'dot', 'dotled', 'titik', 'titik-led'].includes(rawModel) ? 'led' : 'biasa');
            line1.textContent = cfg.text1 || 'Preview Running Text';
            line2.textContent = cfg.text2 || '';
            line2.style.display = (cfg.baris === 2 && String(cfg.text2 || '').trim()) ? 'block' : 'none';
            box.className = 'running-preview-box';
            box.classList.add('preview-' + cfg.animasi);
            if(normalizedModel === 'led') box.classList.add('preview-led');
            if(normalizedModel === 'rgb') {
                box.classList.add('preview-led');
                box.classList.add('preview-rgb');
            }
            if(cfg.warnaPelangi) box.classList.add('preview-rainbow');
            if(cfg.backgroundTransparan) box.classList.add('preview-transparent');
            box.style.setProperty('--rt-preview-color', cfg.warnaText || '#ffffff');
            box.style.setProperty('--rt-preview-bg', cfg.backgroundTransparan ? 'transparent' : (cfg.warnaBackground || '#0f172a'));
            box.style.setProperty('--rt-preview-speed', (cfg.kecepatan || 14) + 's');
            content.style.animation = 'none';
            content.querySelectorAll('span').forEach(function(el) { el.style.animation = 'none'; });
            void content.offsetWidth;
            content.style.animation = '';
            content.querySelectorAll('span').forEach(function(el) { el.style.animation = ''; });
        };
        
        window.loadRunningTextSetting = async function() {
            const status = document.getElementById('rtStatus');
            if(status) status.value = 'Memuat setting...';
            try {
                const req = await fetch(RUNNING_TEXT_ADMIN_API + '?action=get&_=' + Date.now(), { cache: 'no-store' });
                const json = await req.json();
                const data = json && json.success !== false ? (json.data || json.setting || json) : runningTextDefaultSetting;
                window.setRunningTextFormData(data);
                if(status) status.value = 'Berhasil dimuat dari JSON lokal';
            } catch(e) {
                window.setRunningTextFormData(runningTextDefaultSetting);
                if(status) status.value = 'Gagal memuat, memakai default';
                console.warn('Gagal load running text:', e);
            }
        };
        
        window.simpanRunningTextSetting = async function(event) {
            const btn = event && event.currentTarget ? event.currentTarget : null;
            const status = document.getElementById('rtStatus');
            const oldHtml = btn ? btn.innerHTML : '';
            if(btn) { btn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Menyimpan...'; btn.disabled = true; }
            if(status) status.value = 'Menyimpan ke JSON lokal...';
            try {
                const payload = window.getRunningTextFormData();
                const req = await fetch(RUNNING_TEXT_ADMIN_API + '?action=save', {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify(payload)
                });
                const json = await req.json();
                if(!json || json.success === false) throw new Error((json && json.message) ? json.message : 'Gagal menyimpan setting running text.');
                if(status) status.value = 'Tersimpan: ' + new Date().toLocaleString('id-ID');
                alert('Running Text berhasil disimpan!');
            } catch(e) {
                if(status) status.value = 'Gagal menyimpan: ' + e.message;
                alert('Gagal menyimpan Running Text: ' + e.message + '\n\nPastikan file runingtex/apiruning.php sudah dibuat.');
            } finally {
                if(btn) { btn.innerHTML = oldHtml; btn.disabled = false; }
            }
        };
        
        
        window.updateMaintenanceSwitchUi = function(input) {
            if (!input) return;
            const card = document.querySelector('[data-switch-card="' + input.id + '"]');
            const status = document.querySelector('[data-switch-status="' + input.id + '"]');
            if (card) card.classList.toggle('is-on', input.checked);
            if (status) {
                if (input.id === 'cfgMaintenanceTotal') {
                    status.innerHTML = input.checked ? 'ON • Website Dikunci' : 'OFF • Website Aktif';
                } else {
                    status.innerHTML = input.checked ? 'ON • Maintenance' : 'OFF • Aktif Normal';
                }
            }
        };
        
        window.setMaintenanceSwitch = function(id, value) {
            const input = document.getElementById(id);
            if (!input) return;
            input.checked = !!value;
            window.updateMaintenanceSwitchUi(input);
        };
        
        async function loadSettings() {
            const d = await getDoc(doc(db, "pengaturan", "config"));
            if(d.exists()) {
                if(document.getElementById('setWA')) document.getElementById('setWA').value = d.data().wa || "";
                if(document.getElementById('cfgHideAkrab')) document.getElementById('cfgHideAkrab').value = d.data().hideAkrabAll ? "true" : "false";
                if(document.getElementById('cfgHidePoAkrab')) document.getElementById('cfgHidePoAkrab').value = d.data().hidePoAkrab ? "true" : "false";
        
                if(document.getElementById('cfgMaintenanceAkrabSpesial')) window.setMaintenanceSwitch('cfgMaintenanceAkrabSpesial', d.data().maintenanceAkrabSpesial);
                if(document.getElementById('cfgMaintenanceQris')) window.setMaintenanceSwitch('cfgMaintenanceQris', d.data().maintenanceQris);
                if(document.getElementById('cfgMaintenanceQrisGopay')) window.setMaintenanceSwitch('cfgMaintenanceQrisGopay', d.data().maintenanceQrisGopay);
                if(document.getElementById('cfgMaintenanceGopayTf')) window.setMaintenanceSwitch('cfgMaintenanceGopayTf', d.data().maintenanceGopayTf);
                if(document.getElementById('cfgMaintenanceTotal')) window.setMaintenanceSwitch('cfgMaintenanceTotal', d.data().maintenanceTotal);
        
                if(document.getElementById('appVersion')) document.getElementById('appVersion').value = d.data().appVersion || "";
        
                if(document.getElementById('toggleTopupAuto')) {
                    const isAuto = d.data().topup_auto === true;
                    document.getElementById('toggleTopupAuto').checked = isAuto;
                    if(window.updateTopupUI) window.updateTopupUI(isAuto);
                }
            }
        }
        
        window.testApiServer = async (event) => {
            const server = document.getElementById('testApiServer').value;
            const resArea = document.getElementById('testApiResult');
            const btn = event.currentTarget;
            const oriHtml = btn.innerHTML;
            
            btn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Menghubungkan...';
            btn.disabled = true;
            resArea.value = "Menunggu respon dari server " + server + "...";
            
            try {
                let url = '';
                if(server === 'khfy') url = 'khfy_proxyv2.php?action=list';
                else if(server === 'ics') url = 'ics_proxy.php?action=list';
                else if(server === 'paydisini') url = 'paydisini_profile.php';
                else if(server === 'saldo_pusat') url = 'cek_saldo_admin.php';
                
                const req = await fetch(url);
                const res = await req.json();
                resArea.value = JSON.stringify(res, null, 4);
            } catch(e) {
                resArea.value = "ERROR:\n" + e.message + "\n\nPastikan file PHP tersedia di hosting.";
            } finally {
                btn.innerHTML = oriHtml;
                btn.disabled = false;
            }
        };
        
                window.updateTopupUI = function(isAuto) {
            const slider = document.getElementById('sliderTopup');
            const knob = document.getElementById('sliderKnob');
            const txt = document.getElementById('textTopupStatus');
            if(!slider || !knob || !txt) return;
            
            if(isAuto) {
                slider.style.backgroundColor = '#10b981';
                knob.style.transform = 'translateX(22px)';
                txt.innerText = 'AUTO (Paydisini)';
                txt.style.color = '#10b981';
            } else {
                slider.style.backgroundColor = '#ccc';
                knob.style.transform = 'translateX(0)';
                txt.innerText = 'MANUAL';
                txt.style.color = '#ef4444';
            }
        };
        
        window.updateTopupSystem = async function(isAuto) {
            window.updateTopupUI(isAuto);
            window.showNotice('loading', 'Menyimpan', 'Mengubah sistem topup...');
            try {
                await setDoc(doc(db, "pengaturan", "config"), { topup_auto: isAuto }, { merge: true });
                window.showNotice('success', 'Berhasil', 'Sistem topup kini ' + (isAuto ? 'AUTO' : 'MANUAL'));
            } catch(e) {
                window.showNotice('error', 'Gagal', e.message);
                document.getElementById('toggleTopupAuto').checked = !isAuto;
                window.updateTopupUI(!isAuto);
            }
        };
        
        
        window.simpanVersiAplikasi = async () => {
            const pin = prompt("Masukkan PIN Admin untuk mengubah versi sistem:");
            if (pin !== "050213") {
                return alert("PIN Salah! Akses ditolak.");
            }
            const newVersion = document.getElementById('appVersion').value;
            if(!newVersion) return alert("Versi tidak boleh kosong!");
            
            const btn = event.currentTarget;
            const oriText = btn.innerHTML;
            btn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Menyimpan...';
            btn.disabled = true;
        
            try {
                await setDoc(doc(db, "pengaturan", "config"), { appVersion: newVersion }, { merge: true });
                alert("Versi berhasil diperbarui menjadi " + newVersion);
            } catch(e) {
                alert("Gagal menyimpan versi: " + e.message);
            } finally {
                btn.innerHTML = oriText;
                btn.disabled = false;
            }
        };
        
        
        window.simpanSetting = async () => {
            const wa = document.getElementById('setWA').value;
            const hideAkrabAll = document.getElementById('cfgHideAkrab').value === "true";
            const hidePoAkrab = document.getElementById('cfgHidePoAkrab').value === "true";
            const maintenanceAkrabSpesial = document.getElementById('cfgMaintenanceAkrabSpesial').checked === true;
            const maintenanceQris = document.getElementById('cfgMaintenanceQris').checked === true;
            const maintenanceQrisGopay = document.getElementById('cfgMaintenanceQrisGopay').checked === true;
            const maintenanceGopayTf = document.getElementById('cfgMaintenanceGopayTf').checked === true;
            const maintenanceTotal = document.getElementById('cfgMaintenanceTotal').checked === true;
            await setDoc(doc(db, "pengaturan", "config"), {
                wa: wa,
                hideAkrabAll: hideAkrabAll,
                hidePoAkrab: hidePoAkrab,
                maintenanceAkrabSpesial: maintenanceAkrabSpesial,
                maintenanceQris: maintenanceQris,
                maintenanceQrisGopay: maintenanceQrisGopay,
                maintenanceGopayTf: maintenanceGopayTf,
                maintenanceTotal: maintenanceTotal
            }, { merge: true });
            alert("Pengaturan berhasil diperbarui!");
        };
        
        window.toggleAllCheckboxes = (checked) => document.querySelectorAll('.markup-checkbox').forEach(cb => cb.checked = checked);
        window.filterMarkupUI = () => {
            const key = document.getElementById('searchMarkup').value.toLowerCase();
            document.querySelectorAll('#containerMarkupList .markup-item-row').forEach(row => {
                const inputElem = row.querySelector('.input-markup-item');
                if (!inputElem) return;
                const prov = inputElem.getAttribute('data-provider').toLowerCase();
                row.style.display = prov.includes(key) ? 'flex' : 'none';
            });
        };
        
        window.loadMarkupConfig = async () => {
            const container = document.getElementById('containerMarkupList');
            const loader = document.getElementById('loaderMarkup');
            container.innerHTML = ''; loader.style.display = 'block';
            try {
                let savedData = {};
                try {
                    const mRes = await fetch('markup/cachemarkup.json?v=' + new Date().getTime());
                    const mData = await mRes.json();
                    mData.forEach(item => {
                        if(item.nama_produk) savedData[item.nama_produk] = item.markup;
                    });
                } catch(e) { console.log("Belum ada cache markup atau gagal load", e); }
                document.getElementById('markupMasal').value = "";
                let unitA = 'flat'; let valA = savedData['Paket Akrab'] || 0;
                if(String(valA).includes('%')) { unitA = 'percent'; valA = valA.replace('%', ''); }
                document.getElementById('markupAkrab').value = valA;
                document.getElementById('unitAkrab').value = unitA;
        
                let unitA2 = 'flat'; let valA2 = savedData['Paket Akrab v2'] || 0;
                if(String(valA2).includes('%')) { unitA2 = 'percent'; valA2 = valA2.replace('%', ''); }
                document.getElementById('markupAkrabV2').value = valA2;
                document.getElementById('unitAkrabV2').value = unitA2;
        
                let unitKda = 'flat'; let valKda = savedData['KDA (PROMO)'] || 0;
                if(String(valKda).includes('%')) { unitKda = 'percent'; valKda = valKda.replace('%', ''); }
                document.getElementById('markupKdaPromo').value = valKda;
                document.getElementById('unitKdaPromo').value = unitKda;
                const req = await fetch('data_pusat.php?jenis=semua');
                const dataProduk = await req.json();
                const uniqueProviders = [...new Set(dataProduk.map(item => item.produk))].sort();
                loader.style.display = 'none';
                let html = "";
                uniqueProviders.forEach(prov => {
                    let val = savedData[prov] || 0;
                    let unit = 'flat';
                    if(String(val).includes('%')) {
                        unit = 'percent';
                        val = val.replace('%', '');
                    }
                    html += `<div class="markup-item-row">
                        <div class="markup-info">
                            <label style="font-size:11px; font-weight:bold; display:block; color:#555; margin-bottom:4px;" title="${prov}">${prov}</label>
                            <div style="display:flex; gap:5px;">
                                <input type="text" inputmode="numeric" class="input-markup-item" data-provider="${prov}" value="${val}" style="flex:2; padding:8px; border:1px solid #ddd; border-radius:6px; box-sizing:border-box; font-weight:bold; color:#2563eb;">
                                <select class="unit-markup-item" style="flex:1; border:1px solid #ddd; border-radius:6px; font-size:11px; background:white;">
                                    <option value="flat" ${unit === 'flat' ? 'selected' : ''}>Rp</option>
                                    <option value="percent" ${unit === 'percent' ? 'selected' : ''}>%</option>
                                </select>
                            </div>
                        </div>
                        <div class="markup-check-box"><input type="checkbox" class="markup-checkbox"></div>
                    </div>`;
                });
                container.innerHTML = html;
            } catch (e) { loader.style.display = 'none'; container.innerHTML = `<div style="color:red; text-align:center;">Gagal memuat data server: ${e.message}</div>`; }
        };
        
        window.simpanMarkup = async () => {
            const btn = document.querySelector('.btn-fab');
            const oriText = btn.innerHTML;
            btn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> MENYIMPAN...'; btn.disabled = true;
            try {
                let jsonArray = [];
                
                const getValWithUnit = (idVal, idUnit) => {
                    let v = document.getElementById(idVal).value;
                    let u = document.getElementById(idUnit).value;
                    return (u === 'percent' && v !== "") ? v + '%' : v;
                };
        
                const ma = getValWithUnit('markupAkrab', 'unitAkrab');
                if(ma !== "" && ma !== "0") jsonArray.push({ nama_produk: 'Paket Akrab', markup: ma });
                
                const ma2 = getValWithUnit('markupAkrabV2', 'unitAkrabV2');
                if(ma2 !== "" && ma2 !== "0") jsonArray.push({ nama_produk: 'Paket Akrab v2', markup: ma2 });
        
                const maKda = getValWithUnit('markupKdaPromo', 'unitKdaPromo');
                if(maKda !== "" && maKda !== "0") jsonArray.push({ nama_produk: 'KDA (PROMO)', markup: maKda });
                
                const valMasal = document.getElementById('markupMasal').value;
                const tipeMasal = document.getElementById('tipeMarkupMasal').value;
                
                document.querySelectorAll('#containerMarkupList .markup-item-row').forEach(row => {
                    const input = row.querySelector('.input-markup-item');
                    if (!input) return;
                    const unitSelect = row.querySelector('.unit-markup-item');
                    const checkbox = row.querySelector('.markup-checkbox');
                    const providerName = input.getAttribute('data-provider');
                    
                    if (checkbox.checked && valMasal !== "") {
                        input.value = valMasal;
                        unitSelect.value = tipeMasal;
                    }
                    
                    let nominal = input.value;
                    let unit = unitSelect.value;
                    if (nominal !== "" && nominal !== "0") {
                        let finalMarkup = unit === 'percent' ? nominal + '%' : nominal;
                        jsonArray.push({ nama_produk: providerName, markup: finalMarkup });
                    }
                });
                
                const req = await fetch('simpan_markup.php', {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify(jsonArray)
                });
                const res = await req.json();
                
                if (res.status === 'success') {
                    alert("Sukses! Markup berhasil disimpan di cache server.");
                    document.querySelectorAll('.markup-checkbox').forEach(c => c.checked = false);
                    document.getElementById('markupMasal').value = "";
                } else {
                    alert("Gagal: " + (res.message || "Kesalahan Server"));
                }
            } catch(e) { alert("Gagal menyimpan: " + e.message); }
            finally { btn.innerHTML = oriText; btn.disabled = false; }
        };
        
        window.cekSaldoAdmin = async (silent = false) => {
            const display = document.getElementById('statSaldoAdmin');
            if (!silent) {
                display.innerHTML = '<i class="fas fa-spinner fa-spin" style="font-size:20px;"></i>';
                display.style.color = '#999';
            }
        
            try {
                const req = await fetch('cek_saldo_admin.php');
                const res = await req.json();
        
                if(res.status === 'success') {
                    display.innerText = "Rp " + res.saldo_formatted;
                    display.style.color = '#ef4444';
                } else {
                    if (!silent) {
                        display.innerText = "Gagal";
                        alert("Gagal Cek Saldo: " + res.msg);
                    }
                }
            } catch(e) {
                if (!silent) {
                    console.error(e);
                    display.innerText = "Error";
                    alert("Gagal menghubungi server hosting (cek_saldo_admin.php).");
                }
            }
        };
        
        setInterval(() => window.cekSaldoAdmin(true), 15000);
        setTimeout(() => window.cekSaldoAdmin(true), 2000);
        
        
        let cacheUsers = [];
        function loadUsers() {
            onSnapshot(collection(db, "users"), snap => {
                const emailCounts = {};
                snap.forEach(d => { const e = d.data().email; if(e) emailCounts[e] = (emailCounts[e] || 0) + 1; });
                cacheUsers = [];
                let totalSaldo = 0;
                snap.forEach(d => {
                    const data = d.data();
                    const isDup = emailCounts[data.email] > 1;
                    cacheUsers.push({ id: d.id, isDuplicate: isDup, ...data });
                    totalSaldo += (data.saldo || 0);
                });
                cacheUsers.sort((a, b) => {
                    // 1. Prioritas Utama: Akun duplikat muncul di paling atas
                    if (a.isDuplicate !== b.isDuplicate) return (b.isDuplicate ? 1 : 0) - (a.isDuplicate ? 1 : 0);
                    // 2. Prioritas Kedua: Kelompokkan email yang sama agar muncul berdampingan
                    if (a.isDuplicate && b.isDuplicate && a.email !== b.email) return a.email.localeCompare(b.email);
                    // 3. Prioritas Ketiga: Urutan saldo terbanyak (untuk duplikat maupun user normal)
                    return (b.saldo || 0) - (a.saldo || 0);
                });
                document.getElementById('statTotalUser').innerText = snap.size;
                document.getElementById('statTotalSaldo').innerText = "Rp " + new Intl.NumberFormat('id-ID').format(totalSaldo);
                
                renderUserTable(cacheUsers);
                if (window.refreshTotalTopupFromDoniGuard) window.refreshTotalTopupFromDoniGuard();
            });
        }
        
        window.renderUserTable = (data) => {
            let html = "";
            data.forEach(u => {
                const safeUsername = String(u.username || '-').replace(/'/g, "\\'").replace(/`/g, '');
                const safeNama = String(u.nama || '').replace(/'/g, "\\'").replace(/`/g, '');
                const safeWhatsapp = String(u.whatsapp || '').replace(/'/g, "\\'").replace(/`/g, '');
                const safeRole = String(u.role || 'user').replace(/'/g, "\\'").replace(/`/g, '');
                const safeApiKey = String(u.apikey || '').replace(/'/g, "\\'").replace(/`/g, '');
                const initial = String(u.username || u.email || 'U').trim().charAt(0) || 'U';
                const roleClass = u.role === 'pelapak' ? 'role-pelapak' : 'role-user';
                const roleText = u.role === 'pelapak' ? 'Pelapak' : 'User';
                const chatDisabled = !!u.chat_disabled;
                html += `<div class="user-card-admin" data-user-search="${String((u.username || '') + ' ' + (u.email || '')).toLowerCase()}">
                    <div class="user-card-top-admin">
                        <div class="user-avatar-admin">${initial}</div>
                        <div class="user-main-admin">
                            <div class="user-name-admin">
                                ${u.username || '-'}
                                <span class="user-badge-admin ${roleClass}"><i class="fas ${u.role === 'pelapak' ? 'fa-store' : 'fa-user'}"></i> ${roleText}</span>
                                ${u.isDuplicate ? '<span class="user-badge-admin warn"><i class="fas fa-exclamation-triangle"></i> Email Duplikat</span>' : ''}
                            </div>
                            <div class="user-email-admin">${u.email || '-'}</div>
                        </div>
                    </div>
                    <div class="user-meta-grid-admin">
                        <div class="user-meta-admin">
                            <span>UID User</span>
                            <div class="uid-row-admin">
                                <code>UID: ${String(u.id || '').substring(0, 12)}...</code>
                                <button class="copy-uid-admin" onclick="navigator.clipboard.writeText('${u.id}'); window.showNotice('success', 'Tersalin!', 'UID berhasil disalin ke clipboard.');" title="Salin Full UID"><i class="fas fa-copy"></i></button>
                            </div>
                        </div>
                        <div class="user-meta-admin">
                            <span>WhatsApp</span>
                            <b>${u.whatsapp || '-'}</b>
                        </div>
                        <div class="user-meta-admin saldo">
                            <span>Saldo</span>
                            <b>Rp ${new Intl.NumberFormat('id-ID').format(u.saldo || 0)}</b>
                        </div>
                        <div class="user-meta-admin">
                            <span>Status Chat</span>
                            <b><span class="user-badge-admin ${chatDisabled ? 'chat-off' : 'chat-on'}"><i class="fas ${chatDisabled ? 'fa-comment-slash' : 'fa-comment'}"></i> ${chatDisabled ? 'Diblokir' : 'Aktif'}</span></b>
                        </div>
                    </div>
                    <div class="user-action-grid-admin">
                        ${u.role === 'pelapak' ? `<button class="btn-user-store" onclick="bukaLapakUser('${u.id}', '${safeUsername}')"><i class="fas fa-store"></i> Lapak</button>` : ''}
                        <button class="btn-user-history" onclick="window.lihatRiwayatUser('${u.id}', '${safeUsername}')"><i class="fas fa-history"></i> Riwayat</button>
                        <button class="btn-user-edit" onclick="bukaEditUser('${u.id}', '${safeNama}', '${safeUsername}', '${safeWhatsapp}', ${u.saldo || 0}, '${safeRole}', '${safeApiKey}')"><i class="fas fa-pen"></i> Edit</button>
                        <button class="btn-user-chat ${chatDisabled ? 'off' : ''}" onclick="toggleChat('${u.id}', ${chatDisabled})"><i class="fas ${chatDisabled ? 'fa-comment-slash' : 'fa-comment'}"></i> ${chatDisabled ? 'Buka Chat' : 'Blokir Chat'}</button>
                        <button class="btn-user-delete" onclick="hapusUser('${u.id}', '${safeUsername}')"><i class="fas fa-trash"></i> Hapus User</button>
                    </div>
                </div>`;
            });
            const body = document.getElementById('listUserBody');
            if (body) body.innerHTML = html || `<div class="empty-user-card-admin"><i class="fas fa-user-slash" style="font-size:28px; margin-bottom:8px; display:block;"></i>Data pengguna tidak ditemukan</div>`;
            const counter = document.getElementById('userCardCounter');
            if (counter) counter.textContent = `${data.length} User`;
        }
        
        
        window.filterUserTable = () => {
            const keyword = document.getElementById('searchUser').value.toLowerCase();
            const filtered = cacheUsers.filter(u => ((u.username && u.username.toLowerCase().includes(keyword)) || (u.email && u.email.toLowerCase().includes(keyword))));
            renderUserTable(filtered);
        }
        
        window.pushDoniGuard = async (uid, saldo) => {
            if(!confirm('Push saldo ini ke Buku Besar DoniGuard? Ini akan me-reset rantai transaksi user tersebut di hosting agar saldo saat ini dianggap SAH.')) return;
            const btn = event.currentTarget;
            const oriHtml = btn.innerHTML;
            btn.innerHTML = '<i class="fas fa-spinner fa-spin"></i>';
            btn.disabled = true;
            try {
                const response = await fetch('doniguard.php', {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({
                        uid: uid,
                        action: 'topup',
                        produk: 'INITIAL_PUSH_ADMIN',
                        nominal: parseInt(saldo),
                        saldo_akhir_client: parseInt(saldo)
                    })
                });
                const res = await response.json();
                if(res.status === 'success') alert('Berhasil! Saldo user kini telah tercatat di Buku Besar DoniGuard.');
                else alert('Gagal: ' + res.message);
            } catch (e) {
                alert('Error menghubungi doniguard.php. Pastikan file sudah ada di hosting.');
            } finally {
                btn.innerHTML = oriHtml;
                btn.disabled = false;
            }
        };
        
        window.toggleChat = async (uid, currentStatus) => {
            if(confirm('Apakah Anda yakin ingin ' + (currentStatus ? 'membuka' : 'memblokir') + ' akses chat pengguna ini?')) {
                try {
                    await updateDoc(doc(db, "users", uid), { chat_disabled: !currentStatus });
                    showNotice('success', 'Berhasil', 'Status chat diperbarui');
                } catch(e) { alert(e.message); }
            }
        };
        
        
        window.hapusUser = async (uid, username) => {
            if(confirm("PERINGATAN: Menghapus user " + username + " akan menghilangkan data saldo dan riwayat mereka selamanya. Lanjutkan?")) {
                try {
                    await deleteDoc(doc(db, "users", uid));
                    alert("User berhasil dihapus.");
                    loadUsers();
                } catch(e) { alert("Gagal: " + e.message); }
            }
        };
        
        window.bukaMarkupH2H = async (uid, username) => {
            document.getElementById('markupH2H_uid').value = uid;
            document.getElementById('titleMarkupH2H').innerText = username;
            document.getElementById('modalMarkupH2H').style.display = 'flex';
            document.getElementById('markupMasalH2H').value = '';
            
            const container = document.getElementById('containerMarkupListH2H');
            const loader = document.getElementById('loaderMarkupH2H');
            container.innerHTML = ''; loader.style.display = 'block';
            
            try {
                const snap = await getDoc(doc(db, "markup_h2h", uid));
                let savedData = snap.exists() ? snap.data() : {};
                
                const req = await fetch('data_pusat.php?jenis=semua');
                const dataProduk = await req.json();
                const uniqueProviders = [...new Set(dataProduk.map(item => item.produk))].sort();
                
                loader.style.display = 'none';
                let html = "";
                uniqueProviders.forEach(prov => {
                    let val = savedData[prov] !== undefined ? savedData[prov] : '';
                    html += `<div class="markup-item-row h2h-row"><div class="markup-info"><label style="font-size:11px; font-weight:bold; display:block; color:#555; margin-bottom:4px;" title="${prov}">${prov}</label><input type="number" class="input-markup-item-h2h" data-provider="${prov}" value="${val}" placeholder="Default Global" style="width:100%; padding:8px; border:1px solid #ddd; border-radius:6px; box-sizing:border-box; font-weight:bold; color:#d35400;"></div><div class="markup-check-box"><input type="checkbox" class="markup-checkbox-h2h"></div></div>`;
                });
                container.innerHTML = html;
            } catch (e) {
                loader.style.display = 'none';
                container.innerHTML = `<div style="color:red; text-align:center;">Gagal memuat: ${e.message}</div>`;
            }
        };
        
        window.toggleAllCheckboxesH2H = (checked) => document.querySelectorAll('.markup-checkbox-h2h').forEach(cb => cb.checked = checked);
        
        window.filterMarkupH2H = () => {
            const key = document.getElementById('searchMarkupH2H').value.toLowerCase();
            document.querySelectorAll('.h2h-row').forEach(row => {
                const prov = row.querySelector('.input-markup-item-h2h').getAttribute('data-provider').toLowerCase();
                row.style.display = prov.includes(key) ? 'flex' : 'none';
            });
        };
        
        window.simpanMarkupH2H = async () => {
            const uid = document.getElementById('markupH2H_uid').value;
            const btn = document.querySelector('#modalMarkupH2H .btn-save');
            const oriText = btn.innerHTML;
            btn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Menyimpan...'; btn.disabled = true;
            
            try {
                let newData = {};
                const valMasal = document.getElementById('markupMasalH2H').value;
                const parsedMasal = parseInt(valMasal);
                const isMasalValid = !isNaN(parsedMasal);
                
                document.querySelectorAll('.h2h-row').forEach(row => {
                    const input = row.querySelector('.input-markup-item-h2h');
                    const checkbox = row.querySelector('.markup-checkbox-h2h');
                    const providerName = input.getAttribute('data-provider');
                    
                    if (checkbox.checked && isMasalValid) {
                        input.value = parsedMasal;
                    }
                    
                    if(input.value !== '') {
                        let nominal = parseInt(input.value);
                        if(!isNaN(nominal)) newData[providerName] = nominal;
                    }
                });
                
                await setDoc(doc(db, "markup_h2h", uid), newData);
                alert("Sukses! Markup H2H berhasil disimpan.");
                document.querySelectorAll('.markup-checkbox-h2h').forEach(c => c.checked = false);
                document.getElementById('markupMasalH2H').value = "";
            } catch(e) {
                alert("Gagal menyimpan: " + e.message);
            } finally {
                btn.innerHTML = oriText; btn.disabled = false;
            }
        };
        
        
        window.bukaEditUser = (uid, nama, username, wa, saldo, role, apikey) => {
            document.getElementById('editUid').value = uid;
            document.getElementById('editNama').value = nama;
            document.getElementById('editUsername').value = username;
            document.getElementById('editWA').value = wa;
            document.getElementById('editSaldo').value = saldo;
            document.getElementById('editRole').value = role;
            document.getElementById('editOldRole').value = role;
            document.getElementById('editApiKey').value = apikey || '';
            if(document.getElementById('groupApiKey')) document.getElementById('groupApiKey').style.display = role === 'merchant_h2h' ? 'block' : 'none';
            document.getElementById('modalEditUser').style.display = "flex";
        };
        
        window.tutupModalUser = () => document.getElementById('modalEditUser').style.display = "none";
        
        window.generateApiKeyAdmin = () => {
            const uid = document.getElementById('editUid').value;
            if(!uid) return alert("Error: UID tidak ditemukan.");
            const pin = prompt("Tindakan Berbahaya!\nMasukkan PIN Admin untuk generate API Key baru:");
            if (pin !== "050213") {
                return alert("PIN Salah! Operasi dibatalkan.");
            }
            const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
            let newKey = 'SP-';
            for(let i=0; i<20; i++) newKey += chars.charAt(Math.floor(Math.random() * chars.length));
            document.getElementById('editApiKey').value = newKey;
            alert("Berhasil! API Key baru: " + newKey + "\n\nJANGAN LUPA KLIK 'SIMPAN PERUBAHAN' UNTUK MENGAMANKAN DATA.");
        };
        
        
        window.updateUser = async () => {
            const uid = document.getElementById('editUid').value;
            const saldoBaru = parseInt(document.getElementById('editSaldo').value || 0);
        
            const oldRole = document.getElementById('editOldRole').value;
            const newRole = document.getElementById('editRole').value;
        
            
            const btn = document.querySelector('#modalEditUser .btn-save');
            const oriText = btn.innerHTML;
            btn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Mengesahkan...';
            btn.disabled = true;
        
            try {
                await updateDoc(doc(db, "users", uid), {
                    nama: document.getElementById('editNama').value,
                    username: document.getElementById('editUsername').value,
                    whatsapp: document.getElementById('editWA').value,
                    saldo: saldoBaru,
                    role: document.getElementById('editRole').value,
                    apikey: document.getElementById('editApiKey').value
                });
        
                const res = await fetch('doniguard.php', {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({
                        uid: uid,
                        action: 'reset_balance',
                        nominal: saldoBaru,
                        saldo_akhir_client: saldoBaru,
                        produk: 'INITIAL_PUSH_ADMIN'
                    })
                });
                
                const json = await res.json();
        
                if (json.status === 'success') {
                    alert("Data Berhasil Disimpan & Buku Besar DoniGuard Telah Disahkan Ulang!");
                    tutupModalUser();
                    if(document.getElementById('searchUser').value) filterUserTable(); else loadUsers();
                } else {
                    throw new Error("Gagal Sync DoniGuard: " + (json.message || 'Unknown Error'));
                }
        
            } catch(e) {
                alert("Gagal update: " + e.message);
            } finally {
                btn.innerHTML = oriText;
                btn.disabled = false;
            }
        };
        
                        window.bukaDetailTrx = (dataStr) => {
            const data = JSON.parse(decodeURIComponent(dataStr));
            const content = document.getElementById('contentDetailTrx');
            const rawSafe = encodeURIComponent(data.raw_json || '');
            
            content.innerHTML = `
                <div class="detail-row"><span class="detail-label">Waktu</span><span class="detail-value">${data.waktu}</span></div>
                <div class="detail-row"><span class="detail-label">User</span><span class="detail-value">${data.username}</span></div>
                <div class="detail-row"><span class="detail-label">Produk</span><span class="detail-value">${data.produk}</span></div>
                <div class="detail-row"><span class="detail-label">Kode</span><span class="detail-value">${data.kode_produk || '-'}</span></div>
                <div class="detail-row"><span class="detail-label">Tujuan</span><span class="detail-value">${data.tujuan}</span></div>
                <div class="detail-row"><span class="detail-label">Harga</span><span class="detail-value">Rp ${new Intl.NumberFormat('id-ID').format(data.harga || 0)}</span></div>
                <div class="detail-row" style="align-items:center;"><span class="detail-label">Status DB</span><div style="display:flex; gap:5px;"><select id="editStatusTrx" style="padding:4px; border-radius:4px; font-size:12px; border:1px solid #ccc;"><option value="PENDING" ${(data.status || '').toUpperCase() === 'PENDING' ? 'selected' : ''}>PENDING</option><option value="BERHASIL" ${(data.status || '').toUpperCase() === 'BERHASIL' || (data.status || '').toUpperCase() === 'SUKSES' ? 'selected' : ''}>BERHASIL</option><option value="GAGAL" ${(data.status || '').toUpperCase() === 'GAGAL' ? 'selected' : ''}>GAGAL</option></select><button onclick="window.ubahStatusTrx('${data.path}')" style="background:var(--primary); color:white; border:none; padding:4px 8px; border-radius:4px; cursor:pointer; font-size:11px;">Simpan</button></div></div>
                <div class="detail-row"><span class="detail-label">Ref ID</span><span class="detail-value">${data.trx_id || '-'}</span></div>
                <div style="margin-top:15px; font-weight:bold; font-size:12px; color:#888;">SN / KETERANGAN:</div>
                <div class="sn-box-admin">${data.sn || 'Belum ada data'}</div>
                <div style="margin-top:15px; display:grid; grid-template-columns: 1fr 1fr; gap:10px;">
                    <button onclick="lihatRawJson('${rawSafe}')" style="background:#34495e; color:white; border:none; padding:10px; border-radius:8px; cursor:pointer; font-size:12px;"><i class="fas fa-code"></i> Lihat JSON</button>
                    <button onclick="cekStatusLiveAdmin('${data.trx_id}', '${data.tujuan}', '${data.kode_produk}')" style="background:#e67e22; color:white; border:none; padding:10px; border-radius:8px; cursor:pointer; font-size:12px;"><i class="fas fa-sync"></i> Cek Live</button>
                </div>
                <button id="btnRefundTrx" onclick="window.refundTransaksiIni('${data.path}', ${data.harga}, '${data.produk}', '${data.trx_id}')" style="background:${(data.status || '').toUpperCase() === 'GAGAL' ? '#95a5a6' : '#ef4444'}; color:white; border:none; padding:10px; border-radius:8px; cursor:pointer; font-size:12px; margin-top:10px; width:100%; font-weight:bold;" ${(data.status || '').toUpperCase() === 'GAGAL' ? 'disabled' : ''}><i class="fas ${(data.status || '').toUpperCase() === 'GAGAL' ? 'fa-ban' : 'fa-undo-alt'}"></i> ${(data.status || '').toUpperCase() === 'GAGAL' ? 'SUDAH GAGAL / DI-REFUND' : 'REFUND & GAGALKAN TRANSAKSI'}</button>`;
            document.getElementById('modalDetailTrx').style.display = "flex";
        };
        
        window.tutupModalDetail = () => document.getElementById('modalDetailTrx').style.display = "none";
        
        window.refundTransaksiIni = async (path, harga, produk, trxId) => {
            if (!confirm(`Konfirmasi Refund:\n\nProduk: ${produk}\nNominal: Rp ${new Intl.NumberFormat('id-ID').format(harga)}\n\nSaldo akan dikembalikan dan transaksi akan digagalkan. Lanjutkan?`)) return;
        
            const btn = document.getElementById('btnRefundTrx');
            const oriHtml = btn ? btn.innerHTML : 'REFUND';
            if(btn) {
                btn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> MEMPROSES REFUND...';
                btn.disabled = true;
            }
        
            try {
                const parts = path.split('/');
                const uid = parts[1];
                
                // === KEAMANAN FINAL: CEK STATUS REAL-TIME ===
                if (!path.startsWith('ARSIP/')) {
                    const trxRef = doc(db, path);
                    const trxSnap = await getDoc(trxRef);
                    if (trxSnap.exists()) {
                        const statusRealtime = (trxSnap.data().status || '').toUpperCase();
                        if (statusRealtime === 'GAGAL') {
                            alert("⛔ DOUBLE REFUND DICEGAH: Transaksi ini baru saja digagalkan oleh sistem/bot (Data Basi). Saldo sudah aman dan proses dibatalkan.");
                            window.tutupModalDetail();
                            if (document.getElementById('modalUserHistory').style.display === 'flex') {
                                window.lihatRiwayatUser(window.currentViewedUserUid, document.getElementById('histUserTitle').innerText);
                            } else {
                                window.loadRiwayat();
                            }
                            return;
                        }
                    }
                }
        
                if (path.startsWith('ARSIP/')) {
                    await fetch(`api_riwayat.php?action=update_status&uid=${uid}&trx_id=${trxId}&status=GAGAL`);
                } else {
                    await updateDoc(doc(db, path), {
                        status: 'GAGAL',
                        sn: 'DANA DI-REFUND OLEH ADMIN'
                    });
                }
        
                const userRef = doc(db, "users", uid);
                const userSnap = await getDoc(userRef);
                if (!userSnap.exists()) throw new Error("User tidak ditemukan");
        
                const currentSaldo = userSnap.data().saldo || 0;
                const newSaldo = currentSaldo + harga;
                await updateDoc(userRef, { saldo: newSaldo });
        
                await fetch('doniguard.php', {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({
                        uid: uid,
                        action: 'topup',
                        produk: 'REFUND: ' + produk,
                        nominal: harga,
                        saldo_akhir_client: newSaldo,
                        trx_id: 'REF-' + trxId
                    })
                });
        
                alert('SUKSES: Transaksi digagalkan dan saldo telah dikembalikan ke user.');
                window.tutupModalDetail();
                if (document.getElementById('modalUserHistory').style.display === 'flex') {
                    window.lihatRiwayatUser(window.currentViewedUserUid, document.getElementById('histUserTitle').innerText);
                } else {
                    window.loadRiwayat();
                }
            } catch (e) {
                alert('ERROR REFUND: ' + e.message);
            } finally {
                if(btn) { btn.innerHTML = oriHtml; btn.disabled = false; }
            }
        };
        
        window.ubahStatusTrx = async (path) => {
            if(!path || path === 'undefined') return alert('Path dokumen tidak ditemukan!');
            const newStatus = document.getElementById('editStatusTrx').value;
            const btn = event.currentTarget;
            const oriHtml = btn.innerHTML;
            btn.innerHTML = '...';
            btn.disabled = true;
            try {
                if(path && path.startsWith('ARSIP/')) {
                    const parts = path.split('/');
                    const uid = parts[1];
                    const trxId = parts[2];
                    await fetch(`api_riwayat.php?action=update_status&uid=${uid}&trx_id=${trxId}&status=${newStatus}`);
                } else {
                    await updateDoc(doc(db, path), { status: newStatus });
                }
                alert('Status berhasil diubah menjadi ' + newStatus);
                if(document.getElementById('modalUserHistory').style.display === 'flex') {
                    window.lihatRiwayatUser(window.currentViewedUserUid, document.getElementById('histUserTitle').innerText);
                } else {
                    window.loadRiwayat();
                }
            } catch(e) {
                alert('Gagal ubah status: ' + e.message);
            } finally {
                btn.innerHTML = oriHtml;
                btn.disabled = false;
            }
        };
        
        // --- SISTEM KONFIRMASI TOPUP MANUAL ---
        window.loadPendingTopup = () => {
            const container = document.getElementById('listPendingTopup');
            if(!container) return;
            const q = query(collectionGroup(db, 'riwayat_transaksi'), where('kode_produk', '==', 'TOPUP'), where('status', '==', 'PENDING'), orderBy('timestamp', 'desc'));
            onSnapshot(q, (snap) => {
                if(snap.empty) {
                    container.innerHTML = "<div style='text-align:center; padding:20px; color:#aaa;'><i class='fas fa-check-circle' style='font-size:30px; margin-bottom:10px; color:#10b981;'></i><br>Tidak ada antrean topup.</div>";
                    return;
                }
                let html = "";
                snap.forEach(d => {
                    const data = d.data();
                    const pathParts = d.ref.path.split('/');
                    const uid = pathParts[1];
                    const docId = d.id;
                    const date = data.timestamp ? new Date(data.timestamp.seconds*1000).toLocaleString('id-ID') : '-';
                    
                    html += `
                    <div style="background:white; border:1px solid #f59e0b; padding:12px; border-radius:8px; margin-bottom:10px; box-shadow:0 2px 5px rgba(0,0,0,0.05); display:flex; flex-direction:column; gap:8px;">
                        <div style="display:flex; justify-content:space-between; border-bottom:1px dashed #eee; padding-bottom:5px;">
                            <span style="font-size:11px; color:#888;">${date}</span>
                            <span style="font-size:10px; font-weight:bold; background:#fff3cd; color:#856404; padding:2px 6px; border-radius:4px;">${data.metode || 'MANUAL'}</span>
                        </div>
                        <div style="display:flex; justify-content:space-between; align-items:center;">
                            <div>
                                <div style="font-weight:bold; font-size:14px; color:#2c3e50;">${data.username || 'User'}</div>
                                <div style="font-size:11px; color:#666;">UID: ${uid.substring(0,8)}...</div>
                            </div>
                            <div style="text-align:right;">
                                <div style="font-size:16px; font-weight:900; color:var(--primary);">Rp ${new Intl.NumberFormat('id-ID').format(data.harga)}</div>
                            </div>
                        </div>
                        <div style="display:flex; gap:10px; margin-top:5px;">
                            <button onclick="window.terimaTopupManual('${uid}', '${docId}', ${data.harga}, '${data.trx_id || docId}')" style="flex:1; background:#10b981; color:white; border:none; padding:8px; border-radius:6px; font-weight:bold; cursor:pointer;"><i class="fas fa-check"></i> TERIMA</button>
                            <button onclick="window.tolakTopupManual('${uid}', '${docId}')" style="flex:1; background:#ef4444; color:white; border:none; padding:8px; border-radius:6px; font-weight:bold; cursor:pointer;"><i class="fas fa-times"></i> TOLAK</button>
                        </div>
                    </div>`;
                });
                container.innerHTML = html;
            }, (error) => {
                console.error(error);
                if(error.message.includes('index')) {
                     container.innerHTML = "<div style='text-align:center; padding:20px; color:red; font-size:11px;'><b>Error Database:</b> Butuh Index baru di Firestore. Buka Console (F12) dan klik URL Index yang muncul berwarna merah.</div>";
                } else {
                     container.innerHTML = "<div style='text-align:center; padding:20px; color:red;'>Gagal memuat: " + error.message + "</div>";
                }
            });
        };
        
        window.terimaTopupManual = async (uid, docId, nominal, trxId) => {
            if(!confirm(`Terima Topup sebesar Rp ${new Intl.NumberFormat('id-ID').format(nominal)}?`)) return;
            window.showNotice('loading', 'Memproses', 'Menyetujui topup dan menambah saldo...');
            try {
                const userRef = doc(db, "users", uid);
                const userSnap = await getDoc(userRef);
                if(!userSnap.exists()) throw new Error("User tidak ditemukan");
                
                // === AMBIL DATA TELEGRAM DARI TRANSAKSI ===
                const trxRef = doc(db, "users", uid, "riwayat_transaksi", docId);
                const trxSnap = await getDoc(trxRef);
                const tgMsgId = trxSnap.exists() ? trxSnap.data().tg_message_id : null;
                const tgTextOri = trxSnap.exists() ? trxSnap.data().tg_text_ori : "Detail Topup:";
        
                const curSaldo = userSnap.data().saldo || 0;
                const newSaldo = curSaldo + nominal;
        
                // Update Saldo Client Firestore
                await updateDoc(userRef, { saldo: newSaldo });
                // Update Status Riwayat
                await updateDoc(trxRef, {
                    status: 'BERHASIL',
                    sn: 'Topup Berhasil (Divalidasi Admin via Panel)'
                });
        
                // Sinkronisasi ke DoniGuard Buku Besar
                try {
                    await fetch('https://pandawa-digital.com/doniguard.php', {
                        method: 'POST',
                        headers: { 'Content-Type': 'application/json' },
                        body: JSON.stringify({
                            uid: uid,
                            action: 'topup',
                            nominal: nominal,
                            trx_id: trxId,
                            produk: 'TOPUP MANUAL VALIDASI PANEL',
                            saldo_akhir_client: newSaldo
                        })
                    });
                } catch(dgE) { console.log("DoniGuard Error:", dgE); }
        
                // === UPDATE PESAN TELEGRAM ===
                if (tgMsgId) {
                    const updatedText = tgTextOri + `\n\n✅ *STATUS: TOPUP DISETUJUI (Via Panel)*\n💸 Saldo ditambahkan: Rp ${new Intl.NumberFormat('id-ID').format(nominal)}`;
                    fetch(`https://api.telegram.org/bot8490021696:AAGv-lgFCmKCg5x0Tr6xnqS3pQEEENAEZNA/editMessageText`, {
                        method: 'POST',
                        headers: { 'Content-Type': 'application/json' },
                        body: JSON.stringify({
                            chat_id: "-1003888145818",
                            message_id: tgMsgId,
                            text: updatedText,
                            parse_mode: "Markdown"
                        })
                    }).catch(e => console.log('Telegram Edit Error', e));
                }
        
                window.showNotice('success', 'Berhasil', `Topup disetujui. Saldo ditambahkan Rp ${nominal}.`);
            } catch(e) {
                window.showNotice('error', 'Gagal', e.message);
            }
        };
        
        window.tolakTopupManual = async (uid, docId) => {
            const alasan = prompt("Tulis alasan penolakan (Opsional):", "Ditolak Admin");
            if(alasan === null) return;
            window.showNotice('loading', 'Memproses', 'Menolak topup...');
            try {
                // === AMBIL DATA TELEGRAM DARI TRANSAKSI ===
                const trxRef = doc(db, "users", uid, "riwayat_transaksi", docId);
                const trxSnap = await getDoc(trxRef);
                const tgMsgId = trxSnap.exists() ? trxSnap.data().tg_message_id : null;
                const tgTextOri = trxSnap.exists() ? trxSnap.data().tg_text_ori : "Detail Topup:";
        
                await updateDoc(trxRef, {
                    status: 'GAGAL',
                    sn: 'Topup Ditolak: ' + alasan
                });
        
                // === UPDATE PESAN TELEGRAM ===
                if (tgMsgId) {
                    const updatedText = tgTextOri + `\n\n❌ *STATUS: TOPUP DITOLAK (Via Panel)*\nAlasan: ${alasan}`;
                    fetch(`https://api.telegram.org/bot8490021696:AAGv-lgFCmKCg5x0Tr6xnqS3pQEEENAEZNA/editMessageText`, {
                        method: 'POST',
                        headers: { 'Content-Type': 'application/json' },
                        body: JSON.stringify({
                            chat_id: "-1003888145818",
                            message_id: tgMsgId,
                            text: updatedText,
                            parse_mode: "Markdown"
                        })
                    }).catch(e => console.log('Telegram Edit Error', e));
                }
        
                window.showNotice('success', 'Berhasil', 'Topup telah ditolak.');
            } catch(e) {
                window.showNotice('error', 'Gagal', e.message);
            }
        };
        
        function loadTopup() {
            const tbody = document.getElementById('listTopupBody');
            if (tbody) tbody.innerHTML = "<tr><td colspan='6' style='text-align:center'>Memuat data...</td></tr>";
        
            const setTotalTopupStat = (nominal, info = '') => {
                const el = document.getElementById('statTotalTopup');
                if (!el) return;
                el.innerText = "Rp " + new Intl.NumberFormat('id-ID').format(parseInt(nominal || 0));
                if (info) el.title = info;
            };
        
            const hitungTopupDoniGuard = (textData) => {
                const logs = [];
                String(textData || '').split(/\r?\n/).forEach((line, idx) => {
                    if (!String(line || '').trim()) return;
                    try {
                        const log = JSON.parse(line);
                        log.__rawIndex = idx;
                        logs.push(log);
                    } catch(e) {}
                });
        
                logs.sort((a, b) => {
                    const ta = new Date(a.waktu || a.timestamp || 0).getTime() || a.__rawIndex;
                    const tb = new Date(b.waktu || b.timestamp || 0).getTime() || b.__rawIndex;
                    return ta - tb;
                });
        
                const isRefundLog = (log) => {
                    const produk = String(log.produk || '').toUpperCase();
                    const trx = String(log.trx_id || '').toUpperCase();
                    return !!log.is_refund || produk.includes('REFUND') || produk.includes('REFOUND') || /(\-REFUND|\_REFUND|\-REF|\_REF)$/.test(trx) || /^(REFUND|REF)\-/.test(trx);
                };
                const isResetLog = (log) => {
                    const produk = String(log.produk || '').toUpperCase();
                    const type = String(log.type || '').toUpperCase();
                    return type === 'RESET_BALANCE' || produk.includes('INITIAL_PUSH_ADMIN') || produk.includes('RESET') || produk.includes('SALDO AWAL');
                };
                const toNumber = (val) => {
                    const n = parseInt(val || 0);
                    return Number.isFinite(n) ? n : 0;
                };
        
                let lastResetIndex = -1;
                logs.forEach((log, idx) => {
                    if (isResetLog(log)) lastResetIndex = idx;
                });
        
                const auditLogs = lastResetIndex >= 0 ? logs.slice(lastResetIndex) : logs;
                let total = 0;
        
                auditLogs.forEach(log => {
                    if (isResetLog(log) || isRefundLog(log)) return;
                    const type = String(log.type || '').toUpperCase();
                    const nominal = toNumber(log.nominal);
                    const saldoAwal = toNumber(log.saldo_awal);
                    const saldoAkhir = toNumber(log.saldo_akhir);
                    const produk = String(log.produk || '').toUpperCase();
                    const action = String(log.action || '').toUpperCase();
        
                    const masukDariType = type === 'TOPUP' || type === 'PUSH_ADMIN' || action === 'TOPUP';
                    const masukDariProduk = produk.includes('TOPUP') || produk.includes('TRANSFER') || produk.includes('DEPOSIT') || produk.includes('SALDO MASUK');
                    const masukDariRantaiSaldo = saldoAkhir > saldoAwal && nominal > 0;
        
                    if (masukDariType || masukDariProduk || masukDariRantaiSaldo) total += nominal;
                });
        
                return total;
            };
        
            window.refreshTotalTopupFromDoniGuard = async () => {
                const users = (typeof cacheUsers !== 'undefined' && Array.isArray(cacheUsers)) ? cacheUsers : [];
                if (!users.length) {
                    setTotalTopupStat(0, 'Menunggu data user untuk membaca file DoniGuard...');
                    setTimeout(() => {
                        if (window.refreshTotalTopupFromDoniGuard) window.refreshTotalTopupFromDoniGuard();
                    }, 900);
                    return;
                }
        
                setTotalTopupStat(0, 'Menghitung total topup dari file DoniGuard...');
                let totalDoniGuard = 0;
                let fileTerbaca = 0;
        
                const hasil = await Promise.allSettled(users.map(async (u) => {
                    if (!u || !u.id) return 0;
                    const res = await fetch(`user/uid${u.id}.txt?t=${Date.now()}`, { cache: 'no-store' });
                    if (!res.ok) return 0;
                    const textData = await res.text();
                    fileTerbaca++;
                    return hitungTopupDoniGuard(textData);
                }));
        
                hasil.forEach(r => {
                    if (r.status === 'fulfilled') totalDoniGuard += parseInt(r.value || 0);
                });
        
                setTotalTopupStat(totalDoniGuard, `Sumber: file DoniGuard user/uid*.txt | File terbaca: ${fileTerbaca}/${users.length}`);
            };
        
            const q = query(collection(db, "topup_history"), orderBy("timestamp", "desc"));
        
            onSnapshot(q, snap => {
                window.allTopupData = [];
                snap.forEach(d => {
                    const data = d.data();
                    window.allTopupData.push({ id: d.id, ...data });
                });
        
                if (window.refreshTotalTopupFromDoniGuard) window.refreshTotalTopupFromDoniGuard();
                window.renderTopupPage(1);
            });
        }
        
        window.renderTopupPage = function(page) {
            const data = window.allTopupData;
            const tbody = document.getElementById('listTopupBody');
            const pagin = document.getElementById('topupPagination');
            const ITEMS_PER_PAGE = 10;
        
            if(data.length === 0) {
                tbody.innerHTML = "<tr><td colspan='6' style='text-align:center'>Belum ada data topup</td></tr>";
                pagin.innerHTML = "";
                return;
            }
        
            const totalPages = Math.ceil(data.length / ITEMS_PER_PAGE);
            const start = (page - 1) * ITEMS_PER_PAGE;
            const pageData = data.slice(start, start + ITEMS_PER_PAGE);
        
            let html = "";
            pageData.forEach(data => {
                const tgl = data.timestamp ? new Date(data.timestamp.seconds*1000).toLocaleString('id-ID') : "...";
                html += `<tr><td data-label="Waktu">${tgl}</td><td data-label="User">${data.username || data.uid}</td><td data-label="Nominal">Rp ${new Intl.NumberFormat('id-ID').format(data.amount)}</td><td data-label="Metode">${data.service_name || data.service}</td><td data-label="Status"><span class="status-badge" style="background:${data.status=='Success'?'#28a745':data.status=='Pending'?'#ffc107':'#dc3545'}">${data.status}</span></td><td data-label="Aksi">${data.status === 'Pending' ? `<button onclick="cekStatusTopup('${data.unique_code}')" style="padding:5px; font-size:10px; width:auto;">Cek</button>` : '-'}</td></tr>`;
            });
            tbody.innerHTML = html;
        
            let paginHtml = "";
            if (totalPages > 1) {
                const baseStyle = "min-width:26px; height:26px; border-radius:4px; border:1px solid #ddd; background:white; color:#333; cursor:pointer; margin:0 2px; font-weight:bold; font-size:10px;";
                const activeStyle = "min-width:26px; height:26px; border-radius:4px; border:none; background:var(--primary); color:white; cursor:pointer; margin:0 2px; font-weight:bold; font-size:10px; box-shadow:0 2px 5px rgba(0,0,0,0.2);";
        
                if (page > 1) paginHtml += `<button onclick="window.renderTopupPage(${page - 1})" style="${baseStyle}"><i class="fas fa-chevron-left"></i></button>`;
                
                let startPage = Math.max(1, page - 2);
                let endPage = Math.min(totalPages, page + 2);
                
                if (startPage > 1) {
                   paginHtml += `<button onclick="window.renderTopupPage(1)" style="${baseStyle}">1</button>`;
                   if(startPage > 2) paginHtml += `<span style="font-size:10px; color:#999; padding:0 2px;">...</span>`;
                }
        
                for (let i = startPage; i <= endPage; i++) {
                    paginHtml += `<button onclick="window.renderTopupPage(${i})" style="${i === page ? activeStyle : baseStyle}">${i}</button>`;
                }
        
                if (endPage < totalPages) {
                   if(endPage < totalPages - 1) paginHtml += `<span style="font-size:10px; color:#999; padding:0 2px;">...</span>`;
                   paginHtml += `<button onclick="window.renderTopupPage(${totalPages})" style="${baseStyle}">${totalPages}</button>`;
                }
        
                if (page < totalPages) paginHtml += `<button onclick="window.renderTopupPage(${page + 1})" style="${baseStyle}"><i class="fas fa-chevron-right"></i></button>`;
            }
            pagin.innerHTML = paginHtml;
        }
        
        window.cekStatusTopup = async (uniqueCode) => {
            try {
                const req = await fetch('paydisini_cek.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ unique_code: uniqueCode }) });
                const res = await req.json(); alert(res.msg);
            } catch(e) { alert("Gagal cek status"); }
        };
        
        window.loadOrdersFisik = (statusFilter) => {
            const tbody = document.getElementById('listOrdersFisik');
            tbody.innerHTML = "<tr><td colspan='6' style='text-align:center'>Memuat data...</td></tr>";
            const q = query(collection(db, "pesanan_fisik"), where("status", "==", statusFilter), orderBy("timestamp", "desc"));
            onSnapshot(q, (snap) => {
                let html = "";
                snap.forEach(d => {
                    const data = d.data();
                    const date = data.timestamp ? data.timestamp.toDate().toLocaleString() : '-';
                    let btnAksi = "";
                    if(data.status === 'DIKEMAS') { btnAksi = `<button onclick="inputResi('${d.id}')" style="background:#e67e22; color:white; padding:5px 10px; border-radius:5px; border:none; cursor:pointer; font-size:11px;">Input Resi</button><button onclick="tolakPesananFisik('${d.id}')" style="background:#ef4444; color:white; padding:5px 10px; border-radius:5px; border:none; cursor:pointer; font-size:11px; margin-left:5px;">Tolak</button>`; } 
                    else if (data.status === 'DIKIRIM') { btnAksi = `<div style="font-size:11px; margin-bottom:5px;">Resi: <b>${data.resi}</b></div><button onclick="selesaikanPesanan('${d.id}')" style="background:#10b981; color:white; padding:5px 10px; border-radius:5px; border:none; cursor:pointer; font-size:11px;">Selesai</button>`; } 
                    else { btnAksi = `<span style="color:#10b981; font-weight:bold; font-size:11px;"><i class="fas fa-check"></i> Selesai</span>`; }
                    html += `<tr><td data-label="Tanggal" style="font-size:11px;">${date}</td><td data-label="Produk"><b>${data.produk}</b><br><small style="color:var(--primary)">Rp ${new Intl.NumberFormat('id-ID').format(data.total)}</small></td><td data-label="Pembeli"><div style="font-weight:bold; font-size:12px;">${data.username}</div><div style="font-size:10px; color:#555; max-width:200px; line-height:1.2;">${data.alamat_lengkap}</div></td><td data-label="Kurir">${data.kurir}</td><td data-label="Status"><span class="status-badge" style="background:${data.status==='DIKEMAS'?'#f59e0b':data.status==='DIKIRIM'?'#3498db':'#10b981'}">${data.status}</span></td><td data-label="Aksi">${btnAksi}</td></tr>`;
                });
                tbody.innerHTML = html || "<tr><td colspan='6' style='text-align:center'>Tidak ada pesanan.</td></tr>";
            });
        };
        
        window.inputResi = async (docId) => {
            const resi = prompt("Masukkan Nomor Resi Pengiriman:");
            if(!resi) return;
            try { await updateDoc(doc(db, "pesanan_fisik", docId), { status: "DIKIRIM", resi: resi }); alert("Resi berhasil disimpan!"); } catch(e) { alert("Error: " + e.message); }
        };
        window.tolakPesananFisik = async (docId) => {
            const alasan = prompt("Tulis alasan penolakan:");
            if(!alasan) return;
            try { await updateDoc(doc(db, "pesanan_fisik", docId), { status: "DIBATALKAN", resi: "Dibatalkan: " + alasan }); alert("Pesanan ditolak."); } catch(e) { alert("Error: " + e.message); }
        };
        window.selesaikanPesanan = async (docId) => {
            if(!confirm("Pastikan barang sudah diterima. Selesaikan?")) return;
            try { await updateDoc(doc(db, "pesanan_fisik", docId), { status: "SELESAI" }); alert("Pesanan Selesai."); } catch(e) { alert("Error: " + e.message); }
        };
        
        // === SISTEM RIWAYAT BARU (GLOBAL & USER) ===
        window.allAdminTrx = [];
        window.currentStatusFilter = 'SEMUA';
        
        window.filterRiwayatStatus = (status, btn) => {
            window.currentStatusFilter = status;
            document.querySelectorAll('.filter-btn').forEach(b => b.classList.remove('active'));
            if(btn) btn.classList.add('active');
            window.renderAdminTrxPage(1);
        };
        
        window.currentUserTrx = [];
        window.allTopupData = [];
        const ITEMS_PER_PAGE = 10;
        
        // 1. RE-WRITE LOAD RIWAYAT (GLOBAL)
        window.loadRiwayat = async () => {
            const dateInput = document.getElementById('adminTrxDate');
            let dateVal = dateInput ? dateInput.value : '';
            
            if(!dateVal) {
                const today = new Date().toISOString().split('T')[0];
                if(dateInput) dateInput.value = today;
                dateVal = today;
            }
        
            const listArea = document.getElementById('adminTrxList');
            if(listArea) listArea.innerHTML = "<div style='text-align:center; padding:20px;'><i class='fas fa-spinner fa-spin'></i> Mengambil data global...</div>";
        
            const start = new Date(dateVal);
            start.setHours(0,0,0,0);
            const end = new Date(dateVal);
            end.setHours(23,59,59,999);
        
            try {
                window.allAdminTrx = [];
                // 1. Ambil dari Firebase (Live Data)
                const q = query(
                    collectionGroup(db, 'riwayat_transaksi'), 
                    where('timestamp', '>=', start),
                    where('timestamp', '<=', end),
                    orderBy('timestamp', 'desc')
                );
                const snap = await getDocs(q);
                snap.forEach(d => {
                    let item = d.data();
                    item.id = d.id;
                    item.path = d.ref.path;
                    item.source = 'LIVE';
                    item.timestamp_str = item.timestamp ? item.timestamp.toDate().toISOString() : new Date().toISOString();
                    window.allAdminTrx.push(item);
                });
        
                // 2. Ambil dari Hosting (Arsip Data)
                try {
                    const res = await fetch(`api_riwayat.php?action=get_admin_date&date=${dateVal}`);
                    const arsip = await res.json();
                    if(arsip && arsip.data) {
                        arsip.data.forEach(item => {
                            item.source = 'ARSIP';
                            item.path = `ARSIP/${item.uid}/${item.trx_id}`;
                            window.allAdminTrx.push(item);
                        });
                    }
                } catch(e) { console.warn("Gagal load arsip hosting:", e); }
        
                window.allAdminTrx.sort((a,b) => new Date(b.timestamp_str) - new Date(a.timestamp_str));
                window.renderAdminTrxPage(1);
        
            } catch(e) {
                console.error(e);
                let msg = e.message;
                if(msg.includes("index")) msg = "Database perlu Index baru. Buka Console (F12) & klik link Firebase yang muncul.";
                if(listArea) listArea.innerHTML = `<div style='color:red; text-align:center; padding:20px;'>Gagal: ${msg}</div>`;
            }
        };
        
        window.hapusRiwayat = async (path) => {
            if(confirm("Hapus item riwayat ini secara permanen?")) {
                try {
                    if(path && path.startsWith('ARSIP/')) {
                        const parts = path.split('/');
                        const uid = parts[1];
                        const trxId = parts[2];
                        await fetch(`api_riwayat.php?action=hapus_arsip&uid=${uid}&trx_id=${trxId}`);
                    } else {
                        await deleteDoc(doc(db, path));
                    }
                    alert("Riwayat dihapus.");
                    if(document.getElementById('modalUserHistory').style.display === 'flex') {
                        window.lihatRiwayatUser(window.currentViewedUserUid, document.getElementById('histUserTitle').innerText);
                    } else {
                        window.loadRiwayat();
                    }
                } catch(e) { alert("Gagal: " + e.message); }
            }
        };
        
        window.renderAdminTrxPage = function(page) {
            // 1. Filter Data Berdasarkan Status
            let data = window.allAdminTrx;
            if(window.currentStatusFilter !== 'SEMUA') {
                if(window.currentStatusFilter === 'TOPUP') {
                     data = data.filter(d => d.kode_produk === 'TOPUP');
                } else {
                     data = data.filter(d => (d.status || '').toUpperCase() === window.currentStatusFilter);
                }
            }
        
            const area = document.getElementById('adminTrxList');
            const pagin = document.getElementById('adminTrxPagin');
            if(!area) return;
            
            if(data.length === 0) {
                area.innerHTML = "<div style='text-align:center; color:#999; padding:20px; font-size:11px; background:#f9f9f9; border-radius:10px;'>Tidak ada data (" + window.currentStatusFilter + ")</div>";
                pagin.innerHTML = "";
                return;
            }
        
            // 2. Paginasi
            const totalPages = Math.ceil(data.length / ITEMS_PER_PAGE);
            const start = (page - 1) * ITEMS_PER_PAGE;
            const pageData = data.slice(start, start + ITEMS_PER_PAGE);
        
            let html = "";
            pageData.forEach(d => {
                let color = d.status === 'BERHASIL' || d.status === 'Sukses' ? '#d4edda' : (d.status === 'PENDING' ? '#fff3cd' : '#f8d7da');
                let textColor = d.status === 'BERHASIL' || d.status === 'Sukses' ? '#155724' : (d.status === 'PENDING' ? '#856404' : '#721c24');
                
                let dObj = d.timestamp_str ? new Date(d.timestamp_str) : new Date();
                let time = dObj.toLocaleString('id-ID');
                let badgeSource = d.source === 'ARSIP' ? '<i class="fas fa-server" style="color:#94a3b8; font-size:9px; margin-left:5px;" title="Arsip Server"></i>' : '<i class="fab fa-gripfire" style="color:#ff7675; font-size:9px; margin-left:5px;" title="Live Firebase"></i>';
                
                let realUsername = d.username || 'User';
                let isH2H = false;
                let uidStr = d.path ? d.path.split('/')[1] : null;
                if(uidStr && typeof cacheUsers !== 'undefined') {
                    let foundUser = cacheUsers.find(u => u.id === uidStr);
                    if(foundUser) {
                        realUsername = foundUser.username || foundUser.nama || 'User';
                        if(foundUser.role === 'merchant_h2h') isH2H = true;
                    }
                }
                let displayUsername = realUsername;
                let badgeH2H = isH2H ? ' <span style="background:#f59e0b; color:white; font-size:8px; padding:2px 4px; border-radius:3px; vertical-align:middle; margin-left:3px; font-weight:bold;"><i class="fas fa-satellite-dish"></i> H2H</span>' : '';
        
                const dataObj = encodeURIComponent(JSON.stringify({
                    trx_id: d.trx_id || d.id,
                    waktu: time,
                    username: realUsername + (isH2H ? ' (H2H)' : ''),
                    produk: d.produk,
                    kode_produk: d.kode_produk || '',
                    tujuan: d.tujuan,
                    harga: d.harga,
                    status: d.status,
                    path: d.path || ('users/' + window.currentViewedUserUid + '/riwayat_transaksi/' + d.id),
                    sn: d.sn,
                    raw_json: d.raw_json || '{}'
                }));
        
                // 3. TAMPILAN COMPACT (50% Lebih Kecil)
                html += `
                <div onclick="bukaDetailTrx('${dataObj}')" style="background:white; padding:6px 10px; border-radius:6px; border-left:3px solid ${textColor}; box-shadow:0 1px 2px rgba(0,0,0,0.05); font-size:10px; margin-bottom:4px; cursor:pointer; transition:0.1s; line-height:1.2;">
                    <div style="display:flex; justify-content:space-between; margin-bottom:2px;">
                        <div style="display:flex; align-items:center; gap:5px;"><div style="font-weight:bold; color:#2563eb;"><i class="fas fa-user-circle"></i> ${displayUsername}${badgeH2H}</div><i class="fas fa-trash" onclick="event.stopPropagation(); hapusRiwayat('${d.path}')" style="color:#ef4444; cursor:pointer; font-size:10px;" title="Hapus Item"></i></div>
                        <span style="background:${color}; color:${textColor}; padding:1px 6px; border-radius:4px; font-size:9px; font-weight:bold;">${d.status}</span>
                    </div>
                    <div style="display:flex; justify-content:space-between; color:#333; margin-bottom:2px;">
                        <b style="white-space:nowrap; overflow:hidden; text-overflow:ellipsis; max-width:65%;">${d.produk}</b>
                        <b style="color:var(--primary);">Rp ${new Intl.NumberFormat('id-ID').format(d.harga)}</b>
                    </div>
                    <div style="display:flex; justify-content:space-between; color:#777; font-size:9px;">
                        <span>${d.tujuan}</span>
                        <span>${time.split(' ')[1] || time}</span>
                    </div>
                </div>`;
            });
        
            // 4. Render Paginasi
            let paginHtml = "";
            if (totalPages > 1) {
                const baseStyle = "min-width:24px; height:24px; border-radius:4px; border:1px solid #ddd; background:white; color:#333; cursor:pointer; margin:0 1px; font-weight:bold; font-size:9px;";
                const activeStyle = "min-width:24px; height:24px; border-radius:4px; border:none; background:var(--primary); color:white; cursor:pointer; margin:0 1px; font-weight:bold; font-size:9px;";
        
                if (page > 1) paginHtml += `<button onclick="window.renderAdminTrxPage(${page - 1})" style="${baseStyle}"><</button>`;
                
                let startPage = Math.max(1, page - 2);
                let endPage = Math.min(totalPages, page + 2);
                if (startPage > 1) paginHtml += `<button onclick="window.renderAdminTrxPage(1)" style="${baseStyle}">1</button>`;
                if (startPage > 2) paginHtml += `<span style="padding:0 2px; color:#999; font-size:9px;">..</span>`;
        
                for (let i = startPage; i <= endPage; i++) {
                    paginHtml += `<button onclick="window.renderAdminTrxPage(${i})" style="${i === page ? activeStyle : baseStyle}">${i}</button>`;
                }
        
                if (endPage < totalPages) {
                   if(endPage < totalPages - 1) paginHtml += `<span style="padding:0 2px; color:#999; font-size:9px;">..</span>`;
                   paginHtml += `<button onclick="window.renderAdminTrxPage(${totalPages})" style="${baseStyle}">${totalPages}</button>`;
                }
        
                if (page < totalPages) paginHtml += `<button onclick="window.renderAdminTrxPage(${page + 1})" style="${baseStyle}">></button>`;
            }
            
            area.innerHTML = html;
            pagin.innerHTML = paginHtml;
        }
        
        // 2. LOAD RIWAYAT PER USER (MODAL)
        window.lihatRiwayatUser = async (uid, username) => {
            window.currentViewedUserUid = uid;
            document.getElementById('modalUserHistory').style.display = 'flex';
            document.getElementById('histUserTitle').innerText = username;
            const listArea = document.getElementById('listUserHist');
            listArea.innerHTML = "<div style='text-align:center; padding:20px;'><i class='fas fa-spinner fa-spin'></i> Memuat riwayat user...</div>";
        
            try {
                window.currentUserTrx = [];
                // 1. Firebase (Live)
                const q = query(collection(db, "users", uid, "riwayat_transaksi"), orderBy("timestamp", "desc"), limit(50)); 
                const snap = await getDocs(q);
                snap.forEach(d => {
                    let item = d.data();
                    item.id = d.id;
                    item.path = d.ref.path;
                    item.source = 'LIVE';
                    item.timestamp_str = item.timestamp ? item.timestamp.toDate().toISOString() : new Date().toISOString();
                    window.currentUserTrx.push(item);
                });
        
                // 2. Hosting API (Arsip)
                try {
                    const res = await fetch(`api_riwayat.php?action=get_arsip&uid=${uid}`);
                    const arsip = await res.json();
                    if(arsip && arsip.data) {
                        arsip.data.forEach(item => {
                            item.source = 'ARSIP';
                            item.path = `ARSIP/${uid}/${item.trx_id}`;
                            window.currentUserTrx.push(item);
                        });
                    }
                } catch(e) { console.warn("Gagal load arsip user hosting:", e); }
        
                window.currentUserTrx.sort((a,b) => new Date(b.timestamp_str) - new Date(a.timestamp_str));
        
                window.renderUserHistPage(1);
            } catch(e) {
                listArea.innerHTML = `<p style='color:red;'>Error: ${e.message}</p>`;
            }
        };
        
        window.renderUserHistPage = function(page) {
            const data = window.currentUserTrx;
            const area = document.getElementById('listUserHist');
            const pagin = document.getElementById('paginUserHist');
        
            if(data.length === 0) {
                area.innerHTML = "<div style='text-align:center; color:#999; padding:20px;'>Belum ada riwayat transaksi.</div>";
                pagin.innerHTML = "";
                return;
            }
        
            const { html, paginHtml } = paginateData(data, page, 'renderUserHistPage');
            area.innerHTML = html;
            pagin.innerHTML = paginHtml;
        }
        
        function paginateData(dataSet, currentPage, funcName) {
            const totalPages = Math.ceil(dataSet.length / ITEMS_PER_PAGE);
            const start = (currentPage - 1) * ITEMS_PER_PAGE;
            const pageData = dataSet.slice(start, start + ITEMS_PER_PAGE);
        
            let html = "";
            pageData.forEach(d => {
                let color = d.status === 'BERHASIL' || d.status === 'Sukses' ? '#d4edda' : (d.status === 'PENDING' ? '#fff3cd' : '#f8d7da');
                let textColor = d.status === 'BERHASIL' || d.status === 'Sukses' ? '#155724' : (d.status === 'PENDING' ? '#856404' : '#721c24');
                let time = d.timestamp ? new Date(d.timestamp.seconds*1000).toLocaleString('id-ID') : '-';
                
                let realUsername = d.username || 'User';
                let isH2H = false;
                let uidStr = window.currentViewedUserUid;
                if(uidStr && typeof cacheUsers !== 'undefined') {
                    let foundUser = cacheUsers.find(u => u.id === uidStr);
                    if(foundUser) {
                        realUsername = foundUser.username || foundUser.nama || 'User';
                        if(foundUser.role === 'merchant_h2h') isH2H = true;
                    }
                }
                let displayUsername = realUsername;
                let badgeH2H = isH2H ? ' <span style="background:#f59e0b; color:white; font-size:8px; padding:2px 4px; border-radius:3px; vertical-align:middle; margin-left:3px; font-weight:bold;"><i class="fas fa-satellite-dish"></i> H2H</span>' : '';
        
                const dataObj = encodeURIComponent(JSON.stringify({
                    trx_id: d.trx_id || d.id,
                    waktu: time,
                    username: realUsername + (isH2H ? ' (H2H)' : ''),
                    produk: d.produk,
                    kode_produk: d.kode_produk || '',
                    tujuan: d.tujuan,
                    harga: d.harga,
                    status: d.status,
                    path: d.path || ('users/' + window.currentViewedUserUid + '/riwayat_transaksi/' + d.id),
                    sn: d.sn,
                    raw_json: d.raw_json || '{}'
                }));
        
                html += `
                <div onclick="bukaDetailTrx('${dataObj}')" style="background:white; padding:12px; border-radius:8px; border-left:5px solid ${textColor}; box-shadow:0 1px 3px rgba(0,0,0,0.1); font-size:12px; margin-bottom:8px; cursor:pointer; transition:0.2s;">
                    <div style="font-size:11px; font-weight:bold; color:#2563eb; border-bottom:1px dashed #eee; padding-bottom:5px; margin-bottom:5px;"><i class="fas fa-user-circle"></i> ${displayUsername}${badgeH2H}</div>
                    <div style="display:flex; justify-content:space-between; margin-bottom:5px;">
                        <b style="font-size:13px;">${d.produk}</b>
                        <span style="background:${color}; color:${textColor}; padding:2px 8px; border-radius:10px; font-size:10px; font-weight:bold;">${d.status}</span>
                    </div>
                    <div style="display:flex; justify-content:space-between; color:#555;">
                        <span>${d.tujuan}</span>
                        <b style="color:var(--primary);">Rp ${new Intl.NumberFormat('id-ID').format(d.harga)}</b>
                    </div>
                    <div style="margin-top:8px; font-size:10px; color:#999; display:flex; justify-content:space-between; border-top:1px dashed #eee; padding-top:5px;">
                        <span><i class="far fa-clock"></i> ${time}</span>
                        <span>Ref: ${d.trx_id || '-'}</span>
                    </div>
                </div>`;
            });
        
            let paginHtml = "";
            if (totalPages > 1) {
                // Style tombol yang lebih kecil (26px)
                const baseStyle = "min-width:26px; height:26px; border-radius:4px; border:1px solid #ddd; background:white; color:#333; cursor:pointer; margin:0 2px; font-weight:bold; font-size:10px;";
                const activeStyle = "min-width:26px; height:26px; border-radius:4px; border:none; background:var(--primary); color:white; cursor:pointer; margin:0 2px; font-weight:bold; font-size:10px; box-shadow:0 2px 5px rgba(0,0,0,0.2);";
        
                // Prev Button
                if (currentPage > 1) {
                    paginHtml += `<button onclick="window.${funcName}(${currentPage - 1})" style="${baseStyle}"><i class="fas fa-chevron-left"></i></button>`;
                }
        
                // Number Buttons Logic (Smart Window)
                if (totalPages <= 7) {
                    for (let i = 1; i <= totalPages; i++) {
                        paginHtml += `<button onclick="window.${funcName}(${i})" style="${i === currentPage ? activeStyle : baseStyle}">${i}</button>`;
                    }
                } else {
                    let pagesToRender = [1]; 
                    let rangeStart = Math.max(2, currentPage - 1);
                    let rangeEnd = Math.min(totalPages - 1, currentPage + 1);
        
                    if (currentPage <= 4) { rangeEnd = 5; }
                    if (currentPage >= totalPages - 3) { rangeStart = totalPages - 4; }
        
                    if (rangeStart > 2) pagesToRender.push('...');
                    for (let i = rangeStart; i <= rangeEnd; i++) pagesToRender.push(i);
                    if (rangeEnd < totalPages - 1) pagesToRender.push('...');
                    pagesToRender.push(totalPages);
        
                    pagesToRender.forEach(p => {
                        if (p === '...') paginHtml += `<span style="padding:0 5px; line-height:26px; color:#999; font-size:10px;">...</span>`;
                        else paginHtml += `<button onclick="window.${funcName}(${p})" style="${p === currentPage ? activeStyle : baseStyle}">${p}</button>`;
                    });
                }
        
                // Next Button
                if (currentPage < totalPages) {
                    paginHtml += `<button onclick="window.${funcName}(${currentPage + 1})" style="${baseStyle}"><i class="fas fa-chevron-right"></i></button>`;
                }
            }
            return { html, paginHtml };
        }
        
        window.lihatRawJson = (encodedJson) => {
            const area = document.getElementById('areaRawJson');
            const textArea = document.getElementById('textRawJson');
            if(area.style.display === 'none') {
                area.style.display = 'block';
                try { textArea.value = decodeURIComponent(encodedJson); } catch(e) { textArea.value = "Data tidak valid"; }
            } else { area.style.display = 'none'; }
        };
        
        window.cekStatusLiveAdmin = async (refID, tujuan, kode) => {
            if(!refID || refID === '-' || !kode) return alert("Data Transaksi tidak lengkap.");
            const btn = event.currentTarget;
            const oriText = btn.innerHTML;
            btn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Checking...';
            btn.disabled = true;
            try {
                let res;
                let statusAkhir = 'PENDING';
                let snAkhir = '-';
        
                if (refID.startsWith('KF-')) {
                    const req = await fetch(`khfy_proxyv2.php?action=status&refid=${encodeURIComponent(refID)}`);
                    res = await req.json();
                    
                    let targetItem = null;
                    if (res.data && Array.isArray(res.data)) targetItem = res.data[0];
                    else if (res.data && res.data.data && Array.isArray(res.data.data)) targetItem = res.data.data[0];
                    else if (res.data) targetItem = res.data;
                    else if (res.status && res.sn) targetItem = res;
        
                    if(targetItem) {
                        const st = (targetItem.status || targetItem.status_text || targetItem.message || '').toUpperCase();
                        const stCode = parseInt(targetItem.status2 || 0);
                        if(st.includes('SUKSES') || st.includes('BERHASIL') || st.includes('SUCCESS') || stCode === 20) statusAkhir = 'BERHASIL';
                        else if(st.includes('GAGAL') || st.includes('BATAL') || st.includes('REFUND') || st.includes('FAILED') || stCode === 72) statusAkhir = 'GAGAL';
                        snAkhir = targetItem.sn || targetItem.keterangan || targetItem.note || targetItem.message || '-';
                    } else {
                        snAkhir = res.message || 'Format respon tidak dikenali';
                    }
                } else if (refID.startsWith('ICS-')) {
                    const req = await fetch(`ics_proxy.php?action=status&refid=${encodeURIComponent(refID)}`);
                    res = await req.json();
                    if(res.success && res.data) {
                        const statusRaw = (res.data.status || '').toLowerCase();
                        if(statusRaw === 'success') statusAkhir = 'BERHASIL';
                        else if(statusRaw === 'failed') statusAkhir = 'GAGAL';
                        snAkhir = res.data.sn || res.data.message || '-';
                    } else {
                        snAkhir = res.message || 'Gagal mengambil data ICS';
                    }
                } else if (refID.startsWith('KJ-') || refID.startsWith('KAJE-')) {
                    const req = await fetch(`kaje_proxy.php?api_action=status`, {
                        method: 'POST',
                        headers: { 'Content-Type': 'application/json' },
                        body: JSON.stringify({ trx_id: refID })
                    });
                    res = await req.json();
                    if(res.success && res.data) {
                        const statusRaw = (res.data.status || '').toLowerCase();
                        if(statusRaw === 'success' || statusRaw === 'berhasil') statusAkhir = 'BERHASIL';
                        else if(statusRaw === 'failed' || statusRaw === 'gagal') statusAkhir = 'GAGAL';
                        snAkhir = res.data.sn || res.data.message || res.message || '-';
                    } else {
                        snAkhir = res.message || 'Gagal mengambil data KAJE';
                    }
                } else {
                    const req = await fetch('cek_status.php', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({ refID: refID, tujuan: tujuan, kode_produk: kode }) });
                    res = await req.json();
                    statusAkhir = res.status;
                    snAkhir = res.sn;
                }
        
                alert(`STATUS LIVE: ${statusAkhir}\n\nSN/Keterangan: ${snAkhir}`);
                
                const areaRaw = document.getElementById('areaRawJson');
                if(areaRaw) {
                    areaRaw.style.display = 'block';
                    document.getElementById('textRawJson').value = "=== RESPON CEK LIVE ===\n" + JSON.stringify(res, null, 4);
                }
            } catch(e) { alert("Gagal koneksi ke server pengecekan: " + e.message); } 
            finally { btn.innerHTML = oriText; btn.disabled = false; }
        };
            
        
        
        
        
        // --- SYSTEM PRIVATE CHAT ADMIN (HOSTING BASED) ---
        window.activeChatUid = null;
        window.adminChatInterval = null;
        
        window.loadChatUsers = async function() {
            try {
                const res = await fetch('datapesan/api_chat.php?action=get_users');
                const users = await res.json();
                const area = document.getElementById('listChatUsers');
                if(!area) return;
                let html = "";
                users.forEach(u => {
                    const isActive = (u.uid === window.activeChatUid);
                    const bg = isActive ? 'background:#e1effe; border-left:4px solid var(--primary);' : '';
                    html += `<div onclick="bukaChatUser('${u.uid}', '${u.name}')" style="padding:12px 15px; border-bottom:1px solid #eee; cursor:pointer; transition:0.2s; ${bg}">
                        <div style="font-weight:bold; font-size:13px; color:#333; margin-bottom:2px;">${u.name}</div>
                        <div style="font-size:11px; color:#777; white-space:nowrap; overflow:hidden; text-overflow:ellipsis;">${u.last_msg || 'Memulai percakapan...'}</div>
                    </div>`;
                });
                area.innerHTML = html || "<div style='padding:30px 20px; text-align:center; color:#ccc; font-size:12px;'><i class='fas fa-comments' style='font-size:30px; margin-bottom:10px;'></i><br>Tidak ada pesan</div>";
            } catch(e) { console.log("User Load Error", e); }
        };
        
        window.bukaChatUser = function(uid, name) {
            window.activeChatUid = uid;
            document.getElementById('chatHeaderAdmin').innerHTML = `<div style="display:flex; justify-content:space-between; align-items:center; width:100%;"><div><i class="fas fa-user-circle"></i> Chat: <b>${name}</b></div> <button onclick="hapusSemuaChat('${uid}')" style="background:#ef4444; color:white; border:none; padding:6px 10px; border-radius:6px; font-size:10px; cursor:pointer; font-weight:bold; box-shadow:0 2px 5px rgba(0,0,0,0.1);"><i class="fas fa-trash"></i> Bersihkan Chat</button></div>`;
            document.getElementById('chatInputAreaAdmin').style.display = 'flex';
            window.loadPesanPribadi();
            if(window.adminChatInterval) clearInterval(window.adminChatInterval);
            window.adminChatInterval = setInterval(window.loadPesanPribadi, 3000);
            window.loadChatUsers();
        };
        
        window.loadPesanPribadi = async function() {
            if(!window.activeChatUid) return;
            try {
                const res = await fetch(`datapesan/api_chat.php?action=get_messages&uid=${window.activeChatUid}`);
                const msgs = await res.json();
                const box = document.getElementById('adminChatBox');
                if(!box) return;
                let html = "";
                msgs.reverse().forEach(m => {
                    const isAdmin = m.sender === 'admin';
                    const align = isAdmin ? 'align-self: flex-end; background:#dcf8c6; border:1px solid #c3e6cb; border-bottom-right-radius:0;' : 'align-self: flex-start; background:white; border:1px solid #ddd; border-bottom-left-radius:0;';
                    const safeText = encodeURIComponent(m.text || '');
                    const safeName = encodeURIComponent(isAdmin ? 'Saya' : m.name);
                    html += `<div onclick="tampilkanMenuChat(event, '${m.id}', '${safeName}', '${safeText}')" style="cursor:pointer; max-width:80%; padding:10px 14px; border-radius:12px; font-size:13px; box-shadow:0 1px 2px rgba(0,0,0,0.1); margin-bottom:5px; line-height:1.4; transition:0.2s; ${align}" onmouseover="this.style.filter='brightness(0.95)'" onmouseout="this.style.filter='none'">
                        <div style="font-weight:bold; font-size:10px; margin-bottom:4px; opacity:0.6;">${isAdmin ? 'Saya (Admin)' : m.name}</div>
                        <div style="word-wrap:break-word;">${m.text}</div>
                        <div style="text-align:right; font-size:9px; margin-top:4px; opacity:0.5;">${m.time}</div>
                    </div>`;
                });
                box.innerHTML = html;
            } catch(e) { console.log("Gagal load pesan", e); }
        };
        
        window.terpilihChatId = null;
        window.terpilihChatNama = null;
        window.terpilihChatTeks = null;
        
        window.tampilkanMenuChat = function(e, id, namaEsc, teksEsc) {
            e.preventDefault();
            window.terpilihChatId = id;
            window.terpilihChatNama = decodeURIComponent(namaEsc);
            window.terpilihChatTeks = decodeURIComponent(teksEsc);
            
            const menu = document.getElementById('chatContextMenu');
            const overlay = document.getElementById('chatOverlayMenu');
            
            menu.style.display = 'flex';
            overlay.style.display = 'block';
            
            let x = e.clientX;
            let y = e.clientY;
            if (x + 150 > window.innerWidth) x = window.innerWidth - 160;
            if (y + 100 > window.innerHeight) y = window.innerHeight - 110;
            
            menu.style.left = x + 'px';
            menu.style.top = y + 'px';
        };
        
        window.tutupMenuChat = function() {
            document.getElementById('chatContextMenu').style.display = 'none';
            document.getElementById('chatOverlayMenu').style.display = 'none';
        };
        
        window.balasPesanTeks = function() {
            tutupMenuChat();
            const input = document.getElementById('adminChatInputPribadi');
            const snippet = window.terpilihChatTeks.length > 25 ? window.terpilihChatTeks.substring(0,25) + "..." : window.terpilihChatTeks;
            input.value = `[Balas ${window.terpilihChatNama}: "${snippet}"]\n`;
            input.focus();
        };
        
        window.hapusPesanTerpilih = async function() {
            tutupMenuChat();
            if(!confirm("Hapus pesan ini secara permanen?")) return;
            try {
                const fd = new FormData();
                fd.append('action', 'delete');
                fd.append('id', window.terpilihChatId);
                await fetch('datapesan/api_chat.php', { method: 'POST', body: fd });
                window.loadPesanPribadi();
            } catch(e) { alert("Gagal menghapus pesan"); }
        };
        
        window.hapusSemuaChat = async function(uid) {
            if(!confirm("YAKIN HAPUS SEMUA PESAN dengan user ini? Data tidak bisa dikembalikan.")) return;
            try {
                const fd = new FormData();
                fd.append('action', 'delete_all');
                fd.append('uid', uid);
                await fetch('datapesan/api_chat.php', { method: 'POST', body: fd });
                window.loadPesanPribadi();
                window.loadChatUsers();
            } catch(e) { alert("Gagal menghapus semua pesan"); }
        };
        
        
        window.kirimChatAdminPribadi = async function() {
            const input = document.getElementById('adminChatInputPribadi');
            const msg = input.value.trim();
            if(!msg || !window.activeChatUid) return;
            
            input.value = "";
            try {
                const formData = new FormData();
                formData.append('action', 'send');
                formData.append('uid', window.activeChatUid);
                formData.append('pesan', msg);
                formData.append('pengirim', 'admin');
                formData.append('nama', 'Admin');
        
                await fetch('datapesan/api_chat.php', { method: 'POST', body: formData });
                window.loadPesanPribadi();
            } catch(e) { alert("Gagal mengirim balasan"); }
        };
        
        document.addEventListener('DOMContentLoaded', () => {
            setTimeout(() => {
                const inputEl = document.getElementById('adminChatInputPribadi');
                if(inputEl) {
                    inputEl.addEventListener('keypress', function (e) {
                        if (e.key === 'Enter') window.kirimChatAdminPribadi();
                    });
                }
            }, 1000);
        });
        
        // Scan user baru setiap 8 detik jika di halaman chat
        setInterval(() => {
            const el = document.getElementById('view-chat');
            if(el && el.classList.contains('active')) window.loadChatUsers();
        }, 8000);
        
        
        
        // --- SYSTEM PRE-ORDER AKRAB (TERMUX HOSTING INTEGRATION) ---
        window.allPoData = [];
        window.currentPoFilter = 'ANTREAN';
        
        window.startAutoCheckPO = (path, uid, trxId, provider, kode, tujuan) => {
            if (window.poIntervals[path]) return;
            window.poIntervals[path] = setInterval(async () => {
        try {
            let apiUrl = '';
            const prov = (provider || '').toUpperCase();
            let req;
            if (prov.includes('ICS')) {
                req = await fetch(`ics_proxy.php?action=status&refid=${encodeURIComponent(trxId)}`);
            } else if (prov.includes('KHFY')) {
                req = await fetch(`khfy_proxyv2.php?action=status&refid=${encodeURIComponent(trxId)}`);
            } else if (prov.includes('KAJE')) {
                req = await fetch(`kaje_proxy.php?api_action=status`, {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({ trx_id: trxId })
                });
            } else {
                return clearInterval(window.poIntervals[path]);
            }
            const res = await req.json();
            const resString = JSON.stringify(res, null, 2);
            
            const isStillPending = /pending/i.test(resString);
            let isSuccess = false;
        if (res.success === true || res.status === true || res.code === "000") {
            isSuccess = true;
        } else {
            const safeResString = resString.replace(/"success"\s*:\s*false/gi, "");
            isSuccess = /sukses|berhasil|"status"\s*:\s*"success"/i.test(safeResString);
        }
        
            const updateData = { log_api: resString };
            if (isSuccess && !isStillPending) {
                updateData.status = 'BERHASIL';
                updateData.sn = 'Selesai Otomatis via Panel';
                clearInterval(window.poIntervals[path]);
                delete window.poIntervals[path];
            } else {
                updateData.status = 'PENDING';
                updateData.sn = 'Masih dalam antrean Pre-Order';
                if (!isStillPending) {
                    clearInterval(window.poIntervals[path]);
                    delete window.poIntervals[path];
                }
            }
            await updateDoc(doc(db, path), updateData);
        } catch (e) { console.error("Auto Check Error:", e); }
            }, 6000);
        };
        
        window.gantiProviderPO = async (path, currentProv) => {
            const currentUpper = (currentProv || '').toUpperCase();
            const newProv = currentUpper.includes('KHFY') ? 'ICS' : (currentUpper.includes('ICS') ? 'KAJE' : 'KHFY');
            if(!confirm(`Ubah provider dari ${currentProv} ke ${newProv}?`)) return;
            
            try {
        await updateDoc(doc(db, path), { provider: newProv, log_api: `Provider diubah manual oleh Admin ke ${newProv}` });
        window.showNotice('success', 'Berhasil', `Provider diubah ke ${newProv}`);
            } catch(e) {
        alert("Gagal ubah provider: " + e.message);
            }
        };
        
        
        window.bukaModalInjeksiPO = () => {
            document.getElementById('injUid').value = "";
            document.getElementById('injTujuan').value = "";
            document.getElementById('injKode').value = "";
            document.getElementById('injProvider').value = "KHFY";
            document.getElementById('injHarga').value = "";
            document.getElementById('modalInjeksiPO').style.display = "flex";
        };
        
        window.simpanInjeksiPO = async () => {
            const uid = document.getElementById('injUid').value;
            const tujuan = document.getElementById('injTujuan').value;
            const kode = document.getElementById('injKode').value;
            const provider = document.getElementById('injProvider').value;
            const harga = parseInt(document.getElementById('injHarga').value) || 0;
        
            if(!uid || !tujuan || !kode || !provider) return alert("Harap lengkapi semua data form injeksi!");
        
            const btn = document.querySelector('#modalInjeksiPO .btn-save');
            const ori = btn.innerHTML;
            btn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Menginjeksi...'; 
            btn.disabled = true;
        
            try {
        const trxId = "INJ-" + Date.now();
        
        const userTrxPayload = {
            produk: "Pre-Order " + kode,
            kode_produk: kode,
            tujuan: tujuan,
            provider: provider,
            harga: harga,
            status: "PENDING",
            trx_id: trxId,
            timestamp: serverTimestamp(),
            is_po: true,
            sn: "Menunggu Antrean (Injeksi Admin)",
            log_api: 'Dibuat manual oleh Admin (Injeksi)'
        };
        await setDoc(doc(db, "users", uid, "riwayat_transaksi", trxId), userTrxPayload);
        
        alert("Berhasil! PO diinjeksi ke riwayat pengguna.");
        document.getElementById('modalInjeksiPO').style.display = 'none';
            } catch(e) {
        console.error("Injeksi Error:", e);
        alert("Gagal Injeksi: " + e.message + "\nSilakan cek log Console (F12) untuk detail.");
            } finally {
        btn.innerHTML = ori; 
        btn.disabled = false;
            }
        };
        
        window.hapusPOTanpaRefund = async (docId, encodedData) => {
            const data = JSON.parse(decodeURIComponent(encodedData));
            const alasan = prompt("Hapus PO ini TANPA mengembalikan saldo user?\nAlasan pembatalan:");
            if (alasan === null) return;
            
            window.showNotice('loading', 'Menghapus', 'Menghapus antrean (Tanpa Refund)...');
            try {
        await updateDoc(doc(db, data.path), { status: "GAGAL", sn: "Dibatalkan Admin: " + alasan + " (Tanpa Refund)", is_po: false });
        window.showNotice('success', 'Berhasil', 'Status riwayat digagalkan tanpa refund saldo.');
            } catch(e) { 
        window.showNotice('error', 'Gagal', e.message); 
            }
        };
        
        window.fixStuckPO = async () => {
            alert("Fitur ini sudah tidak diperlukan karena antrean ditarik langsung dari riwayat live user.");
        };
        
        window.runPoMasal = async () => {
            const pending = window.allPoData.filter(d => !/batal|gagal|berhasil|sukses/i.test(d.status || ''));
            if(pending.length === 0) return alert("Tidak ada antrean yang perlu di-run.");
            if(!confirm(`Jalankan ${pending.length} antrean secara otomatis dengan jeda 3.5 detik?`)) return;
            
            const statusEl = document.getElementById('runMasalStatus');
            for(let i=0; i < pending.length; i++) {
        const item = pending[i];
        const safeData = encodeURIComponent(JSON.stringify(item));
        await window.runPreOrder(item.docId, safeData, true);
        if(statusEl) statusEl.innerText = `${i+1}/${pending.length} run berhasil`;
        if(i < pending.length - 1) await new Promise(r => setTimeout(r, 3500));
            }
            window.loadPoAkrab();
        };
        window.loadPoAkrab = async () => {
            if(document.getElementById('runMasalStatus')) document.getElementById('runMasalStatus').innerText = '';
            const tbody = document.getElementById('listPoAkrab');
            if(tbody) tbody.innerHTML = "<tr><td colspan='5' style='text-align:center'>Mengambil Antrean dari Riwayat User...</td></tr>";
            
            try {
        const q = query(collectionGroup(db, "riwayat_transaksi"), where("is_po", "==", true));
        onSnapshot(q, (snap) => {
            window.allPoData = [];
            snap.forEach(d => {
                let item = d.data();
                item.docId = d.id;
                item.path = d.ref.path;
                item.uid = d.ref.path.split('/')[1];
                item.provider = item.provider || 'KHFY';
                if(item.status === 'PENDING' && item.sn && item.sn.includes('Masuk Antrian')) {
                    item.status = 'STANDBY (Menunggu Admin)';
                }
                window.allPoData.push(item);
                if (/checking/i.test(item.status) || /auto check/i.test(item.status)) {
                    window.startAutoCheckPO(item.path, item.uid, item.trx_id, item.provider, item.kode_produk, item.tujuan);
                }
            });
            
            window.allPoData.sort((a, b) => {
                let timeA = a.timestamp ? (a.timestamp.seconds || (typeof a.timestamp === 'number' ? a.timestamp / 1000 : 0)) : 0;
                let timeB = b.timestamp ? (b.timestamp.seconds || (typeof b.timestamp === 'number' ? b.timestamp / 1000 : 0)) : 0;
                return timeB - timeA;
            });
            
            window.renderPoAkrabPage();
        }, (error) => {
            let errMsg = error.message;
            if(errMsg.includes('index')) errMsg = "Butuh Index baru di Firestore. Buka Console (F12) dan klik URL Index yang berwarna merah.";
            if(tbody) tbody.innerHTML = `<tr><td colspan='5' style='text-align:center; color:red;'>Error Snapshot: ${errMsg}</td></tr>`;
        });
            } catch(e) {
        if(tbody) tbody.innerHTML = `<tr><td colspan='5' style='text-align:center; color:red;'>Gagal memuat antrean: ${e.message}</td></tr>`;
            }
        };
        
        window.setPoFilter = (filter, btn) => {
            window.currentPoFilter = filter;
            document.querySelectorAll('#view-po-akrab .filter-btn').forEach(b => {
        b.classList.remove('active');
        b.style.background = '#f1f5f9';
        b.style.color = '#64748b';
            });
            if(btn) {
        btn.classList.add('active');
        btn.style.background = '#e1effe';
        btn.style.color = '#2563eb';
            }
            window.renderPoAkrabPage();
        };
        
        window.renderPoAkrabPage = () => {
            const tbody = document.getElementById('listPoAkrab');
            if (!tbody) return;
        
            let dataToRender = window.allPoData;
            if(window.currentPoFilter === 'DIBATALKAN') {
        dataToRender = dataToRender.filter(d => /batal|gagal/i.test(d.status || ''));
            } else if(window.currentPoFilter === 'SUKSES') {
        dataToRender = dataToRender.filter(d => /berhasil|sukses/i.test(d.status || ''));
            } else {
        // ANTREAN (Default)
        dataToRender = dataToRender.filter(d => !/batal|gagal|berhasil|sukses/i.test(d.status || ''));
            }
        
            if (dataToRender.length === 0) {
        tbody.innerHTML = `<tr><td colspan='5' style='text-align:center; color:#999; padding:20px;'>Tidak ada antrean (${window.currentPoFilter})</td></tr>`;
        return;
            }
        
            let html = "";
            dataToRender.forEach(data => {
        let date = '-';
        if (data.timestamp) {
            if (data.timestamp.toDate) {
                date = data.timestamp.toDate().toLocaleString('id-ID');
            } else if (data.timestamp.seconds) {
                date = new Date(data.timestamp.seconds * 1000).toLocaleString('id-ID');
            } else if (typeof data.timestamp === 'number') {
                date = new Date(data.timestamp).toLocaleString('id-ID');
            }
        }
        const safeData = encodeURIComponent(JSON.stringify(data));
        
        // LOGIKA PENCARIAN USERNAME DARI CACHE
        let displayUsername = "User (UID: " + data.uid.substring(0,6) + ")";
        if (typeof cacheUsers !== 'undefined') {
            let foundUser = cacheUsers.find(u => u.id === data.uid);
            if (foundUser) {
                displayUsername = foundUser.username || foundUser.nama || displayUsername;
            }
        }
        
                const isChecking = /checking/i.test(data.status);
        const isCanceled = /batal|gagal/i.test(data.status);
        const isSuccess = /berhasil|sukses/i.test(data.status);
        const isLocked = isCanceled || isSuccess;
        
        let btnAksi = `<div style="display:flex; gap:5px; margin-bottom:5px; flex-direction:column; align-items:flex-end;">
            <button onclick="window.runPreOrder('${data.docId}', '${safeData}')" 
                style="background:${isLocked ? '#94a3b8' : (isChecking ? '#ef4444' : '#10b981')}; color:white; padding:8px; border:none; border-radius:5px; cursor:${isLocked ? 'not-allowed' : 'pointer'}; font-size:11px; font-weight:bold; width:100%; max-width:180px;"
                ${isLocked || isChecking ? 'disabled' : ''}>
                <i class="fas ${isCanceled ? 'fa-times-circle' : (isSuccess ? 'fa-check-circle' : (isChecking ? 'fa-sync fa-spin' : 'fa-play'))}"></i> ${isCanceled ? 'CANCELED' : (isSuccess ? 'SUCCESS' : (isChecking ? 'CHECKING...' : 'RUN (Eksekusi API)'))}
            </button>
            <button onclick="window.selesaiPreOrder('${data.docId}', '${safeData}')" 
                style="background:${isLocked ? '#94a3b8' : '#3b82f6'}; color:white; padding:8px; border:none; border-radius:5px; cursor:${isLocked ? 'not-allowed' : 'pointer'}; font-size:11px; font-weight:bold; width:100%; max-width:180px;"
                ${isLocked ? 'disabled' : ''}>
                <i class="fas fa-check-double"></i> Selesai (Sukses)
            </button>
            <button onclick="window.batalkanPOFirebase('${data.docId}', '${safeData}')" 
                style="background:${isLocked ? '#94a3b8' : '#ef4444'}; color:white; padding:6px; border:none; border-radius:5px; cursor:${isLocked ? 'not-allowed' : 'pointer'}; font-size:11px; width:100%; max-width:180px;"
                ${isLocked ? 'disabled' : ''}>
                <i class="fas fa-undo-alt"></i> Batalkan & Refund
            </button>
            <button onclick="window.hapusPOTanpaRefund('${data.docId}', '${safeData}')" 
                style="background:${isLocked ? '#94a3b8' : '#e67e22'}; color:white; padding:6px; border:none; border-radius:5px; cursor:${isLocked ? 'not-allowed' : 'pointer'}; font-size:11px; width:100%; max-width:180px;"
                ${isLocked ? 'disabled' : ''}>
                <i class="fas fa-ban"></i> Hapus (Tanpa Refund)
            </button>
        </div>`;
        
        let logHtml = data.log_api ? `<div style="margin-top:5px; padding:5px; background:#1e1e1e; color:#00ff00; font-family:monospace; font-size:9px; border-radius:5px; max-height:350px; overflow-y:auto; word-break:break-all; text-align:left; width:100%; white-space:pre-wrap; border:1px solid #444;">${data.log_api}</div>` : '';
        
        html += `<tr>
            <td data-label="Waktu & Status"><div style="text-align:right"><small>${date}</small><br><span class="status-badge" style="background:${isCanceled ? '#ef4444' : (isSuccess ? '#10b981' : '#f59e0b')}; margin-top:4px; display:inline-block;">${isCanceled ? '<i class="fas fa-times-circle"></i> ' : (isSuccess ? '<i class="fas fa-check-circle"></i> ' : '')}${data.status}</span></div></td>
            <td data-label="User Info"><div style="text-align:right"><b style="font-size:13px; color:#2563eb;"><i class="fas fa-user-circle"></i> ${displayUsername}</b><br><small style="color:#888; font-size:9px;">UID: ${data.uid.substring(0,8)}</small></div></td>
            <td data-label="Produk & Tujuan"><div style="text-align:right"><b style="color:var(--primary)">${data.kode_produk}</b><br><b style="font-size:14px; color:#d35400;">${data.tujuan}</b><br><b>Rp ${new Intl.NumberFormat('id-ID').format(data.harga)}</b></div></td>
            <td data-label="Provider"><div style="text-align:right"><span class="status-badge" style="background:#6c5ce7; cursor:pointer;" onclick="window.gantiProviderPO('${data.path}', '${data.provider}')" title="Klik untuk ganti Provider (KHFY/ICS)">${data.provider} <i class="fas fa-exchange-alt" style="font-size:8px; margin-left:3px;"></i></span></div></td>
            <td data-label="Aksi"><div style="display:flex; flex-direction:column; align-items:flex-end;">${btnAksi}${logHtml}</div></td>
        </tr>`;
            });
            tbody.innerHTML = html;
        };
        
        window.batalkanPOFirebase = async (docId, encodedData) => {
            const data = JSON.parse(decodeURIComponent(encodedData));
            const alasan = prompt("Batalkan antrean PO ini dan kembalikan saldo user?\nAlasan:");
            if (alasan === null) return;
            
            window.showNotice('loading', 'Refund', 'Membatalkan & refund...');
            try {
        await updateDoc(doc(db, data.path), { status: "GAGAL", sn: "Dibatalkan Admin: " + alasan, is_po: false });
        
        const uref = doc(db, "users", data.uid); 
        const usnap = await getDoc(uref);
        if(usnap.exists()){
            const ns = (usnap.data().saldo || 0) + data.harga; 
            await updateDoc(uref, { saldo: ns });
            fetch('doniguard.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ uid: data.uid, action: 'topup', produk: 'REFUND PO: '+data.kode_produk, nominal: data.harga, saldo_akhir_client: ns }) }); 
        }
        
        window.showNotice('success', 'Berhasil', 'Antrean dihapus dan saldo di-refund.');
            } catch(e) { 
        window.showNotice('error', 'Gagal', e.message); 
            }
        };
        
        window.runPreOrder = async (docId, encodedData, isSilent = false) => {
            const data = JSON.parse(decodeURIComponent(encodedData));
            if(data.status === "DIBATALKAN USER") {
        if(!isSilent) alert("Gagal! Pesanan ini telah dibatalkan oleh pengguna.");
        return;
            }
            if(!isSilent && !confirm(`Jalankan pesanan ini sekarang?\n\nProduk: ${data.kode_produk}\nTujuan: ${data.tujuan}\nProvider: ${data.provider}`)) return;
        
            if(!isSilent) window.showNotice('loading', 'Mengeksekusi', 'Menembak API Provider...');
            
            try {
        let apiUrl = '';
        let reqOptions = {};
        const prov = (data.provider || '').toUpperCase();
        
        // Pengecekan KETAT Provider
        if (prov === 'ICS' || prov.includes('ICS')) {
            apiUrl = `ics_proxy.php?action=trx`;
            var payload = { code: data.kode_produk, dest: data.tujuan, refid: data.trx_id };
            reqOptions = { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) };
        } else if (prov === 'KHFY' || prov.includes('KHFY')) {
            apiUrl = `khfy_proxyv2.php?action=trx&produk=${data.kode_produk}&tujuan=${data.tujuan}&reff_id=${data.trx_id}`;
            reqOptions = { method: 'GET' };
        } else if (prov === 'KAJE' || prov.includes('KAJE')) {
            apiUrl = `kaje_proxy.php?api_action=order_product`;
            var payload = { product: data.kode_produk, target: data.tujuan, refid: data.trx_id };
            reqOptions = { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) };
        } else {
            // Deteksi Otomatis Berdasarkan Awalan TRX (Fallback)
            if (data.trx_id && data.trx_id.startsWith('IS-')) {
                apiUrl = `ics_proxy.php?action=trx`;
                var payload = { code: data.kode_produk, dest: data.tujuan, refid: data.trx_id };
                reqOptions = { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) };
            } else if (data.trx_id && data.trx_id.startsWith('KF-')) {
                apiUrl = `khfy_proxyv2.php?action=trx&produk=${data.kode_produk}&tujuan=${data.tujuan}&reff_id=${data.trx_id}`;
                reqOptions = { method: 'GET' };
            } else if (data.trx_id && (data.trx_id.startsWith('KJ-') || data.trx_id.startsWith('KAJE-'))) {
                apiUrl = `kaje_proxy.php?api_action=order_product`;
                var payload = { product: data.kode_produk, target: data.tujuan, refid: data.trx_id };
                reqOptions = { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) };
            } else {
                throw new Error("Provider tidak valid! Pastikan provider adalah KHFY, ICS, atau KAJE agar tidak tertukar.");
            }
        }
        
        const req = await fetch(apiUrl, reqOptions);
        const res = await req.json();
        const resString = JSON.stringify(res, null, 2);
        const isPending = /pending/i.test(resString);
        
        // --- FIX: AMBIL ID ASLI DARI RESPON PROXY (Penting agar Cek Status Berhasil) ---
        let actualTrxId = data.trx_id;
        if(res.data && res.data.trx_id) actualTrxId = res.data.trx_id;
        else if(res.data && res.data.refid) actualTrxId = res.data.refid;
        else if(res.data && res.data.ref_id_custom) actualTrxId = res.data.ref_id_custom;
        else if(res.refid) actualTrxId = res.refid;
        
        let isSuccess = false;
        if (res.success === true || res.status === true || res.code === "000") {
            isSuccess = true;
        } else {
            const safeResString = resString.replace(/"success"\s*:\s*false/gi, "");
            isSuccess = /sukses|berhasil|"status"\s*:\s*"success"/i.test(safeResString);
        }
        
        let finalStatus = 'PENDING';
        let finalSn = 'Masih dalam antrean Pre-Order';
        let startAutoCheck = false;
        
        if (isSuccess && !isPending) {
            finalStatus = 'BERHASIL';
            finalSn = 'Selesai Otomatis via API';
        } else {
            finalStatus = 'PENDING';
            finalSn = 'Masih dalam antrean Pre-Order';
            startAutoCheck = isPending;
        }
        
        await updateDoc(doc(db, data.path), {
            log_api: resString,
            status: finalStatus,
            trx_id: actualTrxId,
            sn: finalSn
        });
        
        if (startAutoCheck) {
            window.startAutoCheckPO(data.path, data.uid, actualTrxId, data.provider, data.kode_produk, data.tujuan);
        }
        
        if(!isSilent) {
            document.getElementById('adminNoticeModal').style.display='none';
            if(isPending) alert("⚠️ Pending! Sistem memantau ID: " + actualTrxId);
            else alert("✅ Berhasil! Provider: " + prov);
        }
        
            } catch(e) {
        window.showNotice('error', 'Gagal Run', e.message);
            }
        };
        
        window.selesaiPreOrder = async (docId, encodedData) => {
            const data = JSON.parse(decodeURIComponent(encodedData));
            if(!confirm(`Tandai pesanan ini SELESAI (SUKSES)?\nIni akan mengubah status di user menjadi BERHASIL.`)) return;
        
            window.showNotice('loading', 'Menyelesaikan', 'Mengubah status transaksi...');
            try {
        await updateDoc(doc(db, data.path), { status: "BERHASIL", sn: "Selesai via PO Admin", is_po: false });
        window.showNotice('success', 'Berhasil', 'Pesanan selesai dan status user telah diperbarui.');
            } catch(e) {
        window.showNotice('error', 'Gagal', e.message);
            }
        };
        
        // --- CRUD BANK MANUAL ---
        window.loadBankManual = () => {
            const tbody = document.getElementById('listBankManual');
            if(!tbody) return;
            tbody.innerHTML = "<tr><td colspan='6' style='text-align:center'>Memuat data...</td></tr>";
            onSnapshot(collection(db, "metode_topup"), (snap) => {
                let html = "";
                snap.forEach(d => {
                    const data = d.data();
                    html += `<tr>
                        <td data-label="Logo"><img src="${data.logo || 'icons/bank.png'}" style="height:30px; object-fit:contain; border-radius:4px; background:#fff; padding:2px; border:1px solid #eee;"></td>
                        <td data-label="Nama Bank"><b>${data.nama_bank}</b></td>
                        <td data-label="No. Rekening">${data.no_rek}</td>
                        <td data-label="Atas Nama">${data.atas_nama}</td>
                        <td data-label="Fee (Rp)">Rp ${data.fee || 0}</td>
                        <td data-label="Aksi">
                            <button onclick="window.editBank('${d.id}', '${data.nama_bank}', '${data.no_rek}', '${data.atas_nama}', ${data.fee || 0}, '${data.logo}')" style="background:#f59e0b; color:white; border:none; padding:5px 10px; border-radius:5px; font-size:10px; cursor:pointer;"><i class="fas fa-edit"></i></button>
                            <button onclick="window.hapusBank('${d.id}', '${data.nama_bank}')" style="background:#ef4444; color:white; border:none; padding:5px 10px; border-radius:5px; font-size:10px; cursor:pointer; margin-left:5px;"><i class="fas fa-trash"></i></button>
                        </td>
                    </tr>`;
                });
                tbody.innerHTML = html || "<tr><td colspan='6' style='text-align:center'>Belum ada metode bank</td></tr>";
            });
        };
        
        window.uploadLogoBank = async (e) => {
            const fileInput = document.getElementById('fileLogoBank');
            const output = document.getElementById('bankLogo');
            if(fileInput.files.length === 0) return alert("Pilih gambar logo bank terlebih dahulu!");
            
            const btn = e.currentTarget;
            const oriHtml = btn.innerHTML;
            btn.innerHTML = '<i class="fas fa-spinner fa-spin"></i>';
            btn.disabled = true;
        
            const formData = new FormData();
            formData.append('file_icon[]', fileInput.files[0]);
        
            try {
                const req = await fetch('upload_handler.php', { method: 'POST', body: formData });
                const res = await req.json();
                if(res.status === 'success' && res.files && res.files.length > 0) {
                    output.value = 'icons/' + res.files[0];
                    alert("Logo berhasil diupload dan tersimpan di hosting!");
                } else { 
                    alert("Gagal: " + (res.message || 'Server error saat upload')); 
                }
            } catch(error) { 
                alert("Error koneksi upload: " + error.message); 
            } finally { 
                btn.innerHTML = oriHtml; 
                btn.disabled = false; 
            }
        };
        
        
        window.bukaModalBank = () => {
            document.getElementById('titleModalBank').innerText = "Tambah Bank Manual";
            document.getElementById('bankId').value = "";
            document.getElementById('bankNama').value = "";
            document.getElementById('bankRek').value = "";
            document.getElementById('bankAN').value = "";
            document.getElementById('bankFee').value = "0";
            document.getElementById('bankLogo').value = "";
            document.getElementById('modalBankManual').style.display = "flex";
        };
        
        window.editBank = (id, nama, rek, an, fee, logo) => {
            document.getElementById('titleModalBank').innerText = "Edit Bank Manual";
            document.getElementById('bankId').value = id;
            document.getElementById('bankNama').value = nama;
            document.getElementById('bankRek').value = rek;
            document.getElementById('bankAN').value = an;
            document.getElementById('bankFee').value = fee;
            document.getElementById('bankLogo').value = logo || '';
            document.getElementById('modalBankManual').style.display = "flex";
        };
        
        window.simpanBankManual = async () => {
            const id = document.getElementById('bankId').value;
            const btn = document.querySelector('#modalBankManual .btn-save');
            btn.innerHTML = 'Menyimpan...'; btn.disabled = true;
            const data = {
                nama_bank: document.getElementById('bankNama').value,
                no_rek: document.getElementById('bankRek').value,
                atas_nama: document.getElementById('bankAN').value,
                fee: parseInt(document.getElementById('bankFee').value) || 0,
                logo: document.getElementById('bankLogo').value
            };
            
            try {
                if(!data.nama_bank || !data.no_rek) throw new Error("Nama Bank dan Rekening wajib diisi");
                if(id) await updateDoc(doc(db, "metode_topup", id), data);
                else await addDoc(collection(db, "metode_topup"), data);
                document.getElementById('modalBankManual').style.display = "none";
                alert("Data bank berhasil disimpan!");
            } catch(e) { alert("Error: " + e.message); } finally { btn.innerHTML = 'Simpan Bank'; btn.disabled = false; }
        };
        
        window.hapusBank = async (id, nama) => {
            if(confirm("Yakin ingin menghapus bank " + nama + "?")) {
                try { await deleteDoc(doc(db, "metode_topup", id)); } 
                catch(e) { alert("Error: " + e.message); }
            }
        };
        
        
        // --- SYSTEM AUDIT DONIGUARD ADVANCED CHAIN ---
        window.dgFormatRupiah = (num) => new Intl.NumberFormat('id-ID').format(parseInt(num || 0));
        window.dgSafeText = (val) => String(val ?? '').replace(/[&<>"']/g, (m) => ({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#039;'}[m]));
        window.dgNumber = (val) => {
            const n = parseInt(val || 0);
            return Number.isFinite(n) ? n : 0;
        };
        window.dgIsRefundLog = (log) => {
            const produk = String(log.produk || '').toUpperCase();
            const trx = String(log.trx_id || '').toUpperCase();
            return !!log.is_refund || produk.includes('REFUND') || produk.includes('REFOUND') || /(\-REFUND|\_REFUND|\-REF|\_REF)$/.test(trx) || /^(REFUND|REF)\-/.test(trx);
        };
        window.dgIsResetLog = (log) => {
            const produk = String(log.produk || '').toUpperCase();
            const type = String(log.type || '').toUpperCase();
            return type === 'RESET_BALANCE' || produk.includes('INITIAL_PUSH_ADMIN') || produk.includes('RESET') || produk.includes('SALDO AWAL');
        };
        window.dgLogDirection = (log) => {
            const type = String(log.type || '').toUpperCase();
            if (dgIsResetLog(log)) return 'RESET';
            if (dgIsRefundLog(log)) return 'MASUK';
            if (type === 'TOPUP' || type === 'PUSH_ADMIN') return 'MASUK';
            if (type === 'CORRECTION') return dgNumber(log.saldo_akhir) >= dgNumber(log.saldo_awal) ? 'MASUK' : 'KELUAR';
            return 'KELUAR';
        };
        window.dgAnalyzeLogs = (lines, firebaseSaldo = null) => {
            const logs = [];
            let parseError = 0;
        
            lines.forEach((line, idx) => {
                if (!String(line || '').trim()) return;
                try {
                    const log = JSON.parse(line);
                    log.__line = idx + 1;
                    log.__rawIndex = idx;
                    logs.push(log);
                } catch(e) {
                    parseError++;
                }
            });
        
            logs.sort((a, b) => {
                const ta = new Date(a.waktu || 0).getTime() || a.__rawIndex;
                const tb = new Date(b.waktu || 0).getTime() || b.__rawIndex;
                return ta - tb;
            });
        
            let lastResetIndex = -1;
            logs.forEach((log, idx) => {
                if (dgIsResetLog(log)) lastResetIndex = idx;
            });
        
            const auditLogs = lastResetIndex >= 0 ? logs.slice(lastResetIndex) : logs;
            const auditStartLog = lastResetIndex >= 0 ? logs[lastResetIndex] : null;
            const issues = [];
            const duplicateRefundMap = {};
        
            let saldoAwalPatokan = 0;
            let totalTopupSaldo = 0;
            let totalSaldoDigunakan = 0;
            let totalRefund = 0;
            let totalMasuk = 0;
            let expectedBalance = null;
            let lastSaldoAkhir = null;
        
            auditLogs.forEach((log) => {
                const saldoAwal = dgNumber(log.saldo_awal);
                const nominal = dgNumber(log.nominal);
                const saldoAkhir = dgNumber(log.saldo_akhir);
                const direction = dgLogDirection(log);
                const produk = String(log.produk || '-');
                const trxId = String(log.trx_id || '-');
                const isReset = dgIsResetLog(log);
                const isRefund = dgIsRefundLog(log);
        
                if (isReset) {
                    saldoAwalPatokan = saldoAkhir;
                    expectedBalance = saldoAkhir;
                    lastSaldoAkhir = saldoAkhir;
                    return;
                }
        
                if (expectedBalance !== null && saldoAwal !== expectedBalance) {
                    issues.push({
                        level: 'danger',
                        line: log.__line,
                        waktu: log.waktu || '-',
                        title: 'Rantai saldo putus',
                        detail: `Saldo awal log ini Rp ${dgFormatRupiah(saldoAwal)}, seharusnya mengikuti saldo akhir sebelumnya Rp ${dgFormatRupiah(expectedBalance)}.`,
                        produk,
                        trxId
                    });
                }
        
                const expectedAfter = direction === 'MASUK' ? saldoAwal + nominal : saldoAwal - nominal;
                if (saldoAkhir !== expectedAfter) {
                    issues.push({
                        level: 'danger',
                        line: log.__line,
                        waktu: log.waktu || '-',
                        title: 'Hitungan saldo tidak cocok',
                        detail: `${direction === 'MASUK' ? 'Saldo masuk/topup/refund' : 'Saldo terpakai'} Rp ${dgFormatRupiah(nominal)} dari saldo awal Rp ${dgFormatRupiah(saldoAwal)} harusnya menjadi Rp ${dgFormatRupiah(expectedAfter)}, tetapi log mencatat Rp ${dgFormatRupiah(saldoAkhir)}.`,
                        produk,
                        trxId
                    });
                }
        
                if (isRefund) {
                    totalRefund += nominal;
                    totalMasuk += nominal;
                    const base = String(log.refund_base_id || trxId).replace(/^(REFUND|REF)\-?/i, '').replace(/(\-REFUND|\_REFUND|\-REF|\_REF)$/i, '');
                    if (duplicateRefundMap[base]) {
                        issues.push({
                            level: 'danger',
                            line: log.__line,
                            waktu: log.waktu || '-',
                            title: 'Refund ganda terdeteksi',
                            detail: `Refund untuk transaksi asal ${dgSafeText(base)} muncul lebih dari satu kali. Cek baris ${duplicateRefundMap[base]} dan baris ${log.__line}.`,
                            produk,
                            trxId
                        });
                    } else {
                        duplicateRefundMap[base] = log.__line;
                    }
                } else if (direction === 'MASUK') {
                    totalTopupSaldo += nominal;
                    totalMasuk += nominal;
                }
        
                if (direction === 'KELUAR') totalSaldoDigunakan += nominal;
        
                expectedBalance = saldoAkhir;
                lastSaldoAkhir = saldoAkhir;
            });
        
            const saldoSekarang = firebaseSaldo !== null ? dgNumber(firebaseSaldo) : dgNumber(lastSaldoAkhir);
            const totalPembandingMasuk = saldoAwalPatokan + totalTopupSaldo + totalRefund;
            const totalTerpakaiPlusSisa = totalSaldoDigunakan + saldoSekarang;
            const saldoSeharusnya = totalPembandingMasuk - totalSaldoDigunakan;
            const selisihPembanding = totalPembandingMasuk - totalTerpakaiPlusSisa;
        
            if (firebaseSaldo !== null && lastSaldoAkhir !== null && dgNumber(firebaseSaldo) !== dgNumber(lastSaldoAkhir)) {
                issues.push({
                    level: 'warning',
                    line: '-',
                    title: 'Saldo Firebase beda dengan saldo DoniGuard',
                    detail: `Saldo user di Firebase Rp ${dgFormatRupiah(firebaseSaldo)}, sedangkan saldo akhir DoniGuard Rp ${dgFormatRupiah(lastSaldoAkhir)}. Perlu cek apakah ada transaksi yang belum masuk buku besar setelah ${auditStartLog ? 'INITIAL_PUSH_ADMIN/RESET terakhir' : 'awal log'}.`
                });
            }
        
            if (Math.abs(selisihPembanding) > 0) {
                issues.push({
                    level: 'warning',
                    line: '-',
                    title: 'Pembanding saldo tidak seimbang',
                    detail: `Saldo awal resmi Rp ${dgFormatRupiah(saldoAwalPatokan)} + topup/transfer Rp ${dgFormatRupiah(totalTopupSaldo)} + refund Rp ${dgFormatRupiah(totalRefund)} - saldo digunakan Rp ${dgFormatRupiah(totalSaldoDigunakan)} harusnya sisa Rp ${dgFormatRupiah(saldoSeharusnya)}, tetapi saldo sekarang Rp ${dgFormatRupiah(saldoSekarang)}. Selisih Rp ${dgFormatRupiah(Math.abs(selisihPembanding))}.`
                });
            }
        
            return {
                logs: auditLogs,
                allLogs: logs,
                auditStartLog,
                auditStartLine: auditStartLog ? auditStartLog.__line : 1,
                parseError,
                issues,
                totalMasuk,
                totalKeluar: totalSaldoDigunakan,
                totalSaldoDigunakan,
                saldoAwalPatokan,
                totalTopupSaldo,
                totalRefund,
                saldoSekarang,
                totalPembandingMasuk,
                totalTerpakaiPlusSisa,
                saldoSeharusnya,
                selisihPembanding,
                saldoAkhirDoniGuard: lastSaldoAkhir,
                logCount: auditLogs.length,
                ignoredBeforeReset: lastResetIndex > 0 ? lastResetIndex : 0,
                aman: issues.length === 0
            };
        };
        
        window.renderAuditUserList = (keyword = '') => {
            const container = document.getElementById('containerUserAudit');
            if (!container) return;
            const lower = String(keyword || '').toLowerCase();
            let users = (typeof cacheUsers !== 'undefined') ? cacheUsers : [];
        
            if(keyword) {
                users = users.filter(u =>
                    (u.username && u.username.toLowerCase().includes(lower)) ||
                    (u.nama && u.nama.toLowerCase().includes(lower)) ||
                    (u.email && u.email.toLowerCase().includes(lower))
                );
            }
        
            if(users.length === 0) {
                container.innerHTML = '<div style="text-align:center; color:#999; padding:20px; grid-column:1/-1;">User tidak ditemukan</div>';
                return;
            }
        
            container.innerHTML = users.map(u => `
                <div onclick="openDoniGuardDetailSheet('${dgSafeText(u.id)}','${dgSafeText(u.username || u.email || 'User')}')"
                     style="background:white; padding:10px; border-radius:8px; border:1px solid #ddd; cursor:pointer; transition:0.2s; display:flex; align-items:center; gap:10px; box-shadow:0 1px 3px rgba(0,0,0,0.05);"
                     onmouseover="this.style.borderColor='#2563eb'; this.style.background='#f0f7ff'"
                     onmouseout="this.style.borderColor='#ddd'; this.style.background='white'">
                    <div style="width:35px; height:35px; background:#e1effe; border-radius:50%; display:flex; align-items:center; justify-content:center; color:#2563eb; font-size:14px;">
                        <i class="fas fa-user"></i>
                    </div>
                    <div style="flex:1; overflow:hidden;">
                        <div style="font-weight:bold; font-size:12px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis;">${dgSafeText(u.username || 'User')}</div>
                        <div style="font-size:10px; color:#777;">Saldo: Rp ${dgFormatRupiah(u.saldo||0)}</div>
                    </div>
                    <i class="fas fa-chevron-right" style="font-size:10px; color:#ccc;"></i>
                </div>`).join('');
        };
        
        window.closeDoniGuardDetailSheet = (event) => {
            if (event && event.target && event.target.id !== 'dgDetailSheetOverlay') return;
            const overlay = document.getElementById('dgDetailSheetOverlay');
            const box = document.getElementById('dgDetailSheetBox');
            if (!overlay || !box) return;
            box.style.transform = 'translateY(100%)';
            setTimeout(() => {
                overlay.style.display = 'none';
                document.body.style.overflow = '';
            }, 260);
        };
        
        window.openDoniGuardDetailSheet = async (uid, name) => {
            const overlay = document.getElementById('dgDetailSheetOverlay');
            const box = document.getElementById('dgDetailSheetBox');
            const title = document.getElementById('dgDetailSheetTitle');
            const summary = document.getElementById('dgDetailSheetSummary');
            const content = document.getElementById('dgDetailSheetContent');
            if (!overlay || !box || !content) return loadDoniGuardLog(uid, name);
            overlay.style.display = 'flex';
            document.body.style.overflow = 'hidden';
            title.innerText = name || '-';
            summary.innerText = 'Membaca dan mengurutkan rantai saldo user...';
            content.innerHTML = '<div style="text-align:center; padding:45px; color:#64748b;"><i class="fas fa-microchip fa-spin" style="font-size:30px; margin-bottom:15px;"></i><br>Membuka detail DoniGuard...</div>';
            setTimeout(() => { box.style.transform = 'translateY(0)'; }, 20);
            await loadDoniGuardLog(uid, name, true);
        };
        
        window.dgRenderIssueBox = (issues) => {
            if (!issues || issues.length === 0) {
                return `<div style="background:#ecfdf5; border:1px solid #bbf7d0; color:#166534; border-radius:10px; padding:12px; margin-bottom:12px; font-size:12px;">
                    <b><i class="fas fa-check-circle"></i> Rantai saldo aman.</b><br>Tidak ditemukan saldo loncat, hitungan salah, atau refund ganda.
                </div>`;
            }
            return `<div style="background:#fef2f2; border:1px solid #fecaca; color:#991b1b; border-radius:10px; padding:12px; margin-bottom:12px; font-size:12px;">
                <b><i class="fas fa-triangle-exclamation"></i> Ditemukan ${issues.length} masalah rantai saldo.</b>
                <div style="margin-top:8px; display:grid; gap:6px;">
                    ${issues.map(x => `
                        <div style="background:white; border-left:4px solid ${x.level === 'warning' ? '#f59e0b' : '#ef4444'}; padding:8px; border-radius:6px;">
                            <b>Baris ${dgSafeText(x.line)} - ${dgSafeText(x.title)}</b><br>
                            <span>${x.detail}</span>
                            ${x.trxId ? `<br><small>TRX: ${dgSafeText(x.trxId)} | Produk: ${dgSafeText(x.produk || '-')} | Waktu: ${dgSafeText(x.waktu || '-')}</small>` : ''}
                        </div>
                    `).join('')}
                </div>
            </div>`;
        };
        
        window.loadDoniGuardLog = async (uid, name, useSheet = false) => {
            const container = useSheet ? document.getElementById('dgDetailSheetContent') : document.getElementById('auditLogContainer');
            const summary = useSheet ? document.getElementById('dgDetailSheetSummary') : document.getElementById('auditTargetSummary');
            if (!container) return;
        
            container.innerHTML = '<div id="' + (useSheet ? 'dgSheetLogListContainer' : 'logListContainer') + '" style="padding:10px; background:#f4f7f6; min-height:200px;"></div>';
            const listArea = useSheet ? document.getElementById('dgSheetLogListContainer') : document.getElementById('logListContainer');
        
            if (!useSheet) {
                const target = document.getElementById('auditTargetName');
                if (target) target.innerText = name;
            } else {
                const sheetTitle = document.getElementById('dgDetailSheetTitle');
                if (sheetTitle) sheetTitle.innerText = name;
            }
        
            listArea.innerHTML = '<div style="text-align:center; padding:40px; color:#666;"><i class="fas fa-microchip fa-spin" style="font-size:30px; margin-bottom:15px;"></i><br>DoniGuard sedang menganalisis rantai saldo...</div>';
        
            try {
                const userData = (typeof cacheUsers !== 'undefined' ? cacheUsers : []).find(u => u.id === uid) || {};
                const response = await fetch(`user/uid${uid}.txt?t=${new Date().getTime()}`);
        
                if (!response.ok) {
                    listArea.innerHTML = '<div style="text-align:center; padding:40px; color:#f59e0b;"><i class="fas fa-folder-open" style="font-size:40px;"></i><br><br><b>Belum Ada Data</b><br>User ini belum memiliki buku besar DoniGuard.</div>';
                    if (summary) summary.innerText = '';
                    return;
                }
        
                const textData = await response.text();
                const analysis = dgAnalyzeLogs(textData.split('\n'), userData.saldo ?? null);
                if (summary) {
                    summary.innerText = `Saldo Awal Rp ${dgFormatRupiah(analysis.saldoAwalPatokan)} | Topup/Transfer Rp ${dgFormatRupiah(analysis.totalTopupSaldo)} | Terpakai Rp ${dgFormatRupiah(analysis.totalSaldoDigunakan)} | Refund Rp ${dgFormatRupiah(analysis.totalRefund)} | Saldo Sekarang Rp ${dgFormatRupiah(analysis.saldoSekarang || 0)} | ${analysis.selisihPembanding === 0 ? 'SEIMBANG' : 'SELISIH Rp ' + dgFormatRupiah(Math.abs(analysis.selisihPembanding))}`;
                }
        
                const auditBalanceOk = analysis.saldoSeharusnya === (analysis.saldoSekarang || 0);
                let html = dgRenderIssueBox(analysis.issues);
                html += `
                    <div style="background:#f8fafc; border:1px solid #e2e8f0; border-radius:10px; padding:10px; margin-bottom:12px; font-size:11px; color:#475569;">
                        <b>Patokan audit:</b> ${analysis.auditStartLog ? 'dimulai dari INITIAL_PUSH_ADMIN / RESET baris #' + analysis.auditStartLine + ' tanggal ' + dgSafeText(analysis.auditStartLog.waktu || '-') : 'dimulai dari awal log'}.
                        ${analysis.ignoredBeforeReset ? 'Log sebelum reset yang diabaikan: ' + analysis.ignoredBeforeReset + ' baris.' : ''}
                    </div>
        
                    <div style="background:white; border:1px solid ${auditBalanceOk ? '#bbf7d0' : '#fecaca'}; border-radius:14px; overflow:hidden; margin-bottom:12px; box-shadow:0 4px 14px rgba(15,23,42,.06);">
                        <div style="background:${auditBalanceOk ? '#ecfdf5' : '#fef2f2'}; padding:12px 14px; border-bottom:1px solid ${auditBalanceOk ? '#bbf7d0' : '#fecaca'}; display:flex; justify-content:space-between; align-items:center; gap:10px; flex-wrap:wrap;">
                            <div>
                                <div style="font-size:12px; font-weight:900; color:${auditBalanceOk ? '#166534' : '#991b1b'};"><i class="fas ${auditBalanceOk ? 'fa-check-circle' : 'fa-triangle-exclamation'}"></i> Ringkasan Perhitungan Saldo</div>
                                <div style="font-size:11px; color:#64748b; margin-top:2px;">Rumus mudah: total saldo masuk - saldo digunakan = saldo sekarang.</div>
                            </div>
                            <div style="background:${auditBalanceOk ? '#16a34a' : '#dc2626'}; color:white; padding:7px 10px; border-radius:999px; font-size:11px; font-weight:900;">${auditBalanceOk ? 'SEIMBANG' : 'SELISIH'}</div>
                        </div>
                        <div style="padding:12px; display:grid; gap:8px; font-size:12px;">
                            <div style="display:flex; justify-content:space-between; gap:10px; padding:9px 10px; background:#eef2ff; border-radius:10px;"><span>Saldo awal admin/reset</span><b>Rp ${dgFormatRupiah(analysis.saldoAwalPatokan)}</b></div>
                            <div style="display:flex; justify-content:space-between; gap:10px; padding:9px 10px; background:#ecfdf5; border-radius:10px;"><span>Topup / transfer saldo masuk</span><b>Rp ${dgFormatRupiah(analysis.totalTopupSaldo)}</b></div>
                            <div style="display:flex; justify-content:space-between; gap:10px; padding:9px 10px; background:#f0fdf4; border-radius:10px;"><span>Refund / saldo kembali</span><b>Rp ${dgFormatRupiah(analysis.totalRefund)}</b></div>
                            <div style="display:flex; justify-content:space-between; gap:10px; padding:11px 10px; background:#f8fafc; border:1px solid #cbd5e1; border-radius:10px; font-weight:900;"><span>Total saldo yang pernah masuk</span><b>Rp ${dgFormatRupiah(analysis.totalPembandingMasuk)}</b></div>
                            <div style="display:flex; justify-content:space-between; gap:10px; padding:9px 10px; background:#fff7ed; border-radius:10px;"><span>Dikurangi saldo digunakan</span><b>- Rp ${dgFormatRupiah(analysis.totalSaldoDigunakan)}</b></div>
                            <div style="display:flex; justify-content:space-between; gap:10px; padding:11px 10px; background:#eff6ff; border:1px solid #bfdbfe; border-radius:10px; font-weight:900;"><span>Saldo seharusnya tersisa</span><b>Rp ${dgFormatRupiah(analysis.saldoSeharusnya)}</b></div>
                            <div style="display:flex; justify-content:space-between; gap:10px; padding:11px 10px; background:${auditBalanceOk ? '#ecfdf5' : '#fef2f2'}; border:1px solid ${auditBalanceOk ? '#bbf7d0' : '#fecaca'}; border-radius:10px; font-weight:900; color:${auditBalanceOk ? '#166534' : '#991b1b'};"><span>Saldo user sekarang</span><b>Rp ${dgFormatRupiah(analysis.saldoSekarang || 0)}</b></div>
                        </div>
                    </div>`;
        
                for (let i = analysis.logs.length - 1; i >= 0; i--) {
                    const log = analysis.logs[i];
                    const direction = dgLogDirection(log);
                    const isRefund = dgIsRefundLog(log);
                    const isReset = dgIsResetLog(log);
                    let cardColor = '';
                    let iconMain = '';
                    let title = '';
                    let amountDisplay = '';
                    let narrative = '';
        
                    if (isReset) {
                        cardColor = 'border-left:5px solid #6366f1; background:#f5f3ff;';
                        iconMain = '<div style="background:#6366f1; color:white; width:40px; height:40px; border-radius:50%; display:flex; align-items:center; justify-content:center;"><i class="fas fa-scale-balanced"></i></div>';
                        title = '<span style="color:#4f46e5;">SALDO AWAL ADMIN / RESET</span>';
                        amountDisplay = `<span style="color:#4f46e5; font-weight:bold;">Rp ${dgFormatRupiah(log.saldo_akhir)}</span>`;
                        narrative = `Saldo disahkan ulang oleh sistem/admin. Audit dimulai dari saldo awal resmi <b>Rp ${dgFormatRupiah(log.saldo_akhir)}</b>.`;
                    } else if (direction === 'MASUK') {
                        cardColor = isRefund ? 'border-left:5px solid #10b981; background:#f0fff4;' : 'border-left:5px solid #10b981; background:#ffffff;';
                        iconMain = `<div style="background:#10b981; color:white; width:40px; height:40px; border-radius:50%; display:flex; align-items:center; justify-content:center;"><i class="fas ${isRefund ? 'fa-rotate-left' : 'fa-wallet'}"></i></div>`;
                        title = isRefund ? '<span style="color:#10b981;">REFUND SALDO</span>' : '<span style="color:#10b981;">DEPOSIT / SALDO MASUK</span>';
                        amountDisplay = `<span style="color:#10b981; font-weight:bold;">+ Rp ${dgFormatRupiah(log.nominal)}</span>`;
                        narrative = `${isRefund ? 'Refund/pengembalian saldo' : 'Saldo masuk/topup/transfer'} sebesar Rp ${dgFormatRupiah(log.nominal)}. Rantai: Rp ${dgFormatRupiah(log.saldo_awal)} → <b>Rp ${dgFormatRupiah(log.saldo_akhir)}</b>.`;
                    } else {
                        cardColor = 'border-left:5px solid #f59e0b; background:#ffffff;';
                        iconMain = '<div style="background:#f59e0b; color:white; width:40px; height:40px; border-radius:50%; display:flex; align-items:center; justify-content:center;"><i class="fas fa-shopping-cart"></i></div>';
                        title = '<span style="color:#d35400;">SALDO TERPAKAI</span>';
                        amountDisplay = `<span style="color:#e67e22; font-weight:bold;">- Rp ${dgFormatRupiah(log.nominal)}</span>`;
                        narrative = `Saldo dipakai untuk <b>${dgSafeText(log.produk || '-')}</b> sebesar Rp ${dgFormatRupiah(log.nominal)}. Rantai: Rp ${dgFormatRupiah(log.saldo_awal)} → <b>Rp ${dgFormatRupiah(log.saldo_akhir)}</b>.`;
                    }
        
                    const rowIssues = analysis.issues.filter(x => String(x.line) === String(log.__line));
                    const hasProblem = rowIssues.length > 0;
                    const problemBg = hasProblem ? 'border-left:6px solid #dc2626; background:#fef2f2; box-shadow:0 0 0 1px #fecaca inset, 0 4px 12px rgba(220,38,38,0.12);' : cardColor;
                    const problemBadge = hasProblem ? `<span style="background:#dc2626; color:white; padding:3px 8px; border-radius:99px; font-size:10px; font-weight:800; margin-left:6px;"><i class="fas fa-triangle-exclamation"></i> BERMASALAH</span>` : '';
                    const problemIcon = hasProblem ? '<div style="background:#dc2626; color:white; width:40px; height:40px; border-radius:50%; display:flex; align-items:center; justify-content:center; box-shadow:0 4px 10px rgba(220,38,38,.25);"><i class="fas fa-bug"></i></div>' : iconMain;
                    const issueExplanation = hasProblem ? `
                        <div style="background:#fff; border:1px solid #fecaca; border-left:5px solid #dc2626; padding:10px; border-radius:8px; color:#7f1d1d; font-size:12px; margin-bottom:10px; line-height:1.45;">
                            <div style="font-weight:900; margin-bottom:6px; color:#991b1b;"><i class="fas fa-circle-exclamation"></i> Penjelasan masalah pada log baris #${log.__line}</div>
                            ${rowIssues.map((x, idx) => `
                                <div style="background:#fef2f2; border:1px dashed #fca5a5; border-radius:6px; padding:8px; margin-top:${idx === 0 ? '0' : '6px'};">
                                    <b>${idx + 1}. ${dgSafeText(x.title)}</b><br>
                                    <span>${x.detail}</span><br>
                                    <small style="display:block; margin-top:5px; color:#991b1b;"><b>Artinya:</b> bagian ini tidak mengikuti alur rantai saldo DoniGuard. Cek transaksi, nominal, saldo awal, saldo akhir, dan kemungkinan ada proses saldo yang tidak tercatat / tercatat dobel.</small>
                                </div>
                            `).join('')}
                        </div>` : '';
        
                    html += `
                    <div id="dg-log-line-${log.__line}" style="${problemBg} padding:15px; border-radius:8px; margin-bottom:10px; display:flex; gap:15px; align-items:start;">
                        ${problemIcon}
                        <div style="flex:1;">
                            <div style="display:flex; justify-content:space-between; margin-bottom:5px; gap:10px; flex-wrap:wrap;">
                                <div style="font-weight:800; font-size:13px;">${title} <small style="color:#94a3b8;">#${log.__line}</small> ${problemBadge}</div>
                                <div style="font-size:11px; color:${hasProblem ? '#991b1b' : '#999'};"><i class="far fa-clock"></i> ${dgSafeText(log.waktu || '-')}</div>
                            </div>
                            <div style="display:flex; justify-content:space-between; align-items:center; border-bottom:1px dashed ${hasProblem ? '#fca5a5' : '#eee'}; padding-bottom:8px; margin-bottom:8px; gap:10px;">
                                <div style="font-size:12px; color:${hasProblem ? '#7f1d1d' : '#555'};">Item: <b>${dgSafeText(log.produk || '-')}</b><br><small>TRX: ${dgSafeText(log.trx_id || '-')}</small></div>
                                <div style="font-size:14px;">${amountDisplay}</div>
                            </div>
                            ${issueExplanation}
                            <div style="background:${hasProblem ? '#fff7f7' : 'rgba(0,0,0,0.03)'}; padding:8px; border-radius:6px; font-size:11px; color:${hasProblem ? '#7f1d1d' : '#444'}; line-height:1.4; border:${hasProblem ? '1px solid #fecaca' : 'none'};">
                                <i class="fas fa-info-circle" style="color:${hasProblem ? '#dc2626' : '#777'};"></i> ${narrative}
                            </div>
                        </div>
                    </div>`;
                }
        
                listArea.innerHTML = html || '<div style="text-align:center; padding:20px;">Log Kosong</div>';
            } catch (error) {
                listArea.innerHTML = `<div style="text-align:center; color:red; padding:20px;"><b>Gagal Membaca File:</b><br>${dgSafeText(error.message)}<br><small>Pastikan file uid${dgSafeText(uid)}.txt ada di folder user/</small></div>`;
            }
        };
        
        window.dgAuditRowsCache = [];
        window.dgAuditFilterState = { keyword: '', status: 'all', sort: 'problem' };
        
        window.dgSmartAuditText = (r) => {
            const u = r.user || {};
            const a = r.analysis || {};
            return [
                u.username, u.nama, u.email, u.id, u.wa, u.whatsapp,
                a.issues && a.issues.length ? 'bermasalah masalah error selisih' : 'aman seimbang',
                r.noLog ? 'belum ada log no log' : '',
                r.error ? 'error gagal' : '',
                a.saldoAwalPatokan, a.totalTopupSaldo, a.totalSaldoDigunakan, a.totalRefund, a.saldoSekarang, a.saldoSeharusnya
            ].join(' ').toLowerCase();
        };
        
        window.dgSetAuditFilter = (key, value) => {
            dgAuditFilterState[key] = value;
            renderDoniGuardAuditCards();
        };
        
        window.renderDoniGuardAuditCards = () => {
            const resultWrap = document.getElementById('dgAuditCardsWrap');
            const info = document.getElementById('dgAuditSearchInfo');
            if (!resultWrap) return;
        
            const keyword = String(dgAuditFilterState.keyword || '').trim().toLowerCase();
            const words = keyword.split(/\s+/).filter(Boolean);
            let rows = [...(window.dgAuditRowsCache || [])];
        
            if (words.length) {
                rows = rows.filter(r => {
                    const haystack = dgSmartAuditText(r);
                    return words.every(w => haystack.includes(w));
                });
            }
        
            if (dgAuditFilterState.status === 'aman') {
                rows = rows.filter(r => r.analysis && r.analysis.issues.length === 0);
            } else if (dgAuditFilterState.status === 'masalah') {
                rows = rows.filter(r => (r.analysis && r.analysis.issues.length > 0) || r.error);
            } else if (dgAuditFilterState.status === 'nolog') {
                rows = rows.filter(r => r.noLog);
            }
        
            rows.sort((a, b) => {
                const aa = a.analysis || {};
                const bb = b.analysis || {};
                if (dgAuditFilterState.sort === 'name') return String(a.user?.username || a.user?.email || '').localeCompare(String(b.user?.username || b.user?.email || ''));
                if (dgAuditFilterState.sort === 'saldo') return (bb.analysis?.saldoSekarang || 0) - (aa.saldoSekarang || 0);
                if (dgAuditFilterState.sort === 'topup') return (bb.analysis?.totalTopupSaldo || 0) - (aa.totalTopupSaldo || 0);
                return ((b.analysis?.issues?.length || (b.error ? 1 : 0)) - (a.analysis?.issues?.length || (a.error ? 1 : 0)));
            });
        
            if (info) info.innerText = `Menampilkan ${rows.length} dari ${window.dgAuditRowsCache.length} user`;
        
            if (rows.length === 0) {
                resultWrap.innerHTML = `<div style="text-align:center; padding:28px; color:#64748b; background:#f8fafc; border:1px dashed #cbd5e1; border-radius:14px;"><i class="fas fa-search" style="font-size:24px; margin-bottom:8px;"></i><br>Tidak ada user yang cocok dengan pencarian.</div>`;
                return;
            }
        
            resultWrap.innerHTML = rows.map(r => {
                const u = r.user || {};
                const displayName = dgSafeText(u.username || u.nama || u.email || u.id || 'User');
                const subName = dgSafeText(u.email || u.nama || u.id || '-');
        
                if (r.error) {
                    return `<div style="background:#fef2f2; border:1px solid #fecaca; border-left:6px solid #dc2626; border-radius:16px; padding:14px; box-shadow:0 8px 20px rgba(220,38,38,.08);">
                        <div style="display:flex; justify-content:space-between; gap:10px; align-items:flex-start;">
                            <div><div style="font-weight:900; color:#991b1b; font-size:14px;"><i class="fas fa-user-shield"></i> ${displayName}</div><div style="font-size:11px; color:#7f1d1d; margin-top:2px;">${subName}</div></div>
                            <span style="background:#dc2626; color:white; padding:5px 9px; border-radius:999px; font-size:10px; font-weight:900;">ERROR</span>
                        </div>
                        <div style="margin-top:10px; font-size:12px; color:#7f1d1d; background:white; border-radius:10px; padding:10px;">Gagal audit: ${dgSafeText(r.error)}</div>
                    </div>`;
                }
        
                if (r.noLog) {
                    return `<div style="background:white; border:1px solid #e2e8f0; border-left:6px solid #94a3b8; border-radius:16px; padding:14px; box-shadow:0 8px 20px rgba(15,23,42,.05);">
                        <div style="display:flex; justify-content:space-between; gap:10px; align-items:flex-start;">
                            <div><div style="font-weight:900; color:#334155; font-size:14px;"><i class="fas fa-user"></i> ${displayName}</div><div style="font-size:11px; color:#64748b; margin-top:2px;">${subName}</div></div>
                            <span style="background:#f1f5f9; color:#475569; padding:5px 9px; border-radius:999px; font-size:10px; font-weight:900;">NO LOG</span>
                        </div>
                        <div style="margin-top:10px; font-size:12px; color:#64748b; background:#f8fafc; border-radius:10px; padding:10px;">User ini belum memiliki file DoniGuard, jadi belum ada rantai saldo yang bisa diaudit.</div>
                        <button onclick="openDoniGuardDetailSheet('${dgSafeText(u.id)}','${displayName}')" style="margin-top:10px; width:100%; border:none; background:#2563eb; color:white; border-radius:10px; padding:9px; font-weight:800; cursor:pointer;"><i class="fas fa-folder-open"></i> Buka Detail</button>
                    </div>`;
                }
        
                const a = r.analysis;
                const ok = a.issues.length === 0;
                const saldoOk = (a.saldoSeharusnya || 0) === (a.saldoSekarang || 0);
                const badge = ok ? `<span style="background:#dcfce7; color:#166534; padding:5px 9px; border-radius:999px; font-size:10px; font-weight:900;"><i class="fas fa-check-circle"></i> AMAN</span>` : `<span style="background:#fee2e2; color:#991b1b; padding:5px 9px; border-radius:999px; font-size:10px; font-weight:900;"><i class="fas fa-triangle-exclamation"></i> ${a.issues.length} MASALAH</span>`;
                const resetInfo = a.auditStartLog ? `Audit dimulai dari reset baris #${a.auditStartLine}` : 'Audit dimulai dari awal log';
                const statusText = saldoOk ? 'Saldo seimbang: saldo seharusnya sama dengan saldo sekarang.' : `Saldo selisih Rp ${dgFormatRupiah(Math.abs(a.selisihPembanding || 0))}.`;
                const borderColor = ok ? '#22c55e' : '#ef4444';
                const softBg = ok ? '#f0fdf4' : '#fef2f2';
        
                return `<div style="background:white; border:1px solid ${ok ? '#bbf7d0' : '#fecaca'}; border-left:6px solid ${borderColor}; border-radius:18px; padding:14px; box-shadow:0 10px 24px rgba(15,23,42,.07); overflow:hidden;">
                    <div style="display:flex; justify-content:space-between; gap:10px; align-items:flex-start; margin-bottom:12px;">
                        <div style="min-width:0;">
                            <div style="font-weight:900; color:#0f172a; font-size:15px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis;"><i class="fas fa-user-shield" style="color:${borderColor};"></i> ${displayName}</div>
                            <div style="font-size:11px; color:#64748b; margin-top:2px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis;">${subName}</div>
                            <div style="font-size:10px; color:#94a3b8; margin-top:3px;">${resetInfo}</div>
                        </div>
                        ${badge}
                    </div>
        
                    <div style="background:${softBg}; border:1px solid ${ok ? '#bbf7d0' : '#fecaca'}; border-radius:12px; padding:10px; margin-bottom:10px; font-size:12px; color:${ok ? '#166534' : '#991b1b'}; line-height:1.35;">
                        <b>${saldoOk ? 'SEIMBANG' : 'SELISIH'}</b> — ${statusText}<br>
                        <small>Rumus: saldo awal + topup/transfer + refund - saldo digunakan = saldo sekarang.</small>
                    </div>
        
                    <div style="display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:8px; font-size:11px;">
                        <div style="background:#eef2ff; border-radius:10px; padding:8px;"><span style="color:#64748b;">Saldo awal admin/reset</span><br><b style="color:#4338ca;">Rp ${dgFormatRupiah(a.saldoAwalPatokan)}</b></div>
                        <div style="background:#ecfdf5; border-radius:10px; padding:8px;"><span style="color:#64748b;">Topup/transfer masuk</span><br><b style="color:#15803d;">Rp ${dgFormatRupiah(a.totalTopupSaldo)}</b></div>
                        <div style="background:#f0fdf4; border-radius:10px; padding:8px;"><span style="color:#64748b;">Refund saldo</span><br><b style="color:#059669;">Rp ${dgFormatRupiah(a.totalRefund)}</b></div>
                        <div style="background:#fff7ed; border-radius:10px; padding:8px;"><span style="color:#64748b;">Saldo digunakan</span><br><b style="color:#c2410c;">Rp ${dgFormatRupiah(a.totalSaldoDigunakan)}</b></div>
                        <div style="background:#eff6ff; border-radius:10px; padding:8px;"><span style="color:#64748b;">Saldo seharusnya</span><br><b style="color:#1d4ed8;">Rp ${dgFormatRupiah(a.saldoSeharusnya || 0)}</b></div>
                        <div style="background:${saldoOk ? '#ecfdf5' : '#fef2f2'}; border-radius:10px; padding:8px;"><span style="color:#64748b;">Saldo sekarang</span><br><b style="color:${saldoOk ? '#166534' : '#991b1b'};">Rp ${dgFormatRupiah(a.saldoSekarang || 0)}</b></div>
                    </div>
        
                    ${a.issues.length ? `<div style="margin-top:10px; background:#fff1f2; border:1px dashed #fca5a5; color:#991b1b; border-radius:10px; padding:8px; font-size:11px;"><b>Masalah utama:</b> ${dgSafeText(a.issues[0].title)} — ${a.issues[0].detail}</div>` : ''}
        
                    <button onclick="openDoniGuardDetailSheet('${dgSafeText(u.id)}','${displayName}')" style="margin-top:12px; width:100%; border:none; background:#111827; color:white; border-radius:12px; padding:10px; font-weight:900; cursor:pointer; box-shadow:0 6px 14px rgba(17,24,39,.18);"><i class="fas fa-list-check"></i> Detail Rantai DoniGuard</button>
                </div>`;
            }).join('');
        };
        
        window.runDoniGuardGlobalAudit = async () => {
            const users = (typeof cacheUsers !== 'undefined') ? cacheUsers : [];
            const panel = document.getElementById('dgGlobalAuditPanel');
            const result = document.getElementById('dgGlobalAuditResult');
            const status = document.getElementById('dgGlobalAuditStatus');
            if (!panel || !result) return;
        
            panel.style.display = 'block';
            result.innerHTML = '<div style="text-align:center; padding:25px; color:#475569;"><i class="fas fa-shield-halved fa-spin" style="font-size:28px;"></i><br><br>Mengaudit seluruh rantai saldo user...</div>';
            if (status) status.innerText = 'Memulai audit...';
        
            let audited = 0, aman = 0, bermasalah = 0, temuan = 0;
            let grandSaldoAwal = 0, grandTopup = 0, grandTerpakai = 0, grandRefund = 0, grandSaldoSekarang = 0, grandTopupRefund = 0;
            const rows = [];
        
            for (const u of users) {
                try {
                    if (status) status.innerText = `Mengaudit ${audited + 1}/${users.length}: ${u.username || u.email || u.id}`;
                    const response = await fetch(`user/uid${u.id}.txt?t=${new Date().getTime()}`);
                    if (!response.ok) {
                        rows.push({ user: u, noLog: true, analysis: null });
                        audited++;
                        continue;
                    }
                    const textData = await response.text();
                    const analysis = dgAnalyzeLogs(textData.split('\n'), u.saldo ?? null);
                    audited++;
                    temuan += analysis.issues.length;
                    if (analysis.aman) aman++; else bermasalah++;
        
                    grandSaldoAwal += analysis.saldoAwalPatokan || 0;
                    grandTopup += analysis.totalTopupSaldo || 0;
                    grandTerpakai += analysis.totalSaldoDigunakan || 0;
                    grandRefund += analysis.totalRefund || 0;
                    grandSaldoSekarang += analysis.saldoSekarang || 0;
                    grandTopupRefund += analysis.totalPembandingMasuk || 0;
        
                    rows.push({ user: u, noLog: false, analysis });
                } catch(e) {
                    audited++;
                    bermasalah++;
                    temuan++;
                    rows.push({ user: u, error: e.message, analysis: null });
                }
        
                document.getElementById('dgAuditTotalUser').innerText = audited;
                document.getElementById('dgAuditAman').innerText = aman;
                document.getElementById('dgAuditMasalah').innerText = bermasalah;
                document.getElementById('dgAuditTemuan').innerText = temuan;
            }
        
            const grandSaldoSeharusnya = grandTopupRefund - grandTerpakai;
            const grandBalanceOk = grandSaldoSeharusnya === grandSaldoSekarang;
            window.dgAuditRowsCache = rows;
            window.dgAuditFilterState = { keyword: '', status: 'all', sort: 'problem' };
        
            if (status) status.innerText = `Selesai: ${audited} user diaudit`;
            result.innerHTML = `
                <div style="background:white; border:1px solid ${grandBalanceOk ? '#bbf7d0' : '#fecaca'}; border-radius:14px; overflow:hidden; margin-bottom:12px; box-shadow:0 4px 14px rgba(15,23,42,.06);">
                    <div style="background:${grandBalanceOk ? '#ecfdf5' : '#fef2f2'}; padding:12px 14px; border-bottom:1px solid ${grandBalanceOk ? '#bbf7d0' : '#fecaca'}; display:flex; justify-content:space-between; align-items:center; gap:10px; flex-wrap:wrap;">
                        <div>
                            <div style="font-size:13px; font-weight:900; color:${grandBalanceOk ? '#166534' : '#991b1b'};"><i class="fas ${grandBalanceOk ? 'fa-check-circle' : 'fa-triangle-exclamation'}"></i> Ringkasan Audit Seluruh User</div>
                            <div style="font-size:11px; color:#64748b; margin-top:2px;">Rumus mudah: total saldo masuk - saldo digunakan = saldo sekarang.</div>
                        </div>
                        <div style="background:${grandBalanceOk ? '#16a34a' : '#dc2626'}; color:white; padding:7px 10px; border-radius:999px; font-size:11px; font-weight:900;">${grandBalanceOk ? 'SEIMBANG' : 'SELISIH'}</div>
                    </div>
                    <div style="padding:12px; display:grid; grid-template-columns:repeat(auto-fit,minmax(170px,1fr)); gap:8px;">
                        <div style="background:#eef2ff; border:1px solid #c7d2fe; border-radius:10px; padding:10px;"><small>Saldo Awal Admin/Reset</small><br><b style="color:#4338ca;">Rp ${dgFormatRupiah(grandSaldoAwal)}</b></div>
                        <div style="background:#ecfdf5; border:1px solid #bbf7d0; border-radius:10px; padding:10px;"><small>Topup/Transfer Masuk</small><br><b style="color:#166534;">Rp ${dgFormatRupiah(grandTopup)}</b></div>
                        <div style="background:#f0fdf4; border:1px solid #bbf7d0; border-radius:10px; padding:10px;"><small>Refund</small><br><b style="color:#15803d;">Rp ${dgFormatRupiah(grandRefund)}</b></div>
                        <div style="background:#f8fafc; border:1px solid #cbd5e1; border-radius:10px; padding:10px;"><small>Total Saldo Masuk</small><br><b>Rp ${dgFormatRupiah(grandTopupRefund)}</b></div>
                        <div style="background:#fff7ed; border:1px solid #fed7aa; border-radius:10px; padding:10px;"><small>Saldo Digunakan</small><br><b style="color:#9a3412;">Rp ${dgFormatRupiah(grandTerpakai)}</b></div>
                        <div style="background:#eff6ff; border:1px solid #bfdbfe; border-radius:10px; padding:10px;"><small>Saldo Seharusnya</small><br><b style="color:#1d4ed8;">Rp ${dgFormatRupiah(grandSaldoSeharusnya)}</b></div>
                        <div style="background:${grandBalanceOk ? '#ecfdf5' : '#fef2f2'}; border:1px solid ${grandBalanceOk ? '#bbf7d0' : '#fecaca'}; border-radius:10px; padding:10px;"><small>Saldo Sekarang</small><br><b style="color:${grandBalanceOk ? '#166534' : '#991b1b'};">Rp ${dgFormatRupiah(grandSaldoSekarang)}</b></div>
                    </div>
                </div>
        
                <div style="background:white; border:1px solid #e2e8f0; border-radius:14px; padding:12px; margin-bottom:12px; box-shadow:0 4px 14px rgba(15,23,42,.05);">
                    <div style="display:flex; gap:8px; flex-wrap:wrap; align-items:center; justify-content:space-between;">
                        <div style="flex:1; min-width:220px; position:relative;">
                            <i class="fas fa-search" style="position:absolute; left:12px; top:50%; transform:translateY(-50%); color:#94a3b8;"></i>
                            <input id="dgSmartAuditSearch" type="text" placeholder="Cari pintar: nama, email, UID, aman, masalah, no log..." oninput="dgSetAuditFilter('keyword', this.value)" style="width:100%; padding:11px 12px 11px 36px; border:1px solid #cbd5e1; border-radius:12px; outline:none; font-size:12px;">
                        </div>
                        <select onchange="dgSetAuditFilter('status', this.value)" style="padding:10px; border:1px solid #cbd5e1; border-radius:12px; font-size:12px; background:white;">
                            <option value="all">Semua status</option>
                            <option value="masalah">Bermasalah</option>
                            <option value="aman">Aman</option>
                            <option value="nolog">Belum ada log</option>
                        </select>
                        <select onchange="dgSetAuditFilter('sort', this.value)" style="padding:10px; border:1px solid #cbd5e1; border-radius:12px; font-size:12px; background:white;">
                            <option value="problem">Urut: masalah dulu</option>
                            <option value="name">Urut: nama</option>
                            <option value="saldo">Urut: saldo terbesar</option>
                            <option value="topup">Urut: topup terbesar</option>
                        </select>
                    </div>
                    <div id="dgAuditSearchInfo" style="font-size:11px; color:#64748b; margin-top:8px;">Menampilkan semua user</div>
                </div>
        
                <div style="background:#f8fafc; border:1px solid #e2e8f0; color:#475569; border-radius:10px; padding:10px; margin-bottom:12px; font-size:11px;">
                    Rumus audit: <b>Saldo awal admin/reset + topup/transfer masuk + refund - saldo digunakan = saldo sekarang</b>. Keterangan saldo sekarang sudah ditampilkan langsung di setiap card user, jadi tidak perlu masuk detail dulu.
                </div>
        
                <div id="dgAuditCardsWrap" style="display:grid; grid-template-columns:repeat(auto-fill,minmax(285px,1fr)); gap:12px;"></div>`;
        
            renderDoniGuardAuditCards();
        };
    </script>

    <div id="chatOverlayMenu" class="chat-popup-overlay" onclick="tutupMenuChat()"></div>
    <div id="chatContextMenu" class="chat-popup-menu" style="display:none;">
        <button onclick="balasPesanTeks()"><i class="fas fa-reply"></i> Balas Pesan</button>
        <button onclick="hapusPesanTerpilih()" class="del-btn"><i class="fas fa-trash"></i> Hapus Pesan</button>
    </div>

</body>

</html>