* { box-sizing: border-box; }
html, body { margin: 0; height: 100%; font-family: "Segoe UI", system-ui, sans-serif; }
body { display: flex; flex-direction: column; }

#bar {
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
  background: #263238; color: #b3e5fc; padding: 8px 10px;
}
#bar button {
  border: 0; border-radius: 4px; padding: 7px 12px; cursor: pointer;
  background: #455a64; color: #fff; font-size: 13px;
}
#bar button:hover { filter: brightness(1.1); }
#bar button:disabled { opacity: .38; cursor: default; filter: none; }
#bar button.primary { background: #43a047; font-weight: bold; }
#bar button.primary.running { background: #e53935; }
#bar button.active { background: #ffb300; color: #212121; }
/* tombol khusus (bukan ikon): status paket keanggotaan */
#bar button.plan-btn {
  background: linear-gradient(135deg, #7e57c2, #5c6bc0); font-weight: bold;
  border: 1px solid #b39ddb; letter-spacing: .2px;
}
#bar button.plan-btn.plan-member { background: linear-gradient(135deg, #546e7a, #78909c); }
#bar button.plan-btn.plan-student { background: linear-gradient(135deg, #00897b, #26a69a); }
#bar button.plan-btn.plan-professional { background: linear-gradient(135deg, #5e35b1, #7e57c2); }
#bar button.plan-btn.plan-enterprise { background: linear-gradient(135deg, #ef6c00, #fb8c00); }
/* tombol icon-only: persegi, hanya simbol + tooltip (title) */
#bar button.icon {
  position: relative; width: 38px; height: 34px; padding: 0;
  font-size: 17px; line-height: 1; display: inline-flex;
  align-items: center; justify-content: center;
}
/* ikon SVG dual-tone (flat, sudut membulat). Mewarisi warna tombol via
   currentColor sehingga ikut berubah saat tombol .active (latar amber). */
.ic { width: 20px; height: 20px; display: inline-block; color: #d6f0fb; pointer-events: none; }
#bar button.active .ic { color: #1b2733; }
#bar button.primary .ic { color: #ffffff; }
/* tombol RUN: tampilkan play saat edit, stop saat berjalan */
#btn-run .ic-stop { display: none; }
#btn-run.running .ic-play { display: none; }
#btn-run.running .ic-stop { display: inline-block; }
/* tombol layar penuh: ikon "masuk" vs "keluar" */
#btn-full .ic-exit { display: none; }
#btn-full.on .ic-enter { display: none; }
#btn-full.on .ic-exit { display: inline-block; }
.bar-sep { width: 1px; height: 22px; background: #546e7a; margin: 0 2px; }
/* tombol pindah posisi toolbar: ikon menunjukkan TUJUAN pindahnya */
#btn-barpos .ic-to-top { display: none; }
body.bar-right #btn-barpos .ic-to-right { display: none; }
body.bar-right #btn-barpos .ic-to-top { display: inline-block; }

/* ---------- Mode toolbar DI KANAN ----------
   body jadi baris: #main dulu (order 1), lalu #bar di kanan (order 2). Bilahnya
   pakai grid 2 kolom ikon; tombol berteks & pemisah membentang penuh, dan
   bilahnya bisa digulir sendiri kalau tombolnya lebih tinggi dari layar. */
body.bar-right { flex-direction: row; }
body.bar-right #main { order: 1; min-width: 0; }
body.bar-right #bar {
  order: 2; display: grid; grid-template-columns: repeat(2, 38px);
  gap: 5px; align-content: start; justify-content: center;
  padding: 8px; overflow-y: auto; overflow-x: hidden; flex: 0 0 auto;
}
/* Tombol berteks (HMI, Analisis, Osiloskop, Ladder, BOM, …) membentang penuh.
   Teksnya dijaga satu baris + elipsis: kalau membungkus, tombolnya jadi dua
   baris dan bilah tegak makin panjang sampai isinya harus digulir. */
body.bar-right #bar button:not(.icon) {
  grid-column: 1 / -1; font-size: 11px; padding: 4px 3px; text-align: center;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0;
  /* 'overflow: hidden' mematikan tinggi-minimum otomatis grid item, sehingga
     barisnya boleh menyusut lebih pendek dari tulisannya — tombol jadi
     berdesakan dan hurufnya terpotong atas-bawah. Tinggi dikunci di sini. */
  min-height: 25px; line-height: 1.4;
}
/* sedikit lebih pendek dari mode atas supaya seluruh tombol muat tanpa digulir */
body.bar-right #bar button.icon { width: 38px; height: 30px; }
/* Mode toolbar TEGAK: pesan status/hint pindah ke kanan-ATAS (di kiri bilah
   tegak supaya tak tertutup). Mode mendatar tetap di kanan-bawah (aturan dasar). */
body.bar-right #status { top: 12px; bottom: auto; right: 110px; }
body.bar-right .bar-sep { grid-column: 1 / -1; width: 100%; height: 1px; margin: 2px 0; }
/* Kotak user (kode berbagi + nama + keluar) di bilah TEGAK.
   Bilahnya cuma ~97px, sedangkan isinya berderet satu baris butuh ~102px —
   kode uniknya terpotong. Di sini isinya dibungkus jadi beberapa baris: kode
   mengambil satu baris penuh, nama & tombol keluar berbagi baris di bawahnya. */
body.bar-right #collab, body.bar-right #user-box {
  grid-column: 1 / -1; margin-left: 0; font-size: 11.5px;
  justify-content: center; text-align: center; min-width: 0;
}
/* Bilah tegak lebih panjang dari layar, jadi kotak user (paling bawah) hanya
   terlihat setelah digulir. Ditempelkan ke dasar bilah supaya menu akun
   selalu terjangkau.
   Margin negatif -8px membatalkan padding kiri/kanan #bar, sehingga latar
   gelap + bayangannya membentang SELEBAR bilah (bukan cuma selebar dua kolom
   ikon) — terbaca sebagai kaki bilah, bukan kotak mengambang. */
body.bar-right #user-box {
  position: sticky; bottom: -8px; z-index: 2;
  background: #263238; margin: 2px -8px 0; padding: 4px 8px 6px;
  box-shadow: 0 -6px 10px -6px rgba(0, 0, 0, .55);
  display: flex; justify-content: center;
}
[data-theme="dark"] body.bar-right #user-box { background: #151d22; }
/* Bilah tegak cuma ±97px: NAMA DILEPAS, sisakan foto + panah saja. Namanya
   tetap terbaca di dalam menu (baris pertama), jadi tak ada yang hilang.
   Tombolnya dibuat SELEBAR bilah (seperti tombol berteks di atasnya) dengan
   foto di tengah, supaya tidak tampak seperti pil kecil yang mengambang. */
body.bar-right #user-btn {
  padding: 3px 6px; gap: 4px; max-width: none;
  width: 100%; justify-content: center; border-radius: 6px;
}
body.bar-right #user-btn .uname { display: none; }
/* Menu dibuka ke KIRI (ke arah kanvas) dan naik dari dasar — kalau tetap
   membuka ke bawah-kanan, ia keluar layar karena tombolnya menempel di sudut
   kanan-bawah bilah. */
body.bar-right #user-menu { width: 250px; }
#notif-badge {
  position: absolute; top: -4px; right: -4px; min-width: 16px; height: 16px;
  padding: 0 3px; border-radius: 8px; background: #e53935; color: #fff;
  font-size: 10px; font-weight: bold; line-height: 16px; text-align: center;
}
#collab { font-size: 12px; color: #80cbc4; font-weight: bold; }
/* pesan status: melayang di kanan-bawah supaya tidak menggeser toolbar/kanvas */
#status {
  position: fixed; right: 12px; bottom: 12px; max-width: 42vw; z-index: 40;
  background: rgba(38, 50, 56, .92); color: #b3e5fc;
  padding: 6px 8px 6px 12px; border-radius: 6px; font-size: 13px;
  pointer-events: none; box-shadow: 0 2px 8px rgba(0, 0, 0, .3);
  display: flex; align-items: center; gap: 8px;
}
#status.closed { display: none; }               /* ditutup manual / auto (1 mnt) */
#status-text { min-width: 0; }
#status-close {
  pointer-events: auto; cursor: pointer; background: none; border: 0;
  color: #b3e5fc; font-size: 14px; line-height: 1; padding: 0 2px; opacity: .75;
  flex: 0 0 auto;
}
#status-close:hover { opacity: 1; color: #fff; }

#main { flex: 1; display: flex; min-height: 0; }

#palette {
  width: 188px; background: #37474f; color: #cfd8dc;
  padding: 10px; overflow-y: auto; flex-shrink: 0;
}
#palette h2 { font-size: 13px; color: #fff; margin: 4px 0 10px; }

#domain-tabs { display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 10px; }
#domain-tabs button {
  flex: 1 1 46%; font-size: 10.5px; padding: 5px 6px; border: 0;
  border-radius: 4px; cursor: pointer; background: #455a64; color: #cfd8dc;
}
#domain-tabs button:hover { background: #546e7a; }
#domain-tabs button.active { background: #0288d1; color: #fff; }
.soon { color: #90a4ae; font-size: 12px; text-align: center; padding: 16px 4px; }

/* Kotak cari komponen (di bawah tab kategori) */
#palette-cari { position: relative; margin-bottom: 10px; }
#palette-search {
  width: 100%; box-sizing: border-box; font: inherit; font-size: 11.5px;
  padding: 5px 24px 5px 8px; border: 1px solid #546e7a; border-radius: 4px;
  background: #455a64; color: #eceff1;
}
#palette-search::placeholder { color: #90a4ae; }
#palette-search:focus { outline: none; border-color: #4fc3f7; background: #4a626d; }
/* Chrome menaruh tombol ✕ bawaannya sendiri di input[type=search]; kita pakai
   tombol sendiri agar bisa ikut mengosongkan filter, jadi yang bawaan disembunyikan. */
#palette-search::-webkit-search-cancel-button { display: none; }
#palette-search-clear {
  position: absolute; right: 3px; top: 50%; transform: translateY(-50%);
  border: 0; background: none; color: #b0bec5; cursor: pointer;
  font-size: 12px; line-height: 1; padding: 3px 4px;
}
#palette-search-clear:hover { color: #fff; }
#palette .hasil { color: #90a4ae; font-size: 10.5px; margin: -6px 0 8px; }
#palette-list button .dom {
  display: block; font-size: 9px; color: #607d8b; text-align: center;
  margin-top: 1px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
#palette-list { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; }
#palette-list button {
  border: 1px solid #b0bec5; border-radius: 5px; padding: 3px;
  cursor: pointer; background: #fff; height: 54px;
  display: flex; align-items: center; justify-content: center;
}
#palette-list button:hover { background: #eceff1; border-color: #607d8b; }
#palette-list button.armed {
  background: #fff8e1; border-color: #ffb300; box-shadow: 0 0 0 2px #ffb300 inset;
}
#palette-list svg { width: 100%; height: 46px; display: block; }
/* komponen di luar paket: tetap terlihat tapi terkunci (biar tahu isi upgrade) */
#palette-list button.locked {
  position: relative; background: #eceff1; border-style: dashed; border-color: #cfd8dc;
  cursor: help;
}
#palette-list button.locked svg { opacity: .35; filter: grayscale(1); }
#palette-list button.locked:hover { background: #e0e0e0; border-color: #90a4ae; }
#palette-list button.locked .lock {
  position: absolute; top: 2px; right: 3px; font-size: 11px; line-height: 1; opacity: .75;
}
#palette-list button.locked::after {
  content: attr(data-need); position: absolute; bottom: 1px; left: 0; right: 0;
  font-size: 8.5px; color: #78909c; text-align: center; letter-spacing: .2px;
}

#canvas { flex: 1; background: #fafafa; cursor: default; touch-action: none; }
#canvas.placing { cursor: crosshair; }

/* TANDA AIR paket — menutupi area kanvas, tak pernah menangkap klik.
   Motifnya digambar app.js sebagai background-image (SVG data URI) supaya
   teksnya tajam di layar HiDPI dan tak perlu puluhan elemen DOM. */
/* 'fixed' + ukuran disetel JS dari getBoundingClientRect() kanvas: kanvas bisa
   melebar/menyempit karena palet disembunyikan, toolbar dipindah ke kanan, mode
   fokus, atau laci di HP — menyamakan diri ke persegi kanvas jauh lebih tahan
   daripada menebak lebar palet lewat CSS. */
#watermark {
  position: fixed; z-index: 4;
  pointer-events: none; user-select: none;
  background-repeat: repeat;
}
#watermark.hidden { display: none; }

/* Tombol menu (laci komponen) — HANYA untuk layar sempit.
   Pemilihnya sengaja '#bar #btn-menu' (dua id), bukan '#btn-menu' saja:
   tombol ini juga cocok dengan '#bar button.icon' di atas yang menyetel
   display:inline-flex. Dengan satu id saja, aturan itu lebih khusus
   (1 id + 1 kelas + 1 elemen) sehingga MENANG — dan tombol ☰ ikut muncul di
   layar laptop. Aturan penampil di media query 768px memakai pemilih yang
   sama panjangnya supaya urutannya yang menentukan. */
#bar #btn-menu { display: none; }
#nav-backdrop { display: none; }

/* WARNA KABEL/SELANG — dipakai lewat variabel, BUKAN aturan penimpa di blok
   mode gelap. Alasannya sejarah pahit: dulu mode gelap memakai
   '[data-theme="dark"] #wires polyline { stroke: ... }'. Pemilih itu bernilai
   (1 id + 1 atribut + 1 elemen), sehingga
     - SERI dengan '#wires polyline.phase' dst. tapi ditulis belakangan -> MENANG,
       jadi fasa/netral/udara/air semuanya jadi abu-abu di mode gelap; dan
     - LEBIH KHUSUS dari '#wires .hit' -> area-tarik selebar 14px yang seharusnya
       transparan ikut dicat abu-abu.
   Akibatnya garis putus-putus animasi aliran menggambar di atas pita abu-abu
   sewarna: celah putus-putusnya tak terlihat, animasi aliran seolah MATI di
   mode gelap. Dengan variabel, kekhususan pemilih tak lagi jadi urusan —
   mode gelap cukup mengganti nilainya di :root. */
:root {
  --w-plain:   #9e9e9e;   /* kabel biasa (mode edit) */
  --w-dead:    #9e9e9e;   /* kabel tak bertegangan saat simulasi */
  --w-phase:   #e53935;
  --w-neutral: #1e88e5;
  --w-air:     #00bcd4;   /* udara bertekanan (pneumatik) */
  /* Oli bertekanan (hidrolik). Sengaja jauh dari biru-toska udara: satu gambar
     elektrohidrolik memuat listrik, udara, DAN oli sekaligus, jadi warna jalur
     adalah penanda tercepat bagi siswa tentang apa yang mengalir di sana. */
  --w-oil:     #f57c00;
  --w-pipe:    #90a4ae;   /* pipa kosong */
  --w-wet:     #4fc3f7;   /* berair, diam */
  --w-water:   #0288d1;   /* air mengalir */
  /* refrigeran (AC) */
  --w-refhi:   #ef5350;
  --w-reflo:   #42a5f5;
  --w-ref:     #90a4ae;
  /* PLTU: batu bara, udara bakar, gas buang */
  --w-coal:        #5d4037;
  --w-coal-off:    #a1887f;
  --w-combair:     #29b6f6;
  --w-combair-off: #b3e5fc;
  --w-flue:        #6d4c41;
  --w-flue-off:    #bcaaa4;
}
#wires polyline {
  fill: none; stroke: var(--w-plain); stroke-width: 3;
  stroke-linecap: round; stroke-linejoin: round;
}
#wires polyline.phase { stroke: var(--w-phase); }
#wires polyline.neutral { stroke: var(--w-neutral); }
#wires polyline.dead { stroke: var(--w-dead); }
#wires polyline.air { stroke: var(--w-air); stroke-width: 4; }    /* jalur udara bertekanan (pneumatik) */
#wires polyline.oil { stroke: var(--w-oil); stroke-width: 5; }    /* jalur oli bertekanan (hidrolik) */
#wires polyline.flow { stroke-dasharray: 9 7; animation: flow .5s linear infinite; }
@keyframes flow { to { stroke-dashoffset: -16; } }
/* arah aliran dibalik (udara mengalir dari b->a relatif gambar kabel) */
#wires polyline.flow.reverse { animation-name: flowrev; }
@keyframes flowrev { to { stroke-dashoffset: 16; } }
/* P&ID / perpipaan (fluida air) */
#wires polyline.pipe { stroke: var(--w-pipe); stroke-width: 4; }   /* pipa kosong */
#wires polyline.wet { stroke: var(--w-wet); stroke-width: 5; }    /* berair, diam */
#wires polyline.water { stroke: var(--w-water); stroke-width: 5; }  /* air mengalir */
/* kabel hubung singkat: berkedip merah<->kuning */
#wires polyline.short { stroke: #ff1744 !important; stroke-width: 4;
  animation: shortblink .45s steps(1) infinite; }
@keyframes shortblink { 50% { stroke: #ffc400 !important; } }
/* banner alarm korslet */
#short-alarm { position: fixed; top: 64px; left: 50%; transform: translateX(-50%);
  z-index: 60; display: flex; align-items: center; gap: 8px; max-width: min(560px, 92vw);
  background: #b71c1c; color: #fff; font: bold 13px/1.35 "Segoe UI", sans-serif;
  padding: 10px 16px; border-radius: 8px; box-shadow: 0 6px 20px rgba(0,0,0,.4);
  animation: sablink .7s steps(1) infinite; }
#short-alarm.hidden { display: none; }
#short-alarm .sa-ico { font-size: 18px; }
@keyframes sablink { 50% { background: #ff5252; } }
/* kabel melebihi kemampuan hantar arus (KHA): oranye tebal putus-putus berkedip */
#wires polyline.over { stroke: #ff9800 !important; stroke-width: 5;
  stroke-dasharray: 7 5; animation: overblink .6s steps(1) infinite; }
@keyframes overblink { 50% { stroke: #ffca28 !important; } }
/* LED timer on-delay saat dapat sumber & menghitung tunda: kuning kedip ~1Hz */
.indicator.blink { animation: indblink 1s steps(1) infinite; }
@keyframes indblink { 50% { opacity: .12; } }
/* label arus di samping kabel (saat simulasi) */
#wires text.amp-label { font: 600 9px "Segoe UI", sans-serif; fill: #0d47a1;
  text-anchor: middle; dominant-baseline: central; pointer-events: none;
  paint-order: stroke; stroke: #fff; stroke-width: 2.6px; stroke-linejoin: round; }
#wires text.amp-label.over { fill: #c62828; }     /* merah bila melebihi KHA */
#wires text.amp-label.qflow { fill: #0277bd; }    /* debit air (L/min) pada pipa */
#wires text.amp-label.hidden { display: none; }
/* panel Analisis rangkaian */
#analysis-panel { position: fixed; top: 60px; right: 14px; z-index: 55;
  width: min(360px, 92vw); max-height: 76vh; overflow: auto;
  background: #fff; border-radius: 10px; box-shadow: 0 8px 28px rgba(0,0,0,.28);
  font: 13px/1.45 "Segoe UI", sans-serif; color: #263238; }
#analysis-panel.hidden { display: none; }
.ap-head { display: flex; align-items: center; justify-content: space-between;
  background: #37474f; color: #fff; padding: 9px 13px; border-radius: 10px 10px 0 0;
  font-weight: 600; position: sticky; top: 0; }
.ap-head button { background: none; border: 0; color: #fff; font-size: 15px; cursor: pointer; }
#analysis-body { padding: 10px 14px 14px; }
#analysis-body h4 { margin: 12px 0 5px; font-size: 13px; color: #37474f;
  border-bottom: 1px solid #eceff1; padding-bottom: 3px; }
#analysis-body h4:first-child { margin-top: 0; }
#analysis-body ol.steps { margin: 4px 0; padding-left: 20px; }
#analysis-body ol.steps li { margin: 2px 0; font-family: "Consolas", monospace; font-size: 12px; }
#analysis-body ul { margin: 4px 0; padding-left: 18px; }
#analysis-body ul li { margin: 3px 0; }
.res-ok { background: #e8f5e9; border-left: 3px solid #43a047; padding: 6px 8px; border-radius: 4px; }
.res-note { background: #fff8e1; border-left: 3px solid #ffb300; padding: 6px 8px;
  border-radius: 4px; color: #6d4c00; }
.expr { font-family: "Consolas", monospace; font-size: 11px; color: #607d8b; word-break: break-all; }
/* catatan kecil INLINE (mis. saran kabel di bawah data motor) — bukan kotak */
.sub-note { color: #90a4ae; font-size: 11px; }
.res-warn { background: #ffebee; border-left: 3px solid #e53935; padding: 6px 8px;
  border-radius: 4px; color: #b71c1c; margin: 6px 0; }
.res-info { background: #e3f2fd; border-left: 3px solid #1e88e5; padding: 6px 8px;
  border-radius: 4px; color: #0d47a1; margin: 6px 0; }
.ap-badge { display: inline-block; background: #eceff1; color: #37474f;
  border-radius: 10px; padding: 1px 9px; margin: 1px; font-size: 11px; }
.ap-sub { color: #546e7a; font-size: 11.5px; margin: 3px 0; }
/* Peringatan di panel Analisis: kesalahan yang berakibat nyata di lapangan
   (mis. sistem hidrolik tanpa katup pelepas), bukan sekadar saran gaya. */
.ap-warn { background: #fff8e1; border-left: 3px solid #ffb300; color: #6d4c41;
  font-size: 11.5px; line-height: 1.5; padding: 6px 9px; border-radius: 4px;
  margin: 5px 0; }
table.kha-tbl { width: 100%; border-collapse: collapse; font-size: 11.5px; margin: 4px 0; }
table.kha-tbl th, table.kha-tbl td { border: 1px solid #eceff1; padding: 3px 5px; text-align: left; }
table.kha-tbl thead th { background: #f5f5f5; color: #455a64; font-weight: 600; }
table.kha-tbl tr.over td { background: #ffebee; color: #b71c1c; }
table.kha-tbl .res-note { background: none; border: 0; padding: 0; color: #90a4ae; }
/* cegah sub/sup memuaikan tinggi baris -> baris teks analisis tak lagi tumpang tindih */
#analysis-body sub, #analysis-body sup { font-size: 75%; line-height: 0;
  position: relative; vertical-align: baseline; }
#analysis-body sup { top: -.5em; }
#analysis-body sub { bottom: -.25em; }

/* ---- Galeri gambar komponen ---- */
#images-panel { position: fixed; top: 60px; right: 14px; z-index: 56;
  width: min(380px, 94vw); max-height: 80vh; overflow: auto;
  background: #fff; border-radius: 10px; box-shadow: 0 8px 28px rgba(0,0,0,.28);
  font: 13px/1.45 "Segoe UI", sans-serif; color: #263238; }
#images-panel.hidden { display: none; }
#images-body { padding: 10px 14px 14px; }
#images-list { display: flex; flex-direction: column; gap: 10px; margin-top: 8px; }
.img-card { border: 1px solid #eceff1; border-radius: 8px; padding: 8px; background: #fafafa; }
.img-head { font-weight: 600; color: #37474f; margin-bottom: 6px; }
.img-head .img-type { font-weight: 400; font-size: 11px; color: #90a4ae; }
.img-thumb { display: block; width: 100%; max-height: 160px; object-fit: contain;
  border-radius: 6px; background: #fff; border: 1px solid #eceff1; cursor: zoom-in; }
.img-thumb.empty { display: flex; align-items: center; justify-content: center;
  height: 60px; color: #b0bec5; font-size: 12px; cursor: default; }
.img-url { width: 100%; margin: 6px 0 4px; padding: 5px 7px; box-sizing: border-box;
  border: 1px solid #cfd8dc; border-radius: 5px; font-size: 12px; }
/* asal foto yang sedang tampil (lapisan: komponen/rangkaian/saya/bersama) */
.img-src { display: block; margin: 5px 0 2px; font-size: 11px; color: #78909c; }
.img-src b { color: #1565c0; font-weight: 600; }
.img-scope { display: flex; align-items: center; gap: 5px; margin-top: 5px;
  font-size: 11px; color: #78909c; }
.img-scope select { flex: 1; padding: 3px 5px; font-size: 12px;
  border: 1px solid #cfd8dc; border-radius: 5px; background: #fff; color: #263238; }
.img-btns { display: flex; flex-wrap: wrap; gap: 6px; }
.img-btns button { padding: 4px 8px; font-size: 12px; border: 1px solid #cfd8dc;
  background: #fff; border-radius: 5px; cursor: pointer; }
.img-btns .img-save { background: #1565c0; color: #fff; border-color: #1565c0; }
.img-btns .img-del { color: #c62828; border-color: #ef9a9a; }
.img-badge { font-size: 12px; cursor: pointer; }
/* % bukaan speed controller (dibuat dari app.js, simbolnya tak punya teks) */
.thr-label { font-family: "Segoe UI", sans-serif; font-size: 8px; font-weight: bold;
  fill: #00838f; pointer-events: none; }
/* tanda silinder ("A"/"B") yang ditunjuk sensor posisi — juga dibuat app.js */
.cyl-tag { font-family: "Segoe UI", sans-serif; font-size: 12px; font-weight: bold;
  fill: #37474f; pointer-events: none; }
/* nama koil solenoid ("Y1"/"Y2") di samping kotak solenoid valve pneumatik:
   penunjuk ke komponen Coil bernama sama di rangkaian listrik */
.sol-label { font-family: "Segoe UI", sans-serif; font-size: 11px; font-weight: bold;
  fill: #6a1b9a; pointer-events: none; }

/* ---- Menu klik-kanan untuk tulisan komponen ---- */
#lblmenu { position: fixed; z-index: 210; min-width: 208px;
  background: #fff; border: 1px solid #cfd8dc; border-radius: 8px;
  box-shadow: 0 8px 26px rgba(0,0,0,.28); padding: 5px;
  font: 13px "Segoe UI", sans-serif; color: #263238; user-select: none; }
#lblmenu.hidden { display: none; }
.lm-head { font-size: 11px; color: #78909c; padding: 3px 7px 5px;
  border-bottom: 1px solid #eceff1; margin-bottom: 4px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 240px; }
.lm-item { display: block; width: 100%; text-align: left; background: none;
  border: 0; border-radius: 5px; padding: 6px 8px; font: 13px "Segoe UI", sans-serif;
  color: #263238; cursor: pointer; }
.lm-item:hover { background: #e3f2fd; }
.lm-item.lm-danger { color: #c62828; border-top: 1px solid #eceff1; margin-top: 4px; }
.lm-item.lm-danger:hover { background: #ffebee; }
.lm-hint { float: right; color: #90a4ae; font-size: 11.5px; }
.lm-row { display: flex; align-items: center; gap: 5px; padding: 4px 8px; }
.lm-lbl { width: 48px; color: #607d8b; font-size: 12px; }
.lm-btn { min-width: 28px; padding: 3px 7px; border: 1px solid #cfd8dc;
  background: #fff; border-radius: 5px; cursor: pointer; font-size: 12.5px; color: #263238; }
.lm-btn:hover { background: #e3f2fd; }
.lm-btn.on { background: #1565c0; border-color: #1565c0; color: #fff; }
/* huruf contoh pada tombol B / I: serif supaya "I" miring tak terbaca garis miring */
.lm-btn b, .lm-btn i { font-family: Georgia, "Times New Roman", serif; font-size: 14px; }
#lm-size { width: 52px; padding: 3px 5px; border: 1px solid #cfd8dc;
  border-radius: 5px; font-size: 12.5px; }
#lm-colors { display: flex; gap: 3px; }
.lm-sw { width: 16px; height: 16px; border-radius: 50%; border: 1px solid #b0bec5;
  cursor: pointer; padding: 0; }
.lm-sw.on { box-shadow: 0 0 0 2px #1565c0; }
#lm-color { width: 26px; height: 22px; padding: 0; border: 1px solid #cfd8dc;
  border-radius: 5px; background: #fff; cursor: pointer; }
[data-theme="dark"] #lblmenu { background: #263238; color: #eceff1; border-color: #455a64; }
[data-theme="dark"] .lm-item { color: #eceff1; }
[data-theme="dark"] .lm-item:hover, [data-theme="dark"] .lm-btn:hover { background: #37474f; }
[data-theme="dark"] .lm-btn, [data-theme="dark"] #lm-size, [data-theme="dark"] #lm-color {
  background: #2b383f; color: #eceff1; border-color: #546e7a; }
[data-theme="dark"] .lm-head { border-color: #37474f; }

#lightbox { position: fixed; inset: 0; z-index: 200; background: rgba(0,0,0,.72);
  display: flex; align-items: center; justify-content: center; }
#lightbox.hidden { display: none; }
#lightbox-inner { position: relative; max-width: 92vw; max-height: 88vh; }
#lightbox-img { max-width: 92vw; max-height: 82vh; display: block;
  border-radius: 8px; box-shadow: 0 10px 40px rgba(0,0,0,.5); background: #fff; }
#lightbox-cap { text-align: center; color: #fff; margin-top: 8px; font: 14px "Segoe UI", sans-serif; }
#lightbox-close { position: absolute; top: -12px; right: -12px; width: 30px; height: 30px;
  border-radius: 50%; border: 0; background: #fff; color: #263238; font-size: 16px;
  cursor: pointer; box-shadow: 0 2px 8px rgba(0,0,0,.4); }
#wires .hit { stroke: transparent; stroke-width: 14; cursor: move; }
/* KABEL TERPILIH: polyline .hit yang lebar (biasanya transparan) diberi warna
   -> halo oranye di BELAKANG kabel, jadi warna kabelnya sendiri (fasa/netral/
   pipa/refrigeran) tetap terbaca. */
#wires g.wire.selected .hit { stroke: rgba(255,152,0,.42); }
#canvas.run-mode #wires g.wire.selected .hit { stroke: transparent; }
[data-theme="dark"] #wires g.wire.selected .hit { stroke: rgba(255,183,77,.42); }

.comp { cursor: grab; }
/* TULISAN komponen bisa digeser sendiri (mode edit) supaya tidak saling
   menimpa di rangkaian padat; badan simbol tetap memindahkan semuanya. */
.comp text { cursor: move; }
.comp text:hover { paint-order: stroke; stroke: #ffe082; stroke-width: 3px;
  stroke-linejoin: round; }
.comp text.dragging { paint-order: stroke; stroke: #ffca28; stroke-width: 3.5px;
  stroke-linejoin: round; }
/* label yang dibuat app.js sengaja tak menerima klik -> aktifkan agar bisa digeser */
.comp text.thr-label, .comp text.cyl-tag, .comp text.sol-label { pointer-events: auto; }
/* Tulisan yang DISEMBUNYIKAN: hilang di simulasi dan di hasil ekspor/cetak,
   tapi saat menggambar disisakan bayangannya supaya masih bisa diklik-kanan
   untuk dimunculkan lagi. (Ekspor memakai <svg> baru tanpa id="canvas",
   sehingga aturan bayangan di bawah tidak ikut berlaku di sana.) */
.comp text.lbl-hidden { display: none; }
#canvas:not(.run-mode) .comp text.lbl-hidden { display: block; opacity: .18; }
/* garis tipis dari label yang dijauhkan ke tempat asalnya */
.comp line.lbl-lead { stroke: #b0bec5; stroke-width: .7; stroke-dasharray: 3 2;
  pointer-events: none; }
/* saat simulasi berjalan, tulisan kembali "netral" (klik = interaksi komponen) */
#canvas.run-mode .comp text { cursor: pointer; }
#canvas.run-mode .comp text:hover { stroke: none; }
.comp .term { cursor: pointer; }
/* Terminal listrik = kotak kecil biru muda (symbols.py: TERM_FILL). Isiannya
   diatur lewat ATRIBUT fill oleh updateTerms(): biru muda saat masih bebas,
   transparan begitu sudah berkabel (tetap bisa diklik, tapi tak terlihat lagi
   sehingga yang tampak tinggal garisnya). Dua aturan di bawah sengaja lewat CSS
   supaya MENGALAHKAN atribut itu saat disorot / sedang dipilih. */
/* Disorot: warnanya tetap, hanya diberi sedikit GLOW — terminal yang sudah
   berkabel (isian transparan) sengaja dikembalikan warnanya saat disorot supaya
   tetap bisa ditemukan. Sedang dipilih untuk menyambung: oranye lebih pekat. */
.comp .term:hover {
  fill: #ffcc80;
  filter: drop-shadow(0 0 2px #ffa726) drop-shadow(0 0 5px rgba(255, 152, 0, .55));
}
.comp .term.sel { fill: #ef6c00; }
/* saat simulasi berjalan terminal tak bisa disambung, jadi sorotannya pun
   dimatikan — applyTerms() sudah membuat isiannya transparan. */
#canvas.run-mode .comp .term:hover { fill: transparent; }
/* Komponen TERPILIH: kotak putus-putus di sekeliling gambarnya (rect.selbox
   ditambahkan app.js ke dalam grup komponen, jadi ikut berputar/tercermin).
   Aturan lama menyasar ".hit", yang hanya ada pada KABEL — komponen terpilih
   jadi tak bertanda sama sekali. */
.comp rect.selbox {
  fill: rgba(255,152,0,.10); stroke: #ff9800; stroke-width: 1.2;
  stroke-dasharray: 5 3; pointer-events: none;
}
#canvas.run-mode .comp rect.selbox { display: none; }
/* garis bantu: kisi yang sedang ditempeli saat menggeser */
#guides line.snapguide {
  stroke: #ff9800; stroke-width: 1; stroke-dasharray: 5 4;
  opacity: .85; pointer-events: none;
}
/* komponen "trip"/alarm: sorotan merah (dulu menyasar .hit yang tak ada di komponen) */
.comp.tripped { filter: drop-shadow(0 0 3px #e53935) drop-shadow(0 0 6px rgba(229,57,53,.55)); }

.hidden { display: none !important; }

/* user box di toolbar */
/* ===== Menu pengguna (nama · foto · ▾) =====
   Menampung hal-hal yang jarang ditekan (paket, kode, profil, panel admin,
   keluar) supaya toolbar hanya berisi alat yang dipakai saat menggambar. */
#user-box { margin-left: auto; position: relative; font-size: 13px; }
#user-btn {
  display: flex; align-items: center; gap: 8px; cursor: pointer;
  background: #37474f; color: #eceff1; border: 0; border-radius: 20px;
  padding: 4px 10px 4px 12px; font: inherit; font-size: 13px; max-width: 230px;
}
#user-btn:hover { background: #455a64; }
#user-btn .uname { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#user-btn .caret { font-size: 10px; opacity: .8; }
/* Avatar: foto bila ada, kalau tidak inisial di atas warna dari nama sendiri
   (tak perlu berkas gambar, dan tiap orang tetap mudah dibedakan). */
.ava {
  width: 26px; height: 26px; border-radius: 50%; flex: 0 0 26px;
  display: inline-flex; align-items: center; justify-content: center;
  background: #0288d1 center/cover no-repeat; color: #fff;
  font-size: 11px; font-weight: 700; letter-spacing: .3px; overflow: hidden;
}
.ava.big { width: 40px; height: 40px; flex-basis: 40px; font-size: 15px; }
.ava.huge { width: 72px; height: 72px; flex-basis: 72px; font-size: 26px; }

/* 'fixed', BUKAN 'absolute': dalam mode toolbar tegak, #bar memakai
   overflow-y:auto — wadah yang menggulir MEMOTONG anak yang diposisikan
   absolut, sehingga menunya tak pernah terlihat walau koordinatnya benar.
   Posisinya dihitung di JS (letakkanUserMenu) dari kotak tombolnya. */
#user-menu {
  position: fixed; z-index: 120;
  width: 268px; background: #fff; color: #1f2b31; border-radius: 10px;
  box-shadow: 0 12px 38px rgba(0,0,0,.28), 0 0 0 1px rgba(38,50,56,.10);
  padding: 6px; overflow: hidden;
}
#user-menu.hidden { display: none; }
/* kepala menu diberi latar samar supaya identitas akun terbaca sebagai satu
   blok, bukan mengambang di atas daftar */
#user-menu .um-head { display: flex; align-items: center; gap: 10px;
  padding: 11px 10px; margin: -6px -6px 4px; background: #f5f7f8;
  border-bottom: 1px solid #e4eaed; }
.um-id { min-width: 0; }
.um-nama { font-weight: 700; font-size: 14px; overflow: hidden; text-overflow: ellipsis; }
#user-menu .um-email { font-size: 11.5px; color: #546e7a; overflow: hidden; text-overflow: ellipsis; }
/* Pemilih diawali #user-menu (dua id) BUKAN .um-item saja: butirnya berada di
   dalam <header id="bar">, dan aturan '#bar button' (latar #455a64, teks putih)
   lebih khusus daripada satu kelas — akibatnya teks putih di atas kartu putih,
   dan tiap butir tampak seperti balok abu-abu. Jebakan yang sama pernah
   membuat tombol ☰ muncul di layar laptop. */
#user-menu .um-item {
  display: flex; align-items: center; gap: 10px; width: 100%; text-align: left;
  background: none; border: 0; border-radius: 7px; padding: 9px 10px;
  cursor: pointer; font: inherit; font-size: 13px; color: #1f2b31;
}
#user-menu .um-item:hover { background: #eef2f4; }
#user-menu .um-item.hidden { display: none; }
.um-ic { flex: 0 0 20px; text-align: center; font-size: 14px; }
.um-teks { min-width: 0; font-weight: 600; }
/* #546e7a di atas putih = 5,0:1 (lolos WCAG AA). #78909c yang dipakai semula
   hanya 3,2:1 — terbaca pucat dan itulah yang terasa "kurang enak dilihat". */
#user-menu .um-teks small { display: block; font-size: 11px; color: #546e7a;
  font-weight: 400; margin-top: 1px; }
/* Angka merah di butir "Kelas": jumlah hal yang MENUNGGU orang ini —
   pekerjaan yang belum diperiksa (guru) atau tugas yang belum dikumpulkan
   & harus direvisi (siswa). Ditaruh di menu, bukan di lonceng 🔔, supaya
   tidak tercampur dengan undangan kolaborasi yang sifatnya sekali-jawab. */
#user-menu .um-badge { margin-left: auto; background: #e53935; color: #fff;
  border-radius: 10px; font-size: 10.5px; font-weight: 700; padding: 1px 7px; }
#user-menu .um-badge.hidden { display: none; }
#user-menu .um-item.keluar { color: #c62828; }
#user-menu .um-item.keluar:hover { background: #fdecea; }
#user-menu .um-sep { height: 1px; background: #e4eaed; margin: 5px 8px; }
/* Butir bahasa: pemilih ID/EN dari static/i18n.js. Aturan '#bar button'
   (lihat catatan di atas) juga mengenai tombol pemilihnya, jadi ditimpa di
   sini dengan pemilih yang sama khususnya. */
#user-menu .um-lang { cursor: default; }
#user-menu .um-lang:hover { background: none; }
#user-menu .um-lang .i18n-pilih { margin-left: auto; }
#user-menu .i18n-pilih button { background: none; color: inherit; border: 0; border-radius: 0;
  padding: 5px 10px; font-size: 11.5px; filter: none; }
#user-menu .i18n-pilih button.on { background: #2a78d6; color: #fff; }
#user-menu .plan-chip {
  display: inline-block; border-radius: 10px; padding: 1px 8px;
  font-size: 10.5px; font-weight: 700; color: #fff; background: #5e35b1;
}

/* modal edit profil */
#prof-modal { position: fixed; inset: 0; z-index: 140; background: rgba(0,0,0,.45);
              display: flex; align-items: center; justify-content: center; }
#prof-modal.hidden { display: none; }
#prof-modal h3 { display: flex; align-items: center; gap: 8px; }
#prof-modal h3 .x { margin-left: auto; background: none; border: 0; font-size: 16px;
                    cursor: pointer; color: #78909c; padding: 0 4px; }
.prof-foto { display: flex; align-items: center; gap: 16px; margin: 6px 0 12px; }
.prof-fbtn { display: flex; flex-direction: column; gap: 6px; }
.prof-frow { display: flex; gap: 6px; flex-wrap: wrap; }
.prof-fbtn button { border: 1px solid #cfd8dc; background: #fff; border-radius: 6px;
                    padding: 6px 12px; cursor: pointer; font: inherit; font-size: 12.5px; }
.prof-fbtn button.danger { color: #c62828; border-color: #ef9a9a; }
.prof-fbtn .me { margin: 0; font-size: 11px; color: #90a4ae; }
.prof-sub { margin: 16px 0 2px; font-size: 13px; color: #37474f; }
.prof-sub small { font-weight: 400; color: #90a4ae; }
#prof-modal .hidden { display: none; }

/* ===== Modal "Data & privasi" (hak pengguna atas datanya) =====
   Meminjam kerangka #prof-modal supaya kedua modal akun terasa satu aplikasi. */
#data-modal { position: fixed; inset: 0; z-index: 140; background: rgba(0,0,0,.45);
              display: flex; align-items: center; justify-content: center; }
#data-modal.hidden { display: none; }
#data-modal .hidden { display: none; }
#data-modal h3 { display: flex; align-items: center; gap: 8px; }
#data-modal h3 .x { margin-left: auto; background: none; border: 0; font-size: 16px;
                    cursor: pointer; color: #78909c; padding: 0 4px; }
#data-modal button { border: 1px solid #cfd8dc; background: #fff; border-radius: 6px;
                     padding: 7px 13px; cursor: pointer; font: inherit; font-size: 13px; }
#data-modal button:hover { background: #f4f6f7; }
#data-modal button.danger { color: #c62828; border-color: #ef9a9a; }
#data-modal button.danger:hover { background: #fdecea; }
#data-modal button.danger-solid { background: #c62828; color: #fff; border-color: #c62828; }
#data-modal button.danger-solid:hover { background: #b71c1c; }
#data-modal button:disabled { opacity: .5; cursor: default; }
#data-modal label { display: block; font-size: 12.5px; color: #546e7a; margin: 10px 0 0; }
#data-modal label input { display: block; width: 100%; margin-top: 4px; font: inherit;
                          font-size: 14px; padding: 7px 9px; border: 1px solid #cfd8dc;
                          border-radius: 6px; }
.prof-sub.bahaya { color: #c62828; border-top: 1px solid #ffcdd2; padding-top: 12px;
                   margin-top: 18px; }
table.data-tbl { width: 100%; border-collapse: collapse; font-size: 13px; margin: 4px 0 6px; }
table.data-tbl td { padding: 5px 0; border-bottom: 1px solid #eceff1; }
table.data-tbl td:last-child { text-align: right; font-weight: 600; }
table.data-tbl tr:last-child td { border-bottom: 0; }
.data-tautan { font-size: 12.5px; margin: 4px 0 0; }
.data-tautan a { color: #0277bd; }

[data-theme="dark"] #data-modal button { background: #2b383f; color: #eceff1; border-color: #546e7a; }
[data-theme="dark"] #data-modal button:hover { background: #35454e; }
[data-theme="dark"] #data-modal button.danger { color: #ef9a9a; border-color: #7f3b3b; }
[data-theme="dark"] #data-modal button.danger-solid { background: #b71c1c; color: #fff; }
[data-theme="dark"] #data-modal label input { background: #1b242a; color: #eceff1;
                                              border-color: #546e7a; }
[data-theme="dark"] table.data-tbl td { border-bottom-color: #2f3d45; }
[data-theme="dark"] .prof-sub.bahaya { color: #ef9a9a; border-top-color: #5d2b2b; }

[data-theme="dark"] #user-menu { background: #222d33; color: #eceff1;
  box-shadow: 0 12px 38px rgba(0,0,0,.5), 0 0 0 1px rgba(255,255,255,.07); }
[data-theme="dark"] #user-menu .um-head { background: #1b242a; border-bottom-color: #2f3d45; }
[data-theme="dark"] #user-menu .um-item { color: #eceff1; }
[data-theme="dark"] #user-menu .um-item:hover { background: #2e3d45; }
[data-theme="dark"] #user-menu .um-teks small,
[data-theme="dark"] #user-menu .um-email { color: #9fb3bd; }
[data-theme="dark"] #user-menu .um-sep { background: #2f3d45; }
[data-theme="dark"] #user-menu .um-lang:hover { background: none; }
[data-theme="dark"] #user-menu .um-item.keluar { color: #ef9a9a; }
[data-theme="dark"] #user-menu .um-item.keluar:hover { background: #3a2326; }
[data-theme="dark"] .prof-fbtn button { background: #2b383f; color: #eceff1; border-color: #546e7a; }

/* modal "Buka dari Server" */
#modal {
  position: fixed; inset: 0; z-index: 50; background: rgba(0, 0, 0, .45);
  display: flex; align-items: center; justify-content: center;
}
.modal-box {
  background: #fff; border-radius: 8px; padding: 18px; width: 420px;
  max-width: 92vw;
  max-height: 70vh; overflow: auto; box-shadow: 0 10px 40px rgba(0, 0, 0, .35);
}
.modal-box h3 { margin: 0 0 12px; color: #263238; }

/* --- Modal daftar (#modal): tata letaknya SAMA dengan #shared-modal supaya
       "Buka dari Server", "Pilih Contoh", dan "Rangkaian Bersama" terasa satu
       aplikasi. Aturan tabelnya dipakai bersama (.shl-tbl / .shl-wrap). --- */
#modal .modal-box.wide { display: flex; flex-direction: column; overflow: hidden; }
#modal h3 { display: flex; align-items: center; gap: 8px; margin: 0 0 10px; }
#modal h3 .x { margin-left: auto; background: none; border: 0; font-size: 16px;
  cursor: pointer; color: #78909c; padding: 0 4px; }
#modal h3 .x:hover { color: #263238; }
#modal .muted { font-size: 12.5px; font-weight: 400; color: #78909c; }
#modal .shl-bar.hidden { display: none; }
#modal #modal-search { flex: 1; min-width: 160px; padding: 5px 9px; font-size: 13px;
  border: 1px solid #cfd8dc; border-radius: 5px; }
/* judul kolom tak bisa diurutkan di sini -> jangan beri isyarat bisa diklik */
#modal table.shl-tbl th { cursor: default; }
#modal table.shl-tbl th:hover { background: #eceff1; }
/* Warna teks TIDAK dipatok di sini — biarkan mewarisi .modal-box supaya mode
   gelap ikut berlaku. Sebelumnya #263238 dipaksa, jadi nama berkas gelap di
   atas latar gelap alias tak terbaca. */
.md-nm { font-weight: 600; }
.md-sub { font-size: 11.5px; color: #78909c; margin-top: 1px; }
.md-tag { background: #e1f5fe; color: #01579b; border-radius: 3px; padding: 1px 6px;
  font-size: 10.5px; font-weight: 700; margin-left: 6px; vertical-align: 1px; }
.md-tag.warn { background: #fff3e0; color: #e65100; }
#circuit-list button {
  border: 0; border-radius: 4px; padding: 5px 11px; cursor: pointer;
  background: #546e7a; color: #fff; font-size: 12px; white-space: nowrap;
  margin-left: 5px;
}
#circuit-list button.primary { background: #0288d1; }
#circuit-list button.danger { background: #e53935; }
#modal .shl-foot button { border: 0; border-radius: 4px; padding: 6px 14px;
  cursor: pointer; background: #607d8b; color: #fff; font-size: 12.5px; }
.modal-actions { margin-top: 14px; text-align: right; display: flex; gap: 8px; justify-content: flex-end; }
.modal-actions button {
  border: 0; border-radius: 4px; padding: 7px 14px; cursor: pointer;
  background: #607d8b; color: #fff;
}
.modal-actions button.primary { background: #43a047; font-weight: bold; }
.modal-actions button.danger { background: #e53935; }
.modal-actions button:first-child { margin-right: auto; }   /* Hapus di kiri */

/* modal status paket keanggotaan + perbandingan */
#plan-modal {
  position: fixed; inset: 0; z-index: 60; background: rgba(0, 0, 0, .45);
  display: flex; align-items: center; justify-content: center;
}
.modal-box.wide { width: 820px; max-width: 94vw; max-height: 86vh; }
.plan-hero {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  background: #eceff1; border-radius: 8px; padding: 12px 14px; margin-bottom: 6px;
}
.plan-badge {
  background: #5e35b1; color: #fff; border-radius: 20px; padding: 6px 14px;
  font-weight: bold; font-size: 14px; white-space: nowrap;
}
.plan-badge.plan-member { background: #607d8b; }
.plan-badge.plan-student { background: #00897b; }
.plan-badge.plan-professional { background: #5e35b1; }
.plan-badge.plan-enterprise { background: #ef6c00; }
.plan-hero .why { flex: 1 1 220px; font-size: 12.5px; color: #455a64; line-height: 1.45; }
#plan-body h4 { margin: 16px 0 8px; font-size: 13px; color: #37474f; }
.plan-usage { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 10px; }
.plan-usage .u {
  border: 1px solid #e0e0e0; border-radius: 6px; padding: 8px 10px; font-size: 12px; color: #455a64;
}
.plan-usage .u b { display: block; font-size: 15px; color: #263238; margin-bottom: 4px; }
.plan-usage .bar { height: 6px; border-radius: 3px; background: #e0e0e0; margin-top: 6px; overflow: hidden; }
.plan-usage .bar > i { display: block; height: 100%; background: #43a047; }
.plan-usage .bar.warn > i { background: #fb8c00; }
.plan-usage .bar.full > i { background: #e53935; }
.plan-scroll { overflow-x: auto; }
table.plan-table { border-collapse: collapse; width: 100%; font-size: 12.5px; min-width: 560px; }
table.plan-table th, table.plan-table td {
  border: 1px solid #e0e0e0; padding: 6px 9px; text-align: center; color: #37474f;
}
table.plan-table th:first-child, table.plan-table td:first-child { text-align: left; white-space: nowrap; }
table.plan-table thead th { background: #eceff1; color: #263238; }
table.plan-table td.mine, table.plan-table th.mine { background: #e8f5e9; font-weight: bold; }
table.plan-table td.no { color: #b0bec5; }
table.plan-table td.yes { color: #2e7d32; }
.plan-next { margin-top: 6px; font-size: 12.5px; color: #455a64; line-height: 1.6; }
.plan-next ul { margin: 6px 0 0; padding-left: 20px; }
.plan-note { margin-top: 10px; font-size: 11.5px; color: #78909c; line-height: 1.5; }

/* form di modal (teks & etiket) */
.frm-row { display: flex; gap: 10px; margin: 4px 0; }
.frm-row > div { flex: 1; }
.modal-box label { display: block; font-size: 12px; color: #546e7a; margin: 7px 0 2px; }
.modal-box input, .modal-box select, .modal-box textarea {
  width: 100%; padding: 6px 7px; border: 1px solid #b0bec5; border-radius: 4px;
  font: inherit; font-size: 13px; box-sizing: border-box;
}
.modal-box input[type=color] { padding: 2px; height: 32px; }
.chkrow { display: flex; gap: 12px; font-size: 13px; align-items: center; height: 32px; }
.chkrow label { display: flex; align-items: center; gap: 4px; margin: 0; color: #37474f; }
.chkrow input { width: auto; }
.frm-row button { width: 100%; background: #607d8b; color: #fff; border: 0; border-radius: 4px; padding: 7px 8px; cursor: pointer; font-size: 12px; }

/* anotasi teks & etiket di kanvas */
.anno { cursor: move; }
.frame .fhandle { cursor: move; }

/* halaman login */
body.login-page {
  display: flex; align-items: center; justify-content: center;
  height: 100vh; background: #263238;
}
.login-card {
  background: #fff; padding: 28px; border-radius: 10px; width: 320px;
  box-shadow: 0 8px 30px rgba(0, 0, 0, .35);
}
.login-card h1 { margin: 0; font-size: 22px; color: #263238; }
.login-card .sub { margin: 2px 0 18px; color: #78909c; font-size: 13px; }
.tabs { display: flex; gap: 6px; margin-bottom: 14px; }
.tabs button {
  flex: 1; border: 0; padding: 8px; border-radius: 5px; cursor: pointer;
  background: #eceff1; color: #37474f;
}
.tabs button.active { background: #37474f; color: #fff; }
.login-card form { display: flex; flex-direction: column; gap: 10px; }
.login-card input {
  padding: 9px 10px; border: 1px solid #b0bec5; border-radius: 5px; font-size: 14px;
}
.login-card .primary {
  background: #43a047; color: #fff; border: 0; padding: 10px;
  border-radius: 5px; cursor: pointer; font-weight: bold;
}
.msg { color: #e53935; font-size: 13px; min-height: 16px; margin: 10px 0 0; }
.hint { color: #90a4ae; font-size: 12px; margin: 6px 0 0; }

/* ============================ RESPONSIF (HP / TABLET) ============================ */
/* modal selalu muat di layar kecil */
.modal-box { width: min(360px, 92vw); }

/* Tablet & HP: toolbar jadi satu baris yang bisa digeser mendatar.
   Di layar sempit mode "toolbar di kanan" dipaksa balik ke ATAS — bilah tegak
   memakan lebar kanvas terlalu banyak (setelannya tetap tersimpan). */
@media (max-width: 900px) {
  body.bar-right { flex-direction: column; }
  body.bar-right #main { order: 0; }
  body.bar-right #bar {
    order: 0; display: flex; grid-template-columns: none;
    align-items: center; justify-content: flex-start;   /* jangan center: bilah
       yang meluap jadi tergeser & awalnya tak terjangkau */
    gap: 6px; padding: 8px 10px; overflow-y: visible;
  }
  body.bar-right #bar button.icon { height: 34px; }
  body.bar-right #status { right: 12px; top: auto; bottom: 12px; }
  body.bar-right #bar button:not(.icon) { grid-column: auto; font-size: 13px; padding: 7px 12px; }
  body.bar-right .bar-sep { grid-column: auto; width: 1px; height: 22px; margin: 0 2px; }
  body.bar-right #collab, body.bar-right #user-box { grid-column: auto; }
  /* kembali jadi butir bilah mendatar biasa: buang margin negatif & latar
     "kaki bilah" yang hanya masuk akal saat bilahnya tegak */
  body.bar-right #user-box {
    margin: 0 0 0 auto; padding: 0; background: none; box-shadow: none;
    position: relative; bottom: auto;
  }
  body.bar-right #user-btn {
    width: auto; border-radius: 20px; padding: 4px 10px 4px 12px;
  }
  #bar { flex-wrap: nowrap; overflow-x: auto; -webkit-overflow-scrolling: touch; }
  #bar::-webkit-scrollbar { height: 0; }
  #bar button.icon { flex: 0 0 auto; }
  #collab, #user-box { flex: 0 0 auto; }
  #status { max-width: 70vw; font-size: 12px; }
}

/* HP / tablet kecil: palet jadi laci geser di atas kanvas */
@media (max-width: 768px) {
  #bar #btn-menu { display: inline-flex; }   /* pasangan aturan di atas */
  #main { position: relative; }
  #palette {
    position: absolute; top: 0; left: 0; bottom: 0; width: 78%; max-width: 280px;
    transform: translateX(-100%); transition: transform .25s ease; z-index: 30;
    box-shadow: 2px 0 14px rgba(0, 0, 0, .4);
  }
  body.nav-open #palette { transform: translateX(0); }
  body.nav-open #nav-backdrop {
    display: block; position: absolute; inset: 0; z-index: 25;
    background: rgba(0, 0, 0, .38);
  }
  /* target sentuh lebih besar di palet */
  #palette-list button { height: 60px; }
  #palette-list svg { height: 52px; }
  #domain-tabs button { font-size: 11px; padding: 7px 6px; }
  #user-box { font-size: 12px; }
}

/* layar sangat sempit: status jangan menutupi kanvas */
@media (max-width: 480px) {
  #status { left: 8px; right: 8px; max-width: none; bottom: 8px; text-align: center; }
  #bar { gap: 4px; padding: 6px 8px; }
  #bar button.icon { width: 36px; height: 36px; }
}

/* perangkat sentuh: perjelas bahwa kanvas memakai gestur (bukan scroll halaman) */
@media (pointer: coarse) {
  #canvas { touch-action: none; }
}

/* ==========================================================================
   MODE GELAP (data-theme="dark" pada <html>; tanpa atribut = mode terang)
   Prinsipnya: hanya menimpa permukaan terang. Simbol di kanvas digambar
   dengan warna tetap di sprite (mis. #212121), jadi ditukar lewat pemilih
   atribut — bukan filter — supaya tidak membebani animasi/geser.
   ========================================================================== */
[data-theme="dark"] body { background: #10171b; color: #cfd8dc; }

/* --- toolbar & palet --- */
[data-theme="dark"] #bar { background: #151d22; color: #90caf9; }
[data-theme="dark"] #bar button { background: #2b383f; }
[data-theme="dark"] #bar button.primary { background: #2e7d32; }
[data-theme="dark"] #bar button.primary.running { background: #c62828; }
/* SAKLAR HIDUP/MATI (amber) harus diulang di sini: aturan gelap di atas
   berkekhususan SAMA dengan '#bar button.active' tapi ditulis belakangan,
   jadi tanpa baris ini semua tombol tekan-tahan (aliran, grid, putar, pilih)
   tampak mati di mode gelap — keadaannya tak bisa dibaca sama sekali. */
[data-theme="dark"] #bar button.active { background: #ffb300; color: #212121; }
[data-theme="dark"] #bar button.active .ic { color: #1b2733; }
[data-theme="dark"] .bar-sep { background: #3a4a52; }
[data-theme="dark"] #palette { background: #1a2429; color: #b0bec5; }
[data-theme="dark"] #palette h2 { color: #eceff1; }
[data-theme="dark"] #domain-tabs button { background: #2b383f; color: #b0bec5; }
[data-theme="dark"] #domain-tabs button:hover { background: #37474f; }
/* tab domain yang sedang dipilih — sama perkaranya dengan '#bar button.active'
   di atas: baris gelap sebelumnya seri kekhususan tapi ditulis belakangan */
[data-theme="dark"] #domain-tabs button.active { background: #0288d1; color: #fff; }
[data-theme="dark"] #palette-list button { background: #eceff1; border-color: #546e7a; }
[data-theme="dark"] #palette-list button:hover { background: #fff; border-color: #90a4ae; }
/* terkunci: latar tetap terang tapi redup, supaya simbolnya masih terbaca */
[data-theme="dark"] #palette-list button.locked { background: #b6c1c6; border-color: #546e7a; }
[data-theme="dark"] #palette-list button.locked:hover { background: #c6d0d4; }
[data-theme="dark"] #palette-list button.locked::after { color: #37474f; }

/* --- kanvas & gambar --- */
[data-theme="dark"] #canvas { background: #0f1519; }
[data-theme="dark"] #gridpat path { stroke: #26343c; }
/* tukar warna garis/isi simbol: gelap <-> terang */
[data-theme="dark"] #scene [stroke="#212121"] { stroke: #dfe8ec; }
[data-theme="dark"] #scene [fill="#212121"] { fill: #dfe8ec; }
[data-theme="dark"] #scene [stroke="#263238"] { stroke: #cfd8dc; }
[data-theme="dark"] #scene [fill="#263238"] { fill: #cfd8dc; }
[data-theme="dark"] #scene [stroke="#455a64"] { stroke: #90a4ae; }
[data-theme="dark"] #scene [fill="#455a64"] { fill: #90a4ae; }
[data-theme="dark"] #scene [stroke="#eceff1"] { stroke: #37474f; }
[data-theme="dark"] #scene [fill="#eceff1"] { fill: #2f3e46; }
[data-theme="dark"] #scene [fill="#fff"] { fill: #22303a; }
[data-theme="dark"] #scene [fill="#e1f5fe"] { fill: #17323f; }
[data-theme="dark"] #scene [fill="#cfd8dc"] { fill: #4c626d; }
[data-theme="dark"] #scene [fill="#bdbdbd"] { fill: #5a6f7a; }
[data-theme="dark"] #scene [fill="#e8eaf6"] { fill: #232c3a; }   /* badan PLC */
/* teks nilai analog & nama program pada PLC: cerahkan agar terbaca */
[data-theme="dark"] #scene [fill="#00695c"] { fill: #4db6ac; }
[data-theme="dark"] #scene [fill="#5c6bc0"] { fill: #9fa8da; }
[data-theme="dark"] #scene [fill="#37474f"] { fill: #b0bec5; }
[data-theme="dark"] .comp .term:hover { fill: #ffcc80; }
[data-theme="dark"] .comp .term.sel { fill: #fb8c00; }
[data-theme="dark"] .comp rect.selbox { stroke: #ffb74d; fill: rgba(255,183,77,.14); }
/* label arus: halo gelap supaya terbaca di atas kanvas gelap */
[data-theme="dark"] #wires text.amp-label { fill: #90caf9; stroke: #0f1519; }
[data-theme="dark"] #wires text.amp-label.over { fill: #ff8a80; }
[data-theme="dark"] #wires text.amp-label.qflow { fill: #4fc3f7; }
/* KABEL & SELANG DI MODE GELAP — hanya menukar NILAI variabel (lihat blok
   ':root' di bagian atas berkas). JANGAN kembali menulis
   '[data-theme="dark"] #wires polyline { ... }': pemilih itu mengalahkan
   '#wires .hit' sehingga area-tarik transparan selebar 14 px ikut tercat, dan
   pita sewarna itulah yang menelan celah garis putus-putus — animasi aliran
   jadi tak terlihat sama sekali di mode gelap. */
[data-theme="dark"] {
  --w-plain:   #78909c;
  --w-dead:    #607d8b;
  --w-phase:   #ff5252;   /* dicerahkan: #e53935 terlalu gelap di atas #0f1519 */
  --w-neutral: #64b5f6;
  --w-air:     #26c6da;
  --w-oil:     #ffa726;   /* dicerahkan agar tetap terbaca di atas #0f1519 */
  --w-pipe:    #78909c;
  --w-wet:     #4fc3f7;
  --w-water:   #29b6f6;
  --w-refhi:   #ff6e6b;
  --w-reflo:   #64b5f6;
  --w-ref:     #607d8b;
  --w-coal:        #a1745f;   /* cokelat tua nyaris hilang di latar gelap */
  --w-coal-off:    #6d564d;
  --w-combair:     #4fc3f7;
  --w-combair-off: #37687d;
  --w-flue:        #b08574;
  --w-flue-off:    #6b564e;
}

/* --- modal & panel --- */
[data-theme="dark"] .modal-box { background: #222d33; color: #cfd8dc; }
[data-theme="dark"] .modal-box h3 { color: #eceff1; }
[data-theme="dark"] .modal-box label { color: #90a4ae; }
[data-theme="dark"] .modal-box input,
[data-theme="dark"] .modal-box select,
[data-theme="dark"] .modal-box textarea {
  background: #2b383f; color: #eceff1; border-color: #546e7a;
}
[data-theme="dark"] #circuit-list li { border-bottom-color: #37474f; }
[data-theme="dark"] #circuit-list li span { color: #cfd8dc; }
[data-theme="dark"] #analysis-panel,
[data-theme="dark"] #images-panel { background: #222d33; color: #cfd8dc; }
[data-theme="dark"] .ap-head { background: #172126; }
[data-theme="dark"] #analysis-body h4 { color: #b0bec5; border-bottom-color: #37474f; }
[data-theme="dark"] .res-ok { background: #16311d; color: #a5d6a7; }
[data-theme="dark"] .res-note { background: #322a17; color: #ffd54f; }
[data-theme="dark"] .res-warn { background: #3a1f1f; color: #ff8a80; }
[data-theme="dark"] .res-info { background: #172a3a; color: #90caf9; }
[data-theme="dark"] .ap-badge { background: #2b383f; color: #cfd8dc; }
[data-theme="dark"] .ap-sub { color: #90a4ae; }
[data-theme="dark"] .ap-warn { background: #322a17; color: #ffd54f;
  border-left-color: #ffa000; }
[data-theme="dark"] .expr, [data-theme="dark"] .sub-note { color: #90a4ae; }
[data-theme="dark"] table.kha-tbl th,
[data-theme="dark"] table.kha-tbl td { border-color: #37474f; }
[data-theme="dark"] table.kha-tbl thead th { background: #2b383f; color: #b0bec5; }
[data-theme="dark"] table.kha-tbl tr.over td { background: #3a1f1f; color: #ff8a80; }
[data-theme="dark"] .img-card { background: #1c262b; border-color: #37474f; }
[data-theme="dark"] .img-head { color: #cfd8dc; }
[data-theme="dark"] .img-thumb { background: #263238; border-color: #37474f; }
[data-theme="dark"] .img-url,
[data-theme="dark"] .img-scope select,
[data-theme="dark"] .img-btns button { background: #2b383f; color: #eceff1; border-color: #546e7a; }
[data-theme="dark"] .img-btns .img-save { background: #1565c0; border-color: #1565c0; }
[data-theme="dark"] .img-src b { color: #64b5f6; }

/* --- panel Paket --- */
[data-theme="dark"] .plan-hero { background: #1c262b; }
[data-theme="dark"] .plan-hero .why { color: #b0bec5; }
[data-theme="dark"] #plan-body h4 { color: #b0bec5; }
[data-theme="dark"] .plan-usage .u { border-color: #37474f; color: #b0bec5; }
[data-theme="dark"] .plan-usage .u b { color: #eceff1; }
[data-theme="dark"] .plan-usage .bar { background: #37474f; }
[data-theme="dark"] table.plan-table th,
[data-theme="dark"] table.plan-table td { border-color: #37474f; color: #cfd8dc; }
[data-theme="dark"] table.plan-table thead th { background: #2b383f; color: #eceff1; }
[data-theme="dark"] table.plan-table td.mine,
[data-theme="dark"] table.plan-table th.mine { background: #1b3524; }
[data-theme="dark"] table.plan-table td.no { color: #607d8b; }
[data-theme="dark"] table.plan-table td.yes { color: #81c784; }
[data-theme="dark"] .plan-next, [data-theme="dark"] .plan-note { color: #90a4ae; }

/* tombol tema: bulan saat terang, matahari saat gelap */
#btn-theme .ic-light { display: none; }
[data-theme="dark"] #btn-theme .ic-dark { display: none; }
[data-theme="dark"] #btn-theme .ic-light { display: inline-block; }

/* --- Osiloskop sinyal (sensor / solenoid / tekanan / langkah silinder) --- */
/* Panel bisa DIGESER (lewat judul), DIKECILKAN (tombol – / ▭), dan ditarik
   ukurannya dari sudut kanan-bawah (CSS resize). Kanvas mengikuti ukuran panel
   karena tingginya fleksibel; scopeDraw() dipanggil ulang lewat ResizeObserver. */
#scope-panel { position: fixed; left: 50%; top: 50%; transform: translate(-50%, -50%);
  /* lebar bawaan ditambah 160px saat pengaturan pindah ke kolom kanan, supaya
     layar tetap LEBIH LEBAR daripada tata letak bilah-atas yang lama */
  z-index: 60; width: min(920px, 96vw); height: 560px;
  min-width: 300px; min-height: 120px; max-width: 98vw; max-height: 96vh;
  resize: both; overflow: hidden;
  display: flex; flex-direction: column;
  background: #fff; border-radius: 10px; box-shadow: 0 10px 34px rgba(0,0,0,.34);
  font: 13px/1.45 "Segoe UI", sans-serif; color: #263238; }
#scope-panel.hidden { display: none; }
/* ukuran ringkas: pas untuk mengintip sinyal sambil menggambar */
#scope-panel.compact { width: min(430px, 92vw); height: 300px; }
/* dikecilkan penuh: tinggal bilah judul, tak bisa ditarik ukurannya */
#scope-panel.mini { height: auto !important; min-height: 0; resize: none; }
#scope-panel.mini #scope-body { display: none; }
.sc-drag { cursor: move; user-select: none; flex: 0 0 auto; }
.sc-head-btns { display: flex; align-items: center; gap: 2px; }
.ap-head .sc-head-btns button { padding: 0 5px; line-height: 1; border-radius: 4px; }
.ap-head .sc-head-btns button.on { background: #ffca28; color: #212121; }
/* LAYAR di kiri, PENGATURAN berdiri di kolom kanan. Sebagai bilah mendatar di
   atas, pengaturan ini membungkus jadi 2-3 baris dan memakan tinggi layar;
   sebagai kolom, tingginya tak lagi mengurangi ruang gambar. */
#scope-body { padding: 10px 12px 12px; flex: 1 1 auto; min-height: 0;
  display: flex; flex-direction: row; gap: 10px; overflow: hidden; }
.sc-main { flex: 1 1 auto; min-width: 0; min-height: 0;
  display: flex; flex-direction: column; overflow: auto; }
.sc-bar { flex: 0 0 190px; display: flex; flex-direction: column;
  align-items: stretch; gap: 7px; min-height: 0; overflow-y: auto;
  padding-left: 10px; border-left: 1px solid #cfd8dc; }
.sc-bar label { display: flex; flex-direction: column; align-items: stretch;
  gap: 3px; font-size: 12px; color: #546e7a; }
.sc-bar select, .sc-bar button { font: 12px "Segoe UI", sans-serif; padding: 3px 8px;
  border: 1px solid #b0bec5; border-radius: 5px; background: #eceff1; color: #263238;
  cursor: pointer; width: 100%; box-sizing: border-box; }
.sc-bar button.on { background: #ffca28; border-color: #ffa000; }
.sc-info { margin-top: auto; font-size: 11.5px; color: #78909c; }
[data-theme="dark"] .sc-bar { border-left-color: #37474f; }
/* layar: hitam-hijau seperti osiloskop, digambar oleh <canvas> */
.sc-screen { position: relative; background: #08161a; border-radius: 6px; padding: 0;
  border: 1px solid #37474f; overflow: hidden; flex: 1 1 auto; min-height: 110px; }
.sc-screen canvas { display: block; width: 100%; height: 100%; }
.sc-read { position: absolute; top: 6px; left: 8px; pointer-events: none;
  background: rgba(8,22,26,.86); border: 1px solid #37474f; border-radius: 5px;
  padding: 5px 7px; font: 11px "Consolas", monospace; color: #b2dfdb; white-space: pre; }
.sc-read.hidden { display: none; }
/* satu baris per kanal. Daftar kanal punya gulungan SENDIRI: dengan 8-12 kanal
   daftarnya panjang, dan tanpa ini layar osiloskop terdorong keluar pandangan. */
#sc-chans { margin-top: 8px; display: grid; gap: 4px;
  flex: 0 1 auto; max-height: 240px; overflow-y: auto; overflow-x: hidden;
  padding-right: 2px; }
/* Baris kanal harus MUAT di lebar berapa pun: panel bisa ditarik ukurannya dan
   sejak pengaturan pindah ke kolom kanan, sisa lebarnya lebih sempit. Karena
   itu barisnya boleh membungkus dan selectnya boleh mengecil (media query
   berbasis viewport tidak menolong — yang menyempit panelnya, bukan layarnya). */
.sc-ch { display: flex; align-items: center; gap: 6px; font-size: 12px; flex-wrap: wrap; }
.sc-ch .sc-name { font-weight: 600; color: var(--c); min-width: 34px; }
.sc-ch select { flex: 1 1 110px; min-width: 88px; font: 12px "Segoe UI", sans-serif;
  padding: 2px 5px; border: 1px solid #b0bec5; border-radius: 5px; background: #fff; color: #263238; }
.sc-ch input[type=number] { width: 62px; font: 12px "Segoe UI", sans-serif;
  padding: 2px 4px; border: 1px solid #b0bec5; border-radius: 5px; }
.sc-ch input[type=number]:disabled { background: #eceff1; color: #90a4ae; }
.sc-ch label { display: flex; align-items: center; gap: 3px; color: #546e7a; }
.sc-ch .sc-unit { color: #90a4ae; min-width: 46px; }
/* jumlah kanal bisa diubah: ✕ membuang kanal, ＋ menambah (minimal 4) */
.sc-ch .sc-chdel { border: 1px solid #b0bec5; border-radius: 5px; background: #eceff1;
  color: #78909c; font: 11px "Segoe UI", sans-serif; line-height: 1;
  padding: 3px 5px; cursor: pointer; }
.sc-ch .sc-chdel:hover:not(:disabled) { background: #ffcdd2; border-color: #e57373; color: #c62828; }
.sc-ch .sc-chdel:disabled { opacity: .35; cursor: not-allowed; }
.sc-chadd { display: flex; align-items: center; gap: 8px; margin-top: 5px; flex: 0 0 auto; }
.sc-chadd button { font: 12px "Segoe UI", sans-serif; padding: 3px 10px;
  border: 1px dashed #90a4ae; border-radius: 5px; background: #f5f7f8;
  color: #37474f; cursor: pointer; }
.sc-chadd button:hover:not(:disabled) { background: #e0f2f1; border-color: #26a69a; }
.sc-chadd button:disabled { opacity: .45; cursor: not-allowed; }
[data-theme="dark"] .sc-ch .sc-chdel,
[data-theme="dark"] .sc-chadd button { background: #2b383f; color: #cfd8dc; border-color: #546e7a; }
.sc-note { margin: 0; font-size: 12px; line-height: 1.6; color: #607d8b; }
/* Bantuan "cara pakai" (tombol ? di judul): LAPISAN di atas panel, bukan
   paragraf yang ikut mengambil tinggi — layar osiloskop tetap sepenuh panel. */
.sc-helpbox { position: absolute; left: 10px; right: 10px; top: 42px;
  max-height: calc(100% - 56px);            /* setinggi isinya saja, tak menutup penuh */
  z-index: 3; overflow: auto; padding: 12px 34px 14px 14px;
  background: #fff; border: 1px solid #b0bec5; border-radius: 8px;
  box-shadow: 0 10px 28px rgba(0,0,0,.24); }
.sc-helpbox.hidden { display: none; }
.sc-helpbox h4 { margin: 0 0 7px; font-size: 13px; color: #37474f; }
.sc-help-close { position: absolute; top: 6px; right: 8px; line-height: 1;
  padding: 2px 6px; border: 1px solid #b0bec5; border-radius: 5px;
  background: #eceff1; color: #546e7a; cursor: pointer; font-size: 12px; }
.sc-help-close:hover { background: #ffcdd2; border-color: #e57373; color: #c62828; }
#scope-panel.mini .sc-helpbox { display: none; }   /* dikecilkan = ikut hilang */
[data-theme="dark"] .sc-helpbox { background: #222d33; border-color: #546e7a; }
[data-theme="dark"] .sc-helpbox h4 { color: #cfd8dc; }
[data-theme="dark"] .sc-help-close { background: #2b383f; color: #cfd8dc; border-color: #546e7a; }
/* panel sempit: baris kanal dibuat bisa membungkus supaya tak terpotong */
@media (max-width: 700px) { .sc-ch select { min-width: 90px; } }
#scope-panel.compact .sc-unit { display: none; }
#scope-panel.compact .sc-bar { flex-basis: 148px; }   /* ukuran ringkas: kolom lebih tipis */
/* layar sangat sempit (ponsel): kolom kanan tak muat -> kembali ke bawah layar */
@media (max-width: 560px) {
  #scope-body { flex-direction: column; }
  .sc-bar { flex: 0 0 auto; border-left: 0; border-top: 1px solid #cfd8dc;
    padding-left: 0; padding-top: 8px; margin-top: 8px; }
  .sc-info { margin-top: 0; }
}
#scope-panel.compact #sc-chans { max-height: 120px; }
#scope-panel.compact .sc-chadd .sc-unit { display: inline; }   /* hitungan kanal tetap terlihat */
#scope-panel.compact .sc-ch input[type=number] { width: 58px; }
[data-theme="dark"] #scope-panel { background: #222d33; color: #cfd8dc; }
[data-theme="dark"] .sc-bar label, [data-theme="dark"] .sc-ch label { color: #90a4ae; }
[data-theme="dark"] .sc-bar select, [data-theme="dark"] .sc-bar button,
[data-theme="dark"] .sc-ch select, [data-theme="dark"] .sc-ch input[type=number] {
  background: #2b383f; color: #eceff1; border-color: #546e7a; }
[data-theme="dark"] .sc-ch input[type=number]:disabled { background: #263238; color: #607d8b; }
[data-theme="dark"] .sc-note, [data-theme="dark"] .sc-info { color: #78909c; }

/* --- pipa refrigeran (domain Air Conditioning) --- */
/* warnanya lewat variabel, sama alasannya dengan kabel listrik di atas */
#wires polyline.refhi { stroke: var(--w-refhi); stroke-width: 3.4; }   /* sisi tekanan tinggi (panas) */
#wires polyline.reflo { stroke: var(--w-reflo); stroke-width: 3.4; }   /* sisi tekanan rendah (dingin) */
#wires polyline.ref   { stroke: var(--w-ref); stroke-width: 3; }       /* siklus berhenti */

/* --- PLTU: jalur batu bara, udara bakar & gas buang --- */
#wires polyline.coal    { stroke: var(--w-coal); stroke-width: 4; }    /* batu bara mengalir */
#wires polyline.coal_off{ stroke: var(--w-coal-off); stroke-width: 3.4; stroke-dasharray: 6 5; }
#wires polyline.combair { stroke: var(--w-combair); stroke-width: 3.6; } /* udara bakar */
#wires polyline.combair_off { stroke: var(--w-combair-off); stroke-width: 3; }
#wires polyline.flue    { stroke: var(--w-flue); stroke-width: 4.2; }  /* gas buang panas */
#wires polyline.flue_off{ stroke: var(--w-flue-off); stroke-width: 3.2; stroke-dasharray: 6 5; }

/* --- foto komponen: satu jenis boleh punya BANYAK gambar --- */
.img-strip { display: flex; gap: 6px; flex-wrap: wrap; margin: 6px 0; }
.img-cell { position: relative; width: 84px; cursor: zoom-in; }
.img-cell .img-thumb { width: 84px; height: 64px; object-fit: cover; margin: 0; }
.img-cap { display: block; font-size: 10px; color: #78909c; line-height: 1.2;
  max-height: 24px; overflow: hidden; }
.img-x { position: absolute; top: 2px; right: 2px; width: 18px; height: 18px;
  border: 0; border-radius: 50%; background: rgba(0,0,0,.55); color: #fff;
  font-size: 11px; line-height: 18px; padding: 0; cursor: pointer; }
.img-x:hover { background: #c62828; }
.img-name { width: 100%; margin-top: 4px; padding: 4px 6px; font-size: 12px;
  border: 1px solid #b0bec5; border-radius: 5px; }
/* tombol geser gambar di lightbox */
.lb-nav { position: absolute; top: 50%; transform: translateY(-50%);
  width: 44px; height: 64px; border: 0; border-radius: 6px;
  background: rgba(0,0,0,.45); color: #fff; font-size: 30px; cursor: pointer; z-index: 2; }
.lb-nav:hover { background: rgba(0,0,0,.7); }
.lb-nav.hidden { display: none; }
#lightbox-prev { left: 10px; }
#lightbox-next { right: 10px; }
[data-theme="dark"] .img-name { background: #2b383f; color: #eceff1; border-color: #546e7a; }
[data-theme="dark"] .img-cap { color: #90a4ae; }

/* --- jeda simulasi & pemicu auto-jeda --- */
#bar button#btn-pause.on { background: #ffb300; color: #212121; }
body.paused #canvas { outline: 3px solid #ffb300; outline-offset: -3px; }
.sc-trig { display: flex; flex-direction: column; align-items: stretch; gap: 4px;
  font-size: 12px; color: #546e7a; }
.sc-trig select { max-width: none; }
.sc-trig input { width: 100%; box-sizing: border-box;
  font: 12px "Segoe UI", sans-serif; padding: 3px 5px;
  border: 1px solid #b0bec5; border-radius: 5px; }
.sc-trig.armed { color: #e65100; font-weight: 600; }
[data-theme="dark"] .sc-trig { color: #90a4ae; }
[data-theme="dark"] .sc-trig input { background: #2b383f; color: #eceff1; border-color: #546e7a; }
/* rekam 1 siklus + laporan */
.sc-cyc { display: flex; flex-direction: column; align-items: stretch; gap: 4px;
  font-size: 12px; color: #546e7a;
  border: 1px dashed #b0bec5; border-radius: 6px; padding: 5px 6px; }
.sc-cyc select { max-width: none; }
.sc-cyc.armed { color: #c62828; font-weight: 600; border-color: #ef9a9a; background: #ffebee; }
.sc-bar #sc-cyc-arm.on { background: #ef5350; border-color: #c62828; color: #fff; }
.sc-bar button:disabled { opacity: .5; cursor: not-allowed; }
[data-theme="dark"] .sc-cyc { color: #90a4ae; border-color: #546e7a; }
[data-theme="dark"] .sc-cyc.armed { background: #3a2426; border-color: #c62828; color: #ff8a80; }

/* --- mode PILIH: kursor & kotak seleksi --- */
#canvas.selmode { cursor: default; }
#canvas.selmode .comp { cursor: pointer; }
#guides rect.marquee {
  fill: rgba(2,136,209,.12); stroke: #0288d1; stroke-width: 1.5;
  stroke-dasharray: 5 4; pointer-events: none;
}

/* kode berbagi 8 karakter di kotak user */
#user-box .code-chip {
  background: #37474f; color: #b3e5fc; border: 1px solid #546e7a;
  border-radius: 5px; padding: 3px 8px; margin-right: 8px; cursor: pointer;
  font: 600 12px "Consolas", monospace; letter-spacing: .5px;
}
#user-box .code-chip .ck { margin-right: 4px; }
#user-box .code-chip:hover { background: #455a64; color: #fff; }

/* komponen yang baru diubah rekan di sesi bersama: berdenyut sesaat */
#comps g.comp.remote-edit { animation: remoteEdit 2.2s ease-out 1; }
@keyframes remoteEdit {
  0%   { filter: drop-shadow(0 0 0 rgba(255,152,0,0)); }
  12%  { filter: drop-shadow(0 0 9px rgba(255,152,0,.95)); }
  100% { filter: drop-shadow(0 0 0 rgba(255,152,0,0)); }
}
#collab { cursor: pointer; }

/* --- dialog Bagikan (kolaborasi) --- */
#share-modal { position: fixed; inset: 0; z-index: 120; background: rgba(0,0,0,.45);
  display: flex; align-items: center; justify-content: center; }
#share-modal.hidden { display: none; }
#share-modal .modal-box { width: min(520px, 94vw); }
.share-mycode { background: #eceff1; border-radius: 6px; padding: 8px 10px;
  font-size: 13px; margin-bottom: 12px; }
.share-mycode b { font: 600 15px "Consolas", monospace; letter-spacing: 1px; color: #0277bd; }
.share-mycode button { margin-left: 6px; font-size: 11px; padding: 2px 8px;
  border: 1px solid #b0bec5; border-radius: 4px; background: #fff; cursor: pointer; }
.share-mycode .muted { display: block; margin-top: 3px; font-size: 11.5px; color: #78909c; }
.sm-lbl { display: block; font-size: 12.5px; color: #546e7a; margin-bottom: 10px; }
.sm-lbl input { width: 100%; margin-top: 4px; padding: 7px 9px; font-size: 14px;
  border: 1px solid #b0bec5; border-radius: 5px; }
#sm-code { font-family: "Consolas", monospace; letter-spacing: 1px; text-transform: uppercase; }
.sm-note { font-size: 12px; color: #78909c; background: #fff8e1; border-left: 3px solid #ffb300;
  padding: 7px 9px; border-radius: 4px; margin: 0 0 12px; }
/* blok guru di tab Kelas: memasang rangkaian awal sebuah tugas. Dipisahkan
   garis supaya jelas bahwa ini BUKAN bagian dari alur "kumpulkan tugas" di
   atasnya — dua hal yang kebetulan memakai kelas dan tugas yang sama. */
.sm-guru { border-top: 1px solid #cfd8dc; margin-top: 10px; padding-top: 10px; }
[data-theme="dark"] .sm-guru { border-top-color: #37474f; }
/* tiga cara membagikan dalam satu dialog (kolaborasi / kelas / tautan luar) */
.sm-tabs { display: flex; gap: 4px; margin: 0 0 12px; flex-wrap: wrap; }
.sm-tabs button { font: inherit; font-size: 12.5px; padding: 6px 10px; cursor: pointer;
  border: 1px solid #cfd8dc; background: #f5f7f8; color: #546e7a;
  border-radius: 7px 7px 0 0; border-bottom: 2px solid transparent; }
.sm-tabs button.on { background: #fff; color: #0277bd; font-weight: 600;
  border-bottom-color: #2a78d6; }
.sm-row { display: flex; gap: 10px; align-items: flex-end; flex-wrap: wrap; }
.sm-lbl select { width: 100%; margin-top: 4px; padding: 7px 9px; font-size: 14px;
  border: 1px solid #b0bec5; border-radius: 5px; background: #fff; color: #263238; }
.sm-lbl.sm-chk { display: flex; align-items: center; gap: 6px; padding-bottom: 8px; }
.sm-lbl.sm-chk input { width: auto; margin: 0; }
#sm-lurl { font-family: "Consolas", monospace; font-size: 12.5px; }
.sm-tautan { margin-top: 10px; max-height: 190px; overflow: auto; font-size: 12px; }
.sm-tautan .t { display: flex; gap: 8px; align-items: center; padding: 5px 2px;
  border-bottom: 1px solid #eceff1; }
.sm-tautan .t .nm { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sm-tautan .t .mt { color: #90a4ae; font-size: 11px; white-space: nowrap; }
.sm-tautan .t button { font-size: 11px; padding: 2px 7px; border: 1px solid #b0bec5;
  background: #fff; border-radius: 4px; cursor: pointer; }
.sm-tautan .t.mati .nm { text-decoration: line-through; color: #90a4ae; }
[data-theme="dark"] .sm-tabs button { background: #1c262b; border-color: #37474f; color: #90a4ae; }
[data-theme="dark"] .sm-tabs button.on { background: #2b383f; color: #4fc3f7; }
[data-theme="dark"] .sm-lbl select,
[data-theme="dark"] .sm-tautan .t button { background: #2b383f; color: #eceff1; border-color: #546e7a; }
[data-theme="dark"] .sm-tautan .t { border-color: #37474f; }
[data-theme="dark"] .share-mycode { background: #1c262b; }
[data-theme="dark"] .share-mycode button,
[data-theme="dark"] .sm-lbl input { background: #2b383f; color: #eceff1; border-color: #546e7a; }
[data-theme="dark"] .sm-note { background: #322a17; color: #ffd54f; }

/* --- modal Rangkaian Bersama: tabel besar, cari, urut, halaman --- */
#shared-modal { position: fixed; inset: 0; z-index: 130; background: rgba(0,0,0,.45);
  display: flex; align-items: center; justify-content: center; }
#shared-modal.hidden { display: none; }
#shared-modal .modal-box.wide {
  width: min(1000px, 96vw); max-height: 88vh; display: flex; flex-direction: column;
}
#shared-modal h3 { display: flex; align-items: center; gap: 8px; margin: 0 0 10px; }
#shared-modal h3 .x { margin-left: auto; background: none; border: 0; font-size: 16px;
  cursor: pointer; color: #607d8b; }
.shl-bar { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 10px;
  font-size: 12.5px; color: #546e7a; }
#shl-search { flex: 1; min-width: 200px; padding: 7px 10px; font-size: 13.5px;
  border: 1px solid #b0bec5; border-radius: 5px; }
.shl-bar select, .shl-bar button { padding: 4px 9px; font-size: 12.5px;
  border: 1px solid #b0bec5; border-radius: 5px; background: #eceff1; cursor: pointer; }
.shl-wrap { flex: 1; overflow: auto; border: 1px solid #cfd8dc; border-radius: 6px; }
table.shl-tbl { width: 100%; border-collapse: collapse; font-size: 13px; }
table.shl-tbl th { position: sticky; top: 0; z-index: 1; background: #eceff1;
  text-align: left; padding: 8px 10px; cursor: pointer; user-select: none;
  border-bottom: 1px solid #cfd8dc; white-space: nowrap; }
table.shl-tbl th:hover { background: #dfe6e9; }
table.shl-tbl th.sorted::after { content: attr(data-dir); margin-left: 5px; color: #0288d1; }
table.shl-tbl th.num, table.shl-tbl td.num { text-align: right; }
table.shl-tbl th.act, table.shl-tbl td.act { text-align: right; white-space: nowrap; }
table.shl-tbl td { padding: 7px 10px; border-bottom: 1px solid #eceff1; }
table.shl-tbl tr:hover td { background: #f5f9fb; }
table.shl-tbl td.nm { font-weight: 600; }
.tag-kunci { background: #37474f; color: #fff; border-radius: 3px; padding: 1px 5px;
             font-size: 11px; margin-left: 4px; white-space: nowrap; }
.tag-mine { background: #c8e6c9; color: #1b5e20; border-radius: 3px; padding: 1px 5px;
  font-size: 10.5px; font-weight: 700; margin-right: 4px; }
table.shl-tbl .op, table.shl-tbl .del { border: 1px solid #b0bec5; border-radius: 4px;
  background: #fff; padding: 3px 10px; margin-left: 5px; cursor: pointer; font-size: 12px; }
table.shl-tbl .op { background: #0288d1; color: #fff; border-color: #0288d1; }
table.shl-tbl .del { color: #c62828; border-color: #ef9a9a; }
.shl-empty { padding: 18px; text-align: center; color: #78909c; font-size: 13px; }
.shl-empty.hidden { display: none; }
/* keterangan di atas daftar modal (opt.desc) */
.modal-desc { margin: 0 0 10px; font-size: 12.5px; line-height: 1.45; color: #546e7a; }
.modal-desc.hidden { display: none; }
.modal-desc.warn { background: #fff3e0; border-left: 3px solid #fb8c00;
  color: #6d4c41; padding: 8px 10px; border-radius: 4px; }
[data-theme="dark"] .modal-desc { color: #90a4ae; }
[data-theme="dark"] .modal-desc.warn { background: #33240f; color: #ffcc80;
  border-left-color: #ffa726; }
/* Tab kategori di dalam modal daftar (opt.tabs pada openModal).
   Membungkus baris (flex-wrap): sepuluh disiplin tak muat satu baris di layar
   laptop, dan menggulungnya ke samping menyembunyikan tab paling kanan. */
.md-tabs { display: flex; flex-wrap: wrap; gap: 4px; margin: 0 0 10px; }
.md-tabs.hidden { display: none; }
.md-tabs button {
  font: inherit; font-size: 12px; padding: 5px 11px; cursor: pointer;
  border: 1px solid #cfd8dc; background: #f5f7f8; color: #546e7a;
  border-radius: 14px; line-height: 1.2;
}
.md-tabs button:hover { background: #e3f2fd; border-color: #90caf9; }
.md-tabs button.on { background: #2a78d6; border-color: #2a78d6; color: #fff;
  font-weight: 600; }
[data-theme="dark"] .md-tabs button { background: #1c262b; border-color: #37474f;
  color: #90a4ae; }
[data-theme="dark"] .md-tabs button:hover { background: #26343c; }
[data-theme="dark"] .md-tabs button.on { background: #1565c0; border-color: #1565c0;
  color: #fff; }
.shl-foot { display: flex; align-items: center; gap: 10px; margin-top: 10px; font-size: 12px; }
.shl-pages { margin-left: auto; display: flex; gap: 3px; }
.shl-pages button { min-width: 28px; padding: 3px 6px; border: 1px solid #b0bec5;
  border-radius: 4px; background: #fff; cursor: pointer; font-size: 12px; }
.shl-pages button.cur { background: #0288d1; color: #fff; border-color: #0288d1; }
.shl-pages button:disabled { opacity: .4; cursor: default; }
[data-theme="dark"] #shared-modal .modal-box.wide { background: #222d33; color: #cfd8dc; }
[data-theme="dark"] table.shl-tbl th { background: #2b383f; border-bottom-color: #37474f; }
[data-theme="dark"] table.shl-tbl th:hover { background: #37474f; }
[data-theme="dark"] table.shl-tbl td { border-bottom-color: #2b383f; }
[data-theme="dark"] table.shl-tbl tr:hover td { background: #1c262b; }
[data-theme="dark"] .shl-wrap { border-color: #37474f; }
[data-theme="dark"] #shl-search, [data-theme="dark"] .shl-bar select,
[data-theme="dark"] .shl-bar button, [data-theme="dark"] .shl-pages button,
[data-theme="dark"] table.shl-tbl .op, [data-theme="dark"] table.shl-tbl .del {
  background: #2b383f; color: #eceff1; border-color: #546e7a; }
[data-theme="dark"] table.shl-tbl .op { background: #0277bd; }
/* Mode gelap untuk #modal (Buka dari Server / Pilih Contoh). Aturan .shl-*
   di atas hanya menyasar #shared-modal, jadi bagian yang khas #modal harus
   disebut sendiri — kalau tidak, teksnya abu-abu di atas latar gelap. */
[data-theme="dark"] #modal .modal-box.wide { background: #222d33; color: #cfd8dc; }
[data-theme="dark"] #modal h3 { color: #eceff1; }
[data-theme="dark"] #modal .muted,
[data-theme="dark"] .md-sub { color: #8fa3ad; }
[data-theme="dark"] #modal-search {
  background: #2b383f; color: #eceff1; border-color: #546e7a; }
[data-theme="dark"] #modal-search::placeholder { color: #78909c; }
[data-theme="dark"] .md-tag { background: #1c3a4a; color: #81d4fa; }
[data-theme="dark"] .md-tag.warn { background: #4a3418; color: #ffcc80; }
[data-theme="dark"] .shl-empty { color: #8fa3ad; }
/* Nama berkas di modal kolaborasi: pastikan ikut cerah di mode gelap. */
[data-theme="dark"] table.shl-tbl td.nm,
[data-theme="dark"] .md-nm { color: #eceff1; }
/* angka fisika silinder (posisi · gaya · tekanan) di bawah simbolnya */
.cyl-phys { font-family: "Consolas", monospace; font-size: 9px; fill: #00695c;
  pointer-events: none; }
[data-theme="dark"] .cyl-phys { fill: #4db6ac; }

/* kendaraan listrik: teks besaran di simbol kendaraan */
#comps g.comp .veh-road { stroke-linecap: round; }

/* ==========================================================================
   MODE FOKUS (body.focus-mode) — gambar memakai seluruh layar
   Toolbar & panel komponen tidak dibuang, hanya digeser keluar layar dan
   menyisakan bilah tipis; menyorotnya dengan kursor memunculkannya kembali
   (auto-hide). Tombol yang paling sering dipakai dicerminkan ke #minibar
   yang melayang di kiri-bawah, supaya tetap terjangkau tanpa memunculkan
   toolbarnya lagi.
   ========================================================================== */
#btn-focus .ic-show { display: none; }
body.focus-mode #btn-focus .ic-hide { display: none; }
body.focus-mode #btn-focus .ic-show { display: inline-block; }

/* --- toolbar atas: menyelinap ke atas, sisakan 7px ---
   Sisa 7px itu diberi garis aksen (border, bukan pseudo-elemen ber-posisi):
   #bar & #palette punya isi yang bisa digulir, jadi penanda yang diletakkan
   secara absolut ikut tergulir hilang. Garis tepi selalu di tempatnya. */
body.focus-mode #bar {
  position: fixed; top: 0; left: 0; right: 0; z-index: 65;
  max-height: 100vh; overflow-y: auto;
  transform: translateY(calc(-100% + 7px));
  transition: transform .18s ease, border-color .18s ease;
  box-shadow: 0 6px 22px rgba(0, 0, 0, .38);
  border-bottom: 3px solid rgba(79, 195, 247, .6);
}
body.focus-mode #bar:hover { border-bottom-color: transparent; }
body.focus-mode #bar:hover, body.focus-mode #bar:focus-within { transform: translateY(0); }

/* --- toolbar mode KANAN: menyelinap ke kanan --- */
@media (min-width: 901px) {
  body.focus-mode.bar-right #bar {
    top: 0; bottom: 0; left: auto; right: 0; width: auto;
    transform: translateX(calc(100% - 7px));
    box-shadow: -6px 0 22px rgba(0, 0, 0, .38);
  }
  body.focus-mode.bar-right #bar:hover,
  body.focus-mode.bar-right #bar:focus-within { transform: translateX(0); }
  body.focus-mode.bar-right #bar { border-bottom: 0; border-left: 3px solid rgba(79, 195, 247, .6); }
  body.focus-mode.bar-right #bar:hover { border-left-color: transparent; }
  /* Bilah tersembunyi tak memakan lebar -> pesan status boleh rapat ke tepi.
     Saat bilah disorot & muncul, pesannya digeser supaya ujungnya tidak
     tertutup (#status kini bersaudara dengan #bar, jadi bisa disasar '~'). */
  body.focus-mode.bar-right #status { right: 12px; transition: right .18s ease; }
  body.focus-mode.bar-right #bar:hover ~ #status,
  body.focus-mode.bar-right #bar:focus-within ~ #status { right: 110px; }
}

/* --- panel komponen: menyelinap ke kiri (hanya layar lebar; di HP palet
       memang sudah berupa laci yang dibuka lewat tombol ☰) --- */
@media (min-width: 769px) {
  body.focus-mode #palette {
    position: fixed; top: 0; left: 0; bottom: 0; z-index: 60;
    transform: translateX(calc(-100% + 7px));
    transition: transform .18s ease, border-color .18s ease;
    box-shadow: 6px 0 22px rgba(0, 0, 0, .38);
    border-right: 3px solid rgba(79, 195, 247, .6);
  }
  body.focus-mode #palette:hover, body.focus-mode #palette:focus-within { transform: translateX(0); }
  body.focus-mode #palette:hover { border-right-color: transparent; }
}

/* --- bilah melayang berisi tombol penting --- */
#minibar { display: none; }
body.focus-mode #minibar {
  display: flex; align-items: center; gap: 4px;
  position: fixed; left: 14px; bottom: 14px; z-index: 70;
  padding: 5px 6px; border-radius: 11px;
  background: rgba(38, 50, 56, .88); border: 1px solid rgba(255, 255, 255, .13);
  box-shadow: 0 5px 20px rgba(0, 0, 0, .38);
  opacity: .78; transition: opacity .15s ease;
}
body.focus-mode #minibar:hover, body.focus-mode #minibar:focus-within { opacity: 1; }
#minibar button.icon {
  position: relative; width: 36px; height: 32px; padding: 0; border: 0;
  border-radius: 6px; cursor: pointer; background: #455a64; color: #fff;
  display: inline-flex; align-items: center; justify-content: center;
  /* sebagian cermin isinya TEKS (⏸ ⏮ ⏭), bukan <svg class="ic"> — tanpa
     ukuran huruf sendiri, glifnya ikut ukuran bawaan dan tampak kekecilan */
  font-size: 16px; line-height: 1;
}
#minibar button.icon:hover { filter: brightness(1.15); }
#minibar button.icon:disabled { opacity: .38; cursor: default; filter: none; }
#minibar button.primary { background: #43a047; }
#minibar button.primary.running { background: #e53935; }
#minibar button.active { background: #ffb300; }
#minibar button.active .ic { color: #1b2733; }
.mb-sep { width: 1px; height: 20px; background: #607d8b; margin: 0 3px; }
/* tombol bercabang dua ikon: aturan #bar di atas memakai id, jadi diulang di sini */
#minibar .ic-stop, #minibar .ic-exit, #minibar .ic-light { display: none; }
#minibar button.running .ic-play { display: none; }
#minibar button.running .ic-stop { display: inline-block; }
#minibar button.on .ic-enter { display: none; }
#minibar button.on .ic-exit { display: inline-block; }
[data-theme="dark"] #minibar .ic-dark { display: none; }
[data-theme="dark"] #minibar .ic-light { display: inline-block; }
[data-theme="dark"] #minibar { background: rgba(21, 29, 34, .9); }
[data-theme="dark"] #minibar button.icon { background: #2b383f; }
[data-theme="dark"] #minibar button.primary { background: #2e7d32; }
[data-theme="dark"] #minibar button.primary.running { background: #c62828; }
/* sama seperti pada #bar: aturan '.icon' gelap di atas LEBIH khusus daripada
   '#minibar button.active', jadi keadaan hidup tombol cerminan (mis. animasi
   aliran) harus dinyatakan lagi di mode gelap */
[data-theme="dark"] #minibar button.active { background: #ffb300; }
[data-theme="dark"] #minibar button.active .ic { color: #1b2733; }

/* layar sangat sempit: bilah melayang di kiri-bawah bertabrakan dengan status
   yang membentang penuh -> naikkan sedikit */
@media (max-width: 480px) {
  body.focus-mode #minibar { bottom: 48px; left: 8px; }
}

/* ==========================================================================
   EDITOR LADDER PLC (#ladder-panel)
   Tata letak satu rung: nomor | logika (kolom seri, tiap kolom bisa punya
   beberapa cabang paralel) | keluaran | tombol rung. "Rel" kiri-kanan digambar
   dengan border, bukan gambar — jadi ikut melar mengikuti isinya.
   ========================================================================== */
#ladder-panel {
  position: fixed; left: 60px; top: 80px; z-index: 200;
  width: min(1080px, 94vw); max-height: 82vh;
  display: flex; flex-direction: column;
  background: #fff; color: #263238; border: 1px solid #b0bec5;
  border-radius: 10px; box-shadow: 0 10px 40px rgba(0, 0, 0, .35);
  font-size: 13px;
}
#ladder-panel.hidden { display: none; }
#ladder-panel .ld-drag { cursor: move; }

#ld-bar {
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
  padding: 6px 10px; border-bottom: 1px solid #cfd8dc; background: #eceff1;
}
#ld-bar button {
  border: 1px solid #90a4ae; background: #fff; color: #263238;
  border-radius: 5px; padding: 4px 10px; cursor: pointer; font-size: 12px;
}
#ld-bar button:hover { background: #e3f2fd; border-color: #0288d1; }
.ld-sep { width: 1px; height: 20px; background: #b0bec5; }
.ld-grow { flex: 1; }
#ld-msg { font-size: 12px; color: #2e7d32; }
#ld-msg.bad { color: #c62828; font-weight: bold; }
.ld-io { display: inline-flex; align-items: center; gap: 3px; font-size: 11px; }
.ld-io b { color: #546e7a; margin-right: 2px; }
.ld-chip {
  font-style: normal; font-family: Consolas, monospace; font-size: 10px;
  padding: 2px 4px; border-radius: 3px; background: #cfd8dc; color: #37474f;
}
.ld-chip.on { background: #00c853; color: #fff; }
input.ld-ai { width: 56px; font-size: 11px; padding: 2px 4px; }
.ld-ai-lab { font-family: Consolas, monospace; font-size: 10px; color: #546e7a; }

#ld-body { flex: 1; overflow: auto; padding: 8px 10px; background: #fafafa; }
#ld-foot {
  border-top: 1px solid #cfd8dc; padding: 5px 10px; background: #eceff1;
  font-family: Consolas, monospace; font-size: 11px; color: #00695c;
  min-height: 24px; overflow-x: auto; white-space: nowrap;
}
#ld-foot .ld-dim { color: #78909c; font-family: "Segoe UI", sans-serif; }
.ld-empty { padding: 26px 10px; text-align: center; color: #607d8b; }
.ld-empty span { font-size: 11px; color: #90a4ae; }

/* --- satu rung: gambar SVG di antara dua rel daya --- */
.ld-rung {
  display: flex; align-items: flex-start; gap: 4px; margin-bottom: 4px;
  background: #fff; border: 1px solid #dde5e9; border-radius: 4px;
  padding: 2px 4px; overflow-x: auto;
}
.ld-rung.bad { border-color: #ef9a9a; background: #fff7f7; }
.ld-rung.hot { border-color: #a5d6a7; }
.ld-svg { display: block; flex: 0 0 auto; }

/* rel daya kiri & kanan: garis tebal, seperti busbar di software PLC */
.ld-svg .ld-rail { stroke: #37474f; stroke-width: 3; }
.ld-rung.hot .ld-svg .ld-rail { stroke: #2e7d32; }
/* kawat penghubung antar elemen */
.ld-svg .ld-wire { stroke: #546e7a; stroke-width: 1.6; }
.ld-svg .ld-jn { stroke-width: 1.6; }          /* penghubung cabang paralel */
/* palang kontak & lengkung coil */
.ld-svg .ld-bar { stroke: #263238; stroke-width: 2.2; stroke-linecap: round; }
.ld-svg .ld-coil { fill: none; stroke: #263238; stroke-width: 2.2; }
/* kotak instruksi bernilai (timer / counter / aritmatika) */
.ld-svg .ld-box { fill: #f5f7fa; stroke: #455a64; stroke-width: 1.6; }
.ld-svg .ld-box-sep { stroke: #455a64; stroke-width: 1; }

/* tulisan */
.ld-svg text { font-family: "Consolas", "Segoe UI", monospace; }
.ld-svg .ld-addr { font-size: 11px; fill: #1a237e; text-anchor: middle; }
.ld-svg .ld-op { font-size: 9.5px; font-weight: bold; fill: #263238; text-anchor: middle; }
.ld-svg .ld-in { font-size: 9px; fill: #37474f; text-anchor: middle; }
.ld-svg .ld-in.b { font-weight: bold; fill: #1a237e; }
.ld-svg .ld-mark { font-size: 10px; font-weight: bold; fill: #263238; text-anchor: middle; }
.ld-svg .ld-rnum { font-size: 10px; fill: #90a4ae; text-anchor: end; }

/* satu elemen: area klik transparan menutupi selnya */
.ld-svg .ld-hit { fill: transparent; cursor: pointer; }
.ld-svg .ld-el:hover .ld-hit { fill: rgba(2, 136, 209, .09); }
.ld-svg .ld-el.bad .ld-bar,
.ld-svg .ld-el.bad .ld-coil { stroke: #e53935; }
.ld-svg .ld-el.bad .ld-box { stroke: #e53935; fill: #ffebee; }
.ld-svg .ld-el.bad .ld-addr { fill: #c62828; }

/* MONITOR DARING: jalur yang menghantar disorot hijau tebal (seperti online
   monitoring di TIA Portal / GX Works) */
.ld-svg .ld-el.hot .ld-wire,
.ld-svg .ld-el.hot .ld-bar,
.ld-svg .ld-el.hot .ld-coil { stroke: #00b248; stroke-width: 2.6; }
.ld-svg .ld-el.hot .ld-box { stroke: #00b248; fill: #e8f5e9; }
.ld-rung.hot .ld-svg > .ld-wire { stroke: #00b248; stroke-width: 2.4; }

/* tombol "+" di dalam gambar */
.ld-svg .ld-plus rect { fill: #eceff1; stroke: #b0bec5; stroke-width: 1; cursor: pointer; }
.ld-svg .ld-plus text { font-size: 12px; fill: #607d8b; text-anchor: middle;
  pointer-events: none; }
.ld-svg .ld-plus:hover rect { fill: #c8e6c9; stroke: #43a047; }
.ld-svg .ld-plus:hover text { fill: #2e7d32; }

.ld-rung-btns { display: flex; flex-direction: column; gap: 2px; padding-top: 4px; }

button.ld-mini {
  border: 1px solid #cfd8dc; background: #fff; color: #607d8b;
  border-radius: 4px; padding: 2px 6px; cursor: pointer; font-size: 11px;
}
button.ld-mini:hover { background: #e8f5e9; border-color: #43a047; color: #2e7d32; }
button.ld-mini.ld-del:hover { background: #ffebee; border-color: #e53935; color: #c62828; }

/* --- menu satu sel --- */
#ld-menu {
  position: fixed; z-index: 260; min-width: 250px; max-width: 320px;
  background: #fff; color: #263238; border: 1px solid #b0bec5;
  border-radius: 8px; box-shadow: 0 8px 28px rgba(0, 0, 0, .3); padding: 8px;
  font-size: 12px;
}
#ld-menu.hidden { display: none; }
#ld-menu .ld-row { display: flex; align-items: center; gap: 6px; margin: 4px 0; }
#ld-menu .ld-row > span { flex: 0 0 88px; color: #546e7a; font-size: 11px; }
#ld-menu select, #ld-menu input { flex: 1; min-width: 0; font-size: 12px; padding: 3px 4px; }
#ld-menu .ld-combo { flex: 1; display: flex; min-width: 0; }
#ld-menu .ld-combo input { width: 100%; }
.ld-menu-foot {
  display: flex; gap: 6px; justify-content: flex-end;
  margin-top: 8px; padding-top: 6px; border-top: 1px solid #eceff1;
}

/* --- mode gelap --- */
[data-theme="dark"] #ladder-panel { background: #222d33; color: #cfd8dc; border-color: #455a64; }
[data-theme="dark"] #ld-bar, [data-theme="dark"] #ld-foot { background: #1c262b; border-color: #37474f; }
[data-theme="dark"] #ld-bar button { background: #2b383f; color: #eceff1; border-color: #546e7a; }
[data-theme="dark"] #ld-body { background: #1a2429; }
[data-theme="dark"] .ld-rung { background: #1e272c; border-color: #37474f; }
[data-theme="dark"] .ld-rung.bad { background: #2f2326; border-color: #b71c1c; }
[data-theme="dark"] .ld-rung.hot { border-color: #2e7d32; }
/* gambar ladder di mode gelap: rel & kawat dicerahkan, kotak jadi permukaan gelap */
[data-theme="dark"] .ld-svg .ld-rail { stroke: #b0bec5; }
[data-theme="dark"] .ld-svg .ld-wire { stroke: #78909c; }
[data-theme="dark"] .ld-svg .ld-bar,
[data-theme="dark"] .ld-svg .ld-coil { stroke: #eceff1; }
[data-theme="dark"] .ld-svg .ld-box { fill: #2b383f; stroke: #90a4ae; }
[data-theme="dark"] .ld-svg .ld-box-sep { stroke: #90a4ae; }
[data-theme="dark"] .ld-svg .ld-addr { fill: #90caf9; }
[data-theme="dark"] .ld-svg .ld-op,
[data-theme="dark"] .ld-svg .ld-mark { fill: #eceff1; }
[data-theme="dark"] .ld-svg .ld-in { fill: #b0bec5; }
[data-theme="dark"] .ld-svg .ld-in.b { fill: #90caf9; }
[data-theme="dark"] .ld-svg .ld-el:hover .ld-hit { fill: rgba(79, 195, 247, .14); }
[data-theme="dark"] .ld-svg .ld-el.bad .ld-box { fill: #3a2426; }
[data-theme="dark"] .ld-svg .ld-el.hot .ld-box { fill: #1b3d22; }
[data-theme="dark"] .ld-svg .ld-plus rect { fill: #2b383f; stroke: #546e7a; }
[data-theme="dark"] .ld-svg .ld-plus text { fill: #b0bec5; }
[data-theme="dark"] button.ld-mini { background: #2b383f; color: #b0bec5; border-color: #546e7a; }
[data-theme="dark"] #ld-menu { background: #263238; color: #eceff1; border-color: #455a64; }
[data-theme="dark"] #ld-menu select, [data-theme="dark"] #ld-menu input {
  background: #2b383f; color: #eceff1; border: 1px solid #546e7a; }
[data-theme="dark"] .ld-chip { background: #37474f; color: #b0bec5; }
[data-theme="dark"] #ld-foot { color: #4db6ac; }

/* layar sempit: panel penuh & rung bisa digulir mendatar */
@media (max-width: 900px) {
  #ladder-panel { left: 4px; right: 4px; top: 60px; width: auto; max-height: 86vh; }
}

/* Butir menu BUKAN tombol toolbar. Aturan 'body.bar-right #bar button:not(.icon)'
   (rata-tengah, satu baris, elipsis, grid-column penuh) punya kekhususan
   (1,2,2) sehingga menang atas '#user-menu .um-item' (1,1,0) — akibatnya di
   mode toolbar tegak teks menu jadi rata-tengah dan terpotong. Dua id di
   depan (#bar #user-menu) menang telak dan mengembalikannya. */
#bar #user-menu .um-item {
  text-align: left; white-space: normal; overflow: visible; text-overflow: clip;
  grid-column: auto; font-size: 13px; padding: 9px 10px; min-width: 0;
}
#bar #user-menu .um-teks { white-space: normal; }
#bar #user-menu .um-item:not(.icon) { display: flex; }

/* Lencana "belum terkirim ke server" (mode luring). Kuning, bukan merah:
   pekerjaannya AMAN di perangkat — ini pemberitahuan, bukan galat. */
#bar #luring-badge {
  background: #f9a825; color: #263238; font-weight: 700; width: auto;
  padding: 6px 10px; gap: 3px; display: inline-flex; align-items: center;
}
#bar #luring-badge:hover { background: #fbc02d; }
#bar #luring-badge.hidden { display: none !important; }
#luring-n { font-variant-numeric: tabular-nums; }

/* Tombol rekam saat sedang merekam: merah berdenyut supaya jelas statusnya. */
#btn-rec.recording {
  color: #fff; background: #d32f2f;
  animation: recpulse 1.15s ease-in-out infinite;
}
@keyframes recpulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(211, 47, 47, .55); }
  50%      { box-shadow: 0 0 0 6px rgba(211, 47, 47, 0); }
}

/* ============================================================================
   MODE UJIAN
   ----------------------------------------------------------------------------
   Kelas `ujian` dipasang di <body> oleh app.js selama sebuah sesi ujian
   berjalan. Yang disembunyikan di sini adalah setiap pintu yang bisa
   memasukkan gambar jadi ke kanvas atau membuka saluran ke orang lain.

   Ini LAPISAN KEDUA, bukan penjagaannya. Yang menolak sungguhan adalah server
   (server.py: UJIAN_TUTUP / _ujian_gerbang) — CSS di sini hanya supaya siswa
   tidak melihat tombol yang pasti berakhir dengan pesan galat.
   ========================================================================== */
#ujian-bar {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  background: linear-gradient(90deg, #ad1457, #6a1b9a);
  color: #fff; padding: 7px 12px; font-size: 13px;
  border-bottom: 2px solid #f48fb1;
}
#ujian-bar.hidden { display: none; }
#ujian-bar .uj-tag {
  background: #fff; color: #ad1457; font-weight: bold; letter-spacing: .8px;
  border-radius: 4px; padding: 3px 8px; font-size: 11px;
}
#ujian-bar .uj-judul { font-weight: bold; }
#ujian-bar .uj-kelas { opacity: .8; }
#ujian-bar .uj-sp { flex: 1; }
#ujian-bar .uj-simpan { opacity: .85; font-size: 12px; }
#ujian-bar .uj-sisa {
  font-variant-numeric: tabular-nums; font-size: 16px; font-weight: bold;
  background: rgba(0, 0, 0, .28); border-radius: 5px; padding: 3px 10px;
}
#ujian-bar .uj-sisa.kritis {
  background: #d32f2f; animation: ujdenyut 1s ease-in-out infinite;
}
@keyframes ujdenyut { 0%, 100% { opacity: 1; } 50% { opacity: .55; } }
#ujian-bar button {
  border: 0; border-radius: 4px; padding: 6px 11px; cursor: pointer;
  background: rgba(255, 255, 255, .16); color: #fff; font-size: 13px;
}
#ujian-bar button:hover { background: rgba(255, 255, 255, .3); }
#ujian-bar button.primary { background: #43a047; font-weight: bold; }
#ujian-bar button.primary:hover { background: #4caf50; }
#ujian-bar button:disabled { opacity: .45; cursor: default; }

/* Ujian sudah berakhir: bilahnya tetap terlihat (siswa harus tahu kirimannya
   sudah beku) tapi warnanya turun jadi abu-abu supaya tak lagi mendesak. */
#ujian-bar.beku { background: #455a64; border-bottom-color: #90a4ae; }
#ujian-bar.beku .uj-tag { color: #455a64; }

/* Pintu yang ditutup selama ujian. */
body.ujian #btn-open,
body.ujian #btn-saveas,
body.ujian #btn-share,
body.ujian #btn-shared,
body.ujian #btn-notif,
body.ujian #btn-barpos,
body.ujian #collab,
body.ujian [data-act="example"],
body.ujian #um-kelas,
body.ujian #um-org,
body.ujian #um-studio,
body.ujian #um-admin,
body.ujian #um-code,
body.ujian #um-data,
body.ujian #um-plan,
body.ujian #um-edit,
body.ujian #um-pasang,
body.ujian #luring-badge,
body.ujian #um-sep2 { display: none !important; }

/* Toolbar tegak (btn-barpos) mengubah <body> jadi baris; bilah ujian akan
   ikut jadi kolom sempit di sampingnya. Selama ujian layoutnya dipaksa
   mendatar — dan tombol pemindahnya memang disembunyikan di atas. */
body.ujian { flex-direction: column !important; }
body.ujian #main { order: 1; }

@media (max-width: 700px) {
  #ujian-bar { font-size: 12px; gap: 6px; padding: 6px 8px; }
  #ujian-bar .uj-kelas, #ujian-bar .uj-simpan { display: none; }
}

/* ---- gambar sisipan di kanvas (ikon di sebelah kanan tombol Teks) ---- */
/* Bingkai & gagang HANYA alat bantu menyunting: keduanya dibuang saat
   diekspor (app.js: buildExportSvg) dan tidak digambar saat simulasi
   berjalan, supaya hasil cetak bersih dari kotak-kotak bantu. */
#gambars .gambar { cursor: move; }
#gambars image { image-rendering: auto; }
rect.gb-bingkai {
  fill: none; stroke: #90a4ae; stroke-width: 1; stroke-dasharray: 4 3;
  vector-effect: non-scaling-stroke; pointer-events: none;
}
#gambars .gambar:hover rect.gb-bingkai { stroke: #0288d1; }
rect.gb-gagang {
  fill: #0288d1; stroke: #fff; stroke-width: 1.5;
  vector-effect: non-scaling-stroke; cursor: nwse-resize;
}
[data-theme="dark"] rect.gb-bingkai { stroke: #546e7a; }
/* Saat simulasi berjalan gambar tetap tampil, tapi tak bisa disentuh. */
#canvas.run-mode #gambars { pointer-events: none; }

/* --- Dialog seragam (#app-dialog): pengganti alert/confirm/prompt bawaan ---
   z-index sengaja di atas SEMUA modal lain (tertinggi lain 260): konfirmasi
   sering dimunculkan DARI DALAM modal — mis. "Hapus rangkaian bersama?" yang
   ditekan di dalam daftar Rangkaian Bersama. Kalau tertutup di belakangnya,
   aplikasi tampak menggantung. */
#app-dialog { position: fixed; inset: 0; z-index: 500; background: rgba(0,0,0,.45);
  display: flex; align-items: center; justify-content: center; padding: 16px; }
#app-dialog.hidden { display: none; }
#app-dialog .modal-box { width: min(460px, 96vw); }
#app-dialog h3 { display: flex; align-items: center; gap: 8px; margin: 0 0 10px; }
#app-dialog h3 .x { margin-left: auto; background: none; border: 0; font-size: 16px;
  cursor: pointer; color: #607d8b; }
#dlg-pesan { margin: 0 0 12px; font-size: 13.5px; line-height: 1.6;
  white-space: pre-wrap; word-break: break-word; }
#dlg-pesan.hidden, #dlg-hint.hidden, #dlg-lbl.hidden, #dlg-batal.hidden { display: none; }
#app-dialog #dlg-teks { width: 100%; box-sizing: border-box; }
.dlg-aksi { margin-top: 16px; display: flex; gap: 8px; justify-content: flex-end; }
.dlg-aksi button { border: 0; border-radius: 5px; padding: 8px 16px; cursor: pointer;
  background: #607d8b; color: #fff; font: inherit; font-size: 13px; }
.dlg-aksi button.primary { background: #43a047; font-weight: 600; }
.dlg-aksi button.danger { background: #e53935; font-weight: 600; }
.dlg-aksi button:focus-visible { outline: 2px solid #0288d1; outline-offset: 2px; }
