/* Styling minimal - dibuat sederhana dulu (Sprint 2), difokuskan supaya
   dashboard terlihat rapi dan jelas untuk demo 1 panel. Bisa dipercantik
   belakangan tanpa mengubah struktur HTML/JS. */

* {
  box-sizing: border-box;
}

/* v-cloak (2026-09-21, KANDIDAT KETIGA untuk bug "kadang tampil {{ }} saat
   refresh") -- root cause BEDA dari 2 kandidat sebelumnya (CDN Vue gagal
   dimuat / header COOP-OAC): screenshot terbaru user justru menunjukkan
   modal Ganti Password sudah ter-render BENAR (bukan mustache mentah), yang
   berarti Vue TIDAK gagal mount di kasus ini -- jadi bug lain yang mirip
   gejalanya. Root cause paling mungkin: FOUC (flash of unrendered content),
   masalah YANG SUDAH DIKENAL LUAS untuk setup Vue tanpa build step -- ada
   jeda singkat (biasanya cuma beberapa milidetik) antara browser SELESAI
   parsing HTML mentah (termasuk teks `{{ }}` apa adanya) dan Vue SELESAI
   compile+mount untuk menggantinya dengan nilai sungguhan. Normalnya jeda
   ini nyaris tidak kelihatan mata -- TAPI jeda itu bisa memanjang signifikan
   kalau parsing/eksekusi JS melambat, dan SEMUA screenshot bug yang user
   kirim sejauh ini SELALU dengan tab DevTools (Console/Network) terbuka --
   overhead DevTools yang memperlambat main thread saat parsing HALAMAN BARU
   SAJA DIBUKA adalah penyebab umum yang dikenal memperpanjang jeda FOUC ini
   sampai kelihatan mata, cocok dengan sifat "kadang" (random, tergantung
   seberapa lambat parsing saat itu) dan durasi sangat singkat ("secepat
   mungkin ss" sebelum hilang sendiri) yang dilaporkan user. `v-cloak` adalah
   solusi standar Vue untuk PERSIS masalah ini: Vue otomatis MENGHAPUS
   attribute ini dari elemen begitu proses mount selesai -- sebelum itu,
   aturan CSS di bawah menyembunyikan elemen sepenuhnya, jadi user tidak
   pernah melihat teks `{{ }}`/atribut v-if mentah sama sekali, walau
   mount-nya lambat. Dipasang di elemen `#app` di SEMUA 6 halaman web. */
[v-cloak] {
  display: none !important;
}

body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Arial, sans-serif;
  background: #f1f5f9;
  color: #0f172a;
}

/* ============================================================
   Halaman Login -- disamakan dengan login_screen.dart mobile
   (Decision Log 2026-09-20): header gradien biru + badge logo bulat +
   kartu putih melengkung menimpa sedikit ke header, menggantikan tema
   gelap polos sebelumnya yang tidak konsisten dengan tema terang
   dashboard+mobile. Warna gradien SAMA PERSIS dengan yang dipakai mobile
   (_kPrimaryBlue/_kPrimaryBlueDark) supaya terasa satu produk yang sama.
   ============================================================ */
body.login-body {
  background: #ffffff;
  color: #0f172a;
}

/* REVISI 2026-09-21: sebelumnya .login-page align-items:flex-start dengan
   .login-shell polos (tanpa shadow/radius pembungkus) -- di layar desktop
   (browser lebar) itu tampil sebagai kartu selebar HP (420px) menempel di
   pojok kiri-atas layar kosong, terasa seperti "tampilan mobile yang belum
   disesuaikan" persis keluhan user. Sekarang default (desktop): halaman
   diberi latar abu-abu muda + .login-shell jadi SATU kartu utuh (rounded +
   shadow, overflow hidden supaya sudut kotak .login-header ikut terpotong
   rounded oleh shell-nya) yang berada di TENGAH layar (align-items:center),
   terlihat seperti halaman login web sungguhan. Di layar sempit (media
   query di bawah, HP), dibalik lagi ke gaya lama: edge-to-edge, nempel atas,
   tanpa shadow/radius luar -- supaya di HP tetap terasa seperti native app
   (konsisten dengan mobile), bukan kartu mengambang kekecilan. */
.login-page {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #eef2f7;
  padding: 40px 20px;
}

.login-shell {
  width: 100%;
  max-width: 420px;
  border-radius: 20px;
  overflow: hidden;
  box-shadow: 0 20px 60px rgba(15, 23, 42, 0.12);
}

.login-header {
  padding: 56px 24px 40px;
  text-align: center;
  background: linear-gradient(180deg, #4a90d9, #3b78bd);
}

.login-logo-badge {
  width: 84px;
  height: 84px;
  margin: 0 auto;
  border-radius: 50%;
  background: #ffffff;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 14px;
}

.login-logo-badge img {
  width: 100%;
  height: 100%;
  object-fit: contain;
}

.login-brand {
  margin-top: 14px;
  font-size: 22px;
  font-weight: 700;
  color: #ffffff;
  letter-spacing: 1px;
}

.login-welcome {
  margin-top: 4px;
  font-size: 14px;
  font-weight: 600;
  color: #ffffff;
}

.login-tagline {
  margin-top: 2px;
  font-size: 12px;
  color: rgba(255, 255, 255, 0.75);
}

.login-card {
  background: #ffffff;
  border-radius: 20px;
  padding: 28px 24px 24px;
  margin: -28px 20px 24px;
  box-shadow: 0 10px 30px rgba(15, 23, 42, 0.1);
}

.login-card label {
  display: block;
  font-size: 13px;
  font-weight: 600;
  margin-bottom: 6px;
  color: #334155;
}

.login-card input {
  width: 100%;
  padding: 10px 12px;
  margin-bottom: 16px;
  border-radius: 10px;
  border: 1px solid #dde2e8;
  background: #f7f8fa;
  color: #0f172a;
  font-size: 14px;
}

.login-card input:focus {
  outline: none;
  border-color: #4a90d9;
  background: #ffffff;
}

.login-card button {
  width: 100%;
  padding: 12px;
  border-radius: 10px;
  border: none;
  background: #4a90d9;
  color: #ffffff;
  font-weight: 600;
  font-size: 14px;
  cursor: pointer;
}

.login-card button:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}

.error-message {
  color: #dc2626;
  font-size: 13px;
  margin: 12px 0 0;
}

/* ============================================================
   Dashboard (Sprint 2) - tema terang, mengikuti acuan desain
   bersama web+mobile (Decision Log, 2026-07-26). Skema warna dan
   layout (card summary + list ESP) sengaja disamakan supaya nanti
   mobile app (Flutter, Sprint 4) terasa satu produk yang sama.
   ============================================================ */

body.dashboard-body {
  background: #f1f5f9;
  color: #0f172a;
}

.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 24px;
  background: #ffffff;
  border-bottom: 1px solid #e2e8f0;
}

.topbar h1 {
  font-size: 16px;
  margin: 0;
  color: #0f172a;
}

/* Logo + pemisah + nama halaman di topbar (Decision Log 2026-09-20) --
   parity dengan AppBarBrandTitle mobile (logo ER-SP + garis pemisah tipis
   + nama halaman), sebelumnya web cuma tampilkan teks judul polos tanpa
   logo gambar sama sekali. */
.topbar-brand {
  display: flex;
  align-items: center;
  gap: 10px;
}

.topbar-logo {
  height: 26px;
  width: auto;
  display: block;
}

.topbar-separator {
  width: 1.5px;
  height: 18px;
  background: rgba(15, 23, 42, 0.16);
  border-radius: 999px;
}

.topbar .user-info {
  font-size: 13px;
  color: #64748b;
  display: flex;
  align-items: center;
  gap: 12px;
}

.topbar button,
.icon-button {
  background: #f1f5f9;
  border: 1px solid #e2e8f0;
  color: #334155;
  padding: 6px 12px;
  border-radius: 6px;
  cursor: pointer;
  font-size: 13px;
}

.dashboard-content {
  padding: 24px;
  max-width: 1100px;
  margin: 0 auto;
}

/* Summary cards (TOTAL ESP, ONLINE, OFFLINE, RELAY ON/OFF, RATA-RATA VOLT) */
.summary-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 12px;
  margin-bottom: 20px;
}

.summary-card {
  border-radius: 12px;
  padding: 14px 16px;
}

.summary-card .summary-value {
  font-size: 22px;
  font-weight: 700;
  line-height: 1.2;
}

.summary-card .summary-label {
  font-size: 12px;
  font-weight: 600;
  margin-bottom: 4px;
}

.summary-card .summary-sub {
  font-size: 11px;
  opacity: 0.8;
}

.summary-card.blue { background: #dbeafe; color: #1d4ed8; }
.summary-card.green { background: #dcfce7; color: #15803d; }
.summary-card.red { background: #fee2e2; color: #b91c1c; }
.summary-card.purple { background: #ede9fe; color: #6d28d9; }
.summary-card.orange { background: #ffedd5; color: #c2410c; }
.summary-card.teal { background: #ccfbf1; color: #0f766e; }

/* Search + filter bar */
.toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 12px;
}

.toolbar h2 {
  font-size: 14px;
  font-weight: 700;
  color: #334155;
  margin: 0;
}

.toolbar .toolbar-controls {
  display: flex;
  gap: 8px;
}

.toolbar input,
.toolbar select {
  border: 1px solid #e2e8f0;
  border-radius: 6px;
  padding: 6px 10px;
  font-size: 13px;
  background: #ffffff;
  color: #0f172a;
}

/* List panel */
.panel-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.panel-card {
  background: #ffffff;
  border: 1px solid #e2e8f0;
  border-radius: 12px;
  padding: 16px;
}

.panel-card .panel-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  margin-bottom: 12px;
  gap: 8px;
}

.panel-card .panel-title {
  font-size: 14px;
  font-weight: 700;
  color: #0f172a;
}

/* Aksi Terakhir (2026-08-19) -- kolom TENGAH panel-header, di antara info
   lokasi (kiri) dan status+tombol relay (kanan). Warna value ON/OFF sengaja
   pakai palet yang sama seperti .status-badge (hijau/merah) supaya
   konsisten secara visual dengan indikator status lain di kartu ini. */
.panel-last-action {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  flex-shrink: 0;
}

.last-action-label {
  font-size: 11px;
  color: #94a3b8;
}

.last-action-value {
  font-size: 12px;
  font-weight: 700;
  padding: 2px 10px;
  border-radius: 999px;
}

.last-action-value.on {
  background: #dcfce7;
  color: #15803d;
}

.last-action-value.off {
  background: #fee2e2;
  color: #b91c1c;
}

/* Manual (Decision Log 2026-09-20) -- deteksi tekan langsung di alat lewat
   transisi Beban Aktif tanpa command app. Amber, SENGAJA beda dari palet
   hijau/merah ON/OFF biasa (bukan varian dari keduanya) supaya operator
   langsung sadar ini bukan hasil klik dari app -- selaras dengan warna
   notice cooldown push-button (oranye) yang sudah dipakai di kartu ini. */
.last-action-value.manual {
  background: #fef3c7;
  color: #b45309;
}

.last-action-time {
  font-size: 11px;
  color: #94a3b8;
  white-space: nowrap;
}

.panel-card .panel-subtitle {
  font-size: 12px;
  color: #64748b;
  display: block;
  margin-top: 2px;
}

/* Edit lokasi (Admin/Developer saja, lihat Decision Log) */
.edit-location-btn {
  background: none;
  border: none;
  color: #94a3b8;
  font-size: 13px;
  cursor: pointer;
  margin-left: 6px;
  padding: 0 2px;
}

.edit-location-btn:hover {
  color: #334155;
}

/* Peringatan device offline (Decision Log 2026-07-28), tampil di sebelah
   ikon pensil -- gaya sama seperti .error-message (modal login/password). */
.device-offline-warning {
  color: #b91c1c;
  font-size: 12px;
  font-weight: 600;
  margin-left: 8px;
}

/* Info klik redundan (2026-08-19) -- SENGAJA warna biru/netral, BUKAN merah
   seperti .device-offline-warning: ini bukan masalah/error, cuma info biasa
   ("sudah dalam status itu"), jadi tidak boleh terlihat sama alarming-nya. */
.device-info-notice {
  color: #1d4ed8;
  font-size: 12px;
  font-weight: 600;
  margin-left: 8px;
}

/* "Beban Aktif" (Decision Log 2026-07-28) -- indikator TAMBAHAN dari
   sensor PZEM (voltage/current), terpisah dari status ON/OFF relay. */
.load-active-badge {
  display: inline-block;
  margin-left: 8px;
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 700;
  background: #f1f5f9;
  color: #64748b;
}

.load-active-badge.active {
  background: #dcfce7;
  color: #15803d;
}

.edit-location-form {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
}

.edit-location-form input {
  border: 1px solid #cbd5e1;
  border-radius: 6px;
  padding: 4px 8px;
  font-size: 13px;
  min-width: 160px;
}

.edit-location-form button {
  border: none;
  border-radius: 6px;
  padding: 4px 10px;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
}

.edit-save-btn {
  background: #22c55e;
  color: #ffffff;
}

.edit-cancel-btn {
  background: #f1f5f9;
  color: #64748b;
}

.status-badge {
  font-size: 11px;
  font-weight: 700;
  padding: 3px 10px;
  border-radius: 999px;
  white-space: nowrap;
}

.status-badge.online {
  background: #dcfce7;
  color: #15803d;
}

.status-badge.offline {
  background: #fee2e2;
  color: #b91c1c;
}

/* Kolom sisi kanan panel-header: status-badge di atas, relay-list di
   bawahnya (diminta user, 2026-07-31 -- sebelumnya relay-list adalah baris
   terpisah selebar kartu di bawah seluruh header). */
.panel-status-col {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 8px;
  flex-shrink: 0;
}

.relay-list {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: 8px;
}

/* min-width dihapus 2026-08-09 -- sebelumnya 130px supaya muat label
   "R{index} - nama relay", sekarang labelnya sudah dihapus jadi kotak
   dibiarkan menyesuaikan ukuran ke tombol ON/OFF saja (lebih rapi/pas,
   bukan kotak lebar kosong). */
.relay-row {
  display: flex;
  flex-direction: column;
  gap: 6px;
  background: #f8fafc;
  border: 1px solid #e2e8f0;
  border-radius: 10px;
  padding: 6px 8px;
}

.relay-row .relay-name {
  font-size: 12px;
  font-weight: 600;
  color: #334155;
}

.relay-row .relay-state {
  font-size: 11px;
  color: #94a3b8;
}

/* Tombol ON/OFF (Decision Log 2026-07-26: ikut acuan desain mobile --
   2 tombol terpisah, bukan toggle switch). Tombol yang cocok dengan
   status saat ini tampil terisi warna, yang lain abu-abu netral. */
.relay-actions {
  display: flex;
  gap: 6px;
}

.relay-actions button {
  flex: 1;
  padding: 6px 10px;
  border-radius: 6px;
  border: 1px solid transparent;
  font-size: 11px;
  font-weight: 700;
  cursor: pointer;
}

.relay-actions .btn-on {
  background: #f1f5f9;
  color: #64748b;
  border-color: #e2e8f0;
}

.relay-actions .btn-on.active {
  background: #22c55e;
  color: #ffffff;
}

.relay-actions .btn-off {
  background: #f1f5f9;
  color: #64748b;
  border-color: #e2e8f0;
}

.relay-actions .btn-off.active {
  background: #ef4444;
  color: #ffffff;
}

/* Push-button feedback (Decision Log 2026-08-18, REVISI 2026-08-19): class
   .warning (kuning/amber) DIHAPUS -- desain awal membandingkan ke Ampere
   2 detik setelah klik selalu salah (data PZEM cuma update tiap 5 detik),
   diganti cooldown murni waktu (10 detik disabled, lihat dashboard.js/
   dashboard.html). Opacity berkurang di bawah ini (button:disabled) sudah
   otomatis jadi indikator visual "masih cooldown, belum bisa diklik lagi",
   tidak perlu warna terpisah. */
.relay-actions button:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}

/* Chip cooldown "Tunggu N detik" (2026-09-21) -- sebelumnya tombol cuma
   buram (disabled) tanpa teks penjelasan sama sekali, beda dari mobile yang
   sudah lebih dulu punya chip ini (_NoticeChip, dashboard_screen.dart).
   Warna oranye disamakan dengan Colors.orange.shade50/800 di mobile. */
.cooldown-chip {
  margin-top: 6px;
  font-size: 11px;
  font-weight: 700;
  padding: 2px 10px;
  border-radius: 999px;
  background: #ffedd5;
  color: #c2410c;
  text-align: center;
  white-space: nowrap;
}

.empty-state {
  text-align: center;
  color: #94a3b8;
  padding: 40px 0;
}

/* Modal ganti password (self-service, semua role) */
.modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(15, 23, 42, 0.5);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 50;
  padding: 16px;
}

.modal-card {
  background: #ffffff;
  border-radius: 12px;
  padding: 24px;
  width: 100%;
  max-width: 360px;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
}

.modal-card h2 {
  font-size: 16px;
  margin: 0 0 16px;
  color: #0f172a;
}

.modal-card label {
  display: block;
  font-size: 12px;
  color: #64748b;
  margin-bottom: 4px;
  margin-top: 12px;
}

.modal-card input {
  width: 100%;
  padding: 8px 10px;
  border-radius: 6px;
  border: 1px solid #cbd5e1;
  font-size: 13px;
}

.modal-hint {
  font-size: 11px;
  color: #94a3b8;
  margin: 6px 0 0;
}

.password-success {
  color: #15803d;
  font-size: 12px;
  margin: 10px 0 0;
}

.modal-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  margin-top: 20px;
}

/* Halaman Riwayat & Audit Log */
.audit-table {
  width: 100%;
  border-collapse: collapse;
  background: #ffffff;
  border: 1px solid #e2e8f0;
  border-radius: 12px;
  overflow: hidden;
  font-size: 13px;
}

.audit-table th {
  text-align: left;
  background: #f8fafc;
  color: #64748b;
  font-size: 11px;
  font-weight: 700;
  padding: 10px 12px;
  border-bottom: 1px solid #e2e8f0;
}

.audit-table td {
  padding: 10px 12px;
  border-bottom: 1px solid #f1f5f9;
  vertical-align: top;
}

.audit-table tr.row-denied {
  background: #fef2f2;
}

.audit-table .detail-cell {
  color: #64748b;
  font-family: monospace;
  font-size: 11px;
  max-width: 320px;
  word-break: break-word;
}

.action-badge {
  font-size: 11px;
  font-weight: 700;
  padding: 2px 8px;
  border-radius: 999px;
  white-space: nowrap;
}

.action-badge.denied {
  background: #fee2e2;
  color: #b91c1c;
}

.action-badge.relay {
  background: #ede9fe;
  color: #6d28d9;
}

.action-badge.neutral {
  background: #f1f5f9;
  color: #475569;
}

/* Tabel (Riwayat, Perangkat) di layar sempit gampang overflow -- bungkus
   dengan scroll horizontal daripada memaksa kolom menyempit sampai
   tidak kebaca. */
.table-wrap {
  overflow-x: auto;
  border-radius: 12px;
}

.table-wrap .audit-table {
  min-width: 640px;
}

/* ============================================================
   Responsif - layar sempit (HP/tablet potret). Skema warna dan
   struktur tetap sama, cuma layout dipadatkan supaya tidak overflow.
   ============================================================ */
@media (max-width: 640px) {
  /* Halaman login balik ke gaya edge-to-edge (2026-09-21) -- di layar HP,
     kartu terpusat dengan latar abu-abu di sekelilingnya (gaya desktop di
     atas) malah bikin kartu terlihat kekecilan/terjepit -- balik ke gaya
     lama: nempel penuh ke tepi atas, tanpa shadow/radius luar, background
     putih polos, persis tampilan mobile app aslinya. */
  .login-page {
    align-items: flex-start;
    background: #ffffff;
    padding: 0;
  }

  .login-shell {
    max-width: 100%;
    border-radius: 0;
    box-shadow: none;
  }

  .topbar {
    flex-wrap: wrap;
    gap: 8px;
    padding: 12px 16px;
  }

  .topbar .user-info {
    flex-wrap: wrap;
    gap: 8px;
    width: 100%;
  }

  .dashboard-content {
    padding: 16px 12px;
  }

  .summary-grid {
    grid-template-columns: repeat(2, 1fr);
    gap: 8px;
  }

  .toolbar {
    flex-direction: column;
    align-items: stretch;
    gap: 8px;
  }

  .toolbar .toolbar-controls {
    flex-direction: column;
  }

  .toolbar input,
  .toolbar select {
    width: 100%;
  }

  .panel-header {
    flex-wrap: wrap;
  }

  .panel-status-col {
    align-items: flex-start;
    width: 100%;
  }

  .relay-list {
    width: 100%;
    gap: 10px;
  }

  .relay-row {
    min-width: 0;
    width: 100%;
  }

  .modal-card {
    max-width: 100%;
  }
}
