/* ==========================================================================
   Sistem Monitoring Keuangan Pribadi — gaya tampilan
   --------------------------------------------------------------------------
   Ditulis tangan tanpa kerangka kerja CSS. Aplikasi ini diunggah manual ke
   shared hosting tanpa langkah build, sehingga berkas tunggal yang dapat
   dibaca dan disunting langsung lebih berguna daripada keluaran kompilasi.

   Warna disusun sebagai variabel agar tema gelap hanya perlu mengganti nilai,
   bukan menulis ulang aturan.
   ========================================================================== */

:root {
  /*
   | color-scheme memberi tahu peramban tema mana yang sedang berlaku, dan itu
   | menentukan warna kontrol bawaannya sendiri: ikon kalender pada input
   | tanggal, panah putar pada input angka, batang gulir, dan latar daftar
   | pilihan. Tanpa baris ini, ikon kalender tetap digambar hitam di atas latar
   | gelap dan praktis tidak terlihat — dan itu bukan sesuatu yang dapat
   | diperbaiki dengan aturan warna biasa, karena bagian itu digambar peramban,
   | bukan oleh CSS halaman.
   */
  color-scheme: light;

  --latar: #f6f7f9;
  --permukaan: #ffffff;
  --permukaan-2: #f1f3f6;
  --garis: #e3e7ec;
  --garis-tegas: #cbd3dd;
  --teks: #14181f;
  --teks-lembut: #5b6675;
  --teks-samar: #8b96a5;

  --aksen: #6d4fe0;
  --aksen-lembut: #efeafe;
  --aksen-gelap: #5a3fc4;

  --hijau: #059669;
  --hijau-lembut: #e6f6f0;
  --merah: #dc2626;
  --merah-lembut: #fdecec;
  --kuning: #d97706;
  --kuning-lembut: #fdf3e4;

  --radius: 10px;
  --radius-kecil: 6px;
  --bayang: 0 1px 2px rgba(16, 24, 40, .05), 0 1px 3px rgba(16, 24, 40, .06);
  --bayang-tinggi: 0 4px 12px rgba(16, 24, 40, .10);
  --lebar-maks: 1240px;
}

[data-tema="gelap"] {
  color-scheme: dark;

  --latar: #0e1116;
  --permukaan: #161b22;
  --permukaan-2: #1c222b;
  --garis: #262d38;
  --garis-tegas: #39414e;
  --teks: #e6eaf0;
  --teks-lembut: #9aa6b5;
  --teks-samar: #6b7686;

  --aksen: #8b74f0;
  --aksen-lembut: #221d3c;
  --aksen-gelap: #a692f4;

  --hijau: #2fb98d;
  --hijau-lembut: #10251f;
  --merah: #f87171;
  --merah-lembut: #2a1618;
  --kuning: #eab308;
  --kuning-lembut: #291f0d;

  --bayang: 0 1px 2px rgba(0, 0, 0, .4);
  --bayang-tinggi: 0 6px 18px rgba(0, 0, 0, .5);
}

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--latar);
  color: var(--teks);
  font-family: "Inter", "Segoe UI", -apple-system, BlinkMacSystemFont, Roboto, Helvetica, Arial, sans-serif;
  font-size: 14.5px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

a { color: var(--aksen); text-decoration: none; }
a:hover { text-decoration: underline; }

h1, h2, h3, h4 { margin: 0 0 .5rem; font-weight: 650; line-height: 1.25; letter-spacing: -.01em; }
h1 { font-size: 1.5rem; }
h2 { font-size: 1.15rem; }
h3 { font-size: 1rem; }
p { margin: 0 0 .75rem; }

/* Angka rupiah dibaca sebagai kolom, bukan sebagai kalimat: lebar digit yang
   seragam membuat perbandingan antarbaris dapat dilakukan sekilas. */
.angka, td.angka, th.angka, .nilai-kpi {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}

/* ------------------------------------------------------------------ tata letak */

.pembungkus { max-width: var(--lebar-maks); margin: 0 auto; padding: 0 1.25rem; }

.utama { padding: 1.5rem 0 4rem; }

.baris-judul {
  display: flex; flex-wrap: wrap; gap: 1rem;
  align-items: flex-end; justify-content: space-between;
  margin-bottom: 1.25rem;
}
.baris-judul .keterangan { color: var(--teks-lembut); margin: 0; font-size: .9rem; }

/* -------------------------------------------------------------------- navbar */

.navbar {
  background: var(--permukaan);
  border-bottom: 1px solid var(--garis);
  position: sticky; top: 0; z-index: 50;
}
.navbar-isi { display: flex; align-items: center; gap: 1rem; height: 56px; }

.merek { display: flex; align-items: center; gap: .6rem; font-weight: 680; color: var(--teks); letter-spacing: -.02em; }
.merek:hover { text-decoration: none; }
.merek-ikon {
  width: 28px; height: 28px; border-radius: 8px;
  background: var(--aksen); color: #fff;
  display: grid; place-items: center; font-size: .78rem; font-weight: 700;
}

.menu { display: flex; gap: .15rem; margin-left: .5rem; flex: 1; }
.menu-item { position: relative; }
.menu-tautan {
  display: block; padding: .45rem .7rem; border-radius: var(--radius-kecil);
  color: var(--teks-lembut); font-weight: 550; font-size: .9rem; white-space: nowrap;
}
.menu-tautan:hover { background: var(--permukaan-2); color: var(--teks); text-decoration: none; }
.menu-tautan.aktif { background: var(--aksen-lembut); color: var(--aksen-gelap); }

/*
 | Submenu navbar: jembatan + tenggang tutup.
 |
 | Dahulu submenu berjarak 4px di bawah pemicunya dan disembunyikan dengan
 | display:none. Dua akibatnya, dan keduanya membuat menu menghilang tepat saat
 | hendak diklik:
 |
 |   1. Jarak 4px itu bukan milik siapa-siapa. Kursor yang turun dari pemicu ke
 |      submenu melewatinya, :hover pada keduanya lepas, dan menu menutup di
 |      tengah jalan.
 |   2. display:none menutup seketika. Tangan yang bergerak diagonal — cara
 |      hampir semua orang menuju butir terakhir — sempat keluar sekejap dari
 |      kotak pemicu, dan itu sudah cukup untuk menutupnya.
 |
 | Perbaikannya dua-duanya: ::before mengisi celah sehingga jalur turunnya tetap
 | dianggap "di dalam", dan penyembunyiannya memakai visibility yang dapat
 | ditunda 260 ms. Kembali ke display:none akan menghidupkan lagi keduanya.
 */
.submenu {
  position: absolute; top: calc(100% + 4px); left: 0; min-width: 210px;
  background: var(--permukaan); border: 1px solid var(--garis);
  border-radius: var(--radius); box-shadow: var(--bayang-tinggi);
  padding: .3rem; z-index: 60;

  visibility: hidden; opacity: 0;
  transition: visibility 0s linear .26s, opacity .12s ease .14s;
}

/* Jembatan tak terlihat yang menutupi celah antara pemicu dan submenu. */
.submenu::before {
  content: ''; position: absolute; left: 0; right: 0; top: -8px; height: 8px;
}

.menu-item:hover .submenu, .menu-item:focus-within .submenu {
  visibility: visible; opacity: 1;
  transition: visibility 0s, opacity .12s ease;
}

/* Pemicu tetap bertanda terbuka selama submenunya masih tampil. */
.menu-item:hover > .menu-tautan { background: var(--permukaan-2); color: var(--teks); }
.submenu a { display: block; padding: .45rem .6rem; border-radius: var(--radius-kecil); color: var(--teks-lembut); font-size: .88rem; }
.submenu a:hover { background: var(--permukaan-2); color: var(--teks); text-decoration: none; }

.navbar-kanan { display: flex; align-items: center; gap: .5rem; }

/* ------------------------------------------------------------- menu profil */

.menu-profil { position: relative; }

.pemicu-profil {
  display: grid; place-items: center; padding: 2px; border-radius: 50%;
  background: none; border: 0; cursor: pointer; line-height: 0;
}
.pemicu-profil:hover .avatar, .pemicu-profil.aktif .avatar { border-color: var(--aksen); }
.pemicu-profil:focus-visible { outline: 2px solid var(--aksen); outline-offset: 2px; }

/* Menu profil dibuka lewat klik; :hover sengaja tidak dipakai supaya
   perilakunya sama di layar sentuh. */
.menu-profil .submenu-profil {
  left: auto; right: 0; min-width: 232px;
  max-width: calc(100vw - 1.8rem);

  /* Tanpa tenggang tutup. Tenggang itu ada untuk menolong kursor yang sedang
     menyeberang ke submenu hover; panel ini dibuka dan ditutup dengan klik,
     dan orang yang mengklik di luar atau menekan Escape ingin panelnya hilang
     saat itu juga — bukan seperempat detik kemudian. */
  transition: visibility 0s, opacity .1s ease;
}
.menu-profil.terbuka .submenu-profil {
  visibility: visible; opacity: 1;
  transition: visibility 0s, opacity .12s ease;
}

.kepala-profil {
  display: flex; flex-direction: column; gap: .1rem;
  padding: .5rem .6rem .55rem; margin-bottom: .25rem;
  border-bottom: 1px solid var(--garis);
}
.kepala-profil strong { font-size: .9rem; }
.kepala-profil span { word-break: break-all; }

.submenu a.aktif { background: var(--aksen-lembut); color: var(--aksen-gelap); }

.keluar-profil {
  display: block; width: 100%; text-align: left; margin-top: .25rem;
  padding: .45rem .6rem; border-radius: var(--radius-kecil);
  border: 0; border-top: 1px solid var(--garis); border-top-left-radius: 0; border-top-right-radius: 0;
  background: none; color: var(--merah); font: inherit; font-size: .88rem; cursor: pointer;
}
.keluar-profil:hover { background: var(--merah-lembut); }

.avatar {
  width: 30px; height: 30px; border-radius: 50%;
  background: var(--permukaan-2); color: var(--teks-lembut);
  display: grid; place-items: center; font-size: .75rem; font-weight: 650;
  border: 1px solid var(--garis);
}

.navbar .tombol-menu-mobile { display: none; }
.navbar .tombol-menu-mobile svg { width: 20px; height: 20px; }

/* ---------------------------------------------------------------- pemilih periode */

.pemilih-periode { display: flex; align-items: center; gap: .3rem; }
.pemilih-periode .label-periode {
  font-weight: 600; font-size: .88rem; min-width: 118px; text-align: center;
  padding: .3rem .5rem; border-radius: var(--radius-kecil); background: var(--permukaan-2);
}

/* -------------------------------------------------------------------- kartu */

.kartu {
  background: var(--permukaan);
  border: 1px solid var(--garis);
  border-radius: var(--radius);
  box-shadow: var(--bayang);
  margin-bottom: 1.1rem;
  overflow: hidden;
}
.kartu-kepala {
  padding: .85rem 1.1rem; border-bottom: 1px solid var(--garis);
  display: flex; align-items: center; justify-content: space-between; gap: .75rem; flex-wrap: wrap;
}
.kartu-kepala h2, .kartu-kepala h3 { margin: 0; }
.kartu-kepala .sub { color: var(--teks-lembut); font-size: .85rem; margin: 0; }
.kartu-isi { padding: 1.1rem; }
.kartu-isi.rapat { padding: 0; }

/* ---------------------------------------------------------------------- KPI */

.kisi-kpi {
  display: grid; gap: 1rem; margin-bottom: 1.1rem;
  /*
   | minmax lebih kecil daripada sebelumnya (215px) supaya enam kartu KPI muat
   | dalam satu baris di layar lebar. Dengan 215px, kartu keenam terlempar
   | sendirian ke baris kedua dan barisan itu tampak timpang.
   */
  grid-template-columns: repeat(auto-fit, minmax(185px, 1fr));
}
.kpi {
  background: var(--permukaan); border: 1px solid var(--garis);
  border-radius: var(--radius); padding: 1rem 1.1rem; box-shadow: var(--bayang);
  /*
   | Kartu menjadi wadah kueri supaya angkanya dapat mengukur diri terhadap
   | lebar kartu, bukan terhadap lebar layar. Enam kartu KPI dalam satu baris
   | menyisakan sekitar 150px untuk angka, dan "Rp112.300.000" pada 1,6rem
   | membutuhkan 168px — luber tanpa satu pun penggeser, jadi digitnya
   | terpotong diam-diam. Nominal rupiah tidak punya batas atas yang dapat
   | ditebak; memaku satu ukuran font hanya menunda kejadian yang sama.
   */
  container-type: inline-size;
  /*
   | Nilainya didorong ke bawah supaya seluruh kartu sebaris memuat angkanya
   | pada ketinggian yang sama. Judul kartu bukan teks tetap — salah satunya
   | memuat nama rekening yang dipilih sendiri, dan "Saldo Bank BCA
   | 0860916959" memakai dua baris sementara tetangganya satu. Tanpa ini,
   | angka kartu itu turun sendirian dan barisan yang gunanya justru dibaca
   | sekilas berhenti dapat dibaca sekilas. Memotong judulnya menjadi satu
   | baris juga menyelesaikan perataannya, tetapi dengan membuang nomor
   | rekening yang membedakan satu akun dari akun lain.
   */
  display: flex; flex-direction: column;
}
.kpi .judul-kpi { color: var(--teks-lembut); font-size: .82rem; font-weight: 550; margin-bottom: .35rem; }
.kpi .nilai-kpi {
  margin-top: auto;
  font-size: clamp(1.15rem, 13cqi, 1.6rem);
  font-weight: 680; letter-spacing: -.02em; line-height: 1.15;
}
.kpi .banding { font-size: .8rem; color: var(--teks-lembut); margin-top: .3rem; display: flex; align-items: center; gap: .3rem; }

.naik { color: var(--hijau); }
.turun { color: var(--merah); }
.netral { color: var(--teks-lembut); }

/* -------------------------------------------------------------------- tabel */

.tabel-bungkus { overflow-x: auto; }

/* Tombol aksi di dalam baris tabel tidak boleh menumpuk ke bawah saat kolom
   menyempit — barisnya jadi setinggi dua kali dan tabel terlihat berantakan.
   Bungkusnya sudah dapat digeser mendatar, jadi biarkan melebar. */
.tabel .baris-inline { flex-wrap: nowrap; }

table.tabel { width: 100%; border-collapse: collapse; font-size: .88rem; }
table.tabel th, table.tabel td { padding: .6rem .8rem; text-align: left; border-bottom: 1px solid var(--garis); vertical-align: middle; }
table.tabel th {
  font-weight: 600; color: var(--teks-lembut); font-size: .78rem;
  text-transform: uppercase; letter-spacing: .04em; white-space: nowrap;
  background: var(--permukaan-2); position: sticky; top: 0;
}
table.tabel td.angka, table.tabel th.angka { text-align: right; white-space: nowrap; }
table.tabel tbody tr:hover { background: var(--permukaan-2); }
table.tabel tfoot td {
  font-weight: 680; background: var(--permukaan-2);
  border-top: 2px solid var(--garis-tegas); border-bottom: none;
}
table.tabel .baris-total td { font-weight: 680; background: var(--permukaan-2); }

.tabel-rapat th, .tabel-rapat td { padding: .45rem .6rem; }

.kosong { padding: 2.25rem 1rem; text-align: center; color: var(--teks-samar); }
.kosong strong { display: block; color: var(--teks-lembut); margin-bottom: .25rem; font-weight: 600; }

/* ------------------------------------------------------------------ formulir */

.kisi-form { display: grid; gap: .85rem; grid-template-columns: repeat(auto-fit, minmax(165px, 1fr)); align-items: start; }

.bidang { display: flex; flex-direction: column; gap: .3rem; }
.bidang label { font-size: .82rem; font-weight: 550; color: var(--teks-lembut); }
.bidang .petunjuk { font-size: .78rem; color: var(--teks-samar); }

/*
 | Label diberi tinggi minimum satu setengah baris dan didorong ke bawah.
 |
 | Tanpa ini, kolom yang punya teks petunjuk di bawahnya menjadi lebih tinggi
 | daripada tetangganya, dan seluruh isinya terangkat sehingga label dan kotak
 | isian pada satu baris tidak lagi sejajar. Menyamakan tinggi label lebih
 | dapat diandalkan daripada meratakan seluruh kolom ke atas atau ke bawah,
 | karena label yang panjangnya sampai dua baris pun tetap berakhir pada garis
 | yang sama.
 */
.kisi-form > .bidang > label:first-child,
.baris-form-sebaris > .bidang > label:first-child {
  min-height: 2.1em; display: flex; align-items: flex-end; flex-wrap: wrap;

  /* Label yang memuat elemen tambahan seperti "(opsional)" kehilangan spasi
     antar-katanya begitu menjadi kotak flex — jarak itu dikembalikan di sini. */
  gap: .25rem;
}

input[type="text"], input[type="email"], input[type="password"], input[type="date"],
input[type="number"], input[type="search"], select, textarea {
  width: 100%; padding: .5rem .65rem;
  border: 1px solid var(--garis-tegas); border-radius: var(--radius-kecil);
  background: var(--permukaan); color: var(--teks);
  font: inherit; font-size: .9rem;
  transition: border-color .12s, box-shadow .12s;
}
input:focus, select:focus, textarea:focus {
  outline: none; border-color: var(--aksen);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--aksen) 18%, transparent);
}
input:disabled, select:disabled, textarea:disabled { background: var(--permukaan-2); color: var(--teks-samar); cursor: not-allowed; }
textarea { resize: vertical; min-height: 90px; font-family: inherit; }

input.angka, td input.angka { text-align: right; font-variant-numeric: tabular-nums; }

.centang { display: flex; align-items: center; gap: .45rem; font-size: .87rem; color: var(--teks-lembut); }
.centang input { width: auto; }

/* ------------------------------------------------------------------- tombol */

.tombol {
  display: inline-flex; align-items: center; justify-content: center; gap: .4rem;
  padding: .5rem .85rem; border-radius: var(--radius-kecil);
  border: 1px solid var(--garis-tegas); background: var(--permukaan); color: var(--teks);
  font: inherit; font-size: .875rem; font-weight: 550; cursor: pointer; white-space: nowrap;
  transition: background .12s, border-color .12s, transform .06s;
}
.tombol:hover { background: var(--permukaan-2); text-decoration: none; }
.tombol:active { transform: translateY(1px); }
.tombol:focus-visible { outline: 2px solid var(--aksen); outline-offset: 2px; }

.tombol-utama { background: var(--aksen); border-color: var(--aksen); color: #fff; }
.tombol-utama:hover { background: var(--aksen-gelap); border-color: var(--aksen-gelap); }

.tombol-bahaya { color: var(--merah); border-color: color-mix(in srgb, var(--merah) 35%, var(--garis-tegas)); }
.tombol-bahaya:hover { background: var(--merah-lembut); }

.tombol-kecil { padding: .3rem .55rem; font-size: .8rem; }
.tombol-ikon { padding: .35rem .45rem; line-height: 1; }

.tombol-grup { display: flex; gap: .5rem; flex-wrap: wrap; align-items: center; }

/* -------------------------------------------------------------------- badge */

.lencana {
  display: inline-flex; align-items: center; gap: .3rem;
  padding: .18rem .5rem; border-radius: 999px;
  font-size: .74rem; font-weight: 600; letter-spacing: .01em; white-space: nowrap;
  background: var(--permukaan-2); color: var(--teks-lembut);
}
.lencana-hijau { background: var(--hijau-lembut); color: var(--hijau); }
.lencana-merah { background: var(--merah-lembut); color: var(--merah); }
.lencana-kuning { background: var(--kuning-lembut); color: var(--kuning); }
.lencana-biru { background: var(--aksen-lembut); color: var(--aksen-gelap); }

/* Titik penanda mendampingi warna, sehingga status tetap terbaca oleh pembaca
   yang kesulitan membedakan warna. */
.titik { width: 7px; height: 7px; border-radius: 50%; background: currentColor; flex: none; }

/* ---------------------------------------------------------------- pemberitahuan */

.pesan {
  padding: .7rem 1rem; border-radius: var(--radius); margin-bottom: 1rem;
  border: 1px solid transparent; font-size: .9rem;
  display: flex; gap: .6rem; align-items: flex-start;
}
.pesan-sukses { background: var(--hijau-lembut); border-color: color-mix(in srgb, var(--hijau) 25%, transparent); color: var(--hijau); }
.pesan-galat { background: var(--merah-lembut); border-color: color-mix(in srgb, var(--merah) 25%, transparent); color: var(--merah); }
.pesan-peringatan { background: var(--kuning-lembut); border-color: color-mix(in srgb, var(--kuning) 25%, transparent); color: var(--kuning); }
.pesan-info { background: var(--aksen-lembut); border-color: color-mix(in srgb, var(--aksen) 22%, transparent); color: var(--aksen-gelap); }

.galat-bidang { color: var(--merah); font-size: .78rem; margin-top: .15rem; }

/* ------------------------------------------------------------------- grafik */

.grafik { display: block; width: 100%; height: auto; }

.kisi-grafik { display: grid; gap: 1.1rem; grid-template-columns: repeat(auto-fit, minmax(430px, 1fr)); }

details.data-grafik { margin-top: .75rem; border-top: 1px solid var(--garis); padding-top: .6rem; }
details.data-grafik summary {
  cursor: pointer; font-size: .82rem; color: var(--teks-lembut); font-weight: 550;
  list-style: none; display: inline-flex; align-items: center; gap: .35rem;
}
details.data-grafik summary::-webkit-details-marker { display: none; }
details.data-grafik summary::before { content: "▸"; transition: transform .15s; display: inline-block; }
details.data-grafik[open] summary::before { transform: rotate(90deg); }
details.data-grafik .tabel-bungkus { margin-top: .6rem; max-height: 280px; overflow-y: auto; }

/* -------------------------------------------------------------------- rasio */

.kisi-rasio { display: grid; gap: .9rem; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); }

.kartu-rasio { border: 1px solid var(--garis); border-radius: var(--radius); padding: .9rem 1rem; background: var(--permukaan); }
.kartu-rasio .atas { display: flex; justify-content: space-between; align-items: flex-start; gap: .5rem; margin-bottom: .35rem; }
.kartu-rasio .nama-rasio { font-size: .85rem; font-weight: 600; color: var(--teks-lembut); }
.kartu-rasio .angka-rasio { font-size: 1.5rem; font-weight: 680; letter-spacing: -.02em; }
.kartu-rasio .arti { font-size: .8rem; color: var(--teks-samar); margin-top: .35rem; line-height: 1.45; }
.kartu-rasio .kaki { display: flex; justify-content: space-between; align-items: flex-end; gap: .75rem; margin-top: .5rem; }
.kartu-rasio .kaki .grafik { width: 120px; flex: none; }
.kartu-rasio .kaki > span:first-child { white-space: nowrap; }

.bar-serapan { height: 8px; border-radius: 999px; background: var(--permukaan-2); overflow: hidden; position: relative; }
.bar-serapan span { display: block; height: 100%; border-radius: 999px; background: var(--aksen); }
.bar-serapan .penanda-waktu { position: absolute; top: -3px; bottom: -3px; width: 2px; background: var(--teks-lembut); border-radius: 2px; }

/* --------------------------------------------------------------- editor markdown */

.editor-markdown { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; }
.editor-markdown textarea { min-height: 320px; font-family: "SFMono-Regular", Consolas, "Liberation Mono", monospace; font-size: .85rem; line-height: 1.6; }
.pratinjau-markdown {
  border: 1px solid var(--garis); border-radius: var(--radius-kecil);
  padding: .85rem 1rem; background: var(--permukaan-2); overflow-y: auto; min-height: 320px; max-height: 520px;
}
.alat-markdown { display: flex; gap: .25rem; flex-wrap: wrap; margin-bottom: .5rem; }

.prosa h1, .prosa h2, .prosa h3 { margin-top: 1.1rem; }
.prosa h1:first-child, .prosa h2:first-child, .prosa h3:first-child { margin-top: 0; }
.prosa ul, .prosa ol { padding-left: 1.35rem; margin: 0 0 .75rem; }
.prosa li { margin-bottom: .2rem; }
.prosa blockquote {
  margin: 0 0 .75rem; padding: .35rem 0 .35rem .9rem;
  border-left: 3px solid var(--garis-tegas); color: var(--teks-lembut);
}
.prosa code {
  background: var(--permukaan-2); padding: .1rem .3rem; border-radius: 4px;
  font-family: "SFMono-Regular", Consolas, monospace; font-size: .85em;
}
.prosa pre { background: var(--permukaan-2); padding: .75rem; border-radius: var(--radius-kecil); overflow-x: auto; }
.prosa table { width: 100%; border-collapse: collapse; font-size: .87rem; margin-bottom: .85rem; }
.prosa th, .prosa td { border: 1px solid var(--garis); padding: .4rem .6rem; }
.prosa th { background: var(--permukaan-2); }

/* ------------------------------------------------------------------ halaman masuk */

.halaman-masuk {
  min-height: 100vh; display: grid; place-items: center; padding: 1.5rem;
  background-color: var(--latar); background-size: cover; background-position: center;
}

/*
 | Latar bawaan dipakai selama pengguna belum mengunggah gambarnya sendiri.
 | Digambar dengan gradien, bukan berkas gambar: tidak ada berkas yang perlu
 | diunggah lewat FTP, dan halaman masuk tetap punya wajah walau baru dipasang.
 */
.halaman-masuk.latar-bawaan {
  background-image:
    radial-gradient(1100px 600px at 15% -10%, rgba(139,116,240,.55), transparent 60%),
    radial-gradient(900px 700px at 110% 110%, rgba(109,79,224,.45), transparent 55%),
    linear-gradient(140deg, #3b2f8f 0%, #2e2472 45%, #241c5c 100%);
}

.kotak-masuk { width: 100%; max-width: 420px; }

.kartu-masuk {
  margin-bottom: 0; border-radius: 16px;
  box-shadow: 0 24px 60px rgba(8, 6, 20, .38);
}
.kartu-masuk > .kartu-isi { padding: 2rem 1.9rem; }

.kepala-masuk { text-align: center; margin-bottom: 1.6rem; }
.kepala-masuk h1 { font-size: 1.45rem; margin-bottom: .35rem; letter-spacing: -.01em; }
.kepala-masuk p { color: var(--teks-lembut); font-size: .9rem; margin: 0; }
.logo-masuk { max-height: 56px; max-width: 100%; margin: 0 auto .6rem; display: block; }
.logo-navbar { max-height: 26px; max-width: 160px; display: block; }

.form-masuk .bidang { margin-bottom: 1.05rem; }
.form-masuk label { font-weight: 600; }
.form-masuk input { padding: .62rem .75rem; }

.tombol-blok {
  width: 100%; justify-content: center; padding: .7rem;
  font-weight: 600; font-size: .95rem;
}

.catatan-masuk {
  text-align: center; margin: 1rem 0 0; color: rgba(255, 255, 255, .78);
  text-shadow: 0 1px 2px rgba(0, 0, 0, .35);
}

.pemisah-tipis { height: 1px; background: var(--garis); margin: 1.4rem 0 1rem; }

/* Tombol yang tampil sebagai tautan biasa — dipakai "Batal dan keluar". */
.tautan-samar {
  background: none; border: 0; padding: .35rem; cursor: pointer;
  color: var(--teks-lembut); font-weight: 600; font-size: .85rem;
}
.tautan-samar:hover { color: var(--teks); }

.footer-aplikasi {
  border-top: 1px solid var(--garis); margin-top: 2rem; padding: 1.1rem 0;
  color: var(--teks-samar); font-size: .82rem; text-align: center;
}

/* -------------------------------------------------- berkas merek di setelan */

.pratinjau-berkas {
  display: flex; align-items: center; gap: 1rem; flex-wrap: wrap;
  padding: .85rem; border: 1px dashed var(--garis-tegas); border-radius: var(--radius-kecil);
  background: var(--permukaan-2);
}
.pratinjau-berkas img { max-height: 54px; max-width: 190px; border-radius: 6px; }
.pratinjau-berkas .kosong-berkas { color: var(--teks-samar); font-size: .85rem; }

.pemisah { display: flex; align-items: center; gap: .75rem; margin: 1.1rem 0; color: var(--teks-samar); font-size: .8rem; }
.pemisah::before, .pemisah::after { content: ""; flex: 1; height: 1px; background: var(--garis); }

.tombol-google { display: flex; align-items: center; justify-content: center; gap: .6rem; }
.tombol-google svg { flex: none; }

/* ------------------------------------------------------------------ dua faktor */

.kotak-rahasia {
  font-family: "SFMono-Regular", Consolas, monospace; font-size: 1rem; letter-spacing: .12em;
  background: var(--permukaan-2); border: 1px dashed var(--garis-tegas);
  padding: .7rem; border-radius: var(--radius-kecil); text-align: center; word-break: break-all;
}
.qr-bungkus { display: grid; place-items: center; padding: 1rem; background: #fff; border-radius: var(--radius); border: 1px solid var(--garis); }
.daftar-kode { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: .5rem; }
.daftar-kode code {
  display: block; text-align: center; padding: .5rem;
  background: var(--permukaan-2); border-radius: var(--radius-kecil);
  font-family: "SFMono-Regular", Consolas, monospace; font-size: .9rem; letter-spacing: .05em;
}
.input-kode {
  text-align: center; font-size: 1.4rem !important; letter-spacing: .45em;
  font-family: "SFMono-Regular", Consolas, monospace; padding: .7rem .5rem !important;
  text-indent: .45em; /* mengimbangi letter-spacing agar teksnya benar-benar di tengah */
}

/* ---------------------------------------------------------------------- lain */

.tab-bar { display: flex; gap: .25rem; border-bottom: 1px solid var(--garis); margin-bottom: 1.1rem; overflow-x: auto; }
.tab-bar a {
  padding: .55rem .85rem; color: var(--teks-lembut); font-weight: 550; font-size: .9rem;
  border-bottom: 2px solid transparent; white-space: nowrap;
}
.tab-bar a:hover { color: var(--teks); text-decoration: none; }
.tab-bar a.aktif { color: var(--aksen); border-bottom-color: var(--aksen); }

.dua-kolom { display: grid; gap: 1.1rem; grid-template-columns: 1fr 1fr; }
.tiga-kolom { display: grid; gap: 1.1rem; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); }
.kolom-samping { display: grid; gap: 1.1rem; grid-template-columns: minmax(0, 2fr) minmax(280px, 1fr); align-items: start; }

.daftar-ringkas { list-style: none; margin: 0; padding: 0; }
.daftar-ringkas li {
  display: flex; justify-content: space-between; gap: .75rem;
  padding: .5rem 0; border-bottom: 1px solid var(--garis); font-size: .88rem;
}
.daftar-ringkas li:last-child { border-bottom: none; }
.daftar-ringkas .nilai { font-weight: 600; font-variant-numeric: tabular-nums; }

.pagination { display: flex; gap: .25rem; flex-wrap: wrap; padding: .85rem 1.1rem; align-items: center; }
.pagination a, .pagination span {
  padding: .3rem .6rem; border-radius: var(--radius-kecil); font-size: .85rem;
  border: 1px solid var(--garis); color: var(--teks-lembut);
}
.pagination a:hover { background: var(--permukaan-2); text-decoration: none; }
.pagination .aktif, .pagination [aria-current="page"] span { background: var(--aksen); border-color: var(--aksen); color: #fff; }

.baris-inline { display: flex; gap: .5rem; align-items: center; flex-wrap: wrap; }
.dorong-kanan { margin-left: auto; }
.samar { color: var(--teks-samar); }
.lembut { color: var(--teks-lembut); }
.kecil { font-size: .82rem; }
.tebal { font-weight: 650; }
.tengah { text-align: center; }
.kanan { text-align: right; }
.mt-0 { margin-top: 0; } .mt-1 { margin-top: .5rem; } .mt-2 { margin-top: 1rem; } .mt-3 { margin-top: 1.5rem; }
.mb-0 { margin-bottom: 0; } .mb-1 { margin-bottom: .5rem; } .mb-2 { margin-bottom: 1rem; }
.sembunyi { display: none !important; }
.tampil-ponsel { display: none; }

.baris-form-sebaris { display: grid; gap: .5rem; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); align-items: start; }

/* ------------------------------------------------------------------ responsif */

@media (max-width: 980px) {
  .kolom-samping, .dua-kolom, .editor-markdown { grid-template-columns: 1fr; }
  .kisi-grafik { grid-template-columns: 1fr; }
}

/*
 | Ambang menu hamburger 940px, ditentukan dari pengukuran.
 |
 | Dahulu 760px, dan akibatnya tablet 768–1024px menampilkan menu mendatar yang
 | tidak muat: navbar melebar melampaui layar dan seluruh halaman dapat digeser
 | ke samping. Setelah Pengaturan berpindah ke menu profil, lima butir menu yang
 | tersisa beserta pemilih periode masih muat sampai sekitar 940px — tablet
 | mendatar tetap mendapat menu penuh, tablet tegak mendapat hamburger.
 |
 | Angkanya hasil ukur, bukan tebak: menambah butir menu baru berarti mengukur
 | ulang, bukan menaikkan angka ini sekenanya.
 */
@media (max-width: 940px) {
  .navbar .tombol-menu-mobile { display: inline-flex; }
  .menu {
    display: none; position: absolute; top: 56px; left: 0; right: 0;
    flex-direction: column; background: var(--permukaan);
    border-bottom: 1px solid var(--garis); padding: .5rem; gap: .1rem;
    box-shadow: var(--bayang-tinggi); max-height: calc(100vh - 56px); overflow-y: auto;
    z-index: 40;
  }
  .menu.terbuka { display: flex; }
  .menu-tautan { padding: .6rem .7rem; }
  /* Submenu di dalam daftar hamburger menjadi daftar bertumpuk biasa. Menu
     profil dikecualikan: ia tetap panel mengambang di navbar, dan membuatnya
     static akan melebarkan navbar sampai halaman bisa digeser ke samping. */
  .menu .submenu {
    position: static; border: none; box-shadow: none;
    padding: 0 0 .25rem .75rem; min-width: 0; background: transparent;
    /* Di dalam daftar hamburger tidak ada hover sama sekali; submenunya
       tampil terus, jadi tenggang tutup di atas tidak berlaku di sini. */
    visibility: visible; opacity: 1; transition: none;
  }
  .menu .submenu::before { content: none; }
  .navbar-isi { gap: .4rem; }
  .navbar-kanan { gap: .3rem; margin-left: auto; }
  .menu .keluar-ponsel { border-top: 1px solid var(--garis); margin-top: .35rem; padding-top: .35rem; }
}

@media (max-width: 760px) {
  body { font-size: 14px; }
  .pembungkus { padding: 0 .9rem; }

  /* Nama aplikasi, tombol Keluar, dan avatar baru disembunyikan di ponsel.
     Pada tablet ruangnya masih cukup, dan menyembunyikannya di sana hanya
     membuat navbar tampak kosong tanpa alasan. */
  .sembunyi-ponsel { display: none !important; }
  .tampil-ponsel { display: block; }
  .pemilih-periode .label-periode { min-width: 0; font-size: .78rem; white-space: nowrap; padding: .3rem .4rem; }
  .kpi .nilai-kpi { font-size: 1.35rem; }
  table.tabel th, table.tabel td { padding: .5rem .55rem; }
}

/* ------------------------------------------------------- kartu kredit */

.kartu-kredit-ringkas { margin-top: .9rem; border-top: 1px solid var(--garis); padding-top: .8rem; }
.kk-baris + .kk-baris { margin-top: .9rem; padding-top: .9rem; border-top: 1px dashed var(--garis); }
.kk-kepala { display: flex; justify-content: space-between; align-items: baseline; gap: .5rem; }
.kk-nama { font-weight: 600; }
.kk-tagihan { margin-top: .35rem; }
.kk-rincian { margin-top: .5rem; }
.kk-rincian summary { cursor: pointer; color: var(--aksen); width: fit-content; }
.kk-rincian .daftar-ringkas { margin-top: .4rem; }
.kk-cicilan { margin-top: .4rem; padding-left: .6rem; border-left: 2px solid var(--garis-tegas); }
.kk-cicilan > div + div { margin-top: .2rem; }

.kk-meter {
  height: 7px; border-radius: 4px; background: var(--permukaan-2);
  overflow: hidden; margin: .45rem 0 .3rem;
}
.kk-isi { display: block; height: 100%; border-radius: 4px; }
.kk-aman { background: var(--hijau); }
.kk-waspada { background: var(--kuning); }
.kk-bahaya { background: var(--merah); }
.kk-netral { background: var(--garis-tegas); }

/* ------------------------------------------------------------ pilihan tema */

/* Kedua pratinjau memakai warna yang dipaku, bukan variabel tema: keduanya
   harus tampil sesuai temanya masing-masing pada layar yang sama, sehingga
   pilihannya dapat dibandingkan alih-alih ditebak dari namanya. */

.pilihan-tema { display: flex; gap: 1rem; flex-wrap: wrap; }

.kartu-pilihan {
  display: block; position: relative; cursor: pointer; border: 2px solid var(--garis);
  border-radius: var(--radius); padding: .7rem; background: var(--permukaan);
  transition: border-color .12s ease, box-shadow .12s ease; width: 210px; max-width: 100%;
}
.kartu-pilihan:hover { border-color: var(--garis-tegas); }
/* Dua selektor untuk keadaan yang sama: :has() bagi peramban yang
   mendukungnya, dan kelas .terpilih yang dipasang server serta diperbarui
   JavaScript sebagai jaring pengaman. */
.kartu-pilihan.terpilih,
.kartu-pilihan:has(input:checked) { border-color: var(--aksen); box-shadow: 0 0 0 3px var(--aksen-lembut); }
.kartu-pilihan input { position: absolute; opacity: 0; pointer-events: none; }
.kartu-pilihan:has(input:focus-visible) { outline: 2px solid var(--aksen); outline-offset: 2px; }

.pilihan-nama { display: block; margin-top: .55rem; font-weight: 600; font-size: .9rem; }

.pratinjau-tema {
  display: block; border-radius: var(--radius-kecil); overflow: hidden;
  border: 1px solid rgba(128, 128, 128, .35);
}
.pratinjau-bar { display: block; height: 16px; }
.pratinjau-isi { display: block; padding: .5rem; }
.pratinjau-garis { display: block; height: 6px; border-radius: 3px; margin-bottom: .35rem; width: 55%; }
.pratinjau-garis.panjang { width: 85%; }
.pratinjau-tombol { display: block; height: 12px; width: 44px; border-radius: 4px; margin-top: .5rem; }

.pratinjau-gelap { background: #0e1116; }
.pratinjau-gelap .pratinjau-bar { background: #161b22; border-bottom: 1px solid #262d38; }
.pratinjau-gelap .pratinjau-garis { background: #39414e; }
.pratinjau-gelap .pratinjau-tombol { background: #8b74f0; }

.pratinjau-terang { background: #f6f7f9; }
.pratinjau-terang .pratinjau-bar { background: #ffffff; border-bottom: 1px solid #e3e7ec; }
.pratinjau-terang .pratinjau-garis { background: #cbd3dd; }
.pratinjau-terang .pratinjau-tombol { background: #6d4fe0; }

@media print {
  :root { color-scheme: light; }
  .navbar, .tombol, .tab-bar, .pesan, form { display: none !important; }
  body { background: #fff; }
  .kartu { border: 1px solid #ddd; box-shadow: none; break-inside: avoid; }
}

/* ------------------------------------------------ pengelompokan kewajiban */

/*
 | Utang jangka pendek dikelompokkan menurut kartu kreditnya: satu baris
 | kelompok, lalu baris-baris anggotanya yang diberi lekukan. Lekukannya
 | dipasang lewat padding pada sel pertama, bukan lewat transform atau margin,
 | supaya lebar kolom tabelnya tidak ikut bergeser.
 */
.tabel .baris-kelompok > td {
    background: var(--permukaan-2);
    border-top: 1px solid var(--garis-tegas);
}

.tabel .baris-anak > td:first-child {
    padding-left: 2rem;
    border-left: 2px solid var(--garis);
}

.kisi-angka {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
    gap: 1rem;
}

.kisi-angka .pos-angka {
    display: flex;
    flex-direction: column;
    gap: .15rem;
}

.kisi-angka .pos-angka .label {
    font-size: .82rem;
    color: var(--teks-lembut);
}

.kisi-angka .pos-angka .angka {
    font-size: 1.15rem;
}

.kisi-berkas {
  display: grid; gap: 1.1rem;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
}
.kisi-berkas input[type="file"] { font-size: .85rem; }

/* ------------------------------------------------- sembunyikan saldo */

/*
 | Angka ditutup dengan blur, bukan dengan mengganti teksnya menjadi "•••".
 | Alasannya dua: tata letaknya tidak bergeser sedikit pun saat saklar dibalik,
 | dan bentuk kasarnya tetap terlihat sehingga pemiliknya tahu halamannya tidak
 | kosong — hanya tertutup. Untuk pembaca layar angkanya tetap ada; ini
 | perlindungan dari mata orang di sebelah, bukan kontrol akses.
 |
 | Seluruh aturannya dibatasi pada .utama, yaitu isi halaman. Navbar sengaja
 | tidak ikut: pemilih periode di sana bukan saldo, dan menutupinya membuat
 | orang kehilangan penunjuk bulan yang sedang dibuka.
 */
html[data-sembunyi-saldo="1"] body.bisa-sembunyi-saldo .utama .rahasia,
html[data-sembunyi-saldo="1"] body.bisa-sembunyi-saldo .utama .nilai-kpi,
html[data-sembunyi-saldo="1"] body.bisa-sembunyi-saldo .utama .banding,
html[data-sembunyi-saldo="1"] body.bisa-sembunyi-saldo .utama .angka,
html[data-sembunyi-saldo="1"] body.bisa-sembunyi-saldo .utama .nilai,
html[data-sembunyi-saldo="1"] body.bisa-sembunyi-saldo .utama .kartu svg {
  filter: blur(8px);
  user-select: none;
  transition: filter .12s ease;
}

/* Angka di dalam tombol dan pesan tidak ikut ditutup: yang di sana adalah
   keterangan cara memakainya, bukan saldo. */
html[data-sembunyi-saldo="1"] body.bisa-sembunyi-saldo .utama .tombol .rahasia,
html[data-sembunyi-saldo="1"] body.bisa-sembunyi-saldo .utama .tombol .angka,
html[data-sembunyi-saldo="1"] body.bisa-sembunyi-saldo .utama .pesan .rahasia,
html[data-sembunyi-saldo="1"] body.bisa-sembunyi-saldo .utama .pesan .angka { filter: none; }

/* -------------------------------------------------- tombol berikon */

.pilihan-baris { display: flex; flex-wrap: wrap; gap: .35rem 1rem; margin: .25rem 0 .1rem; }
.label-kecil { display: block; font-size: .82rem; font-weight: 600; color: var(--teks-lembut); }

/* ---------------------------------------------- tombol ikon tanpa teks */

/*
 | Tombol aksi pada tabel hanya berisi ikon. Teksnya tetap ada di markah dan
 | dibacakan pembaca layar; yang disembunyikan hanya tampilannya. Menghapus
 | teksnya sama sekali akan membuat tombol-tombol itu tidak bernama bagi orang
 | yang tidak dapat melihat ikonnya.
 */
.hanya-pembaca-layar {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
}

.tombol-ikon-saja {
  display: inline-grid; place-items: center;
  width: 32px; height: 32px; padding: 0; flex: none;
  /*
   | position:relative wajib. Teks pembaca layar di dalamnya diposisikan
   | absolut; tanpa induk yang berposisi, ia berlabuh pada halaman dan
   | mengambil posisi statisnya — yang berada jauh di kanan bila tombolnya
   | ada di dalam tabel lebar. Akibatnya seluruh halaman dapat digeser ke
   | samping padahal tabelnya sendiri sudah punya penggeser sendiri.
   */
  position: relative;
}
.tombol-ikon-saja svg { width: 16px; height: 16px; }
.tombol.tombol-kecil.tombol-ikon-saja { width: 30px; height: 30px; }

/* ------------------------------------------------------- isian berkas */

/*
 | Tombol bawaan input berkas berbeda-beda di tiap peramban dan selalu tampak
 | asing di antara komponen lain. ::file-selector-button mendandaninya tanpa
 | JavaScript dan tanpa markah tambahan — isian aslinya tetap satu elemen,
 | sehingga tetap dapat diakses papan ketik dan pembaca layar.
 */
input[type="file"] {
  font-size: .86rem; color: var(--teks-lembut);
  padding: .3rem 0; border: 0; background: none; width: 100%;
}
input[type="file"]::file-selector-button {
  margin-right: .7rem; padding: .42rem .8rem;
  border: 1px solid var(--garis-tegas); border-radius: var(--radius-kecil);
  background: var(--permukaan-2); color: var(--teks);
  font: inherit; font-weight: 600; font-size: .85rem; cursor: pointer;
  transition: background .12s ease, border-color .12s ease;
}
input[type="file"]::file-selector-button:hover {
  background: var(--aksen-lembut); border-color: var(--aksen); color: var(--aksen-gelap);
}
input[type="file"]:focus-visible::file-selector-button { outline: 2px solid var(--aksen); outline-offset: 2px; }

.kk-rincian summary { display: flex; align-items: center; gap: .35rem; }
.kk-rincian summary svg { width: 14px; height: 14px; flex: none; }

/* ------------------------------------------------------------- kartu input */
/*
 | Formulir isian dibedakan dari kartu data.
 |
 | Dahulu keduanya memakai bentuk yang sama persis, dan letaknya berpindah-pindah:
 | formulir Pengeluaran dan Pemasukan di atas halaman, formulir Aset, Kewajiban,
 | dan Pengguna di bawah — jadi tempat mengetik harus dicari lebih dahulu di
 | setiap halaman. Sekarang seluruhnya berada tepat di bawah bilah tab dan
 | memakai penanda yang sama: tepi beraksen, kepala bernada aksen, ikon tambah,
 | dan label "Formulir isian".
 |
 | Dibangun di atas <details>/<summary> supaya dapat dilipat tanpa JavaScript —
 | penting untuk formulir panjang seperti Tambah Aset, yang setiap harinya lebih
 | sering dilewati daripada dipakai. Terbuka secara bawaan agar tindakan yang
 | paling sering dilakukan tidak bertambah satu klik.
 */
.kartu-input { border-left: 3px solid var(--aksen); }

.kepala-input {
  background: var(--aksen-lembut);
  cursor: pointer;
  list-style: none;
  flex-wrap: nowrap;
  align-items: center;
}
.kepala-input::-webkit-details-marker { display: none; }
.kepala-input:hover { filter: brightness(1.03); }
.kepala-input:focus-visible { outline: 2px solid var(--aksen); outline-offset: -2px; }

.kepala-input h2 { color: var(--aksen-gelap); }
.teks-kepala-input { flex: 1; min-width: 0; }
.teks-kepala-input .sub { color: var(--teks-lembut); }

.tanda-input {
  flex: 0 0 auto; width: 26px; height: 26px; border-radius: 50%;
  background: var(--aksen); color: #fff; display: grid; place-items: center;
}
.tanda-input svg { width: 15px; height: 15px; }

.lencana-formulir {
  flex: 0 0 auto;
  font-size: .72rem; font-weight: 600; letter-spacing: .02em;
  color: var(--aksen-gelap); background: var(--permukaan);
  border: 1px solid var(--aksen); border-radius: 999px; padding: .1rem .5rem;
}

.tanda-lipat { flex: 0 0 auto; color: var(--aksen-gelap); display: grid; place-items: center; }
.tanda-lipat svg { width: 18px; height: 18px; transition: transform .15s ease; }
details[open] > .kepala-input .tanda-lipat svg { transform: rotate(180deg); }

/* Formulir yang gagal validasi tidak boleh tersembunyi di balik lipatan. */
.kartu-input.ada-galat { border-left-color: var(--merah); }
.kartu-input.ada-galat .kepala-input { background: var(--merah-lembut); }
.kartu-input.ada-galat .kepala-input h2,
.kartu-input.ada-galat .lencana-formulir,
.kartu-input.ada-galat .tanda-lipat { color: var(--merah); }
.kartu-input.ada-galat .tanda-input { background: var(--merah); }
.kartu-input.ada-galat .lencana-formulir { border-color: var(--merah); }

@media (max-width: 560px) {
  /* Label tambahan mengalah lebih dahulu; ikon dan judul yang menjelaskan
     kartu ini tetap ada. */
  .lencana-formulir { display: none; }
}

/* --------------------------------------------- isian menurun di kartu input */
/*
 | Di dalam kartu input, kolom isian disusun ke bawah: satu baris satu kolom,
 | label di kiri dan isiannya di kanan.
 |
 | Bentuk sebelumnya adalah kisi yang mengalir — kolom-kolom berjajar tiga
 | sampai enam per baris, sehingga mengisinya terasa berpindah dari kiri ke
 | kanan lalu turun, dan urutan bacanya berubah setiap kali lebar layar
 | berubah. Susunan menurun membuat urutannya sama di semua lebar, dan
 | pandangan hanya perlu bergerak satu arah.
 |
 | Sengaja dilingkupi `.kartu-input`: baris sunting di dalam tabel memakai
 | `.kisi-form` yang sama dan di sana berjajar memang benar — ruangnya sempit
 | dan kolomnya sedikit.
 */
.kartu-input .kisi-form { display: block; }

.kartu-input .kisi-form > .bidang {
  display: grid;
  grid-template-columns: minmax(140px, 224px) minmax(0, 1fr);
  align-items: center;
  column-gap: 1.25rem; row-gap: .3rem;
  padding: .6rem 0;
  border-top: 1px solid var(--garis);
}
.kartu-input .kisi-form > .bidang:first-child { border-top: 0; padding-top: 0; }
.kartu-input .kisi-form > .bidang:last-child { padding-bottom: 0; }

/* Label kembali sebaris: tinggi minimum dua baris yang dipakai kisi mengalir
   justru merenggangkan barisan ketika labelnya berdampingan dengan isian. */
.kartu-input .kisi-form > .bidang > label:first-child {
  min-height: 0; margin: 0; display: flex; align-items: center; flex-wrap: wrap; gap: .25rem;
  font-size: .88rem; color: var(--teks);
}

/* Isian memenuhi kolomnya sampai tepi kanan kartu — barisan tepi kanan yang
   rata membuat formulirnya terbaca sebagai satu blok, bukan sebagai kolom
   yang berhenti di tengah dengan sisa ruang kosong di sebelahnya. */
.kartu-input .kisi-form > .bidang > :not(label) { width: 100%; }
.kartu-input .kisi-form > .bidang > .petunjuk { grid-column: 2; }

@media (max-width: 640px) {
  /* Ruang mendatar habis lebih dahulu; label naik ke atas isiannya, urutan
     menurunnya tetap sama. */
  .kartu-input .kisi-form > .bidang {
    grid-template-columns: minmax(0, 1fr);
    row-gap: .35rem;
  }
  .kartu-input .kisi-form > .bidang > .petunjuk { grid-column: 1; }
}

/*
 | Kontrol di dalam baris mendatar mengambil lebar seperlunya.
 |
 | Aturan dasar memberi `width: 100%` kepada setiap input dan select — benar
 | untuk kolom isian yang bertumpuk, tetapi di dalam `.baris-inline` membuat
 | ketiga penyaring "Daftar Transaksi" melar selebar kartunya dan bertumpuk ke
 | bawah, padahal ruangnya berlebih. Hanya anak langsung yang diatur di sini;
 | kontrol di dalam `.bidang` tetap memenuhi kolomnya.
 */
.baris-inline > input, .baris-inline > select {
  width: auto; flex: 0 1 auto; min-width: 9rem;
}
@media (max-width: 560px) {
  .baris-inline > input, .baris-inline > select { flex: 1 1 100%; }
}

/*
 | Tombol aksi di kepala halaman berukuran sedikit lebih besar daripada tombol
 | ikon di dalam tabel: keduanya memakai kelas yang sama, tetapi yang di sini
 | berdiri sendiri di sebelah judul, bukan berdesakan di dalam baris tabel.
 */
.tombol-grup .tombol-ikon-saja { width: 38px; height: 38px; }
.tombol-grup .tombol-ikon-saja svg { width: 18px; height: 18px; }

/* Perbandingan jenis cadangan pada kartu "Buat Cadangan Sekarang". */
.daftar-jenis-cadangan {
  list-style: none; margin: 0 0 1rem; padding: 0;
  border: 1px solid var(--garis); border-radius: var(--radius-kecil);
}
.daftar-jenis-cadangan li { padding: .55rem .7rem; color: var(--teks-lembut); }
.daftar-jenis-cadangan li + li { border-top: 1px solid var(--garis); }
.daftar-jenis-cadangan strong { color: var(--teks); }

/* Baris cadangan yang baru saja dibuat, supaya tombol unduhnya tidak dicari. */
.tabel tr.baris-sorot > td { background: var(--aksen-lembut); }
/* Penanda tepi hanya pada sel pertama; pada setiap sel ia terbaca sebagai
   garis-garis di tengah baris, bukan sebagai penanda satu baris. */
.tabel tr.baris-sorot > td:first-child { box-shadow: inset 3px 0 0 var(--aksen); }
/* Navbar melekat di puncak halaman; tanpa jarak ini, baris yang dituju
   berhenti tepat di baliknya dan justru tidak terlihat. */
.tabel tr.baris-sorot { scroll-margin-top: 80px; }

/* ------------------------------------------------------------- backdrop */
/*
 | Kepala halaman yang diperluas: satu bidang berwarna atau bergambar di
 | belakang navbar dan judul halaman, dan kartu pertama menumpanginya.
 |
 | Tingginya bawaan 210px supaya tetap benar tanpa JavaScript sama sekali;
 | `siapkanBackdrop()` mengukur ulang mengikuti tinggi judul yang sebenarnya,
 | karena judul dua baris atau baris tombol yang membungkus membuat angka tetap
 | apa pun salah pada sebagian halaman.
 */
body.ada-backdrop { --tinggi-backdrop: 248px; }

.backdrop {
  position: absolute; top: 0; left: 0; right: 0;
  height: var(--tinggi-backdrop);
  background-repeat: no-repeat;
  z-index: 0;
  pointer-events: none;
}

/* Peredup: menjamin tulisan tetap terbaca di atas gambar apa pun. Lebih pekat
   di bagian atas tempat navbar berada, menipis ke bawah supaya gambarnya tetap
   terlihat sebagaimana adanya. */
.backdrop-peredup {
  position: absolute; inset: 0;
  /*
   | Angkanya hasil pengukuran, bukan selera. Dengan .62 di puncak, foto yang
   | ada bagian terangnya menyisakan kontras 4,27:1 untuk tulisan putih — di
   | bawah ambang 4,5:1, dan itu artinya sebagian orang memang tidak dapat
   | membacanya. Ada uji yang mengukur piksel hasil render sungguhan; kalau
   | angka ini diturunkan, uji itu yang akan memberi tahu.
   |
   | Pekat hanya di jalur navbar dan judul, lalu menipis cepat supaya sisa
   | fotonya tetap terlihat sebagaimana adanya.
   */
  background: linear-gradient(180deg,
    rgba(9, 12, 20, .70) 0%,
    rgba(9, 12, 20, .66) 72%,
    rgba(9, 12, 20, .28) 100%);
}
/* Warna dan gradien dipilih sendiri oleh pemiliknya, jadi tidak perlu diredam
   — hanya sedikit, supaya tulisan putih tetap aman di warna terang. */
body.backdrop-warna .backdrop-peredup,
body.backdrop-gradien .backdrop-peredup {
  background: linear-gradient(180deg, rgba(9, 12, 20, .18) 0%, rgba(9, 12, 20, .06) 100%);
}

/* Isi halaman berdiri di atas bidang itu, bukan di belakangnya.
   Navbar sengaja TIDAK disentuh di sini: ia sudah `position: sticky`, dan
   menimpanya dengan `relative` membuatnya ikut tergulir hilang — sempat
   terjadi, dan navbar yang lenyap saat menggulir jauh lebih buruk daripada
   backdrop yang tidak ada. */
body.ada-backdrop .utama { position: relative; z-index: 1; }

/*
 | Navbar menjadi bening selama masih berada di dalam bidang backdrop, dan
 | kembali padat begitu tergulir keluar. Tanpa itu, navbar yang melekat akan
 | melayang bening di atas isi halaman dan tulisannya hilang di antara angka.
 */
body.ada-backdrop .navbar {
  background: transparent;
  border-bottom-color: transparent;
  transition: background .18s ease, border-color .18s ease;
}
body.ada-backdrop.navbar-padat .navbar {
  background: var(--permukaan);
  border-bottom-color: var(--garis);
}

/* Tulisan di dalam bidang backdrop selalu terang — bidangnya sudah diredam,
   dan warna teks tema tidak dapat menjamin kontras di atas gambar apa pun. */
body.ada-backdrop:not(.navbar-padat) .merek,
body.ada-backdrop:not(.navbar-padat) .menu-tautan,
body.ada-backdrop:not(.navbar-padat) .label-periode,
body.ada-backdrop:not(.navbar-padat) .navbar .tombol-menu-mobile,
body.ada-backdrop:not(.navbar-padat) .pemilih-periode .tombol {
  color: #fff;
}
body.ada-backdrop:not(.navbar-padat) .menu-tautan:hover,
body.ada-backdrop:not(.navbar-padat) .menu-tautan.aktif {
  background: rgba(255, 255, 255, .16); color: #fff;
}
body.ada-backdrop:not(.navbar-padat) .pemilih-periode .tombol,
body.ada-backdrop:not(.navbar-padat) .navbar .tombol-menu-mobile {
  background: rgba(255, 255, 255, .14); border-color: rgba(255, 255, 255, .28);
}

/*
 | Label periode punya latarnya sendiri (--permukaan-2), dan latar itu terang
 | di tema terang. Tulisannya sudah dipaksa putih karena berada di atas
 | backdrop, jadi tanpa aturan ini hasilnya putih di atas putih — tulisan yang
 | benar-benar hilang, bukan sekadar kurang jelas. Sempat terjadi, dan hanya di
 | tema terang; di tema gelap latarnya kebetulan gelap sehingga lolos.
 */
body.ada-backdrop:not(.navbar-padat) .pemilih-periode .label-periode {
  background: rgba(255, 255, 255, .16);
}
body.ada-backdrop:not(.navbar-padat) .avatar { border-color: rgba(255, 255, 255, .5); }

body.ada-backdrop .baris-judul h1 { color: #fff; }
body.ada-backdrop .baris-judul .keterangan { color: rgba(255, 255, 255, .82); }
body.ada-backdrop .baris-judul .tombol:not(.tombol-utama) {
  background: rgba(255, 255, 255, .14); border-color: rgba(255, 255, 255, .3); color: #fff;
}

/* Submenu dan panel profil tetap kartu biasa: keduanya mengambang di atas isi
   halaman, bukan di atas backdrop. */
body.ada-backdrop .submenu { color: var(--teks); }
body.ada-backdrop .submenu a { color: var(--teks-lembut); }

@media (max-width: 760px) {
  body.ada-backdrop { --tinggi-backdrop: 224px; }
}

/* Sebagian orang menyetel perangkatnya untuk menghindari animasi; peralihan
   navbar termasuk yang harus ikut berhenti. */
@media (prefers-reduced-motion: reduce) {
  body.ada-backdrop .navbar { transition: none; }
}

/* ------------------------------------------ pengaturan backdrop */

.baris-warna { display: flex; gap: .5rem; align-items: center; }
.baris-warna input[type="color"] {
  width: 44px; height: 38px; flex: none; padding: 2px;
  border: 1px solid var(--garis-tegas); border-radius: var(--radius-kecil);
  background: var(--permukaan); cursor: pointer;
}
/* Kode HEX dibaca dari kiri seperti teks, bukan dirata kanan seperti nominal. */
.baris-warna .kode-hex {
  text-transform: uppercase; text-align: left;
  font-variant-numeric: tabular-nums; letter-spacing: .02em;
}

/*
 | Pratinjau berukuran sama rasio dengan bidang aslinya (4:1), bukan kotak
 | sekadarnya: yang paling sering mengejutkan orang bukan warnanya melainkan
 | seberapa banyak gambarnya terpotong, dan itu hanya terlihat bila rasionya
 | sama.
 */
.pratinjau-backdrop {
  position: relative; overflow: hidden;
  width: 100%; aspect-ratio: 4 / 1; max-height: 180px;
  border: 1px solid var(--garis); border-radius: var(--radius);
  background: var(--permukaan-2);
  background-size: cover; background-position: center;
  display: grid; place-items: start; align-content: end;
  padding: .9rem 1rem;
}
.pratinjau-backdrop .pratinjau-peredup {
  position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(9, 12, 20, .62) 0%, rgba(9, 12, 20, .28) 100%);
}
.pratinjau-backdrop.pratinjau-polos .pratinjau-peredup { display: none; }
.pratinjau-backdrop.pratinjau-warna .pratinjau-peredup,
.pratinjau-backdrop.pratinjau-gradien .pratinjau-peredup {
  background: linear-gradient(180deg, rgba(9, 12, 20, .18) 0%, rgba(9, 12, 20, .06) 100%);
}
.pratinjau-backdrop .pratinjau-teks {
  position: relative; color: #fff; font-weight: 680; font-size: 1.2rem;
  letter-spacing: -.01em;
}
.pratinjau-backdrop.pratinjau-polos .pratinjau-teks { color: var(--teks); }

.bidang[data-untuk-backdrop], [data-untuk-backdrop] { transition: none; }

/*
 | Bilah tab yang berada di dalam bidang backdrop.
 |
 | Warna aksen di atas bidang berwarna adalah dua warna yang bertabrakan: tab
 | aktif ungu di atas latar biru terbaca sebagai kesalahan, bukan sebagai
 | penanda. Di dalam bidang itu penandanya menjadi putih — kontrasnya datang
 | dari terang-gelap, bukan dari warna, dan itu berlaku untuk warna latar apa
 | pun yang dipilih.
 */
body.ada-backdrop .utama > .pembungkus > .tab-bar,
body.ada-backdrop .tab-bar.di-backdrop {
  border-bottom-color: rgba(255, 255, 255, .28);
}
body.ada-backdrop .utama > .pembungkus > .tab-bar a,
body.ada-backdrop .tab-bar.di-backdrop a { color: rgba(255, 255, 255, .78); }
body.ada-backdrop .utama > .pembungkus > .tab-bar a:hover,
body.ada-backdrop .tab-bar.di-backdrop a:hover { color: #fff; }
body.ada-backdrop .utama > .pembungkus > .tab-bar a.aktif,
body.ada-backdrop .tab-bar.di-backdrop a.aktif {
  color: #fff; border-bottom-color: #fff;
}

/* ------------------------------------------- laman identitas tampilan */
/*
 | Satu kartu, empat bagian bertajuk, dipisahkan garis — bukan satu tumpukan
 | panjang berisi teks, berkas, warna, dan backdrop yang saling berdempetan.
 | Isiannya memakai susunan menurun yang sama dengan kartu input lain
 | (lihat "isian menurun di kartu input").
 */
.bagian-setelan + .bagian-setelan { border-top: 1px solid var(--garis); }
.judul-bagian {
  margin: 0 0 .85rem; font-size: .82rem; font-weight: 650;
  letter-spacing: .04em; text-transform: uppercase; color: var(--teks-samar);
}

.kartu-setelan .kisi-form { display: block; }
.kartu-setelan .kisi-form > .bidang {
  display: grid;
  grid-template-columns: minmax(140px, 224px) minmax(0, 1fr);
  align-items: center;
  column-gap: 1.25rem; row-gap: .3rem;
  padding: .6rem 0;
  border-top: 1px solid var(--garis);
}
.kartu-setelan .kisi-form > .bidang:first-child { border-top: 0; padding-top: 0; }
.kartu-setelan .kisi-form > .bidang:last-child { padding-bottom: 0; }
.kartu-setelan .kisi-form > .bidang > label:first-child {
  min-height: 0; margin: 0; display: flex; align-items: center; flex-wrap: wrap; gap: .25rem;
  font-size: .88rem; color: var(--teks);
}
.kartu-setelan .kisi-form > .bidang > :not(label) { width: 100%; }
.kartu-setelan .kisi-form > .bidang > .petunjuk { grid-column: 2; }

@media (max-width: 640px) {
  .kartu-setelan .kisi-form > .bidang { grid-template-columns: minmax(0, 1fr); row-gap: .35rem; }
  .kartu-setelan .kisi-form > .bidang > .petunjuk { grid-column: 1; }
}

/* Contoh warna aksen: memperlihatkan akibat pilihannya pada empat tempat
   yang paling sering terlihat, bukan sekadar kotak warna. */
.contoh-aksen {
  display: flex; flex-wrap: wrap; gap: .9rem; align-items: center;
  padding: .85rem 1rem; margin-top: .9rem;
  border: 1px solid var(--garis); border-radius: var(--radius);
  background: var(--permukaan-2);
}
.contoh-aksen .lencana-aksen {
  background: var(--aksen-lembut); color: var(--aksen-gelap);
  border-color: color-mix(in srgb, var(--aksen) 30%, transparent);
}
.contoh-aksen .lencana-aksen .titik { background: var(--aksen); }
.contoh-aksen .tab-contoh {
  color: var(--aksen); border-bottom: 2px solid var(--aksen);
  padding-bottom: .25rem; font-weight: 550; font-size: .9rem;
}

/* ==========================================================================
   Aplikasi terpasang (PWA)
   ========================================================================== */

/* Mode terpasang tidak punya bilah alamat, sehingga navbar berhimpit langsung
   dengan jam dan takik kamera. Jarak amannya diambil dari sistem lewat
   env(), bukan ditulis tetap: nilainya berbeda antar perangkat, dan berubah
   ketika ponsel diputar. Kelasnya dipasang JavaScript — CSS sendiri dapat
   membaca display-mode, tetapi hanya lewat media query yang tidak berlaku
   pada peramban lama yang masih dipakai sebagian ponsel. */
.mode-aplikasi .navbar {
  padding-top: env(safe-area-inset-top);
}
.mode-aplikasi .navbar-isi,
.mode-aplikasi .utama > .pembungkus,
.mode-aplikasi .footer-aplikasi > .pembungkus {
  padding-left: max(1rem, env(safe-area-inset-left));
  padding-right: max(1rem, env(safe-area-inset-right));
}
.mode-aplikasi body,
.mode-aplikasi .footer-aplikasi {
  padding-bottom: env(safe-area-inset-bottom);
}

/* Dua bilah yang muncul dari JavaScript. Keduanya melayang di bawah supaya
   tidak menggeser tata letak: bilah yang mendorong halaman ke bawah membuat
   tombol yang sedang dituju jari berpindah tepat sebelum disentuh. */
.bilah-luring,
.bilah-pembaruan {
  position: fixed; z-index: 90;
  left: max(.75rem, env(safe-area-inset-left));
  right: max(.75rem, env(safe-area-inset-right));
  bottom: calc(.75rem + env(safe-area-inset-bottom));
  margin: 0 auto; max-width: 32rem;
  display: flex; align-items: center; justify-content: center; gap: .75rem;
  padding: .7rem 1rem; border-radius: var(--radius);
  font-size: .88rem; line-height: 1.4; text-align: center;
  box-shadow: var(--bayang-tinggi);
  animation: naik-bilah .22s ease;
}

@keyframes naik-bilah {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}

.bilah-luring {
  background: var(--kuning-lembut); color: var(--kuning);
  border: 1px solid color-mix(in srgb, var(--kuning) 28%, transparent);
}
[data-tema="gelap"] .bilah-luring { color: #f4c47a; }

.bilah-pembaruan {
  background: var(--permukaan); color: var(--teks);
  border: 1px solid var(--garis-tegas);
}
.bilah-pembaruan button { flex: none; }

@media (prefers-reduced-motion: reduce) {
  .bilah-luring, .bilah-pembaruan { animation: none; }
}

/* Kartu status pemasangan di Pengaturan → Aplikasi.
   Satu elemen dengan empat keadaan, bukan empat elemen yang disembunyikan
   bergantian: keadaan yang benar hanya diketahui setelah JavaScript berjalan,
   dan blok yang tampil lalu menghilang terlihat seperti halaman yang berkedip.
   Bawaannya "menunggu" — netral dan aman bila JavaScript tidak jalan. */
.status-pasang > * { display: none; }
.status-pasang[data-status-pasang="menunggu"] .saat-menunggu,
.status-pasang[data-status-pasang="siap"] .saat-siap,
.status-pasang[data-status-pasang="terpasang"] .saat-terpasang,
.status-pasang[data-status-pasang="manual"] .saat-manual,
.status-pasang[data-status-pasang="tidak-didukung"] .saat-manual { display: block; }

.langkah-pasang {
  margin: .6rem 0 0; padding-left: 1.15rem;
  color: var(--teks-lembut); font-size: .88rem; line-height: 1.75;
}
.langkah-pasang li::marker { color: var(--teks-samar); }

.lencana-terpasang {
  display: inline-flex; align-items: center; gap: .45rem;
  padding: .3rem .7rem; border-radius: 999px;
  background: var(--hijau-lembut); color: var(--hijau);
  font-size: .82rem; font-weight: 550;
}

/* Kartu pemasangan: ikon di kiri, penjelasan di kanan. Menumpuk di ponsel —
   ikon 72px di samping teks pada layar 360px menyisakan lebar baca yang tidak
   cukup untuk satu kalimat utuh. */
.baris-pwa { display: flex; gap: 1.1rem; align-items: flex-start; }
.baris-pwa .isi-pwa { flex: 1; min-width: 0; }
.baris-pwa .ikon-pratinjau {
  flex: none; width: 72px; height: 72px; border-radius: 18px;
  border: 1px solid var(--garis); background: var(--permukaan-2);
}
.lencana-terpasang svg { width: 14px; height: 14px; }

@media (max-width: 520px) {
  .baris-pwa { flex-direction: column; gap: .8rem; }
}

/* Catatan pembeda tiga lambang "Rp". Diberi latar sendiri karena isinya
   koreksi terhadap dugaan yang wajar, bukan keterangan tambahan — kalau
   tampil sebagai teks samar seperti petunjuk lain, ia tidak akan dibaca
   justru oleh orang yang sedang mencarinya. */
.catatan-ikon {
  padding: .8rem 1rem;
  border: 1px solid var(--garis);
  border-left: 3px solid var(--aksen);
  border-radius: var(--radius-kecil);
  background: var(--permukaan-2);
}
.catatan-ikon p { margin: 0; }
/* Jaraknya diatur di sini, bukan lewat kelas utilitas pada elemennya: aturan
   margin:0 di atas lebih spesifik dan diam-diam mengalahkan kelas itu. */
.catatan-ikon .langkah-pasang { margin: .45rem 0 0; }
.catatan-ikon .langkah-pasang + p,
.catatan-ikon p + p { margin-top: .55rem; }
