/* assets/css/style.css */ @import url('https://fonts.googleapis.com/css2?family=DM+Sans:wght@300;400;500;600;700&family=DM+Mono:wght@400;500&display=swap'); :root { --bg-deep: #f8fafc; --bg-panel: #ffffff; --bg-card: #ffffff; --bg-hover: #f1f5f9; --border: #e2e8f0; --border-light: #cbd5e1; --border-subtle: #f1f5f9; --accent: #4f46e5; --accent-light: #6366f1; --accent-glow: rgba(99, 102, 241, 0.1); --accent-2: #8b5cf6; --text-primary: #1e293b; --text-secondary:#475569; --text-muted: #64748b; --text-hint: #94a3b8; --success: #10b981; --success-bg: #ecfdf5; --success-text: #065f46; --warning: #f59e0b; --warning-bg: #fffbeb; --warning-text: #92400e; --danger: #ef4444; --danger-bg: #fef2f2; --danger-text: #991b1b; --info: #3b82f6; --info-bg: #eff6ff; --info-text: #1e40af; --icon-tint: #64748b; --icon-active: #4f46e5; --radius-xs: 4px; --radius-sm: 8px; --radius: 12px; --radius-lg: 16px; --radius-xl: 20px; --shadow-sm: 0 1px 3px rgba(0,0,0,0.05); --shadow: 0 4px 6px -1px rgba(0,0,0,0.05), 0 2px 4px -1px rgba(0,0,0,0.03); --shadow-lg: 0 10px 15px -3px rgba(0,0,0,0.08); --font: 'DM Sans', sans-serif; --mono: 'DM Mono', monospace; --sidebar-w: 300px; } *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } html, body { height: 100%; font-family: var(--font); background: var(--bg-deep); color: var(--text-primary); overflow: hidden; -webkit-font-smoothing: antialiased; } /* ───────────────────────────────────────────── LAYOUT ───────────────────────────────────────────── */ #app { display: flex; height: 100vh; width: 100vw; } /* ───────────────────────────────────────────── SIDEBAR ───────────────────────────────────────────── */ #sidebar { width: var(--sidebar-w); min-width: var(--sidebar-w); background: var(--bg-panel); border-right: 1px solid var(--border); display: flex; flex-direction: column; z-index: 100; overflow: hidden; } .sidebar-header { padding: 18px 16px 14px; border-bottom: 1px solid var(--border); flex-shrink: 0; background: var(--bg-panel); } .logo { display: flex; align-items: center; gap: 10px; margin-bottom: 3px; } .logo-icon { width: 32px; height: 32px; background: var(--accent); border-radius: var(--radius-sm); display: flex; align-items: center; justify-content: center; flex-shrink: 0; } .logo-icon svg { width: 17px; height: 17px; } .logo-text { font-size: 14px; font-weight: 700; letter-spacing: -0.2px; color: var(--text-primary); } .logo-sub { font-size: 10px; color: var(--text-muted); font-weight: 400; letter-spacing: 0.2px; margin-left: 42px; line-height: 1.4; } /* Tabs */ .sidebar-tabs { display: flex; border-bottom: 1px solid var(--border); flex-shrink: 0; padding: 0 4px; } .tab-btn { flex: 1; padding: 10px 4px; background: transparent; border: none; border-bottom: 2px solid transparent; color: var(--text-muted); font-family: var(--font); font-size: 11px; font-weight: 600; cursor: pointer; transition: all 0.2s; letter-spacing: 0.3px; display: flex; flex-direction: column; align-items: center; gap: 5px; margin-bottom: -1px; } .tab-btn svg { width: 16px; height: 16px; stroke: currentColor; fill: none; } .tab-btn:hover { color: var(--text-secondary); } .tab-btn.active { color: var(--accent-light); border-bottom-color: var(--accent-light); } .sidebar-content { flex: 1; overflow-y: auto; overflow-x: hidden; padding: 14px 12px; } .sidebar-content::-webkit-scrollbar { width: 3px; } .sidebar-content::-webkit-scrollbar-track { background: transparent; } .sidebar-content::-webkit-scrollbar-thumb { background: var(--border-light); border-radius: 2px; } .tab-panel { display: none; } .tab-panel.active { display: block; } /* ───────────────────────────────────────────── STATS ───────────────────────────────────────────── */ .stats-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; margin-bottom: 14px; } .stat-card { background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--radius); padding: 12px 10px; text-align: center; transition: border-color 0.2s; position: relative; overflow: hidden; } .stat-card::before { content: ''; position: absolute; top: 0; left: 0; right: 0; height: 2px; background: var(--accent); opacity: 0.4; } .stat-card--rutin::before { background: var(--danger); opacity: 0.5; } .stat-card--pelatihan::before { background: var(--success); opacity: 0.5; } .stat-card:hover { border-color: var(--border-light); } .stat-number { font-size: 24px; font-weight: 700; font-family: var(--font); color: var(--accent-light); letter-spacing: -0.5px; line-height: 1.1; } .stat-card--rutin .stat-number { color: var(--danger); } .stat-card--pelatihan .stat-number { color: var(--success); } .stat-label { font-size: 9px; color: var(--text-muted); font-weight: 500; text-transform: uppercase; letter-spacing: 0.6px; margin-top: 3px; } /* ───────────────────────────────────────────── EKONOMI GRID (stat avg penghasilan & anggota) ───────────────────────────────────────────── */ .ekon-grid { display: flex; flex-direction: column; gap: 6px; margin-bottom: 14px; } .ekon-card { background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--radius); padding: 10px 12px; display: flex; justify-content: space-between; align-items: center; } .ekon-label { font-size: 11px; color: var(--text-muted); font-weight: 500; } .ekon-value { font-size: 13px; font-weight: 700; font-family: var(--font); color: var(--text-primary); } /* ───────────────────────────────────────────── SECTION TITLE ───────────────────────────────────────────── */ .section-title { font-size: 9px; font-weight: 600; color: var(--text-muted); text-transform: uppercase; letter-spacing: 1px; margin: 14px 0 8px; display: flex; align-items: center; gap: 8px; } .section-title svg { width: 12px; height: 12px; stroke: var(--text-muted); fill: none; flex-shrink: 0; } .section-title::after { content: ''; flex: 1; height: 1px; background: var(--border); } /* ───────────────────────────────────────────── LEGEND ───────────────────────────────────────────── */ .legend-group-label { font-size: 9px; color: var(--text-hint); font-weight: 600; text-transform: uppercase; letter-spacing: 0.8px; margin-bottom: 5px; padding-left: 2px; } .legend-item { display: flex; align-items: center; gap: 8px; padding: 5px 6px; border-radius: var(--radius-sm); margin-bottom: 2px; font-size: 12px; font-weight: 400; color: var(--text-secondary); transition: background 0.15s; cursor: default; } .legend-item:hover { background: var(--bg-card); } .legend-icon { width: 22px; height: 22px; border-radius: 6px; background: var(--bg-card); border: 1px solid var(--border); display: flex; align-items: center; justify-content: center; flex-shrink: 0; } .legend-icon svg { width: 13px; height: 13px; stroke: var(--icon-tint); fill: none; } .legend-dot { width: 10px; height: 10px; border-radius: 50%; flex-shrink: 0; } /* ───────────────────────────────────────────── RADIUS CONTROL ───────────────────────────────────────────── */ .radius-control { background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--radius); padding: 12px; margin-bottom: 10px; } .radius-label { font-size: 11px; font-weight: 500; color: var(--text-secondary); margin-bottom: 10px; display: flex; justify-content: space-between; align-items: center; } .radius-value { font-family: var(--font); font-size: 13px; font-weight: 600; color: var(--accent-light); } .radius-slider { width: 100%; -webkit-appearance: none; appearance: none; height: 3px; border-radius: 2px; background: linear-gradient(to right, var(--accent) 0%, var(--accent) 50%, var(--border-light) 50%); outline: none; cursor: pointer; margin-bottom: 10px; } .radius-slider::-webkit-slider-thumb { -webkit-appearance: none; width: 15px; height: 15px; border-radius: 50%; background: var(--accent-light); border: 2px solid var(--bg-panel); cursor: pointer; transition: transform 0.15s; box-shadow: var(--shadow-sm); } .radius-slider::-webkit-slider-thumb:hover { transform: scale(1.15); } .radius-presets { display: flex; gap: 5px; } .preset-btn { flex: 1; padding: 5px; background: var(--bg-deep); border: 1px solid var(--border); border-radius: var(--radius-sm); color: var(--text-muted); font-size: 10px; font-weight: 600; font-family: var(--font); cursor: pointer; transition: all 0.15s; letter-spacing: 0.2px; } .preset-btn:hover { border-color: var(--accent); color: var(--accent-light); } .preset-btn.active { background: var(--accent); border-color: var(--accent); color: #fff; } /* ───────────────────────────────────────────── SEARCH & DATA LIST ───────────────────────────────────────────── */ .search-box { position: relative; margin-bottom: 8px; } .search-box input { width: 100%; padding: 8px 10px 8px 32px; background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--radius-sm); color: var(--text-primary); font-family: var(--font); font-size: 12px; outline: none; transition: border-color 0.2s; } .search-box input::placeholder { color: var(--text-muted); } .search-box input:focus { border-color: var(--accent); } .search-icon { position: absolute; left: 9px; top: 50%; transform: translateY(-50%); pointer-events: none; } .search-icon svg { width: 14px; height: 14px; stroke: var(--text-muted); fill: none; } .data-list { display: flex; flex-direction: column; gap: 4px; } .data-item { background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--radius); padding: 10px; cursor: pointer; transition: all 0.18s; display: flex; gap: 10px; align-items: flex-start; } .data-item:hover { border-color: var(--accent); background: var(--bg-hover); } .item-icon { width: 28px; height: 28px; border-radius: 7px; background: var(--bg-deep); border: 1px solid var(--border); display: flex; align-items: center; justify-content: center; flex-shrink: 0; } .item-icon svg { width: 14px; height: 14px; stroke: var(--icon-tint); fill: none; } .item-info { flex: 1; min-width: 0; } .item-name { font-size: 12px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; margin-bottom: 2px; color: var(--text-primary); } .item-sub { font-size: 10px; color: var(--text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .item-badge { font-size: 9px; font-weight: 600; padding: 2px 7px; border-radius: 20px; flex-shrink: 0; align-self: flex-start; margin-top: 2px; letter-spacing: 0.3px; } /* ───────────────────────────────────────────── BUTTONS ───────────────────────────────────────────── */ .btn { display: inline-flex; align-items: center; justify-content: center; gap: 6px; padding: 8px 14px; border: none; border-radius: var(--radius-sm); font-family: var(--font); font-size: 12px; font-weight: 600; cursor: pointer; transition: all 0.18s; text-decoration: none; } .btn svg { width: 14px; height: 14px; stroke: currentColor; fill: none; } .btn-primary { background: var(--accent); color: #fff; } .btn-primary:hover { background: #4338ca; } .btn-success { background: #059669; color: #fff; } .btn-success:hover { background: #047857; } .btn-danger { background: #dc2626; color: #fff; } .btn-danger:hover { background: #b91c1c; } .btn-ghost { background: var(--bg-card); color: var(--text-secondary); border: 1px solid var(--border); } .btn-ghost:hover { border-color: var(--border-light); color: var(--text-primary); } .btn-sm { padding: 5px 10px; font-size: 11px; } .btn-xs { padding: 3px 8px; font-size: 10px; } .btn-block { width: 100%; } /* ───────────────────────────────────────────── MAP AREA ───────────────────────────────────────────── */ #map-container { flex: 1; position: relative; overflow: hidden; } #map { width: 100%; height: 100%; } /* ───────────────────────────────────────────── TOOLBAR ───────────────────────────────────────────── */ #map-toolbar { position: absolute; bottom: 20px; right: 16px; z-index: 1000; display: flex; flex-direction: column; gap: 6px; } .tool-btn { width: 38px; height: 38px; border-radius: var(--radius-sm); background: var(--bg-panel); border: 1px solid var(--border); color: var(--text-muted); cursor: pointer; display: flex; align-items: center; justify-content: center; transition: all 0.18s; box-shadow: var(--shadow-sm); } .tool-btn svg { width: 16px; height: 16px; stroke: currentColor; fill: none; } .tool-btn:hover { background: var(--bg-hover); color: var(--text-primary); border-color: var(--accent); } /* ───────────────────────────────────────────── INFO PANEL ───────────────────────────────────────────── */ #info-panel { position: absolute; top: 16px; right: 16px; width: 280px; background: var(--bg-panel); border: 1px solid var(--border); border-radius: var(--radius-lg); z-index: 1000; display: none; box-shadow: var(--shadow-lg); overflow: hidden; } #info-panel.show { display: block; animation: slideIn 0.22s ease; } @keyframes slideIn { from { opacity: 0; transform: translateY(-8px) scale(0.98); } to { opacity: 1; transform: translateY(0) scale(1); } } .info-header { padding: 13px 14px 11px; border-bottom: 1px solid var(--border); display: flex; justify-content: space-between; align-items: center; background: var(--bg-card); } .info-title { font-size: 13px; font-weight: 700; display: flex; align-items: center; gap: 8px; color: var(--text-primary); } .info-title-icon { width: 26px; height: 26px; border-radius: 6px; background: var(--bg-panel); border: 1px solid var(--border); display: flex; align-items: center; justify-content: center; } .info-title-icon svg { width: 14px; height: 14px; stroke: var(--icon-tint); fill: none; } .info-close { width: 24px; height: 24px; border-radius: 6px; background: transparent; border: 1px solid transparent; color: var(--text-muted); font-size: 14px; cursor: pointer; display: flex; align-items: center; justify-content: center; transition: all 0.18s; } .info-close:hover { background: var(--danger-bg); color: var(--danger); } .info-body { padding: 12px 14px; max-height: calc(100vh - 200px); overflow-y: auto; } .info-body::-webkit-scrollbar { width: 3px; } .info-body::-webkit-scrollbar-thumb { background: var(--border-light); border-radius: 2px; } .info-row { display: flex; gap: 8px; margin-bottom: 7px; font-size: 12px; align-items: flex-start; } .info-key { color: var(--text-muted); font-weight: 500; min-width: 82px; flex-shrink: 0; padding-top: 1px; } .info-val { color: var(--text-secondary); word-break: break-word; line-height: 1.5; } .address-box { background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 8px 10px; font-size: 11px; color: var(--text-muted); line-height: 1.5; margin: 0 0 10px; display: flex; gap: 6px; align-items: flex-start; } .addr-icon svg { width: 12px; height: 12px; stroke: var(--text-muted); fill: none; flex-shrink: 0; margin-top: 1px; } .info-coords { font-family: var(--mono); font-size: 10px; color: var(--text-muted); text-align: center; padding: 6px; background: var(--bg-card); border-radius: var(--radius-sm); border: 1px solid var(--border); margin-top: 8px; } .info-section-title { font-size: 9px; font-weight: 600; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.8px; margin: 12px 0 6px; display: flex; align-items: center; gap: 6px; } .info-section-title svg { width: 11px; height: 11px; stroke: currentColor; fill: none; } /* Anggota list in info panel */ .anggota-list { display: flex; flex-direction: column; gap: 4px; } .anggota-item { display: flex; gap: 8px; align-items: flex-start; padding: 6px 8px; background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--radius-sm); } .anggota-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; margin-top: 4px; } .anggota-info { flex: 1; min-width: 0; } .anggota-name { font-size: 11px; font-weight: 600; color: var(--text-primary); } .anggota-meta { font-size: 10px; color: var(--text-muted); line-height: 1.5; margin-top: 1px; } /* Rekomendasi box in info panel */ .rek-box { border-radius: var(--radius-sm); padding: 8px 10px; margin: 8px 0; border-left: 3px solid; } .rek-box.rutin { background: var(--danger-bg); border-color: var(--danger); } .rek-box.pelatihan { background: var(--success-bg); border-color: var(--success); } .rek-box.keduanya { background: var(--warning-bg); border-color: var(--warning); } .rek-box.tidak-ada { background: var(--bg-hover); border-color: var(--border-light); } .rek-box-title { font-size: 10px; font-weight: 700; color: var(--text-primary); margin-bottom: 3px; } .rek-box-desc { font-size: 10px; color: var(--text-muted); line-height: 1.5; } /* ───────────────────────────────────────────── BADGES ───────────────────────────────────────────── */ .badge { display: inline-block; padding: 2px 8px; border-radius: 20px; font-size: 10px; font-weight: 600; letter-spacing: 0.2px; } .badge-sangat-miskin { background: var(--danger-bg); color: var(--danger-text); } .badge-miskin { background: var(--info-bg); color: var(--info-text); } .badge-rentan-miskin { background: var(--warning-bg); color: var(--warning-text); } .badge-belum_terima { background: var(--danger-bg); color: var(--danger-text); } .badge-sudah_terima { background: var(--success-bg); color: var(--success-text); } .badge-sedang_proses { background: var(--warning-bg); color: var(--warning-text); } /* STATUS_CONFIG cls — harus cocok dengan app.js */ .badge-belum-terima { background: var(--danger-bg); color: var(--danger-text); } .badge-sudah-terima { background: var(--success-bg); color: var(--success-text); } .badge-sedang-proses { background: var(--warning-bg); color: var(--warning-text); } /* REK_CONFIG cls */ .badge-bantuan-rutin { background: var(--danger-bg); color: var(--danger-text); } .badge-bantuan-pelatihan { background: var(--success-bg); color: var(--success-text); } .badge-keduanya { background: var(--warning-bg); color: var(--warning-text); } .badge-tidak-ada { background: var(--bg-hover); color: var(--text-muted); } /* ───────────────────────────────────────────── MODAL ───────────────────────────────────────────── */ .modal-overlay { position: fixed; inset: 0; background: rgba(0,0,0,0.6); z-index: 9000; display: none; align-items: center; justify-content: center; backdrop-filter: blur(4px); } .modal-overlay.show { display: flex; } #modal-warga, #modal-ibadah { z-index: 9100; } .modal { background: var(--bg-panel); border: 1px solid var(--border); border-radius: var(--radius-xl); width: 480px; max-width: 95vw; max-height: 90vh; overflow-y: auto; box-shadow: var(--shadow-lg); animation: modalIn 0.22s ease; } @keyframes modalIn { from { opacity: 0; transform: scale(0.96) translateY(-16px); } to { opacity: 1; transform: scale(1) translateY(0); } } .modal::-webkit-scrollbar { width: 3px; } .modal::-webkit-scrollbar-thumb { background: var(--border-light); border-radius: 2px; } .modal-header { padding: 16px 18px; border-bottom: 1px solid var(--border); display: flex; justify-content: space-between; align-items: center; position: sticky; top: 0; background: var(--bg-panel); z-index: 1; } .modal-title { font-size: 14px; font-weight: 700; color: var(--text-primary); } .modal-close { width: 26px; height: 26px; border-radius: var(--radius-sm); background: var(--bg-card); border: 1px solid var(--border); color: var(--text-muted); font-size: 13px; cursor: pointer; display: flex; align-items: center; justify-content: center; transition: all 0.18s; } .modal-close:hover { background: var(--danger-bg); color: var(--danger); border-color: transparent; } /* Modal sub-tabs */ .modal-tabs { display: flex; border-bottom: 1px solid var(--border); background: var(--bg-card); flex-shrink: 0; } .modal-tab-btn { flex: 1; padding: 9px 6px; background: transparent; border: none; border-bottom: 2px solid transparent; color: var(--text-muted); font-family: var(--font); font-size: 11px; font-weight: 600; cursor: pointer; transition: all 0.2s; margin-bottom: -1px; } .modal-tab-btn:hover { color: var(--text-secondary); } .modal-tab-btn.active { color: var(--accent-light); border-bottom-color: var(--accent-light); } .modal-tab-panel { display: none; } .modal-tab-panel.active { display: block; } .modal-body { padding: 18px; } .modal-footer { padding: 12px 18px; border-top: 1px solid var(--border); display: flex; gap: 8px; justify-content: flex-end; position: sticky; bottom: 0; background: var(--bg-panel); z-index: 1; } /* ───────────────────────────────────────────── FORM ───────────────────────────────────────────── */ .form-group { margin-bottom: 13px; } .form-label { display: block; font-size: 10px; font-weight: 600; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.6px; margin-bottom: 5px; } .form-label span { color: var(--danger); } .form-control { width: 100%; padding: 8px 11px; background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--radius-sm); color: var(--text-primary); font-family: var(--font); font-size: 13px; outline: none; transition: border-color 0.18s, box-shadow 0.18s; } .form-control::placeholder { color: var(--text-muted); } .form-control:focus { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-glow); } select.form-control { cursor: pointer; -webkit-appearance: none; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%2394a3b8' stroke-width='2'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: right 10px center; padding-right: 32px; } textarea.form-control { resize: vertical; min-height: 68px; } .form-row { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; } .form-hint { font-size: 10px; color: var(--text-muted); margin-top: 4px; } .coord-display { font-family: var(--mono); font-size: 11px; color: var(--accent-light); background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 8px 10px; } /* Kondisi rumah preview */ .kondisi-rumah-preview { background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--radius); padding: 12px; margin-top: 4px; } .kpr-title { font-size: 10px; font-weight: 600; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.6px; margin-bottom: 10px; } .kpr-grid { display: flex; gap: 6px; } .kpr-item { flex: 1; display: flex; flex-direction: column; align-items: center; gap: 5px; background: var(--bg-deep); border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 8px 6px; font-size: 10px; color: var(--text-secondary); text-align: center; } .kpr-item svg { color: var(--icon-tint); } /* Anggota form items */ .anggota-form-item { background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; } .anggota-form-header { display: flex; justify-content: space-between; align-items: center; padding: 8px 12px; background: var(--bg-hover); border-bottom: 1px solid var(--border); } .anggota-form-title { font-size: 11px; font-weight: 600; color: var(--text-secondary); } .anggota-form-body { padding: 12px; display: grid; grid-template-columns: 1fr 1fr; gap: 8px; } .anggota-form-body .form-group { margin-bottom: 0; } /* Rekomendasi preview box */ .rek-preview { background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--radius); padding: 10px 12px; } /* ───────────────────────────────────────────── TOAST ───────────────────────────────────────────── */ #toast-container { position: fixed; bottom: 80px; right: 20px; z-index: 9999; display: flex; flex-direction: column; gap: 6px; } .toast { background: var(--bg-panel); border: 1px solid var(--border); border-radius: var(--radius); padding: 10px 14px; display: flex; align-items: center; gap: 10px; min-width: 240px; box-shadow: var(--shadow-lg); animation: toastIn 0.25s ease; font-size: 12px; color: var(--text-secondary); } @keyframes toastIn { from { opacity: 0; transform: translateX(16px); } to { opacity: 1; transform: translateX(0); } } .toast.success { border-left: 3px solid var(--success); } .toast.error { border-left: 3px solid var(--danger); } .toast.info { border-left: 3px solid var(--accent-light); } .toast-icon svg { width: 15px; height: 15px; stroke: currentColor; fill: none; } .toast.success .toast-icon { color: var(--success); } .toast.error .toast-icon { color: var(--danger); } .toast.info .toast-icon { color: var(--accent-light); } /* ───────────────────────────────────────────── RADIUS INFO BAR ───────────────────────────────────────────── */ #radius-info { position: absolute; bottom: 72px; left: 50%; transform: translateX(-50%); z-index: 1000; background: var(--bg-panel); border: 1px solid var(--border-light); border-radius: var(--radius); padding: 9px 14px; display: none; gap: 10px; align-items: center; box-shadow: var(--shadow); font-size: 12px; white-space: nowrap; } #radius-info.show { display: flex; } .ri-label { color: var(--text-muted); } .ri-val { color: var(--accent-light); font-weight: 600; font-family: var(--font); } .ri-count { background: var(--danger-bg); color: var(--danger-text); padding: 2px 8px; border-radius: 20px; font-weight: 700; font-size: 11px; } .ri-close { cursor: pointer; color: var(--text-muted); display: flex; align-items: center; justify-content: center; transition: color 0.18s; } .ri-close:hover { color: var(--danger); } .ri-close svg { width: 12px; height: 12px; stroke: currentColor; fill: none; } /* ───────────────────────────────────────────── MODE INDICATOR ───────────────────────────────────────────── */ #mode-indicator { position: absolute; top: 16px; left: 16px; z-index: 1000; background: var(--bg-panel); border: 1px solid var(--border); border-radius: var(--radius); padding: 8px 12px; display: none; align-items: center; gap: 8px; font-size: 12px; font-weight: 500; color: var(--text-secondary); box-shadow: var(--shadow-sm); } #mode-indicator.show { display: flex; } .mode-dot { width: 7px; height: 7px; border-radius: 50%; animation: pulse 1.2s infinite; } .mode-dot.ibadah { background: var(--success); } .mode-dot.warga { background: var(--accent-light); } @keyframes pulse { 0%, 100% { transform: scale(1); opacity: 1; } 50% { transform: scale(1.5); opacity: 0.5; } } /* ───────────────────────────────────────────── LEAFLET OVERRIDES ───────────────────────────────────────────── */ .leaflet-popup-content-wrapper { background: var(--bg-panel) !important; border: 1px solid var(--border) !important; border-radius: var(--radius) !important; box-shadow: var(--shadow-lg) !important; color: var(--text-primary) !important; } .leaflet-popup-content { color: var(--text-primary) !important; font-family: var(--font) !important; } .leaflet-popup-tip { background: var(--bg-panel) !important; } .leaflet-popup-close-button { color: var(--text-muted) !important; } .leaflet-control-zoom a { background: var(--bg-panel) !important; color: var(--text-secondary) !important; border-color: var(--border) !important; font-family: var(--font) !important; } .leaflet-control-zoom a:hover { background: var(--bg-hover) !important; } .leaflet-control-attribution { display: none !important; } /* ───────────────────────────────────────────── SCROLLBAR ───────────────────────────────────────────── */ ::-webkit-scrollbar { width: 5px; } ::-webkit-scrollbar-track { background: transparent; } ::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; } /* ───────────────────────────────────────────── LOADING / EMPTY ───────────────────────────────────────────── */ .loading { display: flex; align-items: center; justify-content: center; padding: 28px; color: var(--text-muted); font-size: 12px; gap: 8px; } .spinner { width: 16px; height: 16px; border: 2px solid var(--border); border-top-color: var(--accent); border-radius: 50%; animation: spin 0.6s linear infinite; } @keyframes spin { to { transform: rotate(360deg); } } .empty-state { text-align: center; padding: 24px 16px; color: var(--text-muted); font-size: 12px; } .empty-state svg { width: 28px; height: 28px; stroke: var(--text-hint); fill: none; margin: 0 auto 8px; display: block; } /* ───────────────────────────────────────────── HOW TO USE BOX ───────────────────────────────────────────── */ .howto-box { font-size: 11px; color: var(--text-muted); line-height: 1.8; background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 10px 12px; } .howto-box b { color: var(--text-secondary); font-weight: 600; } /* ───────────────────────────────────────────── LAPORAN WARGA ───────────────────────────────────────────── */ /* Tab badge counter */ .tab-badge { display: inline-flex; align-items: center; justify-content: center; min-width: 16px; height: 16px; padding: 0 4px; background: var(--danger); color: #fff; border-radius: 10px; font-size: 9px; font-weight: 700; margin-left: 3px; line-height: 1; } /* Laporan card */ .laporan-card { background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--radius); padding: 11px 12px; margin-bottom: 6px; transition: border-color 0.18s; border-left: 3px solid var(--border); } .laporan-card:hover { border-color: var(--accent); } .laporan-card.prioritas-tinggi { border-left-color: var(--danger); } .laporan-card.prioritas-sedang { border-left-color: var(--warning); } .laporan-card.prioritas-rendah { border-left-color: var(--success); } .laporan-card-header { display: flex; justify-content: space-between; align-items: flex-start; gap: 8px; margin-bottom: 6px; } .laporan-card-nama { font-size: 12px; font-weight: 600; color: var(--text-primary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .laporan-card-meta { font-size: 10px; color: var(--text-muted); margin-top: 2px; } .laporan-card-jenis { font-size: 11px; color: var(--text-secondary); margin-bottom: 5px; font-weight: 500; } .laporan-card-desc { font-size: 11px; color: var(--text-muted); line-height: 1.5; background: var(--bg-deep); border-radius: var(--radius-sm); padding: 6px 8px; margin-bottom: 6px; border-left: 2px solid var(--border-light); display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; } .laporan-card-footer { display: flex; justify-content: space-between; align-items: center; gap: 6px; flex-wrap: wrap; } .laporan-card-petugas { font-size: 10px; color: var(--success); font-weight: 600; display: flex; align-items: center; gap: 4px; } .laporan-catatan-admin { font-size: 10px; color: var(--text-muted); background: var(--info-bg); border: 1px solid rgba(59,130,246,0.15); border-radius: var(--radius-sm); padding: 5px 8px; margin-top: 5px; line-height: 1.5; } /* Status badges laporan */ .badge-laporan-pending { background: rgba(245,158,11,0.12); color: #92400e; } .badge-laporan-ditinjau { background: rgba(59,130,246,0.12); color: #1e40af; } .badge-laporan-diproses { background: rgba(139,92,246,0.12); color: #5b21b6; } .badge-laporan-selesai { background: rgba(16,185,129,0.12); color: #065f46; } .badge-laporan-ditolak { background: rgba(239,68,68,0.12); color: #991b1b; } /* Prioritas badges */ .badge-prioritas-tinggi { background: rgba(239,68,68,0.12); color: var(--danger-text); } .badge-prioritas-sedang { background: rgba(245,158,11,0.12); color: var(--warning-text); } .badge-prioritas-rendah { background: rgba(16,185,129,0.12); color: var(--success-text); } /* Admin action area in laporan card */ .laporan-admin-actions { display: flex; gap: 5px; flex-wrap: wrap; margin-top: 8px; padding-top: 8px; border-top: 1px dashed var(--border); } .laporan-admin-actions select { flex: 1; min-width: 110px; font-size: 10px; padding: 4px 8px; border-radius: var(--radius-sm); border: 1px solid var(--border); background: var(--bg-deep); color: var(--text-secondary); font-family: var(--font); cursor: pointer; } .laporan-admin-actions input[type="text"] { flex: 1.5; min-width: 100px; font-size: 10px; padding: 4px 8px; border-radius: var(--radius-sm); border: 1px solid var(--border); background: var(--bg-deep); color: var(--text-secondary); font-family: var(--font); } /* Laporan filter tabs */ .laporan-filter-tabs { display: flex; gap: 4px; flex-wrap: wrap; margin-bottom: 10px; } .laporan-filter-tab { padding: 4px 10px; border-radius: 20px; font-size: 10px; font-weight: 600; border: 1px solid var(--border); background: var(--bg-card); color: var(--text-muted); cursor: pointer; transition: all 0.18s; font-family: var(--font); } .laporan-filter-tab:hover { border-color: var(--accent); color: var(--accent-light); } .laporan-filter-tab.active { background: var(--accent); border-color: var(--accent); color: #fff; } /* Laporkan button in info panel */ .btn-laporkan { display: flex; align-items: center; gap: 6px; width: 100%; margin-top: 8px; padding: 7px 12px; background: rgba(239,68,68,0.08); border: 1px solid rgba(239,68,68,0.25); border-radius: var(--radius-sm); color: var(--danger); font-family: var(--font); font-size: 11px; font-weight: 600; cursor: pointer; transition: all 0.18s; } .btn-laporkan:hover { background: rgba(239,68,68,0.15); border-color: var(--danger); } .btn-laporkan svg { width: 13px; height: 13px; stroke: currentColor; fill: none; flex-shrink: 0; } /* ───────────────────────────────────────────── MOBILE STYLES & HAMBURGER MENU ───────────────────────────────────────────── */ .mobile-menu-btn { display: none; position: absolute; top: 16px; left: 16px; z-index: 2000; width: 42px; height: 42px; border-radius: var(--radius-sm); background: var(--bg-panel); border: 1px solid var(--border); color: var(--text-primary); cursor: pointer; align-items: center; justify-content: center; box-shadow: var(--shadow-sm); transition: all 0.2s; } .mobile-menu-btn svg { width: 22px; height: 22px; } .mobile-menu-btn:hover { background: var(--bg-hover); color: var(--accent); border-color: var(--accent); } /* Overlay for mobile sidebar */ .sidebar-overlay { display: none; position: fixed; inset: 0; background: rgba(0,0,0,0.4); z-index: 2500; backdrop-filter: blur(2px); opacity: 0; transition: opacity 0.3s; } .sidebar-overlay.show { display: block; opacity: 1; } @media (max-width: 768px) { .mobile-menu-btn { display: flex; } #sidebar { position: absolute; top: 0; left: -100%; height: 100%; z-index: 3000; transition: left 0.3s ease; box-shadow: var(--shadow-lg); width: 85vw; /* Adjust width for mobile */ max-width: 340px; } #sidebar.show { left: 0; } #mode-indicator { top: 16px; left: 70px; /* Make space for hamburger button */ } .radius-control { padding: 10px; } }