/* style.css — Kamar Mesin.
 *
 * Nama kelas di berkas ini WAJIB mengikuti markup di index.html dan simpul
 * yang dibuat assets/js/*.js — bukan sebaliknya. Pernah terbalik sekali
 * (2 Sep 2026): berkas ini ditulis ulang dengan kosakata sendiri, 42 kelas
 * jadi tanpa aturan, dan keempat modul tampil bertumpuk karena
 * `.is-tersembunyi` tidak ada. Jalankan `node alat/cek-kelas.mjs` sesudah
 * menyunting berkas ini.
 *
 * Warnanya dibawa dari kamar mesin sungguhan: pelat baja kelabu, gas panas
 * jingga, udara bilas biru dingin, minyak lumas kuning tua.
 */

/* ------------------------------------------------------------- warna */
/* GELAP adalah tema BAKU, bukan sekadar pilihan. Layar di kamar mesin
   hampir selalu dilihat di ruang remang, dan tema terang di situ
   menyilaukan. Yang terang tetap tersedia lewat tombol, dan pilihan itu
   disimpan di perangkat.

   Perhatikan: preferensi tema sistem SENGAJA tidak diikuti. Aplikasi ini
   punya alasan sendiri untuk gelap yang tidak ada hubungannya dengan
   selera pemakai di aplikasi lain — kalau mengikuti sistem, orang dengan
   ponsel bertema terang justru mendapat yang paling menyilaukan di tempat
   ia paling mungkin memakainya. */
:root {
  color-scheme: dark;
  --latar: #10151a;
  --latar-2: #171d24;
  --latar-3: #1f272f;
  --garis: #2c3742;
  --garis-kuat: #4a5a69;
  --teks: #e6edf3;
  --teks-redup: #94a4b4;
  --aksen: #f0883e;          /* gas panas */
  --aksen-lembut: #46280f;
  --udara: #58a6ff;          /* udara bilas */
  --udara-lembut: #14304f;
  --kuning: #d9a441;         /* minyak lumas */
  --merah: #f85149;
  --hijau: #3fb950;
  /* PENUNJUK kedudukan engkol punya warnanya sendiri, TIDAK ikut --merah.
     --merah dipakai untuk bahaya (air ketel rendah, tekanan lewat batas,
     lubang bilas terbuka); kalau penunjuk ikut token itu, tiap penyetelan
     demi keterbacaan penunjuk akan mewarnai ulang alarm — dan sebaliknya.
     Nilainya BUKAN --hijau: #3fb950 punya luminans yang nyaris sama persis
     dengan --aksen (kontras 1,00 : 1), jadi di atas kurva oranye ia hilang
     lebih parah daripada merah. #56d364 diukur 1,31 : 1 terhadap kurva
     (setara merah) dan 8,80 : 1 terhadap latar kartu — merah cuma 5,06. */
  --penunjuk: #56d364;
  /* ASAP punya DUA ujung, dan keduanya milik tema — bukan satu warna tetap.
     Warna asap dulu dipatok #6b6560 di dalam kode gambar, dipilih waktu
     tema terang masih baku. Di latar gelap kontrasnya cuma 1,3-1,6 : 1
     terhadap latar kartu, jadi asapnya praktis tidak kelihatan.

     Di tema gelap arah gelap-terangnya DIBALIK: asap bersih pucat (nyaris
     tak terlihat, dan itu memang benar untuk cerobong yang sehat), asap
     berjelaga condong ke cokelat kotor yang menonjol di latar gelap. Yang
     dijaga bukan warnanya, melainkan pesannya: makin buruk pembakaran,
     makin pekat dan makin kotor asapnya. */
  --asap-bersih: #ded7cb;
  --asap-kotor: #9a7852;
  /* Lumpur & butiran katalis. Sama seperti asap: satu warna tetap tidak
     bisa melayani dua latar yang berlawanan. Yang dipatok #3a3229/#4a4034
     berkontras 12 : 1 di latar putih tapi 1,3-1,7 : 1 di latar gelap —
     hilang sama sekali, termasuk contreng legendanya. */
  --lumpur: #a89c8e;
  --uap: #c7d2da;
  /* MINYAK PANAS & MINYAK DINGIN. Dipakai animasi pelumasan untuk
     membedakan minyak yang MEMBAWA panas dari minyak yang sudah melepaskan
     panasnya — dan pergantian warna di tengah pendingin itulah satu-satunya
     yang menunjukkan panasnya BERPINDAH, bukan sekadar lewat.

     Keduanya sempat dipakai animasi minyak sistem dan minyak silinder
     TANPA PERNAH DIDEFINISIKAN. Akibatnya bukan warna yang meleset
     melainkan garis yang HILANG SAMA SEKALI: `stroke="var(--panas)"` yang
     tidak punya nilai membuat garisnya tidak digambar. Aliran minyak di
     dalam pendingin, di dalam mesin, dan yang kembali ke tangki dasar
     semuanya tak terlihat sejak halaman itu terbit, dan tak satu pun uji
     jatuh — uji tumpang-tindih memeriksa TULISAN, dan gambar tanpa garis
     tetap punya tulisan yang rapi. Sejak sekarang alat/cek-kelas.mjs
     memeriksa tiap var(--x) yang dipakai kode gambar punya nilai.

     Nilainya bukan --aksen dan --udara yang sudah ada: kedua token itu
     sudah punya arti sendiri di halaman yang sama (gas panas dan udara
     bilas), dan memakainya lagi untuk minyak akan membuat empat benda
     berbeda berwarna sama di satu gambar. */
  --panas: #e06c4a;
  --sejuk: #5aa9c9;
  --lebar: 1180px;
  --sudut: 10px;
}

/* Tema terang: hanya kalau pemakai memilihnya sendiri. */
:root[data-tema="terang"] {
  color-scheme: light;
  --latar: #f3f5f7;
  --latar-2: #ffffff;
  --latar-3: #e9edf1;
  --garis: #d7dee5;
  --garis-kuat: #a9b5c1;
  --teks: #141a20;
  --teks-redup: #59697a;
  --aksen: #b25f13;
  --aksen-lembut: #fbe8d7;
  --udara: #1259b8;
  --udara-lembut: #dae8fb;
  --kuning: #8a6410;
  --merah: #c02f28;
  --hijau: #1d7433;
  /* Hijau tua, bukan hijau terang: di latar putih yang harus dikalahkan
     justru sisi TERANGnya. Diukur 1,54 : 1 terhadap kurva dan 7,13 : 1
     terhadap kartu — merah 1,23 dan 5,71, jadi menang di kedua sumbu. */
  --penunjuk: #166534;
  /* Di latar putih asap berjelaga memang hitam — seperti yang dilihat
     orang dari anjungan. */
  --asap-bersih: #b8b0a4;
  --asap-kotor: #3a332c;
  --lumpur: #4a4034;
  --uap: #6b7a86;
  /* Di latar putih keduanya harus DIGELAPKAN, bukan sekadar dipakai ulang:
     yang harus dikalahkan justru sisi terangnya. */
  --panas: #b6431f;
  --sejuk: #1f6f92;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--latar);
  color: var(--teks);
  font: 15px/1.6 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  -webkit-text-size-adjust: 100%;
}

h1, h2, h3 { line-height: 1.25; margin: 0 0 .5em; font-weight: 650; }
h1 { font-size: 1.5rem; }
h2 { font-size: 1.15rem; }
h3 { font-size: 1rem; }
p  { margin: 0 0 .8em; }
a  { color: var(--udara); }
em { font-style: italic; }

/* Satu-satunya cara menyembunyikan sesuatu di aplikasi ini. Pakai !important
   karena beberapa wadah yang disembunyikan punya display sendiri (grid/flex)
   yang kalau tidak dikalahkan akan tetap tampil. */
.is-tersembunyi { display: none !important; }

.kecil { font-size: .86rem; }
.petunjuk { color: var(--teks-redup); }
.petunjuk b, .petunjuk strong { color: var(--teks); }

/* --------------------------------------------------------------- kepala */
.topbar {
  position: sticky; top: 0; z-index: 30;
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 8px 14px;
  background: var(--latar-2);
  border-bottom: 1px solid var(--garis);
}
.brand { display: flex; align-items: center; gap: 9px; font-weight: 700; }
.brand-ikon {
  width: 27px; height: 27px; flex: 0 0 27px;
  display: grid; place-items: center;
  border-radius: 7px; background: var(--aksen); color: #fff;
  font-size: 16px; line-height: 1;
}
.brand-teks { letter-spacing: .2px; }
.brand-teks-pendek { display: none; letter-spacing: .5px; }

/* DAFTAR PERALATAN — dikelompokkan, dan SELURUHNYA terlihat sekaligus.
 *
 * Dulu satu baris mendatar di kepala halaman: dari tujuh belas peralatan
 * yang tampak cuma tiga di HP dan tujuh di meja, sisanya harus dicari
 * dengan menggulir ke samping. jhony, 26 September 2026: "bikin yg simpel
 * tata letak tombol tombol machinery nya, sehingga mudah ditemukan."
 *
 * Satu daftar, dua bentuk:
 *   - >= 1100 px: kolom tetap di sisi kiri, selalu terbuka;
 *   - <  1100 px: panel penuh di bawah kepala, dibuka tombol "Peralatan"
 *     yang sekaligus menyebut peralatan yang sedang dibuka.
 * `--tinggi-kepala` ditulis app.js dari tinggi kepala yang SUNGGUH diukur. */
:root { --lebar-samping: 212px; --tinggi-kepala: 49px; }
.alat-nav { display: none; }
.alat-grup + .alat-grup { margin-top: 8px; }
.alat-grup-judul {
  margin: 0 0 4px; padding: 0 10px;
  font-size: .7rem; font-weight: 700; letter-spacing: .09em;
  text-transform: uppercase; color: var(--teks-redup);
}
.alat-btn {
  display: block; width: 100%; text-align: left;
  background: transparent; color: var(--teks-redup);
  border: 1px solid transparent; border-radius: 8px;
  padding: 5px 10px; font: inherit; font-size: .93rem; font-weight: 600;
  line-height: 1.25; cursor: pointer;
}
@media (hover: hover) { .alat-btn:hover { color: var(--teks); background: var(--latar-3); } }
.alat-btn.is-aktif { color: var(--latar-2); background: var(--aksen); }

.tombol-alat {
  display: flex; align-items: center; gap: 8px;
  flex: 1 1 220px; min-width: 0; min-height: 40px;
  padding: 6px 12px; text-align: left;
  background: var(--latar-3); color: var(--teks);
  border: 1px solid var(--garis-kuat); border-radius: 10px;
  font: inherit; cursor: pointer;
}
.tombol-alat-cap {
  flex: 0 0 auto;
  font-size: .7rem; font-weight: 700; letter-spacing: .09em;
  text-transform: uppercase; color: var(--teks-redup);
}
.tombol-alat-nama {
  flex: 1 1 auto; min-width: 0;
  font-weight: 700; color: var(--aksen);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.tombol-alat-panah { flex: 0 0 auto; color: var(--teks-redup); transition: transform .15s; }
.tombol-alat[aria-expanded="true"] { border-color: var(--aksen); }
.tombol-alat[aria-expanded="true"] .tombol-alat-panah { transform: rotate(180deg); }

@media (min-width: 1100px) {
  body { padding-left: var(--lebar-samping); }
  /* Kepala tetap selebar layar: ia keluar dari tepi kiri yang disisakan
     untuk daftar peralatan. */
  .topbar { margin-left: calc(-1 * var(--lebar-samping)); }
  .brand { margin-right: auto; }
  .tombol-alat { display: none; }
  .alat-nav {
    display: block;
    position: fixed; z-index: 25;
    top: var(--tinggi-kepala); left: 0; bottom: 0;
    width: var(--lebar-samping);
    padding: 12px 10px 20px;
    overflow-y: auto; overscroll-behavior: contain; scrollbar-width: thin;
    background: var(--latar-2);
    border-right: 1px solid var(--garis);
  }
}
@media (max-width: 1099.98px) {
  /* Panel penuh, bukan laci sempit: tujuh belas nama dalam kisi tiga
     kolom (di 390 px) muat SELURUHNYA di satu layar HP, jadi tidak ada yang perlu
     digulir untuk ditemukan. */
  .alat-nav.is-buka {
    display: block;
    position: fixed; z-index: 40;
    top: var(--tinggi-kepala); left: 0; right: 0; bottom: 0;
    padding: 14px 14px 32px;
    overflow-y: auto; overscroll-behavior: contain;
    background: var(--latar);
    border-top: 1px solid var(--garis);
  }
  .alat-nav.is-buka .alat-grup {
    display: grid; gap: 6px;
    grid-template-columns: repeat(auto-fill, minmax(108px, 1fr));
    max-width: 900px;
  }
  .alat-nav.is-buka .alat-grup-judul { grid-column: 1 / -1; padding: 0 2px; }
  .alat-nav.is-buka .alat-btn {
    min-height: 44px; padding: 7px 10px; font-size: .88rem;
    background: var(--latar-2); color: var(--teks);
    border-color: var(--garis);
  }
  .alat-nav.is-buka .alat-btn.is-aktif {
    background: var(--aksen); color: var(--latar-2); border-color: var(--aksen);
  }
  body.menu-alat-buka { overflow: hidden; }
}

/* Baris sub-bagian dari peralatan yang dipilih.
 *
 * TIDAK MELEKAT, dan itu membetulkan cacat lama: aturannya dulu `sticky;
 * top: 49px`, tapi aturan `position: relative` di bawahnya (untuk bayangan
 * tepi) menimpanya — dan `top: 49px` pada elemen relative MENGGESER-nya 49
 * px ke bawah. Hasilnya pita kosong 49 px di atas baris ini di semua lebar,
 * dan baris itu menutupi 49 px teratas isi halaman. */
.sub-nav {
  position: relative; z-index: 29;
  display: flex; gap: 4px; overflow-x: auto; scrollbar-width: thin;
  padding: 6px 14px;
  background: var(--latar-2);
  border-bottom: 1px solid var(--garis);
}

/* TANDA "MASIH ADA LAGI KE KANAN" untuk baris sub-bagian.
 *
 * Lahir dari cacat yang nyata di HP: sesudah modul "Pelumasan silinder"
 * ditambahkan, submenu Mesin Induk jadi empat dan yang keempat terdorong
 * keluar layar 390 px. Ia ADA dan bisa digeser, tapi tidak ada satu pun
 * tanda bahwa ada yang tersembunyi. Bayangan ini muncul di tepi kanan
 * selama daftarnya lebih lebar daripada layarnya. */
.sub-nav::after {
  content: ''; position: sticky; right: 0; flex: 0 0 0;
  align-self: stretch; width: 0;
  box-shadow: 0 0 14px 12px var(--latar-2);
  pointer-events: none;
}
.tab-btn {
  flex: 0 0 auto; white-space: nowrap;
  background: transparent; color: var(--teks-redup);
  border: 1px solid transparent; border-radius: 999px;
  padding: 6px 13px; font: inherit; font-size: .9rem; cursor: pointer;
}
.tab-btn:hover { color: var(--teks); background: var(--latar-3); }
.tab-btn.is-aktif { color: var(--aksen); background: var(--aksen-lembut); font-weight: 620; }
/* Sub-menu tarik-turun (grup Skenario): nama skenarionya satu kalimat, dan
   di HP baris tombol mendorong yang kedua keluar layar. */
.sub-pilih {
  flex: 0 1 auto; max-width: 100%; min-width: 0;
  font: inherit; font-size: .9rem; font-weight: 620;
  color: var(--aksen); background: var(--aksen-lembut);
  border: 1px solid transparent; border-radius: 999px;
  padding: 6px 30px 6px 13px; cursor: pointer;
  text-overflow: ellipsis; white-space: nowrap; overflow: hidden;
}
.sub-pilih:hover { background: var(--latar-3); }
.sub-label {
  flex: 0 0 auto; align-self: center; white-space: nowrap;
  font-size: .85rem; color: var(--teks-redup);
}

.tema-toggle {
  flex: 0 0 auto;
  background: var(--latar-3); color: var(--teks);
  border: 1px solid var(--garis); border-radius: 8px;
  width: 34px; height: 32px; cursor: pointer;
  display: grid; place-items: center;
}
.tema-toggle:hover { border-color: var(--aksen); }

/* Tombol pasang memakai warna aksen, bukan abu-abu seperti tombol tema:
   ia muncul paling banyak sekali dalam hidup pemakaian aplikasi ini, jadi
   ia boleh — dan harus — terlihat sekali lihat. */
.tombol-pasang {
  flex: 0 0 auto;
  display: inline-flex; align-items: center; gap: 6px;
  background: var(--aksen); color: #fff;
  border: 1px solid var(--aksen); border-radius: 8px;
  padding: 6px 11px; height: 32px;
  font: inherit; font-size: .88rem; font-weight: 620;
  cursor: pointer; white-space: nowrap;
}
.tombol-pasang:hover { filter: brightness(1.08); }
.tombol-pasang:disabled { opacity: .6; cursor: default; }

/* Petunjuk pasang iOS: kotak sendiri di kaki halaman supaya tidak terbaca
   sebagai kelanjutan kalimat penyangkalan di atasnya. */
.kaki-pasang {
  border: 1px solid var(--garis); border-radius: 8px;
  padding: 10px 12px; background: var(--latar-2);
}

/* Di layar sempit, deretan peralatan memakan seluruh lebar dan tombol tema
   terdorong turun SENDIRIAN ke baris berikutnya — terlihat seperti tombol
   nyasar. Disusun ulang: baris pertama merek + tombol tema, baris kedua
   deretan peralatan yang memang butuh lebar penuh.

   AMBANGNYA 780, DAN DULU 620 — dan celah di antaranya adalah cacat yang
   dilaporkan jhony 8 September: "tombol tema bergeser ke bawah". Aturan ini
   berhenti di 620, padahal kepalanya baru benar-benar muat satu baris pada
   750. Jadi di SELURUH pita 621-749 px tombol tema berdiri sendirian di baris
   kedua — persis gejala yang aturan ini dibuat untuk mencegahnya, cuma di
   lebar yang tidak pernah diukur. Diukur ulang lebar demi lebar, dan tombol
   Pasang TERBUKTI bukan sebabnya: tanpa tombol itu pun tetap turun.

   AMBANGNYA 920, DAN SEMPAT 780 — dan 780 itu keliru karena SAYA MENGUKUR
   TOMBOL YANG SALAH. `.tema-toggle` dipakai TIGA tombol (penahan layar,
   volume, tema), jadi `querySelector('.tema-toggle')` mengembalikan yang
   pertama — penahan layar — dan ia memang selalu sebaris. Tombol temanya
   yang sungguhan tetap turun, dan jhony melaporkannya lagi: "logo tema belum
   di perbaiki". Ukur lewat ID, jangan lewat kelas yang dipakai bersama.

   Diukur ulang dengan #temaToggle: kepala ini berisi TUJUH anak, bukan
   empat — merek, nav, tombol Pasang, papan alarm, penahan layar, volume,
   tema. Satu barisnya butuh 861 px pada lebar meja, jadi ambangnya 920 (sisa
   ~60 px), bukan 780. */
@media (max-width: 920px) {
  .topbar { row-gap: 6px; }
  .brand { flex: 1 1 auto; order: 1; }
  /* Tombol pasang ikut baris pertama bersama tombol tema — bukan baris
     sendiri. `margin-left:auto` pindah ke tombol pasang kalau ia ada,
     supaya keduanya tetap mepet kanan sebagai satu kelompok. */
  .tombol-pasang { order: 2; margin-left: auto; }
  .tema-toggle { order: 3; margin-left: auto; }
  .tombol-pasang:not([hidden]) ~ .tema-toggle { margin-left: 0; }
  .tombol-alat { order: 4; flex: 1 1 100%; }
}

/* Layar paling sempit: kata "Pasang" dibuang, ikon panah-ke-bawah sudah
   cukup dan merek tetap utuh. Diukur di 360 px — di bawah itu merek mulai
   terpotong kalau tombolnya berlabel. */
/* LAYAR SEMPIT: merek disingkat E/R, dan ambangnya 520 bukan 380.
 *
   Diukur, bukan ditebak. Baris pertama kepala di layar sempit memuat merek +
   tombol Pasang + papan alarm + tiga tombol ikon. Dengan tulisan penuh ia
   butuh 484 px; di bawah itu tombol tema terdorong turun sendirian — persis
   yang dilaporkan jhony, dan yang tidak pernah tertangkap karena uji lamanya
   mengukur tombol yang salah.

   Tiga penghematan sekaligus, dan ketiganya perlu: "Kamar Mesin" -> "E/R"
   (-78 px), label "Pasang" disembunyikan (-57 px), jarak antar tombol 12 ->
   10 px (-10 px). Sisanya 339 px, jadi bahkan layar 360 px pun masih
   bersisa. Menghemat satu saja tidak cukup — pada 390 px kurangnya 94 px. */
@media (max-width: 520px) {
  /* Disembunyikan VISUAL saja, bukan display:none — pembaca layar tetap
     membacakan "Kamar Mesin". Orang yang memakai pembaca layar tidak sedang
     kekurangan tempat. */
  .brand-teks { position: absolute; width: 1px; height: 1px;
    overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  .brand-teks-pendek { display: inline; }
  .tombol-pasang span { position: absolute; width: 1px; height: 1px;
    overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
  .tombol-pasang { padding: 6px 8px; }
  .topbar { column-gap: 10px; }
}

/* LAYAR PALING SEMPIT — 320 px, dan ia masih kurang sekitar 19 px sesudah
   merek disingkat E/R. Diukur: baris pertama butuh 339 px di sana, sebab
   kepala ini berisi enam benda (merek, Pasang, papan alarm, penahan layar,
   volume, tema) dan lima jarak di antaranya.
   Jarak 10 -> 6 px dan tepi 14 -> 8 px menghemat 32 px; sisanya 307. */
@media (max-width: 360px) {
  .topbar { column-gap: 6px; padding-left: 8px; padding-right: 8px; }
  .tema-toggle { width: 32px; }
}

/* ---------------------------------------------------------------- badan */
main { max-width: var(--lebar); margin: 0 auto; padding: 18px 14px 56px; }
.modul:focus { outline: none; }
.modul:focus-visible { outline: 2px solid var(--aksen); outline-offset: 4px; border-radius: 4px; }
.modul-intro { margin-bottom: 18px; }
.modul-intro p { color: var(--teks-redup); max-width: 68ch; }

.kartu {
  background: var(--latar-2);
  border: 1px solid var(--garis);
  border-radius: var(--sudut);
  padding: 15px;
  margin-bottom: 16px;
}
.kartu > h2:first-child, .kartu > h3:first-child { margin-top: 0; }

/* Panggung: dua kolom di layar lebar, satu kolom di HP. Varian -rata membagi
   rata, -sempit memberi kolom kiri lebar tetap. */
.panggung {
  display: grid; gap: 16px; align-items: start;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
  margin-bottom: 16px;
}
.panggung-rata { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
.panggung-sempit { grid-template-columns: minmax(0, 320px) minmax(0, 1fr); }
@media (max-width: 860px) {
  .panggung, .panggung-rata, .panggung-sempit { grid-template-columns: minmax(0, 1fr); }
}

/* -------------------------------------------------------------- kendali */
.kendali {
  display: flex; flex-wrap: wrap; gap: 14px 20px; align-items: flex-end;
  background: var(--latar-2); border: 1px solid var(--garis);
  border-radius: var(--sudut); padding: 13px 15px; margin-bottom: 16px;
}
.kendali-blok {
  flex: 1 1 220px; min-width: 0;
  display: flex; flex-wrap: wrap; align-items: center; gap: 5px 9px;
}
/* Label mengambil satu baris penuh, sisanya berjajar di bawahnya. Satu aturan
   ini melayani ketiga blok: yang berisi penggeser + angka, maupun yang berisi
   tombol + pilihan kecepatan. */
.kendali-blok label {
  flex: 1 0 100%; font-size: .8rem; color: var(--teks-redup);
  text-transform: uppercase; letter-spacing: .04em;
}
.kendali-blok output {
  font-variant-numeric: tabular-nums; font-weight: 700; min-width: 3.4em;
}
.kendali-blok select { width: auto; flex: 0 1 auto; }
/* SUSUNAN PANEL KENDALI (tata-kendali.js) — tiga baris tetap: START/STOP,
   KATUP & SETELAN, SIMULASI. Tiap judul memakan satu baris penuh flex,
   jadi blok sesudahnya selalu mulai di baris baru. */
.kendali-judul {
  flex: 1 1 100%; margin: 0; padding-top: 10px;
  border-top: 1px solid var(--garis);
  font-size: .7rem; font-weight: 700; letter-spacing: .09em;
  text-transform: uppercase; color: var(--teks-redup);
}
.kendali-judul:first-child { padding-top: 0; border-top: 0; }
.kendali-judul--mesin { color: var(--teks); }
/* Petak starter: tiap motor sepetak, seperti group starter panel. */
.kendali--bergolong .kendali-blok[data-golongan="mesin"] {
  /* Sama lebar, supaya petak No. 1 dan No. 2 berjajar rapi seperti di
     panel — bukan selebar tulisannya masing-masing. `!important` karena
     modul-modul menulis `style="flex:0 1 auto"` LANGSUNG di bloknya, dan
     gaya sebaris mengalahkan aturan mana pun tanpanya. */
  flex: 0 1 150px !important; align-self: stretch; align-content: flex-start;
  padding: 8px 10px; border-radius: 8px;
  background: var(--latar-3); border: 1px solid var(--garis);
}
/* Petak berisi banyak tombol (telegraf mesin induk: sebelas perintah)
   bukan petak starter — ia mendapat satu baris penuh, bukan dijepit
   selebar petak pompa. */
.kendali--bergolong .kendali-blok[data-golongan="mesin"]:has(button:nth-of-type(5)) {
  flex: 1 1 100% !important; max-width: none;
}
/* Simulasi bukan tombol kapal: diredupkan sedikit, tetap terbaca. */
.kendali--bergolong .kendali-judul--simulasi { color: var(--teks-redup); font-style: italic; }

/* WARNA TOMBOL MENURUT IEC 60073 — START hijau, STOP merah. Ditandai
   `data-aksi` dari TULISAN tombolnya (tata-kendali.js), sebab satu tombol
   yang sama bergantian berbunyi Start dan Stop. Tombol yang sedang
   memakai warna KEADAAN (is-sudah, is-terpilih) tidak ditimpa: warna itu
   yang menceritakan mesinnya sedang jalan. */
.kendali button[data-aksi="start"]:not(:disabled):not(.is-sudah):not(.is-terpilih) {
  background: var(--hijau); border-color: var(--hijau); color: var(--latar);
  font-weight: 650;
}
.kendali button[data-aksi="stop"]:not(:disabled):not(.is-sudah):not(.is-terpilih) {
  background: transparent; border-color: var(--merah); color: var(--merah);
  font-weight: 650;
}

/* Formulir Oil Record Book: pilihan kode dan butirnya berisi kalimat
   panjang (nama kode Appendix III), dan <select> mengambil lebar teks
   terpanjangnya — sebagai butir flex, lebar minimumnya pun ikut teks itu,
   jadi di layar 390 px ia mendorong seluruh halaman melebar 170 px.
   min-width: 0 yang sesungguhnya menyelesaikannya; width: 100% saja tidak. */
#formY select { width: 100%; max-width: 100%; min-width: 0; flex: 1 1 100%; }
#formY .kendali-blok { min-width: 0; }

/* GULIR TEGAK LEWAT BEGITU SAJA DI ATAS PENGGESER.
 *
 * Dilaporkan jhony 8 September 2026: "sll kegeser gak sengaja". Di layar
 * sentuh, jari yang menggulir halaman dan kebetulan mendarat di atas sebuah
 * penggeser akan MENYERET nilainya — beban mesin, sudut engkol, laju umpan
 * purifier berubah tanpa satu pun tanda bahwa itu perbuatan pemakainya.
 *
 * `touch-action: pan-y` menyerahkan gerak TEGAK kepada halaman dan menyisakan
 * gerak MENDATAR untuk penggesernya. Menggeser dengan sengaja tetap bisa;
 * yang hilang cuma seretan yang tidak diniatkan.
 *
 * Dipasang pada SELURUH penggeser, bukan cuma dua yang dikeluhkan: sebabnya
 * sama di mana pun, dan memperbaikinya satu per satu tiap kali ada yang
 * mengeluh berarti menunggu keluhan yang sama tiga kali lagi. */
input[type="range"] { flex: 1 1 130px; width: 100%; accent-color: var(--aksen); margin: 0;
  touch-action: pan-y; }
select, input[type="text"], input[type="number"] {
  background: var(--latar-3); color: var(--teks);
  border: 1px solid var(--garis-kuat); border-radius: 7px;
  padding: 7px 9px; font: inherit; width: 100%;
}
.input-cari { margin-bottom: 8px; }

.tombol {
  background: var(--latar-3); color: var(--teks);
  border: 1px solid var(--garis-kuat); border-radius: 8px;
  padding: 8px 14px; font: inherit; cursor: pointer; white-space: nowrap;
}
.tombol:hover { border-color: var(--aksen); }

/* Saklar suara yang MENYALA harus terlihat menyala dari seberang ruangan:
   ia satu-satunya kendali di modul ini yang mengubah sesuatu di luar layar,
   dan pemakai yang lupa mematikannya akan menyalahkan aplikasinya. */
.tombol[id="suaraA"][aria-pressed="true"] {
  border-color: var(--aksen); color: var(--aksen); font-weight: 620;
}
.tombol-aksen { background: var(--aksen); color: #fff; border-color: var(--aksen); font-weight: 620; }
.tombol-aksen:hover { filter: brightness(1.08); }
.tombol-kecil { padding: 5px 11px; font-size: .87rem; }

/* ============================================ [hidden] HARUS MENANG
 *
 * Aturan bawaan peramban `[hidden] { display: none }` datang dari
 * stylesheet PERAMBAN, dan aturan apa pun dari stylesheet KITA
 * mengalahkannya — berapa pun spesifisitasnya. Jadi satu baris
 * `display: flex` pada sebuah elemen membuat atribut `hidden`-nya berhenti
 * bekerja sama sekali, tanpa satu peringatan pun.
 *
 * Sudah terjadi, dan akibatnya jauh lebih besar daripada satu elemen yang
 * salah tampil: `.layar-kunci` punya `display: flex` DAN `position: fixed;
 * inset: 0`. Ia karena itu terpasang penuh di atas SELURUH layar sepanjang
 * waktu — juga waktu masa cobanya masih jauh dari habis — dan menangkap
 * setiap ketukan sebelum sampai ke aplikasinya. Yang menemukannya bukan
 * mata melainkan satu uji volume yang jatuh: ketukan di kenop volume
 * mendarat di layar kunci yang seharusnya tidak ada.
 *
 * `!important` DIPAKAI DI SINI, dan cuma di sini. Ia memang palu, tapi
 * yang dipaku sesuatu yang seharusnya tidak pernah bisa ditawar: elemen
 * yang ditandai `hidden` tidak boleh tampil, titik. Menuliskan
 * `.layar-kunci[hidden] { display: none }` cuma menambal satu elemen, dan
 * elemen berikutnya akan mengulangi cacat yang sama.
 */
[hidden] { display: none !important; }

/* --------------------------------------------------------------- gambar */
.svg-bungkus { width: 100%; overflow-x: auto; }
.svg-bungkus > svg { width: 100%; height: auto; display: block; }

/* Di layar sempit, penampang mesin yang diperkecil sampai selebar HP membuat
   tulisannya tak terbaca. Lebih baik ia tetap besar dan digulir MENDATAR DI
   DALAM KOTAKNYA sendiri — badan halaman tetap tidak ikut bergeser. */
@media (max-width: 620px) {
  /* 540, bukan 470: pada 470 huruf terkecil di penampang ("Bak engkol")
     turun jadi 6,3 piksel di layar — muat, tapi tidak terbaca. Angka ini
     bukan selera; ia keluar dari uji yang mengukur tinggi huruf SUNGGUHAN
     di layar dan menuntut sekurangnya 7 piksel. */
  #svgMesin, #svgBagian { min-width: 540px; }
  /* Bowl kini berisi DUA gambar berdampingan (penampang + tampak atas).
     Diperkecil sampai selebar HP, keduanya jadi tak terbaca; lebih baik
     tetap besar dan digulir mendatar DI DALAM KOTAKNYA sendiri. */
  #svgBowl, #svgBowlF { min-width: 660px; }
  /* Ketel memuat sirkuit lengkap sampai tangki kaskade — lebih lebar lagi. */
  #svgKetelG, #svgKetelH { min-width: 780px; }
  /* Kompresor memuat seluruh jalur dari saringan sampai botol angin. */
  #svgKompresor, #svgKompresorJ { min-width: 840px; }
  /* Diagram satu garis generator memuat dua genset, rel, dan empat pemakai
     berdampingan. 660 px: pada lebar itu huruf 12 px turun jadi 7,1 px di
     layar — batas yang dipakai uji tinggi huruf. */
  #svgGenerator { min-width: 660px; }
  /* Penampang 4 tak memuat mesin DAN tabel pembanding 2 tak di sebelahnya. */
  #svg4Tak { min-width: 700px; }
  /* Alur minyak silinder membentang dari tangki simpan di kiri sampai
     ruang bilas di kanan — rantai itu yang jadi isinya, jadi ia tidak bisa
     dipatahkan jadi dua baris. Diperkecil sampai selebar HP, hurufnya
     turun ke 4,4 px dan tidak ada yang terbaca; uji tinggi huruf yang
     menangkapnya. */
  #svgCylOli { min-width: 820px; }
  /* Sirkulasi minyak sistem: gelangnya harus terlihat MENUTUP, dan itu
     tidak mungkin kalau dipatahkan jadi dua baris. */
  #svgSysOli { min-width: 820px; }
  /* Mekanisme bowl: seluruh tulisan penunjuknya berkumpul di lajur kanan,
     dan justru tulisan itulah isi gambarnya. Diperkecil sampai selebar HP,
     yang tersisa cuma bentuk tanpa nama. */
  #svgMekanisme { min-width: 700px; }
  /* EMPAT GAMBAR TERBARU, dan keempatnya berangkat tanpa baris ini —
     ketahuan sekaligus waktu uji peramban penuh akhirnya sampai ke lebar
     HP untuk pertama kalinya sesudah keempatnya dibangun. Angkanya bukan
     kira-kira: diukur dari tinggi huruf SUNGGUHAN di layar 390 px dan
     dinaikkan sampai huruf terkecilnya lewat 7 piksel.

     Air pendingin jaket: 4,4 px sebelum ini. Rangkaiannya membentang dari
     tangki ekspansi sampai pendingin air laut, dan itu memang rantainya. */
  #svgJaket { min-width: 560px; }
  /* Insinerator: 4,2 px. Dari tangki lumpur sampai cerobong. */
  #svgInsinerator { min-width: 600px; }
  /* OWS: 4,2 px. Dari tangki got sampai katup 3-arah — kalau dipatahkan,
     yang hilang justru alur airnya, satu-satunya isi gambar ini. */
  #svgOws { min-width: 600px; }
  /* Air limbah: satu rantai penuh dari toilet sampai katup buang — sama
     lebarnya dengan OWS dan insinerator, dan dengan alasan yang sama:
     dipatahkan jadi dua baris, yang hilang justru rantainya. */
  #svgLimbah { min-width: 600px; }
  /* FWG: 4,2 px pada lebar HP. Gambarnya satu bejana dipotong dengan
     kondensor di atas dan penguap di bawah — susunan atas-bawah itulah
     yang menjelaskan kenapa uap naik sendiri, dan ia hilang begitu
     gambarnya dipatahkan jadi dua baris. */
  #svgFwg { min-width: 640px; }
  /* Ganti bahan bakar: jalur dari dua tangki sampai mesin induk, plus jalur
     ECA yang membentang di bawahnya. Dipatahkan jadi dua baris, yang hilang
     justru jalurnya — dan jalur itulah seluruh isi gambar ini. */
  #svgGantiBbm { min-width: 660px; }
  #svgPendingin { min-width: 700px; }
  #svgDarurat { min-width: 720px; }
  /* Peta jalan minyak kotor: tiga kolom (sumber, tangki lumpur, pintu
     keluar) yang dibaca dari kiri ke kanan — dipatahkan, arah alirnya
     hilang. */
  #svgBuku { min-width: 700px; }
  /* Papan duga tangki: 6,2 px. Tujuh tangki berjajar dalam tiga kelompok;
     yang dibaca orang justru perbandingan ANTAR tangki, jadi memecahnya
     jadi dua baris menghapus gunanya. */
  #svgTangki { min-width: 420px; }
  /* Siklus refrigerasi: kompresor, kondensor, receiver, drier, dan kamar
     berjajar dalam SATU gelang yang harus terlihat menutup — dipatahkan,
     arah putarnya hilang. Tiga kamar berdampingan di halaman makanan
     membuatnya paling lebar di aplikasi ini sesudah kompresor udara. */
  #svgZ { min-width: 900px; }
  #svgAc { min-width: 820px; }
  /* Mesin kemudi: TIGA pandangan berdampingan — anjungan, ruang mesin
     kemudi, dan buritan — dan gunanya justru membandingkan ketiganya
     sekaligus. Dipecah jadi baris, penunjuk sudut di anjungan berhenti
     bisa diadu dengan daun kemudi yang sebenarnya. */
  #svgKemudi { min-width: 940px; }
}

.svg-teks { fill: var(--teks-redup); font-size: 12px; }
.svg-teks-kuat { fill: var(--teks); font-size: 13px; font-weight: 640; }
.svg-nilai { fill: var(--teks); font-size: 12px; font-variant-numeric: tabular-nums; }
/* Angka yang harus terbaca dari jauh — hitungan 45 detik genset darurat dan
   tekanan botol angin. Ukurannya bukan hiasan: yang dibaca orang waktu
   kapal gelap cuma dua angka itu. */
.svg-teks-besar { fill: var(--teks); font-size: 24px; font-weight: 700;
  font-variant-numeric: tabular-nums; }
.svg-garis { stroke: var(--garis-kuat); stroke-width: 1; fill: none; }
/* Dua tingkat kelabu logam: badan besar memakai svg-logam, bagian yang
   bergerak dan bagian kecil memakai svg-logam-2 supaya bentuknya masih
   terbaca saat bertumpuk di atas badan mesin. */
.svg-logam { fill: var(--latar-3); stroke: var(--garis-kuat); stroke-width: 1.5; }
.svg-logam-2 { fill: var(--garis); stroke: var(--garis-kuat); stroke-width: 1; }

.legenda { display: flex; flex-wrap: wrap; gap: 8px 16px; margin-top: 9px; }
.legenda-item { color: var(--teks-redup); font-size: .84rem; display: inline-flex; align-items: center; gap: 5px; }
.contreng {
  display: inline-block; width: 11px; height: 11px; border-radius: 3px;
  flex: 0 0 11px;
  /* Garis tepi tipis: contreng tetap terbaca sebagai KOTAK walaupun isinya
     kebetulan sedekat apa pun dengan latarnya. */
  box-shadow: 0 0 0 1px var(--garis-kuat);
}
/* Contreng untuk PENUNJUK, bukan untuk warna kurva.
   Merah dan oranye cuma berselisih 1,3 : 1 — dua kotak kecil bersebelahan
   dengan warna sedekat itu tidak bisa dibedakan, dan legenda yang tidak
   bisa dibedakan justru menggagalkan gunanya sendiri. Jadi yang membedakan
   bukan warnanya melainkan BENTUKNYA: bulat dan bercincin, persis seperti
   titik penunjuk di dalam diagramnya. Legenda seharusnya memang menyerupai
   benda yang dilabelinya. */
.contreng-titik {
  width: 13px; height: 13px; flex: 0 0 13px;
  border-radius: 50%;
  box-shadow: 0 0 0 2px var(--latar-2), 0 0 0 3px var(--garis-kuat);
}

/* ------------------------------------------------------------- parameter */
.panel-angka {
  display: grid; gap: 8px;
  grid-template-columns: repeat(auto-fill, minmax(132px, 1fr));
}
.angka {
  background: var(--latar-3); border: 1px solid var(--garis);
  border-radius: 8px; padding: 8px 10px;
}
.angka-label { font-size: .73rem; color: var(--teks-redup); text-transform: uppercase; letter-spacing: .04em; }
.angka-nilai { font-variant-numeric: tabular-nums; font-weight: 680; font-size: 1.1rem; margin-top: 2px; }
.angka-satuan { font-size: .76rem; color: var(--teks-redup); font-weight: 400; margin-left: 3px; }

/* KEADAAN besaran: hijau selama di dalam batas normal, merah begitu lewat.
   Yang diwarnai ANGKA-nya, bukan seluruh kotak — kotak penuh warna membuat
   panel berisi belasan besaran terlihat seperti papan lampu disko, dan yang
   lewat batas justru tenggelam di antara yang hijau. Kotak yang lewat batas
   ditambah garis tepi merah supaya masih ketemu dari sudut mata.

   Besaran yang TIDAK punya batas tetap netral: memberinya hijau berarti
   mengarang batas yang tidak pernah ditetapkan, dan panel yang seluruhnya
   hijau berhenti memberi tahu apa pun. */
.angka.is-normal .angka-nilai { color: var(--hijau); }
.angka.is-lewat .angka-nilai { color: var(--merah); }
.angka.is-lewat { border-color: var(--merah); }
/* Batang silinder yang melewati batas suhu gas buang, bukan sekadar
   menyimpang dari saudara-saudaranya. */
.batang-baris.is-lewat .batang-isi { background: var(--merah); }
.batang-baris.is-lewat .batang-nilai { color: var(--merah); }
.angka-beda { font-size: .72rem; margin-top: 3px; font-variant-numeric: tabular-nums; }

/* Merah = lebih tinggi dari mesin sehat, biru = lebih rendah. Dipakai modul
   diagnosa; arahnya lebih penting daripada besarnya. */
.angka.is-naik  { border-color: var(--merah); background: var(--latar-2); }
.angka.is-turun { border-color: var(--udara); background: var(--latar-2); }
.angka.is-naik  .angka-beda { color: var(--merah); }
.angka.is-turun .angka-beda { color: var(--udara); }

.angka-sel { font-variant-numeric: tabular-nums; }

/* --------------------------------------------------- batang tiap silinder */
.batang-silinder { display: grid; gap: 5px; }
 /* Kolom nilai 92px, bukan 62: sejak kenaikan terhadap mesin sehat ikut
    ditulis ("441 °C +59 K"), 62px memaksa angkanya turun baris dan tinggi
    kartunya membengkak dari 216 ke 351 piksel — di HP itu setengah layar
    untuk enam baris yang sama. */
.batang-baris { display: grid; grid-template-columns: 44px 1fr 92px; gap: 8px; align-items: center; }
.batang-nama { font-size: .82rem; color: var(--teks-redup); }
.batang-alur {
  position: relative; height: 17px; border-radius: 4px;
  background: var(--latar-3); border: 1px solid var(--garis); overflow: hidden;
}
/* HIJAU untuk yang normal, diminta jhony. Dan warnanya jadi lebih benar
   daripada aksen: di seluruh aplikasi ini merah melarang, aksen menunggu
   dikerjakan, hijau sudah beres. Enam silinder yang seragam memang "sudah
   beres" — tidak ada yang perlu dikerjakan padanya. Yang menyimpang tetap
   merah di bawah, dan di atas latar hijau ia jauh lebih menonjol daripada
   merah di atas jingga. */
.batang-isi { height: 100%; background: var(--hijau); opacity: .78; }
/* Garis rata-rata: patokan pembanding, digambar di atas batangnya. */
.batang-rata { position: absolute; top: -1px; bottom: -1px; width: 2px; background: var(--teks); opacity: .6; }
.batang-nilai { font-size: .84rem; font-variant-numeric: tabular-nums; text-align: right; }
.batang-baris.is-menyimpang .batang-isi { background: var(--merah); opacity: .85; }
.batang-baris.is-menyimpang .batang-nama,
.batang-baris.is-menyimpang .batang-nilai { color: var(--merah); font-weight: 650; }
/* DI ATAS AMBANG NORMAL: lebih tinggi daripada mesin sehat pada beban yang
   sama, tapi belum melewati batas mutlak dan belum menyimpang dari
   saudara-saudaranya. Merah juga — yang membedakannya dari dua kelas di
   atas cuma angka "+N K" di sebelahnya, sebab yang perlu dibedakan orang
   bukan seberapa merah melainkan APA yang harus dicari. */
.batang-baris.is-tinggi .batang-isi { background: var(--merah); opacity: .82; }
.batang-baris.is-tinggi .batang-nama,
.batang-baris.is-tinggi .batang-nilai { color: var(--merah); font-weight: 650; }
.batang-naik { font-size: .74rem; opacity: .85; white-space: nowrap; }

/* ---------------------------------------------------------------- alarm */
.daftar-alarm { display: grid; gap: 6px; margin-top: 12px; }
.alarm {
  display: flex; gap: 9px; align-items: baseline;
  padding: 7px 10px; border-radius: 7px; font-size: .89rem;
  border-left: 3px solid var(--garis-kuat); background: var(--latar-3);
}
.alarm-ikon {
  flex: 0 0 17px; width: 17px; height: 17px; border-radius: 50%;
  display: inline-grid; place-items: center;
  font-size: .78rem; font-weight: 700; color: var(--latar-2);
  background: var(--garis-kuat); align-self: center;
}
.alarm-bahaya { border-left-color: var(--merah); }
.alarm-bahaya .alarm-ikon { background: var(--merah); }
.alarm-ingat { border-left-color: var(--kuning); }
.alarm-ingat .alarm-ikon { background: var(--kuning); }
/* AWAS di antara ingat dan bahaya. Kelasnya sudah dipasang panel.js sejak
   lama untuk lima puluhan alarm bertingkat 'awas', dan tak satu pun punya
   aturannya — semuanya jatuh ke garis kelabu bawaan, tidak terbedakan dari
   catatan biasa. Ketahuan waktu temuan PSC "berat" tampil sama pucatnya
   dengan temuan "ringan". */
.alarm-awas { border-left-color: var(--aksen); }
.alarm-awas .alarm-ikon { background: var(--aksen); }
.alarm-aman { border-left-color: var(--hijau); color: var(--teks-redup); }
.alarm-aman .alarm-ikon { background: var(--hijau); }

/* ---------------------------------------------------------------- tabel */
.tabel-bungkus { overflow-x: auto; }
table { border-collapse: collapse; width: 100%; font-size: .88rem; }
th, td { text-align: left; padding: 7px 9px; border-bottom: 1px solid var(--garis); }
thead th {
  color: var(--teks-redup); font-weight: 600; font-size: .78rem;
  text-transform: uppercase; letter-spacing: .03em; white-space: nowrap;
}
td.angka-sel { text-align: right; white-space: nowrap; }

/* -------------------------------------------------------------- akordeon */
.akordeon { display: grid; gap: 7px; }
.akordeon details {
  border: 1px solid var(--garis); border-radius: 8px; background: var(--latar-3);
}
.akordeon summary { cursor: pointer; padding: 10px 13px; font-weight: 600; list-style: none; }
.akordeon summary::-webkit-details-marker { display: none; }
.akordeon summary::before { content: "▸ "; color: var(--aksen); }
.akordeon details[open] summary::before { content: "▾ "; }
.akordeon-isi { padding: 0 13px 12px; }
.akordeon-isi > *:last-child { margin-bottom: 0; }

/* ------------------------------------------------------- kotak peringatan */
.catatan {
  border-left: 3px solid var(--udara); background: var(--udara-lembut);
  padding: 10px 13px; border-radius: 0 7px 7px 0; margin: 0 0 16px; font-size: .91rem;
}
.awas {
  border-left: 3px solid var(--merah);
  background: color-mix(in srgb, var(--merah) 11%, transparent);
  padding: 10px 13px; border-radius: 0 7px 7px 0; margin: 0 0 16px; font-size: .91rem;
}
.awas > p:last-child, .catatan > p:last-child { margin-bottom: 0; }

/* ------------------------------------------------------- modul B & pilih */
.pilih-komponen { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 12px; }
/* Tombol biasa sengaja `nowrap` supaya kendali tidak berubah tinggi. Isi
   deretan ini bukan kendali melainkan KALIMAT — "Pipa pemanas bocor —
   minyak masuk kondensat" tidak muat di layar 390 px dan menggeser seluruh
   halaman 6 px ke samping. Di sini teksnya boleh turun baris. */
.pilih-komponen .tombol { white-space: normal; text-align: left; }
.pilih-komponen .tombol.is-terpilih {
  border-color: var(--aksen); background: var(--aksen-lembut); font-weight: 620;
}
.kartu-komponen dt { font-weight: 650; margin-top: 10px; }
.kartu-komponen dt:first-child { margin-top: 0; }
.kartu-komponen dd { margin: 3px 0 0; color: var(--teks-redup); }

/* Penampang modul B: setiap bagiannya bisa diketuk, jadi kotak sorot biru
   bawaan peramban saat disentuh justru mengganggu, dan teksnya tidak boleh
   ikut terblok saat jari menggeser. */
.bagian-svg { -webkit-tap-highlight-color: transparent; user-select: none; }

/* Bagian yang bisa diketuk di penampang (modul B). Sasaran sentuhnya sebuah
   persegi bening yang lebih besar dari gambarnya, jadi jari tetap mengenai
   di HP tanpa perlu memperbesar gambar mesinnya. */
.titik-klik { cursor: pointer; }
.titik-klik:focus { outline: none; }
.sorot { fill: transparent; stroke: transparent; stroke-width: 2.5; transition: fill .12s, stroke .12s; }
.titik-klik:hover .sorot { fill: color-mix(in srgb, var(--aksen) 16%, transparent); stroke: var(--aksen); }
.titik-klik:focus-visible .sorot { fill: color-mix(in srgb, var(--udara) 18%, transparent); stroke: var(--udara); }
.titik-klik.is-terpilih .sorot { fill: color-mix(in srgb, var(--aksen) 24%, transparent); stroke: var(--aksen); }

/* -------------------------------------------------------------- modul C */
.mode-pilih {
  display: inline-flex; gap: 3px; margin-bottom: 14px;
  background: var(--latar-3); border: 1px solid var(--garis);
  border-radius: 999px; padding: 3px;
}
.mode-pilih .tombol { border: 0; background: transparent; color: var(--teks-redup); border-radius: 999px; }
.mode-pilih .tombol[aria-pressed="true"] { background: var(--aksen); color: #fff; font-weight: 620; }

/* Deretan tombol TINDAKAN yang boleh melipat. Sengaja bukan .mode-pilih:
   itu kelompok pilihan yang saling meniadakan dan digambar sebagai satu
   pil, sedangkan ini tindakan yang berdiri sendiri-sendiri. Enam tindakan
   genset (start, pemutus, governor, AVR) tidak muat sebaris di layar 390 px
   dan memang seharusnya melipat, bukan menggeser halaman. */
.deret-tombol { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 10px; }

.pilihan-jawab { display: grid; gap: 7px; margin: 10px 0 12px; }
.jawab {
  text-align: left; width: 100%;
  background: var(--latar-3); color: var(--teks);
  border: 1px solid var(--garis); border-radius: 8px;
  padding: 9px 12px; font: inherit; cursor: pointer;
}
.jawab:hover { border-color: var(--aksen); }
/* Jawaban yang sedang dipilih, sebelum diperiksa. Dua penanda dikenali
   karena dua kuis sempat memakai cara berbeda: modul mesin induk menandainya
   lewat aria-pressed (kebaca pembaca layar tapi TIDAK terlihat mata), modul
   purifier lewat kelas. Keduanya kini menghasilkan tampilan yang sama. */
.jawab.is-pilih,
.jawab[aria-pressed="true"] { border-color: var(--udara); background: var(--udara-lembut); }
.jawab.is-benar { border-color: var(--hijau); background: color-mix(in srgb, var(--hijau) 16%, transparent); }
.jawab.is-salah { border-color: var(--merah); background: color-mix(in srgb, var(--merah) 16%, transparent); }

.umpan {
  margin-top: 12px; padding: 11px 13px; border-radius: 8px;
  border-left: 3px solid var(--garis-kuat); background: var(--latar-3); font-size: .92rem;
}
.umpan.is-benar { border-left-color: var(--hijau); }
.umpan.is-salah { border-left-color: var(--merah); }
.umpan > *:last-child { margin-bottom: 0; }

.skor { margin-top: 10px; font-size: .88rem; color: var(--teks-redup); font-variant-numeric: tabular-nums; }

/* -------------------------------------------------------------- modul D */
#daftarIstilah { display: grid; gap: 7px; margin: 0; }
.istilah { background: var(--latar-3); border: 1px solid var(--garis); border-radius: 8px; padding: 9px 12px; }
.istilah dt { font-weight: 650; }
.istilah dd { margin: 3px 0 0; color: var(--teks-redup); font-size: .9rem; }
.istilah-asing { color: var(--teks-redup); font-weight: 400; font-size: .85rem; font-style: italic; }

/* ----------------------------------------------------------------- kaki */
.footer {
  max-width: var(--lebar); margin: 0 auto;
  padding: 18px 14px 40px; border-top: 1px solid var(--garis);
  color: var(--teks-redup); font-size: .84rem;
}
.footer p { margin-bottom: .4em; }

/* Tangga langkah urutan separator: seluruh langkah terlihat sekaligus,
   yang sedang berjalan disorot. Menggulir mendatar di layar sempit — bukan
   melipat jadi beberapa baris, supaya urutannya tetap terbaca sebagai
   urutan. */
.tangga {
  display: flex; gap: 6px; overflow-x: auto; padding-bottom: 4px;
  scrollbar-width: thin;
}
.tangga-anak {
  flex: 0 0 auto; padding: 4px 10px; border-radius: 999px;
  border: 1px solid var(--garis); color: var(--teks-redup);
  font-size: .78rem; white-space: nowrap;
}
.tangga-anak.is-kini {
  background: var(--aksen); border-color: var(--aksen);
  color: #fff; font-weight: 620;
}

/* Pesan cadangan tombol pasang: muncul sebaris di bawah tombolnya, bukan di
   kaki halaman. Lebar penuh supaya ia turun ke barisnya sendiri di topbar
   dan tidak menggencet deretan peralatan.

   `order` WAJIB, dan ini ketahuan dari layar HP sungguhan, bukan dari uji:
   di layar sempit topbar menyusun ulang isinya (merek order 1, tombol
   pasang 2, tema 3, deretan peralatan 4). Pesan ini ditulis lebih dulu di
   HTML dan order bawaannya 0, jadi ia MENANG di depan semuanya dan
   nangkring di atas judul "Kamar Mesin" — bukan di bawah tombol yang barusan
   ditekan. Angka 9 menaruhnya paling belakang di kedua tata letak. */
.pasang-catatan {
  order: 9;
  flex: 1 1 100%;
  margin: 0;
  padding: 8px 11px;
  border: 1px solid var(--garis);
  border-radius: 8px;
  background: var(--latar-2);
  font-size: .86rem;
  line-height: 1.45;
}

/* Pemisah antar bagian besar di dalam satu modul. Dipakai modul A, yang
   memuat mesin induk DAN pelumasan silindernya — dua topik yang berdiri
   sendiri tapi memang milik mesin yang sama, jadi digabung satu halaman
   alih-alih dipecah jadi submenu yang terdorong keluar layar HP. */
.pemisah-bagian {
  border: 0; border-top: 1px solid var(--garis);
  margin: 34px 0 26px;
}

/* ---------------------------------------------------------------- RUANG
   KONTROL. Papan pantau dibaca dengan cara yang berbeda dari modul lain:
   ia DISAPU, bukan dibaca. Maka yang harus terbaca lebih dulu bukan
   angkanya melainkan KEADAANnya — dan itu dikerjakan warna di satu tempat
   yang sama pada tiap kartu, supaya mata bisa turun lurus di kolom itu
   tanpa menyentuh satu angka pun. */
.papan-kontrol {
  display: grid;
  gap: 12px;
  grid-template-columns: repeat(auto-fill, minmax(268px, 1fr));
}
.kartu-status {
  background: var(--latar-2);
  border: 1px solid var(--garis);
  border-radius: var(--sudut);
  padding: 14px 16px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  /* Pita keadaan di tepi kiri. Border-left, bukan latar berwarna: latar
     berwarna pada tujuh kartu sekaligus membuat seluruh papan berteriak,
     dan yang berteriak semuanya sama saja dengan yang diam semuanya. */
  border-left: 3px solid var(--garis-kuat);
}
.kartu-status.is-jalan { border-left-color: var(--hijau); }
.kartu-status.is-diam { border-left-color: var(--garis-kuat); }
.kartu-status.is-belum { border-left-color: var(--garis); opacity: .72; }

.status-kepala {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 10px; flex-wrap: wrap;
}
.status-kepala h3 { margin: 0; font-size: 15px; }
/* Tombol ke halaman peralatannya, di DASAR kartu (margin-top: auto):
   kartu sebaris sama tinggi, jadi tombol-tombolnya sejajar dan mata tahu
   di mana mencarinya tanpa membaca isinya. */
.status-buka {
  margin-top: auto; align-self: flex-start;
  background: transparent; color: var(--aksen);
  border: 1px solid var(--garis-kuat); border-radius: 8px;
  padding: 5px 10px; min-height: 32px;
  font: inherit; font-size: .84rem; font-weight: 620; cursor: pointer;
}
@media (hover: hover) { .status-buka:hover { border-color: var(--aksen); background: var(--aksen-lembut); } }
.status-tanda {
  font-size: 11px; font-weight: 700; letter-spacing: .06em;
  padding: 2px 8px; border-radius: 999px;
  background: var(--latar-3); color: var(--teks-redup);
  white-space: nowrap;
}
.is-jalan .status-tanda { background: var(--aksen-lembut); color: var(--hijau); }
.is-belum .status-tanda { background: transparent; border: 1px dashed var(--garis-kuat); }

/* Pasangan label-nilai. Grid dua kolom supaya angkanya berbaris rata di
   seluruh kartu — tabular-nums menjaganya tetap rata walau angkanya
   berubah tiap setengah detik. */
.status-nilai {
  margin: 0; display: grid; grid-template-columns: 1fr auto;
  gap: 4px 12px; align-items: baseline;
}
.status-nilai dt { color: var(--teks-redup); font-size: 12px; }
.status-nilai dd {
  margin: 0; font-size: 13px; font-weight: 620;
  font-variant-numeric: tabular-nums; text-align: right;
}
.status-kosong { margin: 0; }

.status-alarm { margin: 0; padding: 0; list-style: none; display: grid; gap: 6px; }
.status-alarm li {
  font-size: 12px; line-height: 1.45; padding: 6px 8px;
  border-radius: 6px; background: var(--latar-3);
}
.status-alarm .alarm-bahaya { color: var(--merah); background: var(--aksen-lembut); }
.status-alarm .alarm-awas { color: var(--kuning); }
.status-alarm .alarm-ingat { color: var(--teks-redup); }
.petunjuk.is-bahaya { color: var(--merah); font-weight: 620; }

/* --------------------------------------------------------- GENERATOR SET
   Tiga kartu, satu per genset. Di layar lebar berdampingan; di HP
   bertumpuk — dan bertumpuk itu justru urutan yang benar untuk membaca
   satu mesin sampai selesai sebelum pindah ke mesin berikutnya. */
.papan-genset {
  display: grid;
  gap: 14px;
  grid-template-columns: repeat(auto-fit, minmax(340px, 1fr));
}
.kartu-genset { display: flex; flex-direction: column; gap: 10px; }

.genset-kendali {
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px; flex-wrap: wrap;
}
/* Tanda keadaan: empat, bukan dua. "Berjalan" dan "memikul beban" memang
   dua hal yang berbeda, dan trip berbeda lagi dari berhenti biasa —
   yang satu keputusan orang, yang satu keputusan proteksi. */
.genset-tanda {
  font-size: 11px; font-weight: 700; letter-spacing: .05em;
  padding: 3px 9px; border-radius: 999px;
  background: var(--latar-3); color: var(--teks-redup);
  white-space: nowrap;
}
.genset-tanda.is-jalan { background: var(--aksen-lembut); color: var(--hijau); }
.genset-tanda.is-siaga { background: var(--latar-3); color: var(--kuning); }
.genset-tanda.is-diam { background: var(--latar-3); color: var(--teks-redup); }
/* BERHENTI merah, diminta jhony, dan sama di mana pun ia muncul: genset
   yang diam adalah genset yang TIDAK BISA dimasukkan ke rel. Kelabu
   membuatnya terbaca sebagai "tidak ada kabar". */
.genset-tanda.is-mati { background: color-mix(in srgb, var(--merah) 12%, transparent); color: var(--merah); }
.genset-tanda.is-trip { background: var(--aksen-lembut); color: var(--merah); }

/* ------------------------------------------------------- URUTAN START
   Daftar bernomor, dan nomornya di sini SUNGGUH berarti urutan: tiap
   langkah mustahil tanpa yang sebelumnya. Tiga keadaan, dan yang gagal
   diberi warna sendiri — urutan yang tertahan tanpa kabar lebih buruk
   daripada urutan yang berhenti. */
.urutan-start {
  margin: 0; padding-left: 1.4em; display: grid; gap: 3px;
  font-size: 12px; color: var(--teks-redup); line-height: 1.5;
}
.urutan-start li::marker { color: var(--garis-kuat); }
.urutan-start li.is-selesai { color: var(--hijau); }
.urutan-start li.is-selesai::marker { color: var(--hijau); }
.urutan-start li.is-kini { color: var(--teks); font-weight: 620; }
.urutan-start li.is-kini::marker { color: var(--aksen); }
.urutan-start li.is-gagal { color: var(--merah); font-weight: 620; }
.urutan-start li.is-gagal::marker { color: var(--merah); }

/* Panel rinci di dalam kartu ruang kontrol. Diberi garis pemisah dan
   jarak di atasnya supaya ia terbaca sebagai LAMPIRAN kartu itu, bukan
   sebagai daftar yang mengambang di antara dua kartu — tanpa pemisah,
   sebelas panel berderet terlihat seperti satu daftar panjang dan
   pengelompokan per mesin yang diminta justru hilang. */
.status-rinci {
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid var(--garis);
}

/* SYNCHROSCOPE DIBATASI LEBARNYA.
   `.svg-bungkus > svg` memberi width:100% — benar untuk diagram yang memang
   ingin selebar mungkin (penampang mesin, grafik droop), tapi salah total
   untuk PIRINGAN BULAT: di ruang kontrol kartunya selebar halaman, jadi
   jarumnya jadi lingkaran sebesar layar dan tulisan di tengahnya melayang
   berjauhan. Di kapal alat ini sebesar telapak tangan, dan membesarkannya
   tidak menambah satu pun keterangan — yang dibaca orang cuma ARAH dan
   LAJU putaran jarumnya. */
/* PANEL SINKRONISASI: tombol A/E (+ selektor & tuas governor) di kiri,
   synchroscope di kanan — satu panel seperti di switchboard. Di bawah
   900 px bertumpuk, jarum tepat di bawah tombolnya. */
.sinkron-panel { display: grid; gap: 14px; margin-top: 10px; }
.sinkron-kiri > .kendali:first-child { margin-top: 0 !important; }
.sinkron-kiri > .kartu { margin-bottom: 0; }
.sinkron-jarum { margin: 0; }
@media (min-width: 900px) {
  .sinkron-panel { grid-template-columns: minmax(0, 1fr) minmax(300px, 400px); align-items: start; }
  /* Jarum ikut melekat selagi kolom kiri (selektor + tuas) digulir. */
  .sinkron-jarum { position: sticky; top: calc(var(--tinggi-kepala) + 12px); }
}
#svgSinkron { max-width: 360px; margin-left: auto; margin-right: auto; }

/* JUDUL URUTAN KAPAL DINGIN — disorot atas permintaan jhony.
   Label kendali lainnya sengaja redup dan kecil: ia cuma menamai tombol di
   sebelahnya. Yang ini bukan nama tombol melainkan JUDUL pelajaran — urutan
   menyiapkan kapal dari nol, satu-satunya hal di halaman ini yang tidak
   bisa ditebak dari melihat mesinnya. Karena itu ia diberi ukuran normal,
   warna aksen, dan garis di kiri: mata harus berhenti di sini, bukan
   melewatinya seperti melewati label tombol. */
.judul-urutan.judul-urutan {
  font-size: .95rem;
  color: var(--aksen);
  font-weight: 700;
  text-transform: none;
  letter-spacing: 0;
  border-left: 3px solid var(--aksen);
  padding-left: 8px;
  margin-bottom: 4px;
}

/* TOMBOL YANG SUDAH DITEKAN — genset yang sudah dijalankan.
   Diminta jhony. Sebelumnya bedanya cuma tulisan Start lawan Stop, dan pada
   tiga genset berjajar itu menuntut membaca satu per satu. Hijau di sini
   berarti "sudah dikerjakan", sejalan dengan tanda BERJALAN di kartunya —
   dan warna aksen sengaja dicabut, sebab aksen menandai pekerjaan yang
   masih MENUNGGU dikerjakan. */
/* ===================================================== PAPAN ALARM KAPAL
   Diminta jhony: tanda alarm di lokal DAN di ruang kontrol, diklik keluar
   asalnya dan sebabnya. Ia duduk di topbar justru supaya dua tempat itu
   terlayani satu kali — topbar ada di setiap halaman.

   BERKEDIP HANYA UNTUK YANG BELUM DITERIMA. Kedipan itu mahal: ia menarik
   mata dari pekerjaan apa pun, dan kalau dipakai untuk keadaan yang menetap
   ia berubah jadi gangguan yang dimatikan orang. Jadi begitu tombol Terima
   ditekan, lampunya menyala TENANG — tetap merah, tetap ada, tidak lagi
   merebut perhatian. Itu pula yang membedakan papan alarm dari hiasan. */
.alarm-tanda {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  border: 2px solid var(--merah);
  color: var(--merah);
  background: color-mix(in srgb, var(--merah) 14%, transparent);
  border-radius: 8px;
  padding: 5px 10px;
  font: inherit;
  font-weight: 800;
  font-size: .82rem;
  letter-spacing: .06em;
  cursor: pointer;
  margin-left: auto;
}
/* AMAN — hijau, dan lambangnya centang bukan segitiga. Papan alarm kapal
   memang selalu menyala: hijau berarti "sistemnya hidup dan tidak ada
   apa-apa", keterangan tersendiri yang berbeda dari papan yang gelap. */
.alarm-tanda.is-aman {
  border-color: var(--hijau);
  color: var(--hijau);
  background: color-mix(in srgb, var(--hijau) 14%, transparent);
}
.alarm-tanda .alarm-centang { display: none; }
.alarm-tanda.is-aman .alarm-centang { display: inline; }
.alarm-tanda.is-aman .alarm-segitiga { display: none; }
.alarm-tanda.is-awas {
  border-color: var(--kuning);
  color: var(--kuning);
  background: color-mix(in srgb, var(--kuning) 16%, transparent);
}
.alarm-tanda .alarm-jumlah { font-variant-numeric: tabular-nums; }
/* Kata "ALARM" disembunyikan di layar sempit — di HP, topbar sudah memuat
   merek, dua baris navigasi, dan dua tombol. Yang tidak boleh hilang
   angkanya dan warnanya; kata itu keterangan, bukan tandanya. */
.alarm-tanda .alarm-kata { display: none; }
@media (min-width: 640px) { .alarm-tanda .alarm-kata { display: inline; } }
.alarm-tanda:hover { filter: brightness(1.12); }
.alarm-tanda.is-baru { animation: alarm-kedip 1s steps(1, end) infinite; }
@keyframes alarm-kedip {
  0%, 49% { opacity: 1; }
  50%, 100% { opacity: .35; }
}
/* Orang yang memilih gerak seminimal mungkin tetap harus melihat alarmnya —
   yang dicabut kedipannya, BUKAN tandanya. Alarm bukan animasi hiasan. */
@media (prefers-reduced-motion: reduce) {
  .alarm-tanda.is-baru { animation: none; outline: 2px dashed currentColor; outline-offset: 2px; }
}

.alarm-panel {
  position: fixed;
  top: 58px;
  right: 12px;
  z-index: 40;
  width: min(420px, calc(100vw - 24px));
  max-height: min(70vh, 560px);
  overflow-y: auto;
  background: var(--latar-2);
  border: 1px solid var(--garis-kuat);
  border-radius: 10px;
  padding: 12px 14px;
  box-shadow: 0 12px 34px rgba(0, 0, 0, .34);
}
.alarm-panel-kepala {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 10px;
}
.alarm-panel-kepala h3 { margin: 0; font-size: 1rem; }
.alarm-panel-tombol { display: flex; gap: 6px; flex-wrap: wrap; }
.alarm-kelompok { margin: 0 0 12px; }
.alarm-kelompok h4 {
  margin: 0 0 5px;
  font-size: .86rem;
  letter-spacing: .04em;
  color: var(--teks-redup);
}
.alarm-kelompok ul { margin: 0 0 7px; padding-left: 0; list-style: none; }
.alarm-baris {
  border-left: 3px solid var(--garis-kuat);
  padding: 4px 0 4px 9px;
  margin-bottom: 5px;
  font-size: .88rem;
  line-height: 1.4;
}
.alarm-baris.is-bahaya { border-left-color: var(--merah); }
.alarm-baris.is-awas { border-left-color: var(--kuning); }
.alarm-baris.is-ingat { border-left-color: var(--garis-kuat); color: var(--teks-redup); }
.alarm-catatan { opacity: .85; }
.alarm-tingkat {
  font-weight: 800;
  font-size: .74rem;
  letter-spacing: .07em;
}
.alarm-baris.is-bahaya .alarm-tingkat { color: var(--merah); }
.alarm-baris.is-awas .alarm-tingkat { color: var(--kuning); }
/* Yang belum diterima diberi tanda di DAFTARNYA juga, bukan cuma di
   lampunya: orang yang membuka panel saat sepuluh alarm sudah menumpuk
   perlu tahu mana yang barusan datang. */
.alarm-baris.is-baru { background: color-mix(in srgb, currentColor 8%, transparent); }
.alarm-ke { margin-bottom: 4px; }

/* STEMPEL INTERLOCK — diminta jhony, dua tempat: di sebelah tombol start
   mesin induk di panel lokal, dan di kartu mesin induk di ruang kontrol.

   Bentuknya sengaja STEMPEL, bukan baris tulisan biasa: ia harus terbaca
   sebagai larangan dalam satu sapuan mata, tanpa dibaca kata per kata.
   Bingkai penuh + huruf besar + jarak huruf melebar adalah tanda yang sama
   yang dipakai plakat di kamar mesin sungguhan.

   Warnanya --merah, token yang sama dengan alarm bahaya — dan itu memang
   satu keluarga: keduanya berkata "jangan diteruskan". Tokennya sudah punya
   nilai sendiri di tema terang (#c02f28) dan gelap (#f85149), jadi tidak
   ada warna yang dipatok mati di sini. */
.stempel-interlock {
  display: inline-flex;
  align-items: center;
  border: 2px solid var(--merah);
  color: var(--merah);
  background: color-mix(in srgb, var(--merah) 12%, transparent);
  border-radius: 6px;
  padding: 3px 10px;
  font-size: .78rem;
  font-weight: 800;
  letter-spacing: .08em;
  line-height: 1.25;
  white-space: nowrap;
  cursor: help;
}

/* SIAP — stempel yang sama, warna kebalikannya. Diminta jhony: "apabila
   semua parameter sudah terpenuhi, stempel yang interlock berubah menjadi
   engine ready warna hijau."

   Hijau di sini berarti hal yang sama dengan hijau di tombol start genset
   dan tombol pompa LO: pekerjaan yang sudah selesai. Kosakata warnanya
   dijaga tetap satu di seluruh aplikasi — merah melarang, aksen menunggu
   dikerjakan, hijau sudah beres. Kalau tiap layar memakai warnanya
   sendiri-sendiri, warna berhenti jadi keterangan dan tinggal jadi hiasan. */
.stempel-interlock.is-siap {
  border-color: var(--hijau);
  color: var(--hijau);
  background: color-mix(in srgb, var(--hijau) 12%, transparent);
}

/* DIAM — bukan merah, bukan hijau, bukan aksen.
 *
 * Kosakata warna stempel ini punya tiga kata: merah MELARANG, aksen SEDANG
 * DIKERJAKAN, hijau SUDAH BERES. Tidak ada satu pun yang benar untuk mesin
 * yang sekadar sedang tidak berputar — dan merah, yang jadi bawaannya,
 * justru yang paling salah: ia berkata "ada yang tidak boleh" untuk pompa
 * yang memang sengaja dimatikan orangnya. Dilaporkan jhony waktu pompa
 * vakum yang mati dan yang siaga sama-sama berbunyi merah. */
.stempel-interlock.is-diam {
  border-color: var(--garis-kuat);
  color: var(--teks-redup);
  background: transparent;
}

/* SEDANG DISTART — bukan merah dan bukan hijau, sebab ia bukan larangan
   dan bukan pula keadaan yang sudah tercapai. Warnanya aksen: pekerjaan
   yang sedang berjalan. Tahapnya cuma beberapa detik, tapi kalau ia
   dihijaukan, aplikasi ini berkata "running" untuk poros yang belum
   sekali pun membakar bahan bakar — persis salah paham yang justru
   sedang diluruskan halaman mesin induk. */
.stempel-interlock.is-mulai {
  border-color: var(--aksen);
  color: var(--aksen);
  background: color-mix(in srgb, var(--aksen) 14%, transparent);
}

/* Di sebelah nama genset pada panel sinkron: stempel yang sama, sedikit
   lebih kecil, sebab ia berdiri BERTIGA berjajar dan yang dibaca orang di
   sana bukan satu kalimat melainkan satu kolom keadaan.

   `.stempel-alat` ukuran yang sama untuk peralatan yang berdiri sendiri —
   stempel di label tombol start OWS. Satu aturan, bukan salinan: kalau
   ukurannya kelak digeser, kedua tempat ikut bergeser bersama, dan
   kosakata warnanya (merah melarang, aksen sedang dikerjakan, hijau sudah
   beres) tetap satu di seluruh aplikasi. */
.stempel-genset,
.stempel-alat {
  margin-left: 8px;
  padding: 2px 8px;
  font-size: .7rem;
  vertical-align: middle;
}

/* Di kartu ruang kontrol ia berdiri sendiri di atas angka-angkanya, bukan
   menempel di samping tombol seperti versi lokalnya. */
.stempel-kartu {
  display: flex;
  justify-content: center;
  margin: 0 0 8px;
  white-space: normal;
  text-align: center;
}

/* DISOROT — kartu yang baru saja didatangi tombol papan alarm. Dua detik,
   lalu hilang sendiri: sorotan yang menetap jadi hiasan, dan yang dicari
   orang bukan kartu yang selalu bersinar melainkan kartu yang BARU SAJA
   ditunjuk. */
.disorot {
  animation: sorot-kartu 2.2s ease-out 1;
  border-radius: var(--sudut);
}
@keyframes sorot-kartu {
  0%   { box-shadow: 0 0 0 3px var(--aksen); }
  70%  { box-shadow: 0 0 0 3px var(--aksen); }
  100% { box-shadow: 0 0 0 3px transparent; }
}
@media (prefers-reduced-motion: reduce) {
  .disorot { animation: none; box-shadow: 0 0 0 3px var(--aksen); }
}

.tombol.is-sudah {
  border-color: var(--hijau);
  color: var(--hijau);
  font-weight: 700;
}

/* ============================================================ VOLUME
   Kenop keras-lirih satu aplikasi. Bentuknya sengaja sekeluarga dengan
   tombol tema dan papan alarm — ketiganya penghuni tetap topbar, dan
   tombol yang berbeda-beda bentuk di satu bilah terbaca sebagai tiga
   aplikasi yang ditempel jadi satu. */
.volume-tombol {
  display: inline-flex; align-items: center; gap: 6px;
  width: auto; padding: 0 9px;
}
.volume-tombol .volume-angka {
  font-size: .78rem; font-variant-numeric: tabular-nums; color: var(--teks-redup);
  display: none;
}
/* Angkanya cuma muncul kalau ada tempatnya. Di HP ikonnya sendiri sudah
   menerangkan, dan angka yang mendesak merek keluar layar lebih merugikan
   daripada angka yang tidak terlihat. */
@media (min-width: 640px) { .volume-tombol .volume-angka { display: inline; } }
.volume-tombol.is-bisu { color: var(--kuning); border-color: currentColor; }
.volume-tombol .volume-silang { display: none; }
.volume-tombol.is-bisu .volume-silang { display: inline; }
.volume-tombol.is-bisu .volume-gelombang { display: none; }

.volume-panel {
  position: fixed;
  top: 58px; right: 12px; z-index: 41;
  width: min(300px, calc(100vw - 24px));
  background: var(--latar-2);
  border: 1px solid var(--garis-kuat);
  border-radius: 10px;
  padding: 12px 14px;
  box-shadow: 0 12px 34px rgba(0, 0, 0, .34);
}
.volume-baris {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 8px; margin-bottom: 6px; font-size: .9rem;
}
.volume-nilai { font-variant-numeric: tabular-nums; color: var(--aksen); font-weight: 620; }
.volume-geser { width: 100%; margin: 0 0 10px; accent-color: var(--aksen); }
.volume-tombol-baris { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 8px; }

/* TOMBOL TERIMA di panel alarm. Disorot karena ia tindakan POKOK di panel
   itu — yang pertama dilakukan orang begitu alarm berbunyi — sementara
   tombol di sebelahnya cuma setelan bunyi. Dua tombol sekelabu berjajar
   memaksa mata membaca keduanya dulu, dan alarm bukan saat yang tepat
   untuk membaca. */
.alarm-terima { position: relative; }
/* Menyala hanya selama ada yang BELUM diterima. Sorotan yang menyala terus
   berhenti dibaca mata dalam beberapa hari — dan tombol yang berhenti
   dibaca sama saja dengan tombol yang sulit ditemukan. */
.alarm-terima.is-perlu {
  box-shadow: 0 0 0 3px var(--aksen-lembut);
  animation: terima-denyut 1.6s ease-in-out infinite;
}
@keyframes terima-denyut {
  0%, 100% { box-shadow: 0 0 0 3px var(--aksen-lembut); }
  50%      { box-shadow: 0 0 0 6px var(--aksen-lembut); }
}
/* Gerak dimatikan untuk yang memintanya — sorotannya tetap ada, cuma diam.
   Yang perlu ditemukan tetap ditemukan tanpa harus berkedip. */
@media (prefers-reduced-motion: reduce) {
  .alarm-terima.is-perlu { animation: none; }
}
.alarm-terima:disabled { animation: none; box-shadow: none; }

/* Uji minat di bawah daftar "Yang belum ada di sini". Diberi jarak dan garis
   pemisah supaya terbaca sebagai ajakan, bukan sebagai butir kelima daftar. */
.minta-usul {
  margin-top: 16px;
  padding-top: 14px;
  border-top: 1px solid var(--garis);
}

/* --------------------------------------------------- BANNER VERSI BARU
   Muncul hanya kalau service worker baru sudah terpasang dan menunggu.
   Ditaruh di BAWAH, bukan atas: bilah alat di kepala halaman sudah padat, dan
   pemberitahuan yang menutupi menu membuat orang menutupnya tanpa membaca.
   Menghormati safe-area supaya tidak tertimpa bilah gestur iPhone. */
.banner-pembaruan {
  position: fixed;
  left: 12px; right: 12px;
  bottom: calc(12px + env(safe-area-inset-bottom, 0px));
  z-index: 60;
  display: flex; align-items: center; gap: 12px;
  padding: 10px 12px;
  background: var(--latar-2);
  border: 1px solid var(--aksen);
  border-radius: 10px;
  box-shadow: 0 6px 24px rgba(0, 0, 0, .45);
}

.banner-pembaruan > span { flex: 1 1 auto; }

.banner-pembaruan__tutup {
  flex: 0 0 auto;
  width: 32px; height: 32px;
  background: none; border: 0; border-radius: 8px;
  color: var(--teks-redup); font: inherit; font-size: 1.25rem; line-height: 1;
  cursor: pointer;
}
.banner-pembaruan__tutup:hover { color: var(--teks); background: var(--latar-3); }

@media (min-width: 640px) {
  .banner-pembaruan { left: auto; right: 16px; max-width: 380px; }
}

/* ------------------------------------------------- PAPAN DUA FO PURIFIER
   Kedua unit selalu terlihat keadaannya; penampang bowl dan mekanisme di
   bawahnya melayani unit yang sedang dipilih. Pola yang sama dengan papan
   genset — di layar lebar berdampingan, di HP bertumpuk, dan bertumpuk itu
   urutan baca yang benar: satu unit selesai dibaca sebelum pindah. */
.papan-purifier {
  display: grid;
  gap: 12px;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  margin-bottom: 14px;
}

.kartu-purifier { display: flex; flex-direction: column; gap: 10px; }

/* Unit yang sedang dibuka diberi garis aksen, bukan latar berbeda: yang
   perlu terbaca sekilas adalah MANA yang jalan, dan itu tugas warna tanda. */
.kartu-purifier.is-dipilih { border-color: var(--aksen); }

.kartu-purifier__kepala {
  display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
}
.kartu-purifier__kepala h3 { margin: 0; font-size: 1rem; }

.kartu-purifier__tanda {
  font-size: .82rem; font-weight: 620; letter-spacing: .3px;
  color: var(--teks-redup);
}
.kartu-purifier.is-jalan .kartu-purifier__tanda { color: var(--hijau); }

.kartu-purifier__nilai { display: flex; gap: 18px; margin: 0; }
.kartu-purifier__nilai div { display: flex; flex-direction: column; gap: 2px; }
.kartu-purifier__nilai dt { font-size: .78rem; color: var(--teks-redup); }
.kartu-purifier__nilai dd { margin: 0; font-variant-numeric: tabular-nums; }

.kartu-purifier__aksi { display: flex; gap: 8px; margin-top: auto; }

/* Pengatur umpan milik tiap unit purifier. Diberi lebar penuh di dalam kartu:
   di HP, penggeser yang berbagi baris dengan label jadi terlalu pendek untuk
   dibidik jari dengan teliti, padahal selisih 200 L/jam di sini mengubah
   efisiensi pemisahan beberapa persen. */
.kartu-purifier__umpan { display: flex; flex-direction: column; gap: 4px; }
.kartu-purifier__umpan label { font-size: .78rem; color: var(--teks-redup); }
.kartu-purifier__umpan input { width: 100%; }
.kartu-purifier__umpan output { font-variant-numeric: tabular-nums; font-size: .9rem; }

/* Judul yang menyebut purifier mana yang sedang dirinci. Diberi garis aksen di
   kiri, bukan sekadar teks tebal: ia harus terbaca sebagai BATAS -- semua yang
   di bawahnya milik unit yang disebut, bukan gabungan keduanya. */
.judul-rinci-purifier {
  margin: 0 0 10px;
  padding-left: 10px;
  border-left: 3px solid var(--aksen);
  font-size: 1rem;
}

/* Purifier tampak luar di kartu tiap unit. Tingginya dipatok supaya dua kartu
   berdampingan tetap sejajar walau tulisan tanda di kepalanya berbeda panjang;
   tanpa itu kartu yang berbunyi "MENGISI WATER SEAL" mendorong gambarnya turun
   dan keduanya berhenti bisa dibandingkan sekilas. */
.kartu-purifier__gambar {
  display: block;
  width: 100%;
  height: 150px;
  overflow: visible;
}
/* M/E LO Purifier digambar lebih kecil. Gambarnya SAMA — viewBox yang sama,
   kode yang sama — cuma tingginya yang dipangkas, jadi tidak ada salinan
   kedua yang bisa menyimpang diam-diam. Diminta jhony: "bikin animasinya
   menyerupai fo Purifier tapi lebih kecil". */
.kartu-purifier__gambar--kecil { height: 108px; }

/* Genset darurat tampak luar. Tingginya dipatok seperti gambar utuh
   purifier, dan alasannya sama: kartunya berdiri di samping panel angka
   yang tingginya ikut jumlah barisnya, jadi gambar yang tingginya ikut
   lebar layar akan membuat kedua kartu itu melompat-lompat waktu jendela
   diubah ukurannya. */
.kartu-darurat__gambar {
  display: block;
  width: 100%;
  height: 248px;
  overflow: visible;
}

/* PENTING: input[type=range] di aplikasi ini bertuliskan `flex: 1 1 130px`, dan
   di dalam wadah KOLOM basis itu berlaku sebagai TINGGI, bukan lebar. Akibatnya
   tiap penggeser di kartu memakan 130 px dan satu kartu membengkak jadi 695 px
   -- hampir seluruh layar HP untuk satu unit, padahal gunanya justru melihat
   keduanya sekaligus. Diukur, bukan ditebak. */
.kartu-purifier__umpan input[type="range"] { flex: 0 0 auto; height: auto; }

.kartu-purifier__gambar { height: 175px; }
  .kartu-purifier__gambar--kecil { height: 126px; }

/* Nomor unit purifier di judul kartu. Dua kartu yang isinya nyaris kembar
   dibedakan paling cepat oleh angkanya -- jadi angkanya yang diberi warna,
   bukan seluruh judulnya. */
.kartu-purifier__no {
  color: var(--aksen);
  font-size: 1.15em;
  font-weight: 700;
}

/* Sasaran sentuh tombol di kartu purifier dinaikkan ke 44 px -- ambang yang
   nyaman untuk jari. Terukur 34 px sebelumnya, dan "tidak bisa dipilih"
   dilaporkan dua kali padahal mekanismenya sehat. */
.kartu-purifier__aksi .tombol { min-height: 44px; }

/* Seluruh kartu bisa diketuk untuk membukanya, jadi ia harus terasa bisa
   diketuk. Yang sedang terbuka tidak: ia sudah jadi tujuan. */
.kartu-purifier { cursor: pointer; }
.kartu-purifier.is-dipilih { cursor: default; }

/* Judul rincian: kata "Rincian" redup, NAMA UNIT-nya yang menonjol. Yang perlu
   terbaca sekilas adalah sedang melihat yang mana, bukan kata yang selalu sama. */
.judul-rinci-purifier { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.judul-rinci-purifier__label {
  font-size: .78rem; font-weight: 400; letter-spacing: .4px;
  text-transform: uppercase; color: var(--teks-redup);
}
.judul-rinci-purifier__unit { color: var(--teks); font-weight: 700; }

/* ------------------------------------------------- Mode Dinas Jaga
 * Kotak keadaan latihan di Ruang Kontrol. Ia BUKAN kartu: sengaja tidak
 * memakai .kartu, sebab kartu di halaman ini berarti "satu peralatan" dan
 * kotak ini bukan peralatan. Yang membedakannya cuma pita di tepi kiri —
 * cukup untuk memisahkan tanpa menambah satu benda baru ke tata letaknya.
 */
.dinas-kotak {
  background: var(--latar-2);
  border: 1px solid var(--garis);
  border-left: 4px solid var(--aksen);
  padding: 14px 16px;
  margin-bottom: 16px;
}
/* TIGA KATA, sama dengan kosakata warna stempel di seluruh aplikasi: aksen
   SEDANG DIKERJAKAN, hijau SUDAH BERES, merah TIDAK BOLEH. `--jalan` memang
   sama dengan bawaannya, dan ia ditulis terang-terangan justru karena itu:
   kelas yang dipakai kode tapi tak punya aturan CSS tidak bisa dibedakan
   dari kelas yang salah tulis. */
.dinas-kotak--jalan { border-left-color: var(--aksen); }
.dinas-kotak--baik  { border-left-color: var(--hijau); }
.dinas-kotak--buruk { border-left-color: var(--merah); }

.dinas-kepala { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
.dinas-lencana {
  font-weight: 700; letter-spacing: .08em; font-size: .82rem;
  text-transform: uppercase; color: var(--aksen);
}
.dinas-kotak--jalan .dinas-lencana { color: var(--aksen); }
.dinas-kotak--baik  .dinas-lencana { color: var(--hijau); }
.dinas-kotak--buruk .dinas-lencana { color: var(--merah); }
/* Jam mundur memakai angka selebar sama, kalau tidak lebarnya bergoyang tiap
   detik dan menarik mata ke tempat yang tidak perlu. */
.dinas-jam { font-variant-numeric: tabular-nums; font-weight: 700; font-size: 1.15rem; }

.dinas-sebab { margin: 8px 0 0; }
.dinas-judul { font-size: .95rem; margin: 18px 0 6px; }
.dinas-jawab { margin: 0 0 6px; }
.dinas-sebab-panjang { color: var(--teks-redup); }

.dinas-angka { display: flex; flex-wrap: wrap; gap: 10px; margin: 14px 0 4px; }
.dinas-angka-sel {
  flex: 1 1 150px; background: var(--latar-3); border: 1px solid var(--garis);
  padding: 8px 11px; display: flex; flex-direction: column; gap: 2px;
}
.dinas-angka-nama { font-size: .76rem; letter-spacing: .05em; text-transform: uppercase; color: var(--teks-redup); }
.dinas-angka-nilai { font-weight: 700; font-variant-numeric: tabular-nums; }

.dinas-langkah { margin: 0 0 4px; padding-left: 20px; }
.dinas-langkah li { margin-bottom: 4px; }

.dinas-garis { list-style: none; margin: 0; padding: 0; }
.dinas-garis li {
  display: flex; gap: 12px; padding: 5px 0 5px 10px;
  border-left: 3px solid var(--garis);
}
.dinas-garis-jam {
  font-variant-numeric: tabular-nums; color: var(--teks-redup);
  flex: 0 0 46px; font-size: .88rem;
}
/* Warnanya SAMA dengan papan alarm yang sudah ada: awas kuning, bahaya merah,
   pulih hijau. Garis waktu yang memakai kosakata warna sendiri akan memaksa
   orang menerjemahkan dua kali. */
.dinas-p--awas   { border-left-color: var(--kuning); }
.dinas-p--bahaya { border-left-color: var(--merah); }
.dinas-p--baik   { border-left-color: var(--hijau); }
.dinas-p--temu   { border-left-color: var(--aksen); }

.dinas-kaki { margin-top: 14px; }

/* Daftar jawaban Mode Dinas Jaga. Dibungkus sendiri, bukan diletakkan begitu
   saja, supaya tombolnya membungkus rapi di lebar HP dan tiap tombol tetap
   cukup besar untuk jempol. */
.dinas-pilihan { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
.dinas-pilihan .dinas-jawab { min-height: 44px; text-align: left; }

/* Misi dan perintah anjungan. Perintah anjungan sengaja paling menonjol di
   dalam kotak: di kapal ia BERDERING, dan yang jaga menjawabnya dalam hitungan
   detik. Kotak yang setara dengan barisan angka di sekitarnya akan membuatnya
   terlewat — dan telegraf yang terlewat itulah yang dicatat di buku jaga. */
.dinas-misi { margin: 8px 0 0; }
.dinas-anjungan {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px 12px;
  margin: 12px 0 6px; padding: 10px 12px;
  border: 2px solid var(--aksen); background: var(--aksen-lembut);
}
.dinas-anjungan.is-telat { border-color: var(--merah); }
.dinas-anjungan-kop {
  font-size: .72rem; font-weight: 700; letter-spacing: .12em;
  text-transform: uppercase; color: var(--teks-redup);
}
.dinas-anjungan-kata { font-weight: 700; font-size: 1.15rem; letter-spacing: .02em; }
.dinas-anjungan-detik {
  margin-left: auto; font-variant-numeric: tabular-nums; color: var(--teks-redup);
  font-size: .86rem;
}
.dinas-anjungan.is-telat .dinas-anjungan-detik { color: var(--merah); font-weight: 700; }

/* ------------------------------------------------- Bilah misi
 * Tampil di setiap halaman selama misi berjalan. MELEKAT di bawah kepala
 * halaman: yang sedang membaca panel di tengah halaman tetap melihatnya.
 *
 * `top` mengikuti tinggi kepala satu baris (49 px), sama dengan .sub-nav —
 * dan di layar sempit kepalanya DUA baris, jadi di situ ia ikut tidak
 * melekat, persis seperti .sub-nav. Dua ambang yang harus bergerak bersama.
 */
.misi-bilah {
  position: sticky; top: var(--tinggi-kepala); z-index: 28;
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 16px;
  padding: 7px 14px;
  background: var(--latar-2);
  border-bottom: 1px solid var(--garis);
  border-left: 4px solid var(--aksen);
  font-size: .88rem;
}
@media (max-width: 920px) { .misi-bilah { position: static; } }

/* BILAH TENAGA KAPAL — "kapal ini sedang bertenaga apa".
   Bentuknya sengaja kembar dengan bilah misi di atasnya (melekat di bawah
   kepala halaman, tepi kiri berwarna) supaya keduanya terbaca sebagai satu
   golongan: keterangan keadaan, bukan kendali. Warnanya kuning — ini bukan
   alarm (tidak ada yang rusak) melainkan keadaan yang tidak boleh dikira
   normal. Waktu keduanya muncul bersamaan, yang ini duduk di bawahnya,
   dan pada layar sempit keduanya berhenti melekat supaya tidak memakan
   separuh layar. */
.bilah-tenaga {
  position: sticky; top: var(--tinggi-kepala); z-index: 27;
  padding: 7px 14px;
  background: var(--latar-2);
  border-bottom: 1px solid var(--garis);
  border-left: 4px solid var(--kuning);
  font-size: .88rem; color: var(--teks);
}
@media (max-width: 920px) { .bilah-tenaga { position: static; } }
.bilah-tenaga b { color: var(--kuning); }
.bilah-tenaga .bilah-tenaga__sebab { color: var(--teks-redup); }
.misi-bilah b { font-variant-numeric: tabular-nums; }
.misi-bilah .misi-cap {
  font-size: .72rem; font-weight: 700; letter-spacing: .1em;
  text-transform: uppercase; color: var(--teks-redup);
}
/* Perintah anjungan mengambil alih seluruh bilahnya — kalau ia cuma satu
   butir di antara angka lain, ia akan terlewat persis waktu ia paling
   penting. */
.misi-bilah.is-anjungan { border-left-color: var(--merah); background: var(--aksen-lembut); }
.misi-bilah.is-anjungan .misi-perintah { font-weight: 700; font-size: 1.02rem; }
.misi-bilah.is-sandar { border-left-color: var(--hijau); }
/* TERLAMBAT MENJAWAB TELEGRAF. Dibedakan dari `is-anjungan` biasa, sebab
   keduanya sama-sama merah di tepi kiri dan orang yang sedang menelusuri
   gangguan tidak akan menyadari bedanya. Yang berubah di sini KETERANGANNYA,
   bagian yang memuat hitungan mundur sampai misi gagal. */
.misi-bilah.is-telat { border-left-color: var(--merah); }
.misi-bilah.is-telat .misi-cap { color: var(--merah); }
.misi-bilah.is-telat .misi-perintah { color: var(--merah); }

/* ---------------------------------------------------- MASA COBA & KUNCI */
/* Lencana masa coba di kepala halaman. Sengaja TENANG selama masih
   longgar dan baru memerah di hari terakhir: lencana yang mendesak sejak
   hari pertama berhenti dibaca pada hari kedua. */
/* BARISNYA SENDIRI, bukan sebaris dengan tombol kepala.
 *
 * Diukur, bukan dikira: dengan lencana ini sebaris, tombol tema turun ke
 * baris kedua di 320, 390, 521, DAN 921 px — dan itu terjadi bahkan waktu
 * tulisannya dipendekkan jadi "3 hari" (55 px). Kepala halaman ini memang
 * sudah tidak punya sisa ruang: merek, dua baris navigasi, tombol alarm,
 * pasang, layar, volume, dan tema. Apa pun yang ditambahkan mendorong
 * sesuatu turun.
 *
 * Jadi ia mengikuti pola `.pasang-catatan` yang sudah ada di kepala yang
 * sama: satu baris penuh untuk dirinya sendiri, di bawah tombol-tombolnya.
 * Yang hilang cuma kepadatan; yang dijaga tombol yang tetap bisa dijangkau
 * di layar 320 px. */
.lencana-coba {
  order: 8;
  flex: 1 1 100%;
  align-self: stretch;
  padding: 5px 11px; border-radius: 8px;
  font-size: .78rem; font-weight: 700; letter-spacing: .02em;
  border: 1px solid var(--garis-kuat); color: var(--teks-redup);
  background: var(--latar-2);
}
/* DI MEJA IA KEMBALI SEBARIS. Alasan baris sendiri di atas lahir waktu
   kepala masih memuat deretan tujuh belas peralatan; sejak daftar itu
   pindah ke sisi kiri (>= 1100 px), kepala berisi merek dan tombol saja,
   dan satu baris penuh untuk empat kata cuma memakan tinggi layar. */
@media (min-width: 1100px) {
  .lencana-coba { order: 0; flex: 0 0 auto; align-self: center; }
  /* Merek di kiri, SEMUA sisanya satu kelompok di kanan. Tanpa ini papan
     alarm (margin-left: auto) membagi ruang kosong dengan merek, dan
     lencana + tombol Pasang terdampar di tengah kepala. */
  .alarm-tanda { margin-left: 0; }
}
.lencana-coba.is-tipis {
  border-color: var(--aksen); color: var(--aksen);
  background: color-mix(in srgb, var(--aksen) 12%, transparent);
}

/* Layar kunci. `position: fixed` dengan inset 0 — bukan overlay yang
   digulir bersama halaman: yang terakhir bisa dilewati begitu saja dengan
   menggulir, dan itu bukan kunci. */
.layar-kunci {
  position: fixed; inset: 0; z-index: 90;
  /* KABUR, bukan cuma redup. Pada 94% tembus pandang, kepala halaman yang
     punya latar pekatnya sendiri tetap terbaca TAJAM di belakangnya —
     tombol alarm, gigi, dan tema terlihat hidup padahal seluruhnya sudah
     tidak bisa ditekan (elementFromPoint di situ mengembalikan layar kunci,
     bukan tombolnya). Tombol yang tampak hidup padahal mati lebih buruk
     daripada tombol yang jelas mati: orang menekannya berkali-kali lalu
     menyangka aplikasinya rusak, bukan terkunci.

     Kapalnya sengaja masih SAMAR terlihat di belakang, tidak dihapus sama
     sekali — ia masih ada, dan memang masih berjalan; yang hilang cuma
     jalan masuknya. */
  background: color-mix(in srgb, var(--latar-1) 82%, transparent);
  -webkit-backdrop-filter: blur(7px);
  backdrop-filter: blur(7px);
  overflow-y: auto; padding: 20px 14px 40px;
  display: flex; align-items: flex-start; justify-content: center;
}
/* Badan halaman TIDAK ikut digulir di belakangnya. Tanpa ini, menggulir di
   dalam kotak kunci sampai ujung akan meneruskan gulirannya ke aplikasi di
   belakang — yang terlihat seperti kunci yang bocor. */
body.is-terkunci { overflow: hidden; }

.kunci-kotak {
  width: 100%; max-width: 27rem; margin-top: 4vh;
  background: var(--latar-2); border: 1px solid var(--garis-kuat);
  border-radius: 12px; padding: 22px 20px;
}
.kunci-kotak h2 { margin: 0 0 12px; font-size: 1.25rem; }
.kunci-utama { margin: 0 0 16px; color: var(--teks-redup); }
.kunci-harga { margin: 0 0 4px; font-size: 1.05rem; }
.kunci-harga b { color: var(--aksen); font-size: 1.35rem; }
.kunci-catatan { margin: 0 0 14px; font-size: .87rem; color: var(--teks-redup); }
.kunci-opsional { font-weight: 400; text-transform: none; letter-spacing: 0; }

.kunci-borang { display: flex; flex-direction: column; gap: 6px; }
.kunci-borang label {
  font-size: .78rem; color: var(--teks-redup);
  text-transform: uppercase; letter-spacing: .04em;
}
.kunci-borang input {
  padding: 9px 11px; font: inherit; width: 100%;
  background: var(--latar-1); color: var(--teks);
  border: 1px solid var(--garis-kuat); border-radius: 7px;
}
.kunci-borang input:focus-visible { outline: 2px solid var(--aksen); outline-offset: 1px; }
.kunci-borang button { margin-top: 8px; }

.kunci-garis { border: 0; border-top: 1px solid var(--garis); margin: 20px 0 14px; }
.kunci-punya summary { cursor: pointer; font-weight: 640; padding: 4px 0; }
.kunci-punya summary:focus-visible { outline: 2px solid var(--aksen); outline-offset: 2px; }
.kunci-punya .kunci-borang { margin-top: 10px; }
#kunciMasuk { font-variant-numeric: tabular-nums; letter-spacing: .08em; }

/* Tombol Google menggambar dirinya sendiri di dalam sini. Tingginya
   ditetapkan supaya kotaknya tidak melompat waktu tombol itu akhirnya
   muncul — dan di layar tanpa sinyal, ruang kosong ini yang menjelaskan
   bahwa ada sesuatu yang gagal dimuat, bukan halaman yang setengah jadi. */
.daftar-google { display: flex; justify-content: center; min-height: 44px; margin: 4px 0 2px; }
#daftarKelonggaran { margin-top: 10px; width: 100%; }

.kunci-pesan { margin: 14px 0 0; font-size: .88rem; color: var(--teks-redup); min-height: 1.2em; }
.kunci-pesan.is-buruk { color: var(--merah); }
.kunci-nilai {
  font-size: 1.5rem; font-weight: 800; letter-spacing: .12em;
  color: var(--aksen); font-variant-numeric: tabular-nums;
  margin: 4px 0 12px;
}
.kunci-baca { margin: 2px 0 0; font-size: .8rem; color: var(--teks-redup);
  font-variant-numeric: tabular-nums; min-height: 1.1em; }
.kabar-lisensi {
  position: fixed; left: 50%; transform: translateX(-50%); bottom: 18px; z-index: 95;
  max-width: min(30rem, calc(100vw - 28px)); margin: 0;
  padding: 11px 16px; border-radius: 10px;
  background: var(--latar-3); color: var(--teks);
  border: 1px solid var(--hijau);
  box-shadow: 0 6px 20px rgba(0, 0, 0, .45);
  font-size: .9rem;
}

