/* ==========================================================================
   NETWORK-MANAGEMENT — lapisan khusus aplikasi ini.

   style.css adalah design system yang dipinjam apa adanya dari fiberhome-master
   (token warna, .card, .btn, .data-table, .modal, .terminal-window). File ini
   sengaja TERPISAH dan dimuat sesudahnya: apa pun yang khas switch — sel port,
   chip VLAN, wizard provisioning — ditulis di sini, supaya style.css bisa
   disegarkan dari proyek sebelahnya tanpa menabrak apa pun.
   ========================================================================== */

/* ------------------------------ chip & badge ------------------------------ */
.chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 9px;
  border-radius: var(--radius-full);
  font-size: 11px;
  font-weight: 600;
  background: var(--bg-surface-elevated);
  color: var(--text-secondary);
  border: 1px solid var(--border-subtle);
  white-space: nowrap;
}

.chip.ok      { background: var(--signal-good-bg);    color: var(--signal-good);    border-color: transparent; }
.chip.warn    { background: var(--signal-warn-bg);    color: var(--signal-warn);    border-color: transparent; }
.chip.danger  { background: var(--signal-danger-bg);  color: var(--signal-danger);  border-color: transparent; }
.chip.muted   { background: var(--signal-offline-bg); color: var(--signal-offline); border-color: transparent; }
.chip.primary { background: var(--primary-glow);      color: var(--primary);        border-color: transparent; }

.chip.mono { font-family: var(--font-mono); letter-spacing: -0.02em; }

.chip-row {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  align-items: center;
}

/* VLAN yang belum masuk allow-pass uplink diberi garis putus-putus:
   itu penanda paling sering dibutuhkan saat mitra "port up tapi tidak jalan". */
.vlan-chip {
  cursor: default;
  font-family: var(--font-mono);
}
.vlan-chip.no-uplink {
  border: 1px dashed var(--signal-warn);
  color: var(--signal-warn);
  background: var(--signal-warn-bg);
}

/* ------------------------------ titik status ------------------------------ */
.dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  display: inline-block;
  flex-shrink: 0;
}
.dot.up      { background: var(--signal-good); box-shadow: 0 0 6px var(--signal-good); }
.dot.down    { background: var(--signal-offline); }
.dot.admin   { background: var(--signal-danger); }

/* ------------------------------ tabel port ------------------------------ */
.port-name {
  font-family: var(--font-mono);
  font-weight: 600;
  white-space: nowrap;
}

.data-table tr.port-free td { opacity: 0.72; }
.data-table tr.port-uplink td {
  background: var(--primary-glow);
}
.data-table tr.port-uplink:hover td { background: var(--primary-glow); }

.row-actions {
  display: flex;
  gap: 5px;
  justify-content: flex-end;
}

.muted-text {
  color: var(--text-muted);
  font-size: 12px;
}

/* ------------------------------ toolbar & filter ------------------------------ */
.toolbar {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
  margin-bottom: 12px;
}
.toolbar .spacer { flex: 1; }

.filter-bar {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 8px;
  margin-bottom: 12px;
}

/* ------------------------------ kartu perangkat ------------------------------ */
.device-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 14px;
}

.device-card {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-bottom: 0;
}

.device-card .device-head {
  display: flex;
  align-items: flex-start;
  gap: 10px;
}

.device-icon {
  width: 40px;
  height: 40px;
  border-radius: var(--radius-md);
  background: linear-gradient(135deg, var(--primary), var(--accent-purple));
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}

.device-meta {
  display: flex;
  flex-direction: column;
  gap: 8px;
  font-size: 12px;
  color: var(--text-secondary);
}

.meter {
  height: 6px;
  border-radius: var(--radius-full);
  background: var(--bg-surface-elevated);
  overflow: hidden;
}
.meter > span {
  display: block;
  height: 100%;
  background: linear-gradient(90deg, var(--primary), var(--accent-blue));
}

/* ------------------------------ daftar kunci-nilai ------------------------------ */
.kv {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 10px;
}
.kv > div {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.kv .k {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-muted);
  font-weight: 600;
}
.kv .v {
  font-size: 13px;
  font-weight: 600;
  color: var(--text-primary);
  word-break: break-word;
}

/* ------------------------------ terminal ------------------------------ */
/* Tinggi tetap 280px dari design system cocok untuk konsol; pratinjau CLI
   panjangnya berubah-ubah, jadi dibiarkan menyesuaikan isi. */
.terminal-body.auto {
  height: auto;
  min-height: 90px;
  max-height: 340px;
}

.term-ok  { color: #7dd3fc; }
.term-err { color: #fda4af; font-weight: 700; }
.term-out { color: #94a3b8; }
.term-note{ color: #fbbf24; }

/* ------------------------------ keadaan kosong ------------------------------ */
.empty-state {
  text-align: center;
  padding: 44px 20px;
  color: var(--text-muted);
}
.empty-state .icon {
  width: 54px;
  height: 54px;
  border-radius: var(--radius-lg);
  background: var(--bg-surface-elevated);
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0 auto 12px;
  color: var(--text-secondary);
}
.empty-state h3 {
  font-size: 15px;
  color: var(--text-primary);
  margin-bottom: 4px;
}
.empty-state p {
  font-size: 13px;
  max-width: 440px;
  margin: 0 auto 14px;
  line-height: 1.6;
}

/* ------------------------------ peringatan ------------------------------ */
.notice {
  display: flex;
  gap: 10px;
  padding: 11px 13px;
  border-radius: var(--radius-md);
  font-size: 12.5px;
  line-height: 1.55;
  margin-bottom: 12px;
  border: 1px solid transparent;
}
.notice svg { flex-shrink: 0; width: 17px; height: 17px; margin-top: 1px; }
.notice.warn   { background: var(--signal-warn-bg);   color: var(--signal-warn);   border-color: rgba(245,158,11,.28); }
.notice.danger { background: var(--signal-danger-bg); color: var(--signal-danger); border-color: rgba(239,68,68,.28); }
.notice.info   { background: var(--primary-glow);     color: var(--primary);       border-color: rgba(6,182,212,.28); }
.notice ul { margin: 0; padding-left: 16px; }

/* ------------------------------ langkah diagnostik ------------------------------ */
.steps { display: flex; flex-direction: column; gap: 8px; }
.step {
  display: flex;
  gap: 10px;
  align-items: flex-start;
  padding: 9px 11px;
  border-radius: var(--radius-md);
  background: var(--bg-surface-elevated);
  border: 1px solid var(--border-subtle);
  font-size: 12.5px;
}
.step .step-icon { flex-shrink: 0; margin-top: 1px; }
.step.ok   .step-icon { color: var(--signal-good); }
.step.fail .step-icon { color: var(--signal-danger); }
.step .step-name { font-weight: 700; }
.step .step-detail { color: var(--text-secondary); line-height: 1.5; }

/* ------------------------------ animasi ------------------------------ */
.spin { animation: netman-spin 1s linear infinite; }
@keyframes netman-spin { to { transform: rotate(360deg); } }

.skeleton {
  background: linear-gradient(90deg, var(--bg-surface-elevated) 25%,
              var(--bg-card-hover) 37%, var(--bg-surface-elevated) 63%);
  background-size: 400% 100%;
  animation: netman-shimmer 1.3s ease infinite;
  border-radius: var(--radius-sm);
  height: 13px;
}
@keyframes netman-shimmer {
  0% { background-position: 100% 50%; }
  100% { background-position: 0 50%; }
}

/* ------------------------------ navigasi bawah (mobile) ------------------------------ */
.bottom-nav {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  height: 60px;
  background: var(--bg-surface);
  border-top: 1px solid var(--border-subtle);
  display: none;
  justify-content: space-around;
  align-items: center;
  z-index: 45;
  padding-bottom: env(safe-area-inset-bottom);
}
.bottom-nav a {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  font-size: 10.5px;
  font-weight: 600;
  color: var(--text-muted);
  text-decoration: none;
}
.bottom-nav a.active { color: var(--primary); }
.bottom-nav svg { width: 18px; height: 18px; }

.mobile-only { display: none; }

@media (max-width: 767px) {
  .sidebar { display: none; }
  .bottom-nav { display: flex; }
  .mobile-only { display: inline-flex; }
  .content-body { padding: 14px; }
  .device-grid { grid-template-columns: 1fr; }
  .row-actions { justify-content: flex-start; }
}

/* ------------------------------ halaman login ------------------------------ */
.login-wrap {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  background:
    radial-gradient(1000px 500px at 15% -10%, var(--primary-glow), transparent 60%),
    var(--bg-app);
}
.login-card {
  width: 100%;
  max-width: 380px;
  margin-bottom: 0;
}
.login-brand {
  display: flex;
  align-items: center;
  gap: 11px;
  margin-bottom: 18px;
}

/* Disembunyikan di layar sempit (label tombol, identitas pengguna di topbar). */
@media (max-width: 640px) {
  .hide-mobile { display: none !important; }
}

/* ==========================================================================
   PALET TUNGGAL — PUTIH MONOKROM
   Satu tema saja (tidak ada terang/gelap) dan tanpa biru sama sekali.
   Blok ini sengaja di paling bawah: style.css mendefinisikan token biru/cyan
   untuk :root dan [data-theme="light"]; di sini semuanya ditimpa sekaligus,
   jadi style.css tetap utuh dan tidak perlu ikut diubah.

   Yang TIDAK ikut jadi abu-abu: hijau/kuning/merah status. Warna itu memikul
   makna (link up, peringatan, gagal) — kalau ikut diseragamkan, tabel port
   kehilangan satu-satunya isyarat cepat yang dipakai orang saat menelusuri
   gangguan.
   ========================================================================== */

:root,
:root[data-theme="light"],
:root[data-theme="dark"] {
  --bg-app: #f4f4f5;
  --bg-surface: #ffffff;
  --bg-surface-elevated: #fafafa;
  --bg-card: #ffffff;
  --bg-card-hover: #f4f4f5;
  --bg-modal: #ffffff;

  --border-subtle: #e4e4e7;
  --border-focus: rgba(24, 24, 27, 0.45);

  --text-primary: #18181b;
  --text-secondary: #52525b;
  --text-muted: #a1a1aa;

  /* "primary" sekarang grafit, bukan biru */
  --primary: #18181b;
  --primary-hover: #27272a;
  --primary-glow: rgba(24, 24, 27, 0.07);

  --accent-blue: #18181b;
  --accent-purple: #3f3f46;

  --signal-offline: #71717a;
  --signal-offline-bg: rgba(113, 113, 122, 0.10);

  --glass-blur: blur(0px);
}

/* --- komponen yang menuliskan biru langsung (bukan lewat token) --- */
.btn-primary {
  background: var(--primary);
  color: #ffffff;
  box-shadow: none;
  border-color: var(--primary);
}
.btn-primary:hover { background: var(--primary-hover); filter: none; }

.brand-icon,
.device-icon {
  background: var(--primary);
  box-shadow: none;
}

.nav-link.active {
  background: var(--bg-card-hover);
  color: var(--text-primary);
  border: 1px solid var(--border-subtle);
}

.card:hover { border-color: #d4d4d8; }

.meter > span { background: var(--primary); }

/* Chip "primary" jadi chip PADAT gelap. Di tabel port, itu yang membedakan
   VLAN tagged dari untagged sekarang setelah warna biru dilepas. */
.chip.primary {
  background: var(--primary);
  color: #ffffff;
  border-color: var(--primary);
}

.scroll-slim,
.table-container.scroll-slim { scrollbar-color: #d4d4d8 transparent; }
.scroll-slim::-webkit-scrollbar-thumb { background: #d4d4d8; }
.scroll-slim::-webkit-scrollbar-thumb:hover { background: #a1a1aa; }

/* --- terminal ikut terang --- */
.terminal-window {
  background: var(--bg-surface-elevated);
  border: 1px solid var(--border-subtle);
  box-shadow: none;
}
.terminal-header {
  background: var(--bg-card-hover);
  border-bottom: 1px solid var(--border-subtle);
}
.term-dot.red,
.term-dot.yellow,
.term-dot.green { background: #d4d4d8; }

.terminal-body { color: var(--text-secondary); }
.terminal-input-bar { background: var(--bg-card-hover); }
.terminal-prompt,
.terminal-input { color: var(--text-primary); }

.term-ok   { color: var(--text-primary); font-weight: 600; }
.term-out  { color: var(--text-muted); font-weight: 400; }
.term-err  { color: var(--signal-danger); font-weight: 700; }
.term-note { color: var(--signal-warn); }

/* --- halaman login: putih polos, tanpa aura warna --- */
.login-wrap { background: var(--bg-app); }

/* ==========================================================================
   FACEPLATE SWITCH (dashboard)
   Port digambar seperti susunan fisiknya: ganjil di baris atas, genap di baris
   bawah — `grid-auto-flow: column` dengan 2 baris menghasilkan itu tanpa perlu
   menghitung posisi tiap port.

   Di sinilah warna sengaja dipakai, walau sisa aplikasi monokrom: gunanya
   memang supaya satu lirikan cukup untuk tahu ada yang putus.
   ========================================================================== */

.faceplate-group { margin-bottom: 10px; }

.faceplate-label {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--text-muted);
  margin-bottom: 5px;
}

.faceplate-chassis {
  /* inline-flex, bukan flex: kotak bodinya MEMELUK isinya. Kalau meregang
     selebar kartu, switch 6 port tampil sebagai sekelompok port kecil di pojok
     kotak raksasa — persis yang bikin tampilannya terasa janggal. */
  display: inline-flex;
  align-items: center;
  gap: 11px;
  max-width: 100%;
  padding: 11px 13px;
  border-radius: var(--radius-md);
  background: var(--bg-surface-elevated);
  border: 1px solid var(--border-subtle);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .8), inset 0 -1px 0 rgba(0, 0, 0, .04);
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

.chassis-tag {
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .04em;
  color: var(--text-muted);
  writing-mode: vertical-rl;
  transform: rotate(180deg);
  padding: 2px 0;
  border-right: 1px solid var(--border-subtle);
  padding-right: 8px;
  white-space: nowrap;
  flex-shrink: 0;
}

.faceplate {
  display: grid;
  grid-template-rows: repeat(2, auto);
  grid-auto-flow: column;
  /* Lebar kolom DIKUNCI. Tanpa ini grid meregang mengikuti lebar kartu dan
     switch 6 port tampil sebagai empat port berjauhan — susunannya jadi tidak
     lagi mirip bodi aslinya, yang justru satu-satunya gunanya gambar ini. */
  grid-auto-columns: 30px;
  justify-content: start;
  gap: 4px;
  flex: 0 0 auto;
}

.pport {
  width: 30px;
  height: 21px;
  border-radius: 3px;
  border: 1px solid var(--border-subtle);
  background: var(--bg-surface);
  color: var(--text-muted);
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 700;
  line-height: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  padding: 0;
  transition: transform .12s ease;
}
.pport:hover { transform: translateY(-1px); }
.pport:focus-visible { outline: 2px solid var(--primary); outline-offset: 1px; }

/* bebas — belum ada mitra di atasnya */
.pport.free { border-style: dashed; }

/* ada mitra, link hidup */
.pport.on {
  background: var(--signal-good);
  border-color: var(--signal-good);
  color: #ffffff;
}
/* ada mitra, link hidup, ADA trafik — dibuat berdenyut supaya kelihatan hidup */
.pport.on.live { animation: netman-live 1.8s ease-in-out infinite; }

/* ada mitra tapi link MATI — ini yang dicari saat ada laporan gangguan */
.pport.los {
  background: var(--signal-danger);
  border-color: var(--signal-danger);
  color: #ffffff;
}

/* sengaja di-shutdown dari sisi switch */
.pport.adm {
  background: var(--signal-warn-bg);
  border-color: var(--signal-warn);
  color: var(--signal-warn);
}

/* tidak ada config tapi link hidup — ada kabel nyantol yang belum didaftar */
.pport.stray {
  background: var(--bg-card-hover);
  border-color: var(--text-secondary);
  color: var(--text-secondary);
}

/* port uplink ke router */
.pport.uplink {
  background: var(--primary);
  border-color: var(--primary);
  color: #ffffff;
}

@keyframes netman-live {
  0%, 100% { box-shadow: 0 0 0 0 rgba(24, 128, 56, 0.55); }
  50%      { box-shadow: 0 0 0 3px rgba(24, 128, 56, 0); }
}

.legend {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  font-size: 10.5px;
  color: var(--text-muted);
  margin-top: 8px;
}
.legend span { display: inline-flex; align-items: center; gap: 5px; }
.legend i {
  width: 11px;
  height: 9px;
  border-radius: 2px;
  border: 1px solid var(--border-subtle);
  display: inline-block;
}
.legend i.free { border-style: dashed; background: var(--bg-surface); }
.legend i.on   { background: var(--signal-good); border-color: var(--signal-good); }
.legend i.los  { background: var(--signal-danger); border-color: var(--signal-danger); }
.legend i.adm  { background: var(--signal-warn-bg); border-color: var(--signal-warn); }
.legend i.stray{ background: var(--bg-card-hover); border-color: var(--text-secondary); }
.legend i.uplink { background: var(--primary); border-color: var(--primary); }

/* --- baris peringatan per perangkat --- */
.alert-row {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-bottom: 10px;
}
.alert-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 10px;
  border-radius: var(--radius-full);
  font-size: 11.5px;
  font-weight: 600;
  border: 1px solid transparent;
}
.alert-pill.danger { background: var(--signal-danger-bg); color: var(--signal-danger); }
.alert-pill.warn   { background: var(--signal-warn-bg);   color: var(--signal-warn); }
.alert-pill.ok     { background: var(--signal-good-bg);   color: var(--signal-good); }
.alert-pill.info   { background: var(--bg-card-hover);    color: var(--text-secondary); }
.alert-pill b { font-weight: 800; }

.port-link {
  font-family: var(--font-mono);
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 2px;
}

/* Cincin dalam kuning = redaman menipis. Ditumpuk DI ATAS warna keadaan port
   (hijau/merah), bukan menggantikannya: satu port bisa saja hidup dan bertrafik
   tapi redamannya sudah mendekati ambang — dua kabar berbeda yang dua-duanya
   perlu terlihat. */
.pport.optic-bad {
  box-shadow: inset 0 0 0 2px var(--signal-warn);
}

/* ------------------------------ tabel di layar sempit ------------------------------
   Petugas menandai lunas sambil berdiri di depan rumah pelanggan, satu tangan
   memegang HP. Kalau tombolnya baru kelihatan setelah menggeser tabel ke
   samping, aksi yang paling sering dipakai justru jadi yang paling sulit
   dijangkau. Jadi di layar sempit kolom yang bisa ditunda disembunyikan, dan
   yang tersisa cukup: siapa, berapa, sudah/belum, tombolnya. */
.only-sempit { display: none; }

@media (max-width: 767px) {
  .hide-sempit { display: none !important; }
  .only-sempit { display: block; }
  /* tanpa kolom yang disembunyikan, lebar minimumnya tidak perlu lagi —
     biarkan tabelnya muat tanpa geser ke samping */
  .data-table.rapat-di-hp { min-width: 0; }
  .data-table.rapat-di-hp th,
  .data-table.rapat-di-hp td { padding: 10px 6px; }
}


/* ------------------------------ kartu yang bisa diklik ------------------------------ */
/* Angka di dashboard adalah pertanyaan ("149 belum bayar" -> siapa saja?).
   Membuatnya tautan berarti jawabannya sejauh satu klik, bukan mencari sendiri
   lewat menu dan penyaring. Tampilannya harus tetap kartu, bukan teks biru
   bergaris bawah. */
a.stat-card {
  text-decoration: none;
  color: inherit;
  transition: transform .12s ease, box-shadow .12s ease, border-color .12s ease;
}
a.stat-card:hover {
  transform: translateY(-1px);
  box-shadow: var(--shadow-lg);
  border-color: var(--border-strong, var(--border-subtle));
}
a.stat-card:active { transform: none; }

/* Penyaring yang sedang dipakai ditandai, supaya orang tahu daftar di bawah
   ini sudah tersaring — bukan mengira itu seluruh datanya. */
a.stat-card.stat-aktif {
  border-color: var(--primary);
  box-shadow: 0 0 0 1px var(--primary) inset;
}
