/* SH Manager — tema gelap.
   Warna diambil dari palet referensi data-viz pada surface gelapnya sendiri
   (page #0d0d0d, kartu #1a1a19), jadi kontras & status-nya sudah tervalidasi. */

:root {
  color-scheme: dark;

  --plane:        #0d0d0d;   /* latar halaman */
  --surface:      #1a1a19;   /* kartu / panel */
  --surface-2:    #222221;   /* elemen dalam kartu */
  --screen-bg:    #050505;   /* kotak layar HP */

  --ink:          #ffffff;
  --ink-2:        #c3c2b7;
  --ink-muted:    #898781;
  --grid-line:    #2c2c2a;
  --baseline:     #383835;
  --hairline:     rgba(255,255,255,.10);

  --series-1:     #3987e5;   /* seri tunggal grafik */
  --accent:       #3987e5;

  --good:         #0ca30c;
  --warning:      #fab219;
  --serious:      #ec835a;
  --critical:     #d03b3b;

  --r:            10px;
  --r-sm:         7px;
  --tile-w:       164px;

  font-family: system-ui, -apple-system, "Segoe UI", sans-serif;
}

* { box-sizing: border-box; }

html, body {
  margin: 0; padding: 0; height: 100%;
  background: var(--plane); color: var(--ink);
  font-size: 14px; line-height: 1.45;
}

.hidden { display: none !important; }
.grow { flex: 1 1 auto; }
.mono { font-family: ui-monospace, "Cascadia Mono", Consolas, monospace; }
.small { font-size: 12px; }
.tiny { font-size: 11.5px; }
code { font-family: ui-monospace, Consolas, monospace; background: var(--surface-2); padding: 1px 4px; border-radius: 4px; }

/* ---------------------------------------------------------------- topbar */

.topbar {
  display: flex; align-items: center; gap: 18px;
  padding: 10px 16px;
  background: var(--surface);
  border-bottom: 1px solid var(--hairline);
  position: sticky; top: 0; z-index: 40;
  flex-wrap: wrap;
}
.brand { display: flex; align-items: center; gap: 9px; font-size: 15px; white-space: nowrap; }
.brand-mark { font-size: 19px; }
.brand-text b { font-weight: 650; }

.statrow { display: flex; gap: 8px; flex: 1 1 auto; flex-wrap: wrap; }
.stat {
  background: var(--surface-2); border: 1px solid var(--hairline);
  border-radius: var(--r-sm); padding: 5px 11px; min-width: 74px;
}
.stat b { display: block; font-size: 17px; line-height: 1.15; font-weight: 640; }
.stat span { font-size: 11px; color: var(--ink-muted); }
.stat.is-good b   { color: var(--good); }
.stat.is-warn b   { color: var(--warning); }
.stat.is-crit b   { color: var(--critical); }

.topbar-actions { display: flex; align-items: center; gap: 9px; }
.conn { display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--ink-muted); }
.conn i { width: 8px; height: 8px; border-radius: 50%; background: var(--ink-muted); }
.conn.ok i   { background: var(--good); }
.conn.bad i  { background: var(--critical); }

.banner {
  padding: 9px 16px; background: #3a1d1d; color: #ffd9d9;
  border-bottom: 1px solid var(--hairline); font-size: 13px;
}

/* ---------------------------------------------------------------- layout */

.layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 390px;
  gap: 14px; padding: 14px;
  align-items: start;
}
@media (max-width: 1180px) { .layout { grid-template-columns: minmax(0, 1fr); } }

/* Panel kanan disembunyikan supaya grid HP dapat seluruh lebar layar. Kolomnya
   dihapus dari grid, bukan cuma panelnya disembunyikan — kalau tidak, sisa 390px
   tetap kosong dan tidak ada yang bertambah lega. Panelnya tetap ada di DOM,
   jadi semua isinya tetap hidup dan langsung siap saat dibuka lagi. */
.layout.panel-tutup { grid-template-columns: minmax(0, 1fr); }
.layout.panel-tutup > .panel { display: none; }

.wall {
  background: var(--surface); border: 1px solid var(--hairline);
  border-radius: var(--r); padding: 12px; min-width: 0;
}
.wall-toolbar { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin-bottom: 12px; }
.selinfo { font-size: 12px; color: var(--ink-2); }
.selinfo b { color: var(--ink); }

.grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(var(--tile-w), 1fr));
  gap: 10px;
}
.empty { padding: 30px; text-align: center; color: var(--ink-muted); }

/* ---------------------------------------------------------------- tile */

.tile {
  background: var(--surface-2); border: 1px solid var(--hairline);
  border-radius: var(--r); padding: 8px; cursor: pointer;
  display: flex; flex-direction: column; gap: 6px;
  transition: border-color .12s, box-shadow .12s;
  position: relative; user-select: none;
}
.tile:hover { border-color: #4a4a47; }
.tile.selected { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
.tile.is-offline { opacity: .58; }

.tile-head { display: flex; align-items: center; gap: 6px; font-size: 12px; }
.tile-head .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--ink-muted); flex: none; }
.tile-head .dot.online { background: var(--good); }
.tile-head .dot.warn   { background: var(--warning); }
.tile-head .dot.bad    { background: var(--critical); }
.tile-head .slot { font-variant-numeric: tabular-nums; color: var(--ink-muted); font-size: 11px; }
.tile-head .name { flex: 1 1 auto; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 560; }
.tile-head .batt { font-variant-numeric: tabular-nums; font-size: 11.5px; color: var(--ink-2); flex: none; }
.tile-head .batt.low  { color: var(--critical); }
.tile-head .batt.mid  { color: var(--warning); }
.tile-head .batt.chg::after { content: "⚡"; }
.tile-head .batt.pwr::after { content: " ⌁"; color: var(--ink-muted); }

.screen {
  position: relative; background: var(--screen-bg);
  border-radius: var(--r-sm); overflow: hidden;
  aspect-ratio: 9 / 16; display: flex; align-items: center; justify-content: center;
}
.screen img { width: 100%; height: 100%; object-fit: contain; display: block; }
.screen .ph { color: #3a3a38; font-size: 11px; }
/* Video ubin mode Live. Dibuat persis seperti <img> yang digantikannya supaya
   ubin tidak berubah ukuran saat mode Live dinyalakan atau dimatikan. */
.tile-live { width: 100%; height: 100%; object-fit: contain; display: block; background: var(--screen-bg); }
/* Penanda tipis bahwa ubin ini bergerak langsung, bukan gambar diam. */
.screen.is-live::after {
  content: "⚡"; position: absolute; right: 4px; top: 3px;
  font-size: 9px; line-height: 1; color: #ffdb92; opacity: .85;
  pointer-events: none; text-shadow: 0 0 3px rgba(0,0,0,.9);
}
.screen .off {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
  font-size: 10px; color: var(--ink-muted); letter-spacing: .04em;
  background: rgba(13,13,13,.75); padding: 2px 7px; border-radius: 999px;
  border: 1px solid var(--hairline); pointer-events: none;
}

.tile-meta {
  display: flex; align-items: center; gap: 6px;
  font-size: 11px; color: var(--ink-muted); min-height: 15px;
}
.tile-meta .ssid { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 1 1 auto; }
.tile-meta .ssid.via-wifi { color: var(--series-1); }
.bars { display: inline-flex; align-items: flex-end; gap: 1.5px; height: 10px; }
.bars i { width: 2.5px; background: var(--baseline); border-radius: 1px; }
.bars i:nth-child(1) { height: 3px; } .bars i:nth-child(2) { height: 5px; }
.bars i:nth-child(3) { height: 7.5px; } .bars i:nth-child(4) { height: 10px; }
.bars i.on { background: var(--good); }
.bars.weak i.on { background: var(--warning); }

.tile-alerts { display: flex; flex-wrap: wrap; gap: 3px; min-height: 0; }
.chip {
  font-size: 10px; padding: 1px 6px; border-radius: 999px;
  background: rgba(208,59,59,.16); color: #ffb3b3; white-space: nowrap;
}
.chip.warn { background: rgba(250,178,25,.16); color: #ffdb92; }

.tile-actions { display: flex; gap: 5px; }
.tile-actions .btn { flex: 1 1 0; padding: 3px 0; font-size: 11px; }

.bar { height: 3px; background: var(--baseline); border-radius: 2px; overflow: hidden; }
.bar i { display: block; height: 100%; width: 0; background: var(--accent); transition: width .25s; }
.bar i.ok   { background: var(--good); }
.bar i.bad  { background: var(--critical); }

/* ---------------------------------------------------------------- panel */

.panel {
  background: var(--surface); border: 1px solid var(--hairline);
  border-radius: var(--r); overflow: hidden;
  position: sticky; top: 74px; max-height: calc(100vh - 90px);
  display: flex; flex-direction: column;
}
@media (max-width: 1180px) { .panel { position: static; max-height: none; } }

.tabs { display: flex; border-bottom: 1px solid var(--hairline); background: var(--surface-2); flex: none; }
.tab {
  flex: 1 1 0; padding: 9px 4px; background: none; border: 0; cursor: pointer;
  color: var(--ink-muted); font-size: 12px; font-family: inherit;
  border-bottom: 2px solid transparent;
}
.tab:hover { color: var(--ink-2); }
/* Tombol lipat panel. `flex: none` supaya ia tidak ikut mengambil lebar sama
   dengan tab lain — isinya cuma satu tanda. */
.tab-lipat {
  flex: none; width: 30px; padding: 9px 0; font-size: 14px; line-height: 1;
  border-left: 1px solid var(--hairline);
}
.tab-lipat:hover { color: var(--ink); background: var(--surface); }
.tab.active { color: var(--ink); border-bottom-color: var(--accent); background: var(--surface); }

.tabpane { display: none; padding: 12px; overflow-y: auto; }
.tabpane.active { display: block; }

.group { border: 1px solid var(--hairline); border-radius: var(--r-sm); margin-bottom: 9px; background: var(--surface-2); }
.group > summary { padding: 8px 11px; cursor: pointer; font-size: 12.5px; font-weight: 560; list-style: none; }
.group > summary::-webkit-details-marker { display: none; }
.group > summary::before { content: "▸ "; color: var(--ink-muted); }
.group[open] > summary::before { content: "▾ "; }
.group > *:not(summary) { margin: 0 11px 9px; }
.group.static { padding: 11px; }
.group.static > * { margin: 0 0 9px; }

.section-label { font-size: 12px; font-weight: 620; color: var(--ink-2); padding: 6px 0 2px; margin: 0 11px !important; border-top: 1px solid var(--hairline); }
.section-label:first-of-type { border-top: none; padding-top: 0; }

.chart-bar { display: flex; gap: 2px; align-items: flex-end; height: 60px; margin: 0 11px 6px; }
.chart-bar .bar-col { flex: 1; background: var(--accent); border-radius: 2px 2px 0 0; min-height: 2px; position: relative; }
.chart-bar .bar-col.fail { background: var(--critical); }
.chart-bar .bar-col span { position: absolute; bottom: -16px; left: 0; right: 0; text-align: center; font-size: 9px; color: var(--ink-muted); }

.stat { text-align: center; min-width: 60px; }
.stat b { display: block; font-size: 18px; }
.stat span { font-size: 10px; color: var(--ink-muted); }
.stat.is-good b { color: var(--good); }
.stat.is-warn b { color: var(--warning); }
.stat.is-crit b { color: var(--critical); }

/* Kapabilitas sosial */
/* Blok kesiapan HP yang bisa dilipat. Tertutup secara bawaan: isinya 20 chip dan
   itu mendorong seluruh tombol aksi ke luar layar. Ringkasan per aplikasi tetap
   tampil di baris judulnya, jadi melipatnya tidak menyembunyikan informasi. */
.sos-cap-box { margin: 0 11px 6px; }
.sos-cap-box > summary {
  display: flex; align-items: center; gap: 8px; cursor: pointer;
  font-size: 12px; color: var(--ink-2); padding: 3px 0; list-style: none;
}
.sos-cap-box > summary::-webkit-details-marker { display: none; }
.sos-cap-box > summary::before {
  content: "▸"; color: var(--ink-muted); font-size: 10px; flex: none;
  transition: transform .15s;
}
.sos-cap-box[open] > summary::before { transform: rotate(90deg); }
.sos-cap-box > summary:hover { color: var(--ink); }
.sos-cap-box .cap-ringkas {
  color: var(--ink-muted); font-size: 11px; margin-left: auto;
  font-variant-numeric: tabular-nums; text-align: right;
}
.sos-cap-box .cap-ringkas b { color: var(--ink-2); font-weight: 600; }
.sos-cap-box .cap-ringkas .r-warn { color: var(--warning); }
.sos-cap-box .cap-ringkas .r-bad  { color: var(--critical); }
.sos-cap-box > summary + * { margin-top: 4px; }

.sos-cap-summary { margin: 0 0 6px; font-size: 12px; }
.sos-cap-summary .cap-bar { display: flex; gap: 6px; flex-wrap: wrap; }
.sos-cap-summary .cap-chip { padding: 3px 8px; border-radius: 12px; font-size: 11.5px; display: inline-flex; align-items: center; gap: 4px; cursor: pointer; }
.sos-cap-summary .cap-chip:hover { outline: 1px solid var(--grid-line); }
/* Baris HP yang sedang terpilih di tabel kesiapan. Kelasnya sudah dipasang kode
   sejak lama tapi tidak punya aturan apa pun, jadi penandanya tak pernah terlihat. */
.sos-cap-detail tr.row-sel { background: rgba(90, 140, 255, .12); }
.sos-cap-detail tr.row-sel td:first-child { box-shadow: inset 2px 0 0 var(--accent); }
.sos-cap-summary .cap-chip.good { background: rgba(12,163,12,.18); color: var(--good); }
.sos-cap-summary .cap-chip.warn { background: rgba(250,178,25,.18); color: var(--warning); }
.sos-cap-summary .cap-chip.bad  { background: rgba(208,59,59,.18); color: var(--critical); }
.sos-cap-detail { margin: 0 0 4px; }
.sos-cap-detail > summary { font-size: 11.5px; cursor: pointer; color: var(--ink-muted); }
.sos-cap-detail .v-yes { color: var(--good); }
.sos-cap-detail .v-no  { color: var(--critical); }
.sos-cap-detail .v-unk { color: var(--ink-muted); }

.row { display: flex; gap: 6px; align-items: center; }
.row.wrap { flex-wrap: wrap; }
.grid2 { display: grid; grid-template-columns: 1fr 1fr; gap: 6px 8px; }
.field { display: flex; flex-direction: column; gap: 3px; }
.field label { font-size: 11px; color: var(--ink-muted); }

.hint { color: var(--ink-muted); font-size: 12px; margin: 0 0 9px; }
.hint b { color: var(--ink); }

.input {
  background: var(--plane); color: var(--ink);
  border: 1px solid var(--hairline); border-radius: var(--r-sm);
  padding: 6px 9px; font-size: 12.5px; font-family: inherit; min-width: 0; flex: 1 1 auto;
}
.input:focus { outline: none; border-color: var(--accent); }
/* Kotak banyak baris: lebar penuh dan hanya bisa ditarik vertikal, supaya tidak
   merusak tata letak kolom di sebelahnya. */
textarea.input { width: 100%; resize: vertical; line-height: 1.45; }
.input.slim { flex: 0 1 auto; max-width: 150px; }
.input[type=file] { padding: 4px; }
.input[type=number] { font-variant-numeric: tabular-nums; }

.check { display: flex; align-items: center; gap: 5px; font-size: 11.5px; color: var(--ink-2); }
.switch { display: flex; align-items: center; gap: 5px; font-size: 12px; color: var(--ink-2); cursor: pointer; }

.btn {
  background: var(--surface-2); color: var(--ink);
  border: 1px solid var(--hairline); border-radius: var(--r-sm);
  padding: 6px 11px; font-size: 12.5px; font-family: inherit; cursor: pointer;
  white-space: nowrap; flex: none;
}
.btn:hover:not(:disabled) { border-color: #55554f; background: #2b2b29; }
.btn:disabled { opacity: .45; cursor: not-allowed; }
.btn.accent { background: var(--accent); border-color: var(--accent); color: #fff; }
.btn.accent:hover:not(:disabled) { background: #2f76cf; }
.btn.sending { background: var(--warning) !important; border-color: var(--warning) !important; color: #000 !important; opacity: 1 !important; cursor: wait; animation: pulse-btn 0.8s ease-in-out infinite; }
@keyframes pulse-btn { 0%, 100% { opacity: 1; } 50% { opacity: 0.55; } }
.btn.ghost { background: transparent; }
.btn.warn { border-color: #6b5316; color: #ffdb92; }
.btn.danger { border-color: #6b2626; color: #ffb3b3; }
.btn.danger:hover:not(:disabled) { background: #331616; }

.keypad { display: grid; grid-template-columns: repeat(3, 1fr); gap: 5px; }
.keypad .btn { padding: 6px 2px; font-size: 11.5px; }

/* ---------------------------------------------------------------- daftar & tabel */

.list { display: flex; flex-direction: column; gap: 5px; max-height: 340px; overflow-y: auto; }
.list-item {
  background: var(--plane); border: 1px solid var(--hairline); border-radius: var(--r-sm);
  padding: 7px 9px; font-size: 12px; display: flex; gap: 8px; align-items: center;
}
.list-item .grow { overflow: hidden; text-overflow: ellipsis; }
.list-item .meta { color: var(--ink-muted); font-size: 11px; }
.list-item .tag { background: var(--accent); color: #fff; border-radius: 10px; padding: 2px 8px; font-size: 10.5px; font-weight: 700; min-width: 22px; text-align: center; flex: none; }

.tablewrap { overflow-x: auto; max-height: 60vh; }
.table { width: 100%; border-collapse: collapse; font-size: 11.5px; }
.table th, .table td { text-align: left; padding: 5px 7px; border-bottom: 1px solid var(--grid-line); white-space: nowrap; }
.table th { color: var(--ink-muted); font-weight: 500; position: sticky; top: 0; background: var(--surface); }
.table td { font-variant-numeric: tabular-nums; }
.table td.name { font-variant-numeric: normal; }
/* Tabel di panel Bantuan berisi kalimat, bukan angka: isinya harus boleh turun
   baris. Tabel data justru sebaliknya — dipotong lebih enak dibaca daripada
   dibungkus, karena itu aturan nowrap di atas tetap jadi bawaan. */
.table.wrap { font-size: 12px; }
.table.wrap th, .table.wrap td { white-space: normal; vertical-align: top; }
.table.wrap td:first-child { font-variant-numeric: normal; }
.v-good { color: var(--good); } .v-warn { color: var(--warning); } .v-crit { color: var(--critical); }
.v-dim { color: var(--ink-muted); font-size: 10.5px; }

/* Sel tabel yang bisa diedit langsung (tab Akun). */
.table input.cell {
  background: transparent; border: 1px solid transparent; border-radius: 4px;
  color: var(--ink); font-family: inherit; font-size: 11.5px;
  padding: 2px 5px; width: 100%; min-width: 90px;
}
.table input.cell:hover { border-color: var(--grid-line); }
.table input.cell:focus { outline: none; border-color: var(--accent); background: var(--plane); }
.table input.cell.saved { border-color: var(--good); }
.table input.cell::placeholder { color: #4a4a46; }

.alerts { display: flex; flex-direction: column; gap: 4px; margin-bottom: 10px; }
.alert-row {
  background: rgba(208,59,59,.10); border-left: 2px solid var(--critical);
  padding: 5px 9px; border-radius: 4px; font-size: 11.5px;
}
.alert-row.warn { background: rgba(250,178,25,.10); border-left-color: var(--warning); }
.alert-row b { font-weight: 580; }

.jobcard { background: var(--plane); border: 1px solid var(--hairline); border-radius: var(--r-sm); padding: 8px 10px; }
.jobcard .jobhead { display: flex; gap: 8px; align-items: baseline; font-size: 12px; margin-bottom: 5px; }
.jobcard .jobhead .grow { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.jobcard .st { font-size: 10.5px; padding: 1px 6px; border-radius: 999px; background: var(--surface-2); color: var(--ink-2); }
.jobcard .st.selesai { background: rgba(12,163,12,.18); color: #97e397; }
.jobcard .st.gagal, .jobcard .st.dibatalkan { background: rgba(208,59,59,.18); color: #ffb3b3; }
.jobcard .st.sebagian { background: rgba(250,178,25,.18); color: #ffdb92; }
.jobitems { margin-top: 6px; max-height: 170px; overflow-y: auto; font-size: 11px; }
.jobitems div { display: flex; gap: 6px; padding: 3px 0; border-top: 1px solid var(--grid-line); }
.jobitems .out { color: var(--ink-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 1 1 auto; }
/* Baris yang GAGAL dibiarkan membungkus penuh. Alasan kegagalan justru ada di
   ujung kalimat — memotongnya dengan elipsis membuang satu-satunya info berguna. */
.jobitems div.bad { align-items: flex-start; }
.jobitems div.bad .out {
  white-space: normal; overflow: visible; text-overflow: clip;
  color: #ffb3b3; line-height: 1.35;
}
.jobitems div.bad > span:first-child { color: var(--critical); }

/* Sukses yang buktinya TIDAK penuh. Diperlakukan sama seperti baris gagal dalam
   satu hal yang menentukan: catatannya ada di ujung kalimat, jadi barisnya harus
   membungkus penuh. Warnanya kuning, bukan merah — pekerjaannya kemungkinan besar
   berhasil, yang tidak ada hanyalah buktinya. */
.jobitems div.ragu { align-items: flex-start; }
.jobitems div.ragu .out {
  white-space: normal; overflow: visible; text-overflow: clip;
  color: #ffdb92; line-height: 1.35;
}
.jobitems div.ragu > span:first-child { color: var(--warning); }

/* ---------------------------------------------------------------- modal */

.modal {
  position: fixed; inset: 0; background: rgba(0,0,0,.72);
  display: flex; align-items: center; justify-content: center; z-index: 90; padding: 18px;
}
.modal-card {
  background: var(--surface); border: 1px solid var(--hairline); border-radius: var(--r);
  width: min(940px, 100%); max-height: 92vh; display: flex; flex-direction: column; overflow: hidden;
}
/* `flex-wrap: wrap` di sini bukan kosmetik. Tanpa itu, deretan tombol meluber ke
   kanan dan `.modal-card` yang ber-`overflow:hidden` MEMOTONGNYA — di layar HP,
   tombol ✕ yang berada paling kanan jadi benar-benar tidak bisa dijangkau, bukan
   sekadar perlu digeser. */
.modal-head { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; padding: 10px 14px; border-bottom: 1px solid var(--hairline); }
.modal-head h2 { margin: 0; font-size: 15px; font-weight: 600; min-width: 0; }

@media (max-width: 720px) {
  /* Layar sempit: judul + ✕ selalu di baris pertama, tombol aksi turun ke baris
     kedua. Tombol tutup harus ada di tempat yang dicari orang — pojok kanan atas —
     dan tidak boleh pernah ikut terdorong. */
  .modal { padding: 6px; }
  .modal-card { max-height: 96vh; }
  /* Gap 6px, bukan 8px: lebar dalam header di layar 384px cuma 341px, sedangkan
     ketiga tombol aksi butuh 114+115+101 = 330px. Dengan gap 8px totalnya 346px —
     lewat 5px, dan 5px itu membuang satu baris penuh (header jadi 144px, seperlima
     layar HP). Padding tombol ikut dikecilkan supaya ada kelonggaran, bukan pas-pasan. */
  .modal-head { padding: 8px 10px; gap: 6px; }
  .modal-head h2 { flex: 1 1 auto; font-size: 14px; }
  /* Pemisah baris setinggi nol: memaksa tombol aksi turun ke baris kedua supaya
     baris pertama HANYA berisi judul dan ✕. Tanpa ini ✕ terjepit di antara judul
     dan tombol scrcpy — masih bisa disentuh, tapi bukan tempat orang mencarinya,
     dan bersebelahan dengan tombol yang membuka scrcpy kalau salah sentuh. */
  .modal-head::after { content: ""; flex-basis: 100%; height: 0; order: 1; }
  #modal-close { order: 0; margin-left: auto; }
  #modal-mirror, #modal-ukur, #modal-shot { order: 2; }
  /* Sasaran sentuh yang layak jari, bukan kursor. Tinggi naik, lebar dihemat —
     ✕ tidak terpengaruh karena selektor id-nya menang atas yang ini. */
  .modal-head .btn { min-height: 34px; padding-left: 7px; padding-right: 7px; }
  #modal-close { min-width: 44px; font-size: 16px; }
}
.modal-body { display: grid; grid-template-columns: 300px minmax(0, 1fr); gap: 16px; padding: 14px; overflow-y: auto; }
@media (max-width: 720px) { .modal-body { grid-template-columns: 1fr; } }

/* Mode perbesar: panel info disembunyikan, layar HP mengisi seluruh lebar modal
   dan dibatasi tinggi viewport supaya tetap utuh tanpa perlu menggulir. */
.modal-card.zoom { width: min(560px, 100%); }
.modal-card.zoom .modal-body { grid-template-columns: minmax(0, 1fr); }
.modal-card.zoom .modal-info { display: none; }
.modal-card.zoom .modal-screen img { max-height: 74vh; width: auto; max-width: 100%; margin: 0 auto; }
.modal-card.zoom .modal-screen { display: flex; flex-direction: column; align-items: center; }
.modal-card.zoom .mirror-bar,
.modal-card.zoom .navbar-mini { width: min(340px, 100%); }
#btn-zoom { padding: 3px 9px; font-size: 13px; }
.modal-screen img,
.modal-screen video {
  width: 100%; background: var(--screen-bg); border-radius: var(--r-sm);
  cursor: crosshair; display: block; border: 1px solid var(--hairline);
  /* Cegah browser menyeret gambar / menggulir halaman saat menyeret di layar HP. */
  touch-action: none; user-select: none; -webkit-user-drag: none;
}
.modal-card.zoom .modal-screen video { max-height: 74vh; width: auto; max-width: 100%; margin: 0 auto; }
.modal-screen video.hidden, .modal-screen img.hidden { display: none; }
#smooth-label { font-weight: 600; }

/* Gema sentuhan. Sengaja di luar alur tata letak: teks yang berubah panjang di
   dalam alur akan melipat ulang baris kontrol, menggeser video, dan mengubah tap
   jadi seret di tengah gerakan. */
.modal-screen { position: relative; }
.touch-echo {
  position: absolute; left: 8px; top: 8px; pointer-events: none;
  background: rgba(0,0,0,.6); color: #fff; font-size: 11px;
  padding: 2px 7px; border-radius: 6px; font-variant-numeric: tabular-nums;
}
.touch-echo:empty { display: none; }

/* Kilatan sentuh — digambar DI PERANGKAT INI, tanpa menunggu gambar dari HP.
 *
 * Lewat cermin, satu ketukan butuh perjalanan bolak-balik penuh sebelum
 * hasilnya terlihat (terukur 97 ms median dari LAN, lebih lama lewat internet).
 * Layar yang diam selama itu terbaca sebagai "ketukanku tidak masuk", lalu
 * orang mengetuk lagi — dan ketukan kedua itulah yang berbahaya: di kolom
 * komentar jadi huruf dobel, di tombol Like jadi like lalu unlike.
 *
 * Kilatan ini tidak mempercepat apa pun. Ia hanya menjawab "ketukanmu diterima"
 * seketika, sehingga tak ada alasan mengetuk dua kali.
 *
 * Sengaja di luar alur tata letak, alasan yang sama dengan .touch-echo: apa pun
 * yang menambah tinggi di sini akan menggeser video di tengah gerakan jari. */
.tap-kilat {
  position: absolute; width: 36px; height: 36px; margin: -18px 0 0 -18px;
  border-radius: 50%; pointer-events: none; z-index: 3;
  border: 2px solid rgba(255, 255, 255, .95);
  background: rgba(255, 255, 255, .25);
  /* Garis gelap tipis di luar cincin putih: layar HP bisa putih polos (kolom
     teks, daftar) dan cincin putih saja lenyap di atasnya. */
  box-shadow: 0 0 0 1px rgba(0, 0, 0, .5), 0 0 0 1px rgba(0, 0, 0, .5) inset;
  animation: tap-kilat .40s ease-out forwards;
}
@keyframes tap-kilat {
  from { transform: scale(.35); opacity: .95; }
  to   { transform: scale(1.6); opacity: 0; }
}
/* Menghormati pengguna yang mematikan animasi di sistemnya: kilatannya tetap
   ada (itu justru inti fiturnya), hanya tidak membesar — muncul lalu hilang. */
@media (prefers-reduced-motion: reduce) {
  .tap-kilat { animation: tap-kilat-diam .40s steps(2, end) forwards; }
  @keyframes tap-kilat-diam { from { opacity: .95; } to { opacity: 0; } }
}
.mirror-bar { margin-top: 7px; gap: 6px 8px; flex-wrap: wrap; }
.mirror-bar .input.slim { max-width: 92px; padding: 3px 6px; font-size: 11.5px; }
/* Kolom layar sempit, jadi baris ini memang membungkus. Tombol perbesar didorong
   ke tepi kanan supaya terlihat disengaja, bukan tercecer di awal baris baru. */
#btn-zoom { margin-left: auto; }

/* Baris papan ketik: hanya muncul saat mode Ketik menyala. */
.kbd-bar { align-items: center; }
.kbd-bar .btn { padding: 3px 8px; font-size: 11.5px; }
.kbd-text { flex: 1 1 150px; min-width: 110px; padding: 3px 7px; font-size: 12px; }
.kbd-status { font-size: 11px; color: var(--ink-muted); }
.kbd-status.on { color: var(--good); }
.kbd-status.off { color: var(--warning); }

/* ===========================================================================
   Mode operasi di HP.

   Masalah yang diperbaiki: di layar 360-412px, gambar HP setinggi ~780px
   mendorong SEMUA kendali ke bawah garis pandang. Untuk menyentuh layar HP
   orang harus menggulir ke atas, untuk menekan Back menggulir ke bawah lagi —
   jendela mirror praktis tak bisa dioperasikan dari HP.

   Penyelesaiannya bukan mengecilkan tulisan, melainkan membuang yang tidak
   dipakai saat mengoperasikan: mode video, Live, ukur elemen, dan scrcpy-di-PC
   pindah ke balik ⚙; catatan & grafik ke balik ℹ. Sisanya - layar, Sentuh,
   Ketik, dan tombol navigasi - muat dalam satu layar tanpa digulir.
   =========================================================================== */

/* ⚙ dan ℹ tidak ada gunanya di layar lebar: di sana semuanya sudah muat, dan
   melipatnya hanya menambah satu ketukan tanpa menghemat apa pun. */
.hp-saja { display: none; }

@media (max-width: 720px) {
  .hp-saja { display: inline-flex; }

  /* Seluruh layar. Tak ada apa pun di belakang jendela ini yang bisa dilihat di
     HP, jadi setiap piksel yang dipakai bingkai adalah piksel yang hilang dari
     layar HP yang sedang dikendalikan. */
  .modal { padding: 0; }
  .modal-card { width: 100%; height: 100dvh; max-height: none; border: 0; border-radius: 0; }

  /* Kepala kembali SATU baris. Pemisah baris di aturan 720px di atas dipasang
     saat tiga tombol aksi masih ada di sana; sekarang mereka bersembunyi di
     balik ⚙, jadi pemisah itu hanya menyisakan baris kosong — dihidupkan lagi
     hanya ketika ⚙ ditekan dan tombolnya benar-benar muncul. */
  .modal-head::after { display: none; }
  .modal-card.lanjut .modal-head::after { display: block; }

  .modal-card:not(.lanjut) .lanjutan { display: none; }
  .modal-card:not(.info) .modal-info,
  .modal-card:not(.info) #mirror-hint { display: none; }

  /* Rantai tinggi yang PASTI: kartu 100dvh -> body -> kolom layar. Tanpa salah
     satu mata rantai ini, `max-height:100%` pada gambar tak punya acuan dan
     diabaikan browser — gambarnya kembali meluber ke bawah layar. */
  .modal-body { display: flex; flex-direction: column; flex: 1; min-height: 0; gap: 8px; padding: 8px; }
  .modal-screen { display: grid; grid-template-rows: minmax(0, 1fr); gap: 6px; flex: 1; min-height: 0; }

  /* Layar HP mengisi sisa ruang. `object-fit: contain` dipakai supaya gambar
     juga DIPERBESAR saat sumbernya kecil — tangkapan layar diam hanya 180x320,
     dan dengan `width:auto` ia akan tampil sebesar perangko di tengah layar.

     Bilah kosong yang ditinggalkan object-fit membuat kotak elemen lebih besar
     daripada gambarnya. Itu ditangani di sisi JS oleh `kotakIsi()`, yang dipakai
     pointOnDevice() dan pointOnVideo(); tanpa itu setiap ketukan meleset sejauh
     lebar bilahnya, dan melesetnya tanpa gejala karena sentuhan tetap terkirim. */
  .modal-screen img, .modal-screen video, #modal-canvas {
    width: 100%; height: 100%; max-width: 100%; max-height: 100%;
    object-fit: contain; margin: 0;
  }

  /* Urutan menurut jangkauan jempol, bukan urutan di HTML: tombol navigasi
     tepat di bawah layar — di tempat bilah navigasi HP aslinya berada — lalu
     baris centang, lalu papan ketik. */
  .navbar-mini { order: 1; }
  .mirror-bar:not(.kbd-bar) { order: 2; }
  #kbd-bar { order: 3; }
  #screen-text { order: 4; }
  #mirror-hint { order: 5; }

  /* Sasaran sentuh seukuran jari, bukan kursor. */
  .mirror-bar { margin-top: 0; gap: 6px; }
  .mirror-bar .btn, .kbd-bar .btn { min-height: 40px; padding: 0 12px; font-size: 13px; }
  .mirror-bar .check { min-height: 40px; font-size: 13px; }
  .mirror-bar .check input[type="checkbox"] { width: 18px; height: 18px; }
  .navbar-mini { gap: 6px; }
  .navbar-mini .btn { flex: 1 1 0; min-height: 46px; font-size: 18px; }
  /* 16px: di bawah itu iOS memperbesar seluruh halaman saat kolom difokuskan,
     dan tata letak yang sudah pas jadi berantakan. */
  .kbd-text { min-height: 40px; font-size: 16px; }
  .mirror-bar .input.slim { max-width: 120px; font-size: 13px; min-height: 40px; }
}

/* Daftar teks layar HP — jalur salin HP -> PC saat tak ada kolom yang aktif. */
.screen-text {
  margin-top: 7px; padding: 8px 10px; background: var(--surface-2);
  border: 1px solid var(--hairline); border-radius: var(--r-sm);
}
.screen-text ul { list-style: none; margin: 4px 0 0; padding: 0; max-height: 190px; overflow-y: auto; }
.screen-text li {
  padding: 4px 6px; border-radius: var(--r-sm); font-size: 12px; cursor: pointer;
  word-break: break-word; border: 1px solid transparent;
}
.screen-text li:hover { background: var(--surface); border-color: var(--hairline); }
.navbar-mini { margin-top: 6px; gap: 5px; }
.navbar-mini .btn { flex: 1 1 0; padding: 4px 0; font-size: 13px; }
.modal-info { display: flex; flex-direction: column; gap: 9px; min-width: 0; }

/* IP publik di tile. Warna khusus untuk yang menyimpang dari mayoritas — itu yang
   perlu terlihat sekilas, entah karena memang ditunnel atau karena bocor. */
.tile .pubip {
  font-size: 10px; color: var(--ink-muted); padding: 0 8px 3px;
  font-variant-numeric: tabular-nums; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis;
}
.tile .pubip:empty { display: none; }
.tile .pubip.beda { color: var(--accent); font-weight: 600; }

/* ---------------------------------------------------------------- kirim media */

.media-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(84px, 1fr));
  gap: 7px; margin-top: 9px;
}
.media-item {
  position: relative; border: 2px solid transparent; border-radius: var(--r-sm);
  overflow: hidden; cursor: pointer; background: var(--surface-2); aspect-ratio: 1;
}
.media-item img { width: 100%; height: 100%; object-fit: cover; display: block; }
.media-item.on { border-color: var(--accent); }
/* Tanda centang hanya muncul saat terpilih — kotak kosong di tiap petak bikin
   gridnya ramai padahal informasinya nihil. */
.media-item .pick {
  position: absolute; top: 3px; left: 3px; width: 17px; height: 17px; border-radius: 50%;
  background: var(--accent); color: #fff; font-size: 11px; line-height: 17px;
  text-align: center; display: none;
}
.media-item.on .pick { display: block; }
.media-item .tag {
  position: absolute; bottom: 0; left: 0; right: 0; padding: 2px 4px;
  background: rgba(0,0,0,.65); color: #fff; font-size: 9.5px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.media-item .kill {
  position: absolute; top: 3px; right: 3px; width: 17px; height: 17px; border-radius: 50%;
  background: rgba(0,0,0,.6); color: #fff; border: 0; font-size: 11px; line-height: 17px;
  cursor: pointer; padding: 0;
}
.media-item .kill:hover { background: var(--critical); }
.media-item .vid {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  font-size: 22px; color: #fff; text-shadow: 0 1px 4px rgba(0,0,0,.8); pointer-events: none;
}

.kv { display: grid; grid-template-columns: auto 1fr; gap: 2px 12px; margin: 0; font-size: 12px; }
.kv dt { color: var(--ink-muted); }
.kv dd { margin: 0; font-variant-numeric: tabular-nums; }

/* ---------------------------------------------------------------- grafik */

.charts { display: grid; gap: 10px; }
.chart { margin: 0; position: relative; background: var(--surface-2); border: 1px solid var(--hairline); border-radius: var(--r-sm); padding: 8px 10px 6px; }
.chart figcaption { font-size: 11.5px; color: var(--ink-2); margin-bottom: 4px; }
.chart figcaption .unit { color: var(--ink-muted); }
.chart svg { width: 100%; height: 90px; display: block; overflow: visible; }
.chart .gridline { stroke: var(--grid-line); stroke-width: 1; vector-effect: non-scaling-stroke; }
.chart .axis { stroke: var(--baseline); stroke-width: 1; vector-effect: non-scaling-stroke; }
.chart .serie { fill: none; stroke: var(--series-1); stroke-width: 2; vector-effect: non-scaling-stroke;
                stroke-linejoin: round; stroke-linecap: round; }
.chart .cross { stroke: var(--ink-muted); stroke-width: 1; vector-effect: non-scaling-stroke; stroke-dasharray: 3 3; }
.chart .dot { fill: var(--series-1); stroke: var(--surface-2); stroke-width: 2; }
.chart .tick { fill: var(--ink-muted); font-size: 9px; }
.chart .nodata { fill: var(--ink-muted); font-size: 11px; }
.chart-tip {
  position: absolute; pointer-events: none; z-index: 5;
  background: var(--plane); border: 1px solid var(--hairline); border-radius: 5px;
  padding: 4px 8px; font-size: 11px; white-space: nowrap;
  font-variant-numeric: tabular-nums; transform: translate(-50%, -130%);
}

/* ---------------------------------------------------------------- toast */

.toasts { position: fixed; right: 16px; bottom: 16px; display: flex; flex-direction: column; gap: 7px; z-index: 120; }
.toast {
  background: var(--surface); border: 1px solid var(--hairline); border-left: 3px solid var(--accent);
  border-radius: var(--r-sm); padding: 9px 13px; font-size: 12.5px; max-width: 360px;
  box-shadow: 0 8px 24px rgba(0,0,0,.5); animation: slide .18s ease-out;
}
.toast.ok   { border-left-color: var(--good); }
.toast.bad  { border-left-color: var(--critical); }
.toast.warn { border-left-color: var(--warning); }
@keyframes slide { from { opacity: 0; transform: translateX(14px); } to { opacity: 1; transform: none; } }

::-webkit-scrollbar { width: 9px; height: 9px; }
::-webkit-scrollbar-track { background: var(--plane); }
::-webkit-scrollbar-thumb { background: #34342f; border-radius: 5px; }
::-webkit-scrollbar-thumb:hover { background: #454540; }

/* Ringkasan status login akun per platform (tab Akun). */
.akun-ringkas { display: flex; flex-wrap: wrap; gap: 7px; margin: 8px 0 10px; }
.akun-ringkas-item {
  border: 1px solid var(--hairline); border-radius: var(--r-sm);
  padding: 6px 10px; font-size: 11.5px; background: var(--surface-2);
}
.akun-ringkas-item .ar-plat { font-weight: 600; margin-right: 7px; }

/* Panel Lokasi & Proxy: daftar proxy aktif per HP + kotak peringatan terukur. */
.proxy-daftar { display: flex; flex-direction: column; gap: 4px; margin-top: 8px; }
.proxy-baris {
  display: flex; gap: 10px; align-items: baseline; font-size: 11.5px;
  border: 1px solid var(--hairline); border-radius: var(--r-sm);
  padding: 5px 9px; background: var(--surface-2);
}
.proxy-baris b { min-width: 74px; }
.warn-box {
  border: 1px solid var(--warn, #b8860b); border-radius: var(--r-sm);
  padding: 8px 10px; background: rgba(184, 134, 11, .10);
}

/* Permukaan gambar jalur WebCodecs. Ukurannya disamakan dengan <video> supaya
   berpindah jalur tidak mengubah tata letak jendela Detail sedikit pun. */
#modal-canvas { display: block; max-width: 100%; height: auto; border-radius: 8px;
                background: #000; touch-action: none; }
