/* =====================================================================
   Nota — lembar gaya utama

   Ditulis tangan, tanpa framework dan tanpa langkah build. Semuanya
   disajikan dari domain sendiri, jadi Content-Security-Policy bisa
   dikunci ketat dan aplikasi tetap jalan waktu sinyal hilang.

   Susunan berkas:
     1. Token warna & tema
     2. Dasar
     3. Tata letak
     4. Navigasi bawah
     5. Komponen
     6. Formulir
     7. Halaman khusus (scan, review, dashboard)
     8. Animasi
   ===================================================================== */


/* =====================================================================
   1. TOKEN

   Warna dasar diambil dari dunia struk itu sendiri: kertas termal yang
   agak kehijauan, tinta printer kasir yang gelap, dan satu aksen hijau
   tua seperti layar mesin EDC.
   ===================================================================== */

:root {
    --kertas:       #F4F6F2;
    --permukaan:    #FFFFFF;
    --permukaan-2:  #EDF0EA;
    --tinta:        #14191A;
    --tinta-lembut: #5B6462;
    --tinta-samar:  #8A9391;
    --garis:        #DDE2D9;
    --garis-halus:  #E9ECE5;

    --aksen:        #1F6F5C;
    --aksen-terang: #E2EFE9;
    --aksen-gelap:  #175449;

    --bagus:        #1F6F5C;
    --bagus-bg:     #E2EFE9;
    --hati:         #8F5807;
    --hati-bg:      #F8F0DC;
    --bahaya:       #A33128;
    --bahaya-bg:    #F9E7E4;

    /* Nuansa khusus kartu Hutang & Piutang.
       Hutang bukan pengeluaran dan bukan aset — dia kewajiban yang
       berpindah tangan. Warnanya sengaja dibedakan supaya mata tidak
       menyamakannya dengan kartu belanja di atasnya. Nila kebiruan,
       masih satu keluarga dengan hijau tinta kasir, tapi jelas beda. */
    --nota:         #46557F;
    --nota-bg:      #EDF0F7;
    --nota-garis:   #C9D2E6;

    /* Kekayaan: aset dan tabungan.

       Dua kartu ini satu-satunya di beranda yang angkanya NAIK kalau kamu
       melakukan hal yang benar — semua kartu lain bercerita tentang uang
       yang berkurang. Warnanya berbeda supaya kelompok "kekayaan" terbaca
       sebagai kelompok, bukan sisa halaman. */
    --aset:         #8A6224;
    --aset-bg:      #FAF4E8;
    --aset-garis:   #E8D9BC;

    --tabung:       #3E9B6E;
    --tabung-bg:    #EAF4EF;
    --tabung-garis: #C2DFD2;

    /* Saldo kas: satu-satunya angka yang BERJALAN lintas bulan.
       Semua angka lain menjawab "berapa dalam rentang ini". */
    --kas:          #7A4F9E;
    --kas-bg:       #F4EFF9;
    --kas-garis:    #DECDEC;

    --bayang-1: 0 1px 2px rgba(20, 25, 26, .05);
    --bayang-2: 0 2px 4px rgba(20, 25, 26, .06), 0 8px 20px -10px rgba(20, 25, 26, .16);
    --bayang-3: 0 4px 8px rgba(20, 25, 26, .08), 0 16px 32px -12px rgba(20, 25, 26, .22);

    --radius:    14px;
    --radius-sm: 9px;
    --radius-lg: 20px;

    --nav-tinggi: 64px;
    --aman-bawah: env(safe-area-inset-bottom, 0px);

    --pegas: cubic-bezier(.34, 1.56, .64, 1);
    --halus: cubic-bezier(.4, 0, .2, 1);
}

@media (prefers-color-scheme: dark) {
    :root:not([data-tema="terang"]) {
        --kertas:       #0E1211;
        --permukaan:    #171B1A;
        --permukaan-2:  #1E2422;
        --tinta:        #E7EBE5;
        --tinta-lembut: #98A19D;
        --tinta-samar:  #6B7472;
        --garis:        #272E2C;
        --garis-halus:  #1F2523;

        --aksen:        #56C4A0;
        --aksen-terang: #16302A;
        --aksen-gelap:  #7DD9BC;

        --bagus:        #56C4A0;
        --bagus-bg:     #16302A;
        --hati:         #D9A441;
        --hati-bg:      #2E2716;
        --bahaya:       #E28078;
        --bahaya-bg:    #331E1C;

        --nota:         #9DB0DE;
        --nota-bg:      #1B2233;
        --nota-garis:   #2A3450;

        --aset:         #D9BC7E;
        --aset-bg:      #26210F;
        --aset-garis:   #3A3218;

        --tabung:       #7FCFA8;
        --tabung-bg:    #14241C;
        --tabung-garis: #1F3A2D;

        --kas:          #C0A2E0;
        --kas-bg:       #1E1729;
        --kas-garis:    #322544;

        --bayang-1: 0 1px 2px rgba(0, 0, 0, .4);
        --bayang-2: 0 2px 6px rgba(0, 0, 0, .45);
        --bayang-3: 0 8px 24px rgba(0, 0, 0, .55);
    }
}

:root[data-tema="gelap"] {
    --kertas:       #0E1211;
    --permukaan:    #171B1A;
    --permukaan-2:  #1E2422;
    --tinta:        #E7EBE5;
    --tinta-lembut: #98A19D;
    --tinta-samar:  #6B7472;
    --garis:        #272E2C;
    --garis-halus:  #1F2523;

    --aksen:        #56C4A0;
    --aksen-terang: #16302A;
    --aksen-gelap:  #7DD9BC;

    --bagus:        #56C4A0;
    --bagus-bg:     #16302A;
    --hati:         #D9A441;
    --hati-bg:      #2E2716;
    --bahaya:       #E28078;
    --bahaya-bg:    #331E1C;

    --nota:         #9DB0DE;
    --nota-bg:      #1B2233;
    --nota-garis:   #2A3450;

    --aset:         #D9BC7E;
    --aset-bg:      #26210F;
    --aset-garis:   #3A3218;

    --tabung:       #7FCFA8;
    --tabung-bg:    #14241C;
    --tabung-garis: #1F3A2D;

    --kas:          #C0A2E0;
    --kas-bg:       #1E1729;
    --kas-garis:    #322544;

    --bayang-1: 0 1px 2px rgba(0, 0, 0, .4);
    --bayang-2: 0 2px 6px rgba(0, 0, 0, .45);
    --bayang-3: 0 8px 24px rgba(0, 0, 0, .55);
}


/* =====================================================================
   2. DASAR
   ===================================================================== */

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

/* Atribut hidden HARUS menang atas display apa pun yang ditulis di sini.
   Ini bukan kerapian — ini pernah jadi bug beneran. Lembar profil diberi
   "display:flex" supaya isinya bisa menggulir, dan aturan itu mengalahkan
   display:none bawaan browser untuk [hidden]. Hasilnya: lembar yang
   MENURUT KODE tertutup tetap menutupi seluruh halaman Masuk dan menelan
   setiap ketukan — tombolnya ada, kelihatan, tapi tidak bisa ditekan,
   dan tidak ada satu pun tanda kenapa.
   Ditemukan waktu robot uji gagal menekan tombol yang jelas-jelas terlihat. */
[hidden] { display: none !important; }

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

body {
    margin: 0;
    background: var(--kertas);
    color: var(--tinta);
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
                 "Helvetica Neue", "Noto Sans", sans-serif;
    font-size: 16px;
    line-height: 1.55;
    -webkit-font-smoothing: antialiased;
    -webkit-tap-highlight-color: transparent;
    overscroll-behavior-y: contain;

    /* ANGKA SELEBAR SAMA, DI SELURUH APLIKASI.

       Aplikasi ini isinya kolom nominal yang dibaca dengan cara dipindai
       ke bawah, bukan dibaca satu-satu. Dengan angka proporsional, "1"
       lebih sempit daripada "8", jadi tiap baris bergeser sedikit dan
       mata kehilangan garis lurus untuk diikuti — Rp 600.000 dan
       Rp 850.000 tidak sejajar walaupun dua-duanya rata kanan.

       Dulu ini ditulis satu per satu di .angka, .nilai-besar,
       .nilai-sedang, .kisi-nilai — dan tiap kali ada tempat baru yang
       menampilkan uang, tempat itu ketinggalan. Ditaruh di body sekali
       supaya tidak bisa lupa. Yang bukan angka tidak terpengaruh. */
    font-variant-numeric: tabular-nums;
}

h1, h2, h3, h4 {
    margin: 0;
    line-height: 1.2;
    letter-spacing: -0.02em;
    font-weight: 700;
}

h1 { font-size: 1.6rem; }
h2 { font-size: 1.15rem; }
h3 { font-size: .98rem; }

p { margin: 0; }

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

a:active { opacity: .7; }

img { max-width: 100%; display: block; }

.mono {
    font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
    font-variant-numeric: tabular-nums;
}

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

:focus-visible {
    outline: 2px solid var(--aksen);
    outline-offset: 2px;
    border-radius: 4px;
}

::selection {
    background: var(--aksen-terang);
    color: var(--aksen-gelap);
}


/* =====================================================================
   3. TATA LETAK
   ===================================================================== */

.bungkus {
    max-width: 640px;
    margin-inline: auto;
    padding: 0 16px calc(var(--nav-tinggi) + var(--aman-bawah) + 24px);
}

.bungkus-lebar { max-width: 900px; }

.kepala {
    position: sticky;
    top: 0;
    z-index: 40;
    background: color-mix(in srgb, var(--kertas) 88%, transparent);
    backdrop-filter: saturate(180%) blur(14px);
    -webkit-backdrop-filter: saturate(180%) blur(14px);
    border-bottom: 1px solid var(--garis-halus);
    padding: 12px 0 11px;
    margin-bottom: 16px;
}

.kepala-isi {
    max-width: 640px;
    margin-inline: auto;
    padding: 0 16px;
    display: flex;
    align-items: center;
    gap: 12px;
    min-height: 34px;
}

.kepala-judul {
    font-size: 1.28rem;
    font-weight: 700;
    letter-spacing: -0.025em;
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.kepala-aksi {
    display: flex;
    gap: 8px;
    flex-shrink: 0;
}

.tumpuk      { display: flex; flex-direction: column; gap: 16px; }
.tumpuk-sm   { display: flex; flex-direction: column; gap: 10px; }
.tumpuk-xs   { display: flex; flex-direction: column; gap: 6px; }
.baris       { display: flex; align-items: center; gap: 10px; }
.baris-antara{ display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.isi-sisa    { flex: 1; min-width: 0; }

.grid-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px; }
.grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }

.judul-bagian {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 10px;
    margin-bottom: 10px;
}

.judul-bagian h2 { font-size: 1rem; }

.label-kecil {
    font-size: .68rem;
    font-weight: 700;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--tinta-samar);
}

.teks-lembut { color: var(--tinta-lembut); font-size: .88rem; }
.teks-samar  { color: var(--tinta-samar);  font-size: .82rem; }
.teks-kecil  { font-size: .78rem; }
.teks-kanan  { text-align: right; }
.teks-tengah { text-align: center; }

.potong {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.sembunyi { display: none !important; }

.gulir-x {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: thin;
}


/* =====================================================================
   4. NAVIGASI BAWAH

   Lima slot dengan tombol Scan menonjol di tengah. Ditaruh di bawah
   supaya jempol tidak perlu naik ke atas layar.
   ===================================================================== */

.nav {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 50;
    height: calc(var(--nav-tinggi) + var(--aman-bawah));
    padding-bottom: var(--aman-bawah);
    background: color-mix(in srgb, var(--permukaan) 92%, transparent);
    backdrop-filter: saturate(180%) blur(16px);
    -webkit-backdrop-filter: saturate(180%) blur(16px);
    border-top: 1px solid var(--garis);
    display: flex;
    align-items: stretch;
}

.nav-item {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 3px;
    color: var(--tinta-samar);
    font-size: .62rem;
    font-weight: 600;
    letter-spacing: .01em;
    text-decoration: none;
    position: relative;
    transition: color .18s var(--halus);
}

/* Lencana pemberitahuan di menu bawah.
   .nav-item sudah position:relative, jadi tinggal ditempel. */
.nav-lencana {
    position: absolute;
    top: 4px;
    left: 50%;
    margin-left: 4px;
    min-width: 16px;
    height: 16px;
    padding: 0 4px;
    border-radius: 999px;
    background: var(--bahaya);
    color: #fff;
    font-size: .58rem;
    font-weight: 700;
    line-height: 16px;
    text-align: center;
    box-shadow: 0 0 0 2px var(--permukaan);
}

.nav-item svg {
    width: 22px;
    height: 22px;
    stroke: currentColor;
    fill: none;
    stroke-width: 1.8;
    stroke-linecap: round;
    stroke-linejoin: round;
    transition: transform .28s var(--pegas);
}

.nav-item.aktif { color: var(--aksen); }
.nav-item.aktif svg { transform: translateY(-1px) scale(1.06); }

/* Titik penanda halaman aktif */
.nav-item.aktif::after {
    content: "";
    position: absolute;
    top: 6px;
    width: 4px;
    height: 4px;
    border-radius: 50%;
    background: var(--aksen);
    animation: munculTitik .3s var(--pegas);
}

.nav-item:active svg { transform: scale(.9); }

/* Tombol scan di tengah */
.nav-scan {
    flex: 0 0 auto;
    width: 62px;
    display: flex;
    align-items: center;
    justify-content: center;
    position: relative;
}

.nav-scan-tombol {
    position: absolute;
    top: -18px;
    width: 56px;
    height: 56px;
    border-radius: 50%;
    background: var(--aksen);
    color: #fff;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: var(--bayang-3), 0 0 0 5px var(--kertas);
    transition: transform .3s var(--pegas);
    border: none;
    cursor: pointer;
}

.nav-scan-tombol svg {
    width: 26px;
    height: 26px;
    stroke: currentColor;
    fill: none;
    stroke-width: 2;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.nav-scan-tombol:active { transform: scale(.88); }


/* =====================================================================
   5. KOMPONEN
   ===================================================================== */

/* --- Kartu ------------------------------------------------------------

   TIGA TINGKAT, BUKAN SATU.

   Beranda pernah memuat sebelas kartu yang semuanya berteriak sama
   keras: permukaan putih yang sama, radius sama, garis tepi sama,
   bayangan sama. Waktu semuanya kartu, tidak ada yang jadi kartu — mata
   masuk ke halaman dan tidak punya tempat mendarat.

   Sekarang bentuknya menyatakan perannya:

     .kartu-utama   pahlawan   — bayangan penuh, radius besar, satu per layar
     .kartu         bisa ditindak — garis tepi, TANPA bayangan
     .kartu-sunyi   cuma dibaca  — tanpa kotak sama sekali, cuma garis pemisah

   Yang dihapus dari .kartu cuma bayangannya. Kedengaran sepele, tapi
   bayangan itulah yang membuat sebelas kotak sama-sama tampak
   mengambang di tingkat yang sama. */

.kartu {
    background: var(--permukaan);
    border: 1px solid var(--garis);
    border-radius: var(--radius);
    padding: 14px;
}

.kartu-rapat { padding: 11px 13px; }
.kartu-lega  { padding: 18px; }

/* Tingkat tiga: yang cuma dibaca, tidak pernah ditekan.

   Kekayaan bersih, ringkasan aset, catatan penjelas. Isinya penting,
   tapi tidak ada yang bisa dilakukan di sana — dan sesuatu yang
   berbingkai seperti tombol akan terus ditawar-tawarkan ke mata
   walaupun tidak menawarkan apa pun. */
.kartu-sunyi {
    background: none;
    border: none;
    border-top: 1px solid var(--garis-halus);
    border-radius: 0;
    padding: 14px 2px 2px;
}

.kartu-klik {
    display: block;
    color: inherit;
    transition: transform .18s var(--halus), background .18s var(--halus);
}

.kartu-klik:active {
    transform: scale(.985);
    background: var(--permukaan-2);
}

/* --- Kartu ringkasan besar di beranda --- */

.kartu-utama {
    background: var(--permukaan);
    border: 1px solid var(--garis);
    border-radius: var(--radius-lg);
    padding: 18px;
    box-shadow: var(--bayang-2);
    position: relative;
    overflow: hidden;
}

/* Tepi bergerigi seperti struk yang disobek */
.kartu-utama::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    bottom: -1px;
    height: 8px;
    background: var(--garis);
    -webkit-mask: radial-gradient(circle at 50% 100%, transparent 0 4px, #000 4.5px) 50% 100% / 12px 100% repeat-x;
    mask: radial-gradient(circle at 50% 100%, transparent 0 4px, #000 4.5px) 50% 100% / 12px 100% repeat-x;
}

.nilai-besar {
    font-size: 2.35rem;
    font-weight: 700;
    letter-spacing: -0.04em;
    line-height: 1.02;
}

.nilai-sedang {
    font-size: 1.28rem;
    font-weight: 700;
    letter-spacing: -0.025em;
}

/* --- Simbol mata uang --------------------------------------------------

   "Rp" bukan angka, tapi dulu dia ditulis sebesar dan setebal angkanya.
   Akibatnya tiap baris dimulai dengan dua huruf gelap yang mendorong
   digitnya menjauh dari tepi, dan kolom nominal jadi tidak punya awalan
   yang lurus — mata membaca "Rp" dulu di tiap baris sebelum sampai ke
   angka yang sebenarnya dicari.

   Dikecilkan dan dipudarkan. Simbolnya tetap ada — ini aplikasi dua mata
   uang, membuangnya akan membuat Rp dan RM tidak bisa dibedakan — tapi
   dia jadi keterangan, bukan isi. */
.uang-sim {
    font-size: .72em;
    font-weight: 600;
    color: var(--tinta-samar);
    letter-spacing: 0;
    margin-inline-end: .18em;
}

/* --- Lencana --- */

.lencana {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 3px 8px;
    border-radius: 999px;
    font-size: .7rem;
    font-weight: 700;
    letter-spacing: .01em;
    background: var(--permukaan-2);
    color: var(--tinta-lembut);
    white-space: nowrap;
}

.lencana-bagus  { background: var(--bagus-bg);  color: var(--bagus); }
.lencana-hati   { background: var(--hati-bg);   color: var(--hati); }
.lencana-bahaya { background: var(--bahaya-bg); color: var(--bahaya); }
.lencana-aksen  { background: var(--aksen-terang); color: var(--aksen); }

/* --- Tombol --- */

.tombol {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 7px;
    padding: 11px 17px;
    border-radius: var(--radius-sm);
    border: 1px solid transparent;
    background: var(--aksen);
    color: #fff;
    font-size: .92rem;
    font-weight: 600;
    font-family: inherit;
    cursor: pointer;
    transition: transform .16s var(--halus), opacity .16s var(--halus);
    text-decoration: none;
    min-height: 44px;   /* target sentuh nyaman di HP */
}

.tombol:active { transform: scale(.96); }
.tombol:disabled { opacity: .5; cursor: not-allowed; transform: none; }

.tombol svg {
    width: 18px;
    height: 18px;
    stroke: currentColor;
    fill: none;
    stroke-width: 1.9;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.tombol-garis {
    background: var(--permukaan);
    color: var(--tinta);
    border-color: var(--garis);
}

.tombol-hantu {
    background: transparent;
    color: var(--tinta-lembut);
    border-color: transparent;
    padding-inline: 10px;
}

.tombol-bahaya { background: var(--bahaya); }

.tombol-kecil {
    padding: 7px 12px;
    font-size: .82rem;
    min-height: 36px;
    border-radius: 8px;
}

.tombol-penuh { width: 100%; }

.tombol-ikon {
    width: 38px;
    height: 38px;
    min-height: 38px;
    padding: 0;
    border-radius: 10px;
    background: var(--permukaan-2);
    color: var(--tinta-lembut);
    border: 1px solid var(--garis);
}

/* --- Pesan kilat --- */

.kilat-wadah {
    position: fixed;
    left: 12px;
    right: 12px;
    top: 12px;
    z-index: 90;
    display: flex;
    flex-direction: column;
    gap: 8px;
    pointer-events: none;
}

.kilat {
    background: var(--permukaan);
    border: 1px solid var(--garis);
    border-left: 3px solid var(--aksen);
    border-radius: var(--radius-sm);
    padding: 11px 14px;
    box-shadow: var(--bayang-3);
    font-size: .88rem;
    line-height: 1.45;
    pointer-events: auto;
    animation: masukAtas .38s var(--pegas);
    max-width: 620px;
    margin-inline: auto;
    width: 100%;
}

.kilat-error   { border-left-color: var(--bahaya); }
.kilat-success { border-left-color: var(--bagus); }

/* Bukan kesalahan, tapi juga bukan kabar baik: sesuatu tersimpan, hanya
   saja ada bagian yang belum lengkap — misalnya aset tersimpan tapi
   kursnya belum ada. */
.kilat-perhatian { border-left-color: var(--hati); }
.kilat-keluar  { animation: keluarAtas .28s var(--halus) forwards; }

/* --- Daftar --- */

.daftar {
    display: flex;
    flex-direction: column;
    background: var(--permukaan);
    border: 1px solid var(--garis);
    border-radius: var(--radius);
    overflow: hidden;
}

.daftar-baris {
    display: flex;
    align-items: center;
    gap: 11px;
    padding: 12px 14px;
    border-bottom: 1px solid var(--garis-halus);
    color: inherit;
    text-decoration: none;
    transition: background .15s var(--halus);
}

.daftar-baris:last-child { border-bottom: none; }
.daftar-baris:active { background: var(--permukaan-2); }

.ikon-bulat {
    width: 38px;
    height: 38px;
    border-radius: 11px;
    display: grid;
    place-items: center;
    font-size: 1.05rem;
    flex-shrink: 0;
    background: var(--permukaan-2);
}

/* Ikon garis untuk hal-hal sistem. Satu bahasa dengan navigasi bawah,
   dan yang terpenting: ikut warna teksnya, jadi dia benar di mode gelap
   tanpa perlu aset kedua. */
.ikon {
    stroke: currentColor;
    fill: none;
    stroke-width: 1.7;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.ikon-bulat > .ikon { color: var(--tinta-lembut); }

/* Di kartu berwarna, ikon sistemnya ikut warna kartunya. Kalau dia
   tetap warna tinta, dia jadi satu-satunya benda gelap di kartu yang
   selebihnya sudah sepakat pada satu warna — dan mata membacanya
   sebagai sesuatu yang berbeda jenis, padahal cuma ikon judulnya. */
.kartu-aset   .baris-antara > .ikon { color: var(--aset); }
.kartu-tabung .baris-antara > .ikon { color: var(--tabung); }
.kartu-kas    .baris-antara > .ikon { color: var(--kas); }
.kartu-nota   .baris-antara > .ikon { color: var(--nota); }

/* --- Keadaan kosong --- */

.kosong {
    text-align: center;
    padding: 34px 20px;
    color: var(--tinta-samar);
}

.kosong-ikon {
    font-size: 2.4rem;
    margin-bottom: 10px;
    opacity: .55;
}

.kosong h3 {
    color: var(--tinta-lembut);
    margin-bottom: 5px;
    font-size: .95rem;
}

/* --- Bar kemajuan --- */

.bar {
    height: 7px;
    background: var(--permukaan-2);
    border-radius: 999px;
    overflow: hidden;
}

.bar-isi {
    height: 100%;
    background: var(--aksen);
    border-radius: 999px;
    transition: width .7s var(--pegas);
}

/* Batang untuk bulan yang sudah lewat.
   Sengaja aksen yang diredupkan, BUKAN warna garis: warna garis hampir
   sama persis dengan dasar batangnya, jadi batang penuh pun tampak
   kosong. Opacity dipakai supaya jarak warnanya terjaga di terang dan
   gelap sekaligus, tanpa perlu dua token yang bisa lupa disamakan. */
.bar-isi.bar-lalu {
    background: var(--aksen);
    opacity: .42;
}

/* --- Baris ringkasan angka --- */

.rincian {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 12px;
    padding: 6px 0;
    font-size: .89rem;
}

.rincian + .rincian { border-top: 1px dashed var(--garis-halus); }

.rincian-total {
    border-top: 1px solid var(--garis) !important;
    margin-top: 4px;
    padding-top: 10px;
    font-weight: 700;
    font-size: 1rem;
}

/* --- Pemilih periode --- */

.pil-periode {
    display: flex;
    gap: 6px;
    overflow-x: auto;
    padding: 2px 0 4px;
    scrollbar-width: none;
}

.pil-periode::-webkit-scrollbar { display: none; }

.pil {
    flex-shrink: 0;
    padding: 7px 13px;
    border-radius: 999px;
    background: var(--permukaan);
    border: 1px solid var(--garis);
    color: var(--tinta-lembut);
    font-size: .8rem;
    font-weight: 600;
    text-decoration: none;
    transition: all .18s var(--halus);
    white-space: nowrap;
}

.pil.aktif {
    background: var(--aksen);
    border-color: var(--aksen);
    color: #fff;
}


/* =====================================================================
   LIPATAN — <details> yang dipakai sebagai menu dan sebagai penjelasan

   KENAPA <details>, BUKAN JAVASCRIPT

   Content-Security-Policy di aplikasi ini melarang skrip sebaris, jadi
   tiap tombol buka-tutup harus menitip perilakunya ke app.js. Itu
   berarti satu tombol lagi yang bisa diam-diam berhenti bekerja waktu
   skripnya gagal dimuat — dan halaman yang tombolnya diam terlihat
   persis seperti halaman yang tombolnya tidak diklik.

   <details> membuka dan menutup tanpa satu baris skrip pun, keadaannya
   dibaca pembaca layar dengan benar, dan tetap bekerja di halaman
   offline. Yang perlu ditulis cuma penampilannya.
   ===================================================================== */

.lipat > summary {
    list-style: none;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: 5px;
    -webkit-tap-highlight-color: transparent;
}

.lipat > summary::-webkit-details-marker { display: none; }

/* Panah yang berputar waktu terbuka — satu-satunya tanda bahwa ini
   bisa ditekan, jadi dia tidak boleh hilang. */
.lipat > summary::after {
    content: "";
    width: 6px;
    height: 6px;
    border-right: 1.5px solid currentColor;
    border-bottom: 1.5px solid currentColor;
    transform: translateY(-2px) rotate(45deg);
    transition: transform .2s var(--halus);
    opacity: .6;
}

.lipat[open] > summary::after { transform: translateY(1px) rotate(-135deg); }

/* --- Lipatan sebagai MENU: pemilih periode yang ringkas ------------- */

.menu-lipat { position: relative; }

.menu-lipat > summary {
    padding: 5px 11px;
    border: 1px solid var(--garis);
    border-radius: 999px;
    background: var(--permukaan);
    font-size: .78rem;
    font-weight: 650;
    color: var(--tinta-lembut);
}

.menu-lipat > summary:hover { color: var(--tinta); }

.menu-lipat-isi {
    position: absolute;
    z-index: 30;
    top: calc(100% + 6px);
    inset-inline-start: 0;
    min-width: 168px;
    padding: 5px;
    background: var(--permukaan);
    border: 1px solid var(--garis);
    border-radius: var(--radius-sm);
    box-shadow: var(--bayang-3);
    display: flex;
    flex-direction: column;
    gap: 1px;
}

/* Menu yang menempel di tepi kanan layar akan terpotong kalau dibuka ke
   kanan. Varian ini dipakai waktu pemicunya ada di sisi kanan. */
.menu-lipat-kanan .menu-lipat-isi {
    inset-inline-start: auto;
    inset-inline-end: 0;
}

.menu-lipat-isi a {
    padding: 9px 11px;
    border-radius: 7px;
    font-size: .84rem;
    font-weight: 600;
    color: var(--tinta-lembut);
    white-space: nowrap;
}

.menu-lipat-isi a:hover { background: var(--permukaan-2); }

.menu-lipat-isi a.aktif {
    background: var(--aksen-terang);
    color: var(--aksen-gelap);
}

/* --- Lipatan sebagai PENJELASAN ------------------------------------

   Kalimat yang menjelaskan kenapa sebuah angka berperilaku aneh memang
   perlu ada — tapi dia perlu ada waktu DITANYAKAN, bukan setiap kali
   halamannya dibuka. Penjelasan permanen setinggi tiga baris di atas
   daftar adalah tanda bahwa desainnya menitipkan pekerjaannya ke teks. */

.info-lipat > summary {
    width: 22px;
    height: 22px;
    justify-content: center;
    border-radius: 999px;
    background: var(--permukaan-2);
    color: var(--tinta-lembut);
    font-size: .72rem;
    font-weight: 700;
    flex-shrink: 0;
}

.info-lipat > summary::after { display: none; }

.info-lipat > p {
    margin-top: 7px;
    color: var(--tinta-samar);
    font-size: .78rem;
    line-height: 1.5;
}

/* --- Lipatan sebagai KOTAK CARI -------------------------------------

   Kotak cari selalu-terbuka memakan 58px di atas daftar, setiap kali,
   untuk sesuatu yang dipakai sesekali. Dilipat jadi satu keping yang
   duduk sebaris dengan pemilih periode — dua baris chrome jadi satu.

   Kalau pencariannya sedang aktif, lipatannya dibuka paksa lewat
   atribut open: penyaring yang sedang bekerja tapi tidak kelihatan
   adalah cara tercepat membuat orang mengira datanya hilang. */

.cari-lipat > summary {
    padding: 5px 11px;
    border: 1px solid var(--garis);
    border-radius: 999px;
    background: var(--permukaan);
    font-size: .78rem;
    font-weight: 650;
    color: var(--tinta-lembut);
}

.cari-lipat > summary::after { display: none; }

.cari-lipat[open] > summary {
    background: var(--aksen-terang);
    border-color: var(--aksen-terang);
    color: var(--aksen-gelap);
}

.cari-lipat > div { padding-top: 8px; }

/* Baris penyaring: cari + periode, satu baris, boleh menggulir kalau
   labelnya panjang. Posisinya relative supaya menu di dalamnya
   menggantung ke baris ini, bukan ke seluruh halaman. */
.baris-saring {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    flex-wrap: wrap;
}

.baris-saring > .cari-lipat[open] { flex: 1 1 100%; order: 2; }

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

.grafik-wadah {
    position: relative;
    width: 100%;
}

.grafik-wadah canvas { display: block; width: 100% !important; }


/* =====================================================================
   6. FORMULIR
   ===================================================================== */

.bidang { display: flex; flex-direction: column; gap: 5px; }

.bidang label {
    font-size: .78rem;
    font-weight: 600;
    color: var(--tinta-lembut);
}

input[type="text"], input[type="email"], input[type="password"],
input[type="number"], input[type="date"], input[type="time"],
input[type="search"], select, textarea {
    width: 100%;
    padding: 11px 13px;
    border: 1px solid var(--garis);
    border-radius: var(--radius-sm);
    background: var(--permukaan);
    color: var(--tinta);
    font-size: 16px;   /* 16px mencegah iOS memperbesar layar saat fokus */
    font-family: inherit;
    line-height: 1.4;
    transition: border-color .18s var(--halus), box-shadow .18s var(--halus);
    -webkit-appearance: none;
    appearance: none;
}

input:focus, select:focus, textarea:focus {
    outline: none;
    border-color: var(--aksen);
    box-shadow: 0 0 0 3px var(--aksen-terang);
}

input::placeholder, textarea::placeholder { color: var(--tinta-samar); }

textarea { resize: vertical; min-height: 76px; }

select {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5L6 6.5L11 1.5' stroke='%238A9391' stroke-width='1.6' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 13px center;
    padding-right: 34px;
}

.input-uang { position: relative; }

.input-uang .simbol {
    position: absolute;
    left: 13px;
    top: 50%;
    transform: translateY(-50%);
    color: var(--tinta-samar);
    font-size: .88rem;
    font-weight: 600;
    pointer-events: none;
}

.input-uang input {
    padding-left: 42px;
    font-variant-numeric: tabular-nums;
}

/* --- Kolom nominal sebagai PAHLAWAN ----------------------------------

   Di formulir pemasukan, pengeluaran, aset, dan setoran, kolom nominal
   dulu tampil persis sama dengan kolom Catatan: tinggi yang sama, huruf
   yang sama, bobot yang sama. Padahal hampir seluruh alasan orang
   membuka halaman itu ada di kolom tersebut — sisanya keterangan.

   Bentuk yang sama untuk kepentingan yang jauh berbeda memaksa mata
   membaca label dulu untuk tahu mana yang penting. Angkanya sekarang
   dibesarkan sampai seukuran angka di kartu ringkasan, jadi apa yang
   sedang diketik terbaca sekali lihat — termasuk waktu jempol menutupi
   separuh layar. */

.input-uang.besar input {
    font-size: 1.85rem;
    font-weight: 700;
    letter-spacing: -0.03em;
    padding: 14px 14px 14px 52px;
    line-height: 1.2;
}

.input-uang.besar .simbol {
    font-size: 1rem;
    left: 15px;
}

/* --- Ikon kalender bawaan ---------------------------------------------

   input[type=date] menggambar ikonnya sendiri, dan warnanya ditentukan
   browser: hitam pekat di mode terang, dan di mode gelap sering tetap
   hitam sehingga hampir tidak kelihatan di atas permukaan gelap. Satu
   ikon yang tidak ikut aturan warna aplikasi, tepat di sebelah kolom
   yang mengikutinya.

   filter dipakai karena elemen bayangan ini tidak menerima properti
   warna apa pun — cuma itu satu-satunya pegangan yang ada. */
input[type="date"]::-webkit-calendar-picker-indicator,
input[type="time"]::-webkit-calendar-picker-indicator {
    opacity: .45;
    cursor: pointer;
}

input[type="date"]::-webkit-calendar-picker-indicator:hover,
input[type="time"]::-webkit-calendar-picker-indicator:hover { opacity: .8; }

@media (prefers-color-scheme: dark) {
    :root:not([data-tema="terang"]) input[type="date"]::-webkit-calendar-picker-indicator,
    :root:not([data-tema="terang"]) input[type="time"]::-webkit-calendar-picker-indicator {
        filter: invert(1);
        opacity: .55;
    }
}

[data-tema="gelap"] input[type="date"]::-webkit-calendar-picker-indicator,
[data-tema="gelap"] input[type="time"]::-webkit-calendar-picker-indicator {
    filter: invert(1);
    opacity: .55;
}

/* --- Sakelar --- */

.sakelar {
    display: inline-flex;
    align-items: center;
    gap: 9px;
    cursor: pointer;
    user-select: none;
}

.sakelar input { position: absolute; opacity: 0; width: 0; height: 0; }

.sakelar-jalur {
    width: 42px;
    height: 25px;
    border-radius: 999px;
    background: var(--permukaan-2);
    border: 1px solid var(--garis);
    position: relative;
    transition: background .22s var(--halus), border-color .22s var(--halus);
    flex-shrink: 0;
}

.sakelar-bulat {
    position: absolute;
    top: 2px;
    left: 2px;
    width: 19px;
    height: 19px;
    border-radius: 50%;
    background: var(--permukaan);
    box-shadow: var(--bayang-1);
    transition: transform .26s var(--pegas);
}

.sakelar input:checked + .sakelar-jalur {
    background: var(--aksen);
    border-color: var(--aksen);
}

.sakelar input:checked + .sakelar-jalur .sakelar-bulat {
    transform: translateX(17px);
}

.sakelar input:focus-visible + .sakelar-jalur {
    box-shadow: 0 0 0 3px var(--aksen-terang);
}

/* --- Pilihan segmen (mis. IDR / MYR) --- */

.segmen {
    display: flex;
    background: var(--permukaan-2);
    border: 1px solid var(--garis);
    border-radius: var(--radius-sm);
    padding: 3px;
    gap: 3px;
}

.segmen label {
    flex: 1;
    text-align: center;
    padding: 8px 10px;
    border-radius: 6px;
    font-size: .84rem;
    font-weight: 600;
    color: var(--tinta-lembut);
    cursor: pointer;
    transition: all .2s var(--halus);
}

.segmen input { position: absolute; opacity: 0; width: 0; height: 0; }

.segmen input:checked + label {
    background: var(--permukaan);
    color: var(--aksen);
    box-shadow: var(--bayang-1);
}


/* --- Kartu berwarna: artinya tetap, volumenya turun ------------------

   Beranda punya lima keluarga aksen: hijau belanja, ungu kas, emas aset,
   tosca tabungan, nila hutang. Satu per satu pilihannya beralasan —
   masing-masing menandai jenis uang yang berbeda, dan itu memang perlu
   dibedakan.

   Berbarengan, hasilnya lain. Lima kartu berlatar warna di satu layar
   membuat halaman tidak punya warna dominan, dan mata kehilangan
   jangkar: tidak ada yang menonjol karena semuanya menonjol.

   Yang diubah bukan warnanya, tapi LUASNYA. Warna sekarang cuma di
   angka dan di satu garis tipis di kiri — bukan di latar, garis tepi,
   dan label sekaligus. "Kas itu ungu" tetap terbaca dalam sekali lihat,
   tapi halamannya kembali punya satu suara.

   Satu-satunya yang masih berlatar warna: kartu "Belum diperiksa".
   Dia bukan informasi, dia permintaan — dan tepat satu permintaan
   berwarna per layar masih bisa dilihat sebagai permintaan. */

.kartu-nota,
.kartu-aset,
.kartu-tabung,
.kartu-kas {
    background: var(--permukaan);
    position: relative;
    overflow: hidden;
}

/* Garis tipis di tepi kiri — pengganti seluruh latar berwarna. */
.kartu-nota::before,
.kartu-aset::before,
.kartu-tabung::before,
.kartu-kas::before {
    content: "";
    position: absolute;
    inset-block: 0;
    inset-inline-start: 0;
    width: 3px;
    background: currentColor;
}

.kartu-nota   { border-color: var(--garis); color: var(--nota); }
.kartu-aset   { border-color: var(--garis); color: var(--aset); }
.kartu-tabung { border-color: var(--garis); color: var(--tabung); }
.kartu-kas    { border-color: var(--garis); color: var(--kas); }

/* Isi kartunya kembali ke warna teks biasa — yang boleh ikut berwarna
   cuma angkanya dan labelnya. */
.kartu-nota > *,
.kartu-aset > *,
.kartu-tabung > *,
.kartu-kas > * { color: var(--tinta); }

.kartu-nota .judul-bagian h2 { color: var(--nota); }
.kartu-nota .label-kecil     { color: var(--nota); opacity: .85; }

/* --- Sebut member dengan @ ---
   Satu kotak yang menerima nama bebas ATAU sesama member. Daftarnya
   melayang di atas isian berikutnya, bukan mendorongnya turun — kalau
   mendorong, tombol Simpan ikut lompat tiap kali orang mengetik. */
.sebut { position: relative; }

.sebut-daftar {
    position: absolute;
    z-index: 30;
    inset-inline: 0;
    top: calc(100% + 4px);
    margin: 0;
    padding: 4px;
    list-style: none;
    max-height: 220px;
    overflow-y: auto;
    background: var(--permukaan);
    border: 1px solid var(--garis);
    border-radius: var(--radius-sm);
    box-shadow: var(--bayang-2);
}

.sebut-opsi {
    padding: 9px 10px;
    border-radius: 7px;
    font-size: .9rem;
    cursor: pointer;
}

.sebut-opsi.sorot,
.sebut-opsi:hover { background: var(--aksen-terang); color: var(--aksen-gelap); }

.sebut-terpilih {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-top: 6px;
}

.tautan-kecil {
    background: none;
    border: none;
    padding: 0;
    font: inherit;
    font-size: .78rem;
    color: var(--tinta-samar);
    text-decoration: underline;
    cursor: pointer;
}

/* --- Kelompok kekayaan: aset & tabungan ---
   Dua kartu ini isinya satu-satunya angka yang naik kalau kamu melakukan
   hal yang benar, jadi angkanya yang diberi warna — bukan kotaknya. */
.kartu-aset   .label-kecil,
.kartu-aset   .nilai-sedang { color: var(--aset); }
.kartu-tabung .label-kecil,
.kartu-tabung .nilai-sedang { color: var(--tabung); }
.kartu-kas    .label-kecil,
.kartu-kas    .nilai-sedang { color: var(--kas); }

/* Simbol mata uang ikut warna angkanya, cuma lebih pudar — kalau dia
   tetap abu-abu netral, "Rp" akan terlihat seperti bagian dari label di
   atasnya, bukan bagian dari angka di sebelahnya. */
.nilai-sedang  .uang-sim,
.nilai-besar   .uang-sim,
.nilai-raksasa .uang-sim,
.kisi-nilai    .uang-sim { color: currentColor; opacity: .55; }

/* Judul kartu utama: dulu ditulis sekecil keterangan, padahal itu judul
   angka terbesar di layar. */
.judul-utama {
    font-size: .82rem;
    font-weight: 700;
    letter-spacing: .02em;
    color: var(--tinta-lembut);
}


/* --- Pilihan bertumpuk -----------------------------------------------
   Radio yang tiap pilihannya perlu satu-dua kalimat penjelasan, jadi
   tidak muat di .segmen yang sebaris. Dipakai untuk keputusan yang
   akibatnya tidak kelihatan dari nama pilihannya saja — misalnya kapan
   sebuah hutang ikut dihitung sebagai pengeluaran. */

.pilihan {
    display: flex;
    gap: 10px;
    align-items: flex-start;
    padding: 11px 12px;
    border: 1px solid var(--garis);
    border-radius: var(--radius-sm);
    cursor: pointer;
    transition: border-color .2s var(--halus), background .2s var(--halus);
}

.pilihan + .pilihan { margin-top: 7px; }

.pilihan input {
    margin: 2px 0 0;
    flex-shrink: 0;
    accent-color: var(--aksen);
}

.pilihan > span {
    display: flex;
    flex-direction: column;
    gap: 3px;
}

.pilihan b { font-size: .88rem; font-weight: 650; }

.pilihan:has(input:checked) {
    border-color: var(--aksen);
    background: var(--permukaan-2);
}

.pilihan:has(input:focus-visible) { outline: 2px solid var(--aksen); outline-offset: 2px; }

.pilihan:has(input:disabled) { opacity: .5; cursor: not-allowed; }


/* =====================================================================
   7. HALAMAN KHUSUS
   ===================================================================== */

/* --- Layar scan --- */

.scan-area {
    aspect-ratio: 3 / 4;
    max-height: 58vh;
    border: 2px dashed var(--garis);
    border-radius: var(--radius-lg);
    background: var(--permukaan);
    display: grid;
    place-items: center;
    text-align: center;
    padding: 22px;
    position: relative;
    overflow: hidden;
    transition: border-color .25s var(--halus), background .25s var(--halus);
    cursor: pointer;
}

.scan-area:active {
    border-color: var(--aksen);
    background: var(--aksen-terang);
}

.scan-area img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.scan-ikon {
    width: 54px;
    height: 54px;
    stroke: var(--aksen);
    fill: none;
    stroke-width: 1.5;
    stroke-linecap: round;
    stroke-linejoin: round;
    margin-bottom: 12px;
}

/* Garis pindai yang bergerak turun-naik di atas foto saat OCR jalan */
.pindai::before {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    height: 42%;
    background: linear-gradient(
        to bottom,
        transparent,
        color-mix(in srgb, var(--aksen) 22%, transparent),
        transparent
    );
    animation: garisPindai 2.1s var(--halus) infinite;
    z-index: 2;
}

.pindai::after {
    content: "";
    position: absolute;
    inset: 0;
    background: rgba(0, 0, 0, .28);
    z-index: 1;
}

.pindai-teks {
    position: absolute;
    inset: 0;
    display: grid;
    place-items: center;
    z-index: 3;
    color: #fff;
    font-weight: 600;
    font-size: .92rem;
    text-shadow: 0 1px 8px rgba(0, 0, 0, .6);
}

/* --- Layar review --- */

.item-review {
    background: var(--permukaan);
    border: 1px solid var(--garis);
    border-radius: var(--radius);
    padding: 11px 12px;
    display: flex;
    flex-direction: column;
    gap: 9px;
    position: relative;
    transition: opacity .25s var(--halus), border-color .25s var(--halus),
                transform .25s var(--halus);
}

/* Baris yang angkanya meragukan disorot */
.item-review.ditandai {
    border-color: var(--hati);
    background: var(--hati-bg);
}

/* Barang punya teman: tetap terlihat, tapi diredupkan */
.item-review.dikecualikan {
    opacity: .5;
    border-style: dashed;
}

.item-review.dikecualikan .item-nama {
    text-decoration: line-through;
    text-decoration-color: var(--tinta-samar);
}

.item-review.dihapus {
    animation: kecilMenghilang .28s var(--halus) forwards;
}

.item-nama {
    font-weight: 600;
    font-size: .93rem;
    line-height: 1.3;
}

.item-angka {
    display: grid;
    grid-template-columns: 68px 1fr 92px;
    gap: 7px;
    align-items: center;
}

.item-angka input {
    padding: 8px 10px;
    font-size: 15px;
    text-align: right;
    font-variant-numeric: tabular-nums;
}

.item-angka .kali {
    text-align: center;
    color: var(--tinta-samar);
    font-size: .8rem;
}

.item-aksi {
    display: flex;
    gap: 6px;
    align-items: center;
    flex-wrap: wrap;
}

/* --- Sorotan di dashboard --- */

.sorotan {
    display: flex;
    gap: 9px;
    align-items: flex-start;
    padding: 11px 13px;
    border-radius: var(--radius-sm);
    background: var(--permukaan-2);
    font-size: .86rem;
    line-height: 1.45;
}

.sorotan-bagus     { background: var(--bagus-bg);  color: var(--bagus); }
.sorotan-perhatian { background: var(--hati-bg);   color: var(--hati); }

.sorotan-ikon { flex-shrink: 0; font-size: 1rem; line-height: 1.3; }

/* --- Baris kategori dengan bar --- */

.kategori-baris {
    display: flex;
    align-items: center;
    gap: 11px;
    padding: 9px 0;
}

.kategori-bar {
    height: 5px;
    border-radius: 999px;
    background: var(--permukaan-2);
    overflow: hidden;
    margin-top: 5px;
}

.kategori-bar span {
    display: block;
    height: 100%;
    border-radius: 999px;
    transition: width .8s var(--pegas);
}

/* --- Rincian "Ke mana uangnya": barisnya bisa ditekan ---
   Di beranda baris kategori cuma tampilan, jadi tanpa garis pemisah.
   Di halaman rincian tiap baris adalah tautan ke Riwayat — pemisah dan
   umpan balik sentuhan yang membedakan "daftar" dari "tombol". */
a.kategori-baris { text-decoration: none; color: inherit; }
a.kategori-baris:active { background: var(--permukaan-2); }

.kartu-rincian .kategori-baris {
    border-bottom: 1px solid var(--garis-halus);
    padding: 11px 0;
}

.kartu-rincian .kategori-baris:last-child { border-bottom: none; }

/* --- Tabel admin --- */

.tabel {
    width: 100%;
    border-collapse: collapse;
    font-size: .84rem;
    min-width: 480px;
}

.tabel th {
    text-align: left;
    font-size: .66rem;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--tinta-samar);
    padding: 8px 10px;
    border-bottom: 1px solid var(--garis);
    white-space: nowrap;
    font-weight: 700;
}

.tabel td {
    padding: 10px;
    border-bottom: 1px solid var(--garis-halus);
    vertical-align: middle;
}

.tabel tr:last-child td { border-bottom: none; }

/* --- Panel lipat --- */

details.panel {
    background: var(--permukaan);
    border: 1px solid var(--garis);
    border-radius: var(--radius);
    overflow: hidden;
}

details.panel > summary {
    padding: 13px 14px;
    cursor: pointer;
    font-weight: 600;
    font-size: .92rem;
    list-style: none;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
}

details.panel > summary::-webkit-details-marker { display: none; }

details.panel > summary::after {
    content: "";
    width: 7px;
    height: 7px;
    border-right: 2px solid var(--tinta-samar);
    border-bottom: 2px solid var(--tinta-samar);
    transform: rotate(45deg);
    transition: transform .25s var(--halus);
    flex-shrink: 0;
    margin-right: 3px;
}

details.panel[open] > summary::after { transform: rotate(-135deg); }

details.panel > .panel-isi {
    padding: 0 14px 14px;
    border-top: 1px solid var(--garis-halus);
    padding-top: 13px;
    animation: bukaPanel .28s var(--halus);
}

/* ---------------------------------------------------------------------
   Kartu Sorotan: bentuk mingguan + kotak sorotan

   Empat batang yang menjawab pertanyaan yang tidak pernah bisa dijawab
   satu angka: "Rp 5.650.000 bulan ini" bunyinya sama untuk orang yang
   membelanjakannya merata dan untuk orang yang membayar sewa sekali di
   tanggal 1.

   Tingginya datang dari PHP sebagai persen (lihat ForecastService).
   Sengaja tidak dihitung di sini — pembagi nol menunggu bulan yang
   belum ada pengeluarannya sama sekali.
   --------------------------------------------------------------------- */

.minggu-deret {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 8px;
    margin: 12px 0 4px;
}

.minggu-satu { text-align: center; min-width: 0; }

.minggu-batang {
    height: 46px;
    border-radius: var(--radius-sm);
    background: var(--permukaan-2);
    display: flex;
    align-items: flex-end;
    overflow: hidden;
}

.minggu-batang > span {
    display: block;
    width: 100%;
    border-radius: var(--radius-sm);
    background: var(--aksen);
    opacity: .45;
    transition: height .4s var(--halus);
    /* Batang bernilai nol tetap punya sisa tipis, supaya bedanya
       "tidak ada pengeluaran" dan "minggunya belum datang" terbaca
       sebagai dasar yang sama, bukan sebagai batang yang hilang. */
    min-height: 2px;
}

.minggu-kini .minggu-batang > span { opacity: 1; }

/* Minggu yang belum datang: wadahnya lebih pudar, supaya "belum
   terjadi" tidak terlihat sama dengan "tidak ada pengeluaran". */
.minggu-belum .minggu-batang { background: var(--garis-halus); }
.minggu-belum .minggu-batang > span { display: none; }
.minggu-belum .minggu-nilai { color: var(--tinta-samar); }

.minggu-label {
    font-size: .68rem;
    color: var(--tinta-samar);
    margin-top: 5px;
    letter-spacing: .02em;
}

.minggu-kini .minggu-label { color: var(--aksen); font-weight: 600; }

.minggu-nilai {
    font-size: .72rem;
    color: var(--tinta-lembut);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/*
   Kotak sorotan tidak punya judul, dan itu disengaja.

   Label yang mengumumkan sesuatu akan lucu membuat kalimat yang biasa
   saja terasa gagal. Yang menandainya cuma garis di kiri.
*/
.kotak-sorotan {
    margin: 12px 0;
    padding: 11px 13px;
    border-left: 3px solid var(--aksen);
    border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
    background: var(--aksen-terang);
    color: var(--tinta);
    font-size: .9rem;
    line-height: 1.55;
}

/* Baris hasil di dalam panel: yang dijumlahkan berdiri di atas garis. */
.baris-hasil {
    border-top: 1px solid var(--garis-halus);
    padding-top: 9px;
    margin-top: 3px;
    font-weight: 600;
}


/* ---------------------------------------------------------------------
   Kredit pembuat

   Pemicunya baris biasa di dasar halaman; isinya lembar yang naik dari
   bawah layar, pola yang sudah dikenal orang dari aplikasi HP.
   --------------------------------------------------------------------- */

.kredit-baris {
    display: flex;
    align-items: center;
    gap: 11px;
    width: 100%;
    padding: 12px 14px;
    background: var(--permukaan);
    border: 1px solid var(--garis);
    border-radius: var(--radius);
    cursor: pointer;
    font-family: inherit;
    color: inherit;
    text-align: left;
    transition: transform .18s var(--halus), border-color .18s var(--halus);
}

.kredit-baris:active {
    transform: scale(.985);
    border-color: var(--tinta-samar);
}

.kredit-nama {
    display: block;
    font-weight: 600;
    font-size: .89rem;
}

.kredit-peran {
    display: block;
    font-size: .78rem;
    color: var(--tinta-samar);
    margin-top: 1px;
}

.kredit-avatar {
    width: 38px;
    height: 38px;
    border-radius: 50%;
    object-fit: cover;
    flex-shrink: 0;
    background: var(--permukaan-2);
}

.kredit-avatar-besar {
    width: 76px;
    height: 76px;
    border-radius: 50%;
    object-fit: cover;
    margin-inline: auto;
    background: var(--permukaan-2);
    display: block;
}

/* Lingkaran berisi inisial, dipakai kalau tidak ada foto */
.kredit-avatar-teks {
    display: grid;
    place-items: center;
    background: var(--aksen-terang);
    color: var(--aksen);
    font-weight: 700;
    letter-spacing: .02em;
}

span.kredit-avatar.kredit-avatar-teks  { font-size: .82rem; }
span.kredit-avatar-besar.kredit-avatar-teks { font-size: 1.7rem; }

/* Pemicu berbentuk teks, untuk halaman masuk */
.kredit-tautan {
    background: none;
    border: none;
    padding: 0;
    font: inherit;
    color: var(--aksen);
    cursor: pointer;
    text-decoration: underline;
    text-underline-offset: 2px;
}

/* --- Lembar yang naik dari bawah --- */

.lembar-tirai {
    position: fixed;
    inset: 0;
    z-index: 80;
    background: rgba(10, 14, 13, .5);
    backdrop-filter: blur(2px);
    -webkit-backdrop-filter: blur(2px);
    animation: tiraiMuncul .22s var(--halus);
}

.lembar {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 85;
    max-height: 88vh;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    background: var(--permukaan);
    border-top: 1px solid var(--garis);
    border-radius: var(--radius-lg) var(--radius-lg) 0 0;
    box-shadow: var(--bayang-3);
    padding-bottom: calc(18px + var(--aman-bawah));
    animation: lembarNaik .34s var(--pegas);
}

/* Di layar lebar, tampil sebagai kotak di tengah — bukan lembar bawah */
@media (min-width: 640px) {
    .lembar {
        left: 50%;
        bottom: auto;
        top: 50%;
        transform: translate(-50%, -50%);
        width: min(440px, calc(100vw - 40px));
        border-radius: var(--radius-lg);
        border: 1px solid var(--garis);
        animation: kotakMuncul .3s var(--pegas);
    }

    .lembar-gagang { display: none; }
}

.lembar-gagang {
    width: 38px;
    height: 4px;
    border-radius: 999px;
    background: var(--garis);
    margin: 9px auto 2px;
}

.lembar-isi {
    padding: 14px 18px 4px;
    display: flex;
    flex-direction: column;
    gap: 14px;
}

/* =====================================================================
   Lembar profil pembuat — sampul, avatar menumpuk, baris ikon
   ===================================================================== */

/* Tingginya 80% layar, BUKAN "setinggi isinya".

   Bedanya terasa: dengan tinggi mengikuti isi, lembar ini melompat-lompat
   ukurannya tergantung berapa paragraf bio yang ditulis orang, dan
   sampulnya kadang setengah layar kadang seiris tipis. Tinggi tetap
   membuat bentuknya bisa diprediksi, dan isinya yang menggulir di dalam. */
.lembar-profil {
    height: 80vh;
    max-height: 80vh;
    display: flex;
    flex-direction: column;
    padding-bottom: 0;
}

.lembar-profil .lembar-isi {
    flex: 1;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    padding-bottom: calc(18px + var(--aman-bawah));
}

@media (min-width: 640px) {
    .lembar-profil { height: auto; max-height: 80vh; }
}

.kredit-sampul {
    position: relative;
    height: 132px;
    flex-shrink: 0;
    overflow: hidden;
    background: var(--permukaan-2);
}

.kredit-sampul img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

/* Sampul tanpa gambar tetap terlihat disengaja. */
.kredit-sampul-polos {
    background: linear-gradient(135deg, var(--aksen) 0%, var(--tabung, var(--aksen)) 100%);
}

.kredit-kepala {
    flex-shrink: 0;
    text-align: center;
    padding: 0 18px 4px;
    /* Avatar menumpuk di batas sampul: setengah di atas, setengah di
       bawah. Margin negatifnya separuh tinggi avatar plus tebal cincin. */
    margin-top: -42px;
}

.lembar-profil .kredit-avatar-besar {
    width: 78px;
    height: 78px;
    border: 3px solid var(--permukaan);
    box-shadow: var(--bayang-2);
    position: relative;
    z-index: 1;
}

.kredit-judul {
    font-size: 1.15rem;
    margin-top: 8px;
    line-height: 1.3;
}

.kredit-peran-besar {
    font-size: .84rem;
    color: var(--tinta-samar);
    margin-top: 2px;
}

.kredit-ikon-baris {
    display: flex;
    justify-content: center;
    flex-wrap: wrap;
    gap: 8px;
    margin-top: 11px;
}

.kredit-ikon {
    width: 36px;
    height: 36px;
    border-radius: 50%;
    display: grid;
    place-items: center;
    background: var(--permukaan-2);
    border: 1px solid var(--garis);
    color: var(--tinta-lembut);
    text-decoration: none;
    transition: background .15s var(--halus), color .15s var(--halus);
}

.kredit-ikon:hover,
.kredit-ikon:focus-visible {
    background: var(--aksen);
    color: #fff;
    border-color: var(--aksen);
}

.kredit-ikon-emoji { font-size: .95rem; line-height: 1; }

/* Judul "TENTANG": huruf kecil renggang berwarna aksen, seperti label
   bagian di halaman lain — supaya bionya punya kepala, bukan muncul
   begitu saja. */
.kredit-tentang {
    font-size: .72rem;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: var(--aksen);
    margin-bottom: 7px;
}

.kredit-tautan-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(104px, 1fr));
    gap: 8px;
}

.kredit-tautan-kartu {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 11px 12px;
    border: 1px solid var(--garis);
    border-radius: var(--radius-sm);
    background: var(--permukaan-2);
    color: var(--tinta);
    font-size: .84rem;
    font-weight: 600;
    text-decoration: none;
    transition: transform .16s var(--halus), border-color .16s var(--halus);
}

.kredit-tautan-kartu:active {
    transform: scale(.96);
    border-color: var(--aksen);
}

.kredit-tautan-ikon { font-size: 1.05rem; line-height: 1; }

.kredit-kaki {
    border-top: 1px solid var(--garis-halus);
    padding-top: 12px;
}

@keyframes tiraiMuncul {
    from { opacity: 0; }
    to   { opacity: 1; }
}

@keyframes lembarNaik {
    from { transform: translateY(100%); }
    to   { transform: translateY(0); }
}

@keyframes kotakMuncul {
    from { opacity: 0; transform: translate(-50%, -46%) scale(.96); }
    to   { opacity: 1; transform: translate(-50%, -50%) scale(1); }
}

/* Kelas penutup, dipasang JavaScript sebelum elemennya disembunyikan */
.lembar-tutup       { animation: lembarTurun .24s var(--halus) forwards; }
.lembar-tirai-tutup { animation: tiraiHilang .24s var(--halus) forwards; }

@keyframes lembarTurun {
    to { transform: translateY(100%); }
}

@keyframes tiraiHilang {
    to { opacity: 0; }
}

@media (min-width: 640px) {
    .lembar-tutup { animation: kotakHilang .22s var(--halus) forwards; }

    @keyframes kotakHilang {
        to { opacity: 0; transform: translate(-50%, -50%) scale(.96); }
    }
}


/* =====================================================================
   8. ANIMASI

   Semuanya hanya menyentuh transform dan opacity — dua properti yang
   bisa dijalankan kartu grafis, jadi tetap mulus di HP lama.
   ===================================================================== */

@keyframes masukAtas {
    from { opacity: 0; transform: translateY(-14px) scale(.97); }
    to   { opacity: 1; transform: translateY(0) scale(1); }
}

@keyframes keluarAtas {
    to { opacity: 0; transform: translateY(-10px); }
}

@keyframes munculTitik {
    from { opacity: 0; transform: scale(0); }
    to   { opacity: 1; transform: scale(1); }
}

@keyframes garisPindai {
    0%   { transform: translateY(-100%); }
    100% { transform: translateY(240%); }
}

@keyframes kecilMenghilang {
    to { opacity: 0; transform: scale(.94) translateX(-16px); height: 0; padding: 0; margin: 0; }
}

@keyframes bukaPanel {
    from { opacity: 0; transform: translateY(-6px); }
    to   { opacity: 1; transform: translateY(0); }
}

@keyframes munculNaik {
    from { opacity: 0; transform: translateY(12px); }
    to   { opacity: 1; transform: translateY(0); }
}

@keyframes berdenyut {
    0%, 100% { opacity: 1; }
    50%      { opacity: .45; }
}

@keyframes kilauSkeleton {
    to { background-position-x: -200%; }
}

/* Muncul berurutan — dipakai untuk daftar di beranda */
.muncul { animation: munculNaik .42s var(--halus) backwards; }
.muncul:nth-child(1) { animation-delay: .03s; }
.muncul:nth-child(2) { animation-delay: .07s; }
.muncul:nth-child(3) { animation-delay: .11s; }
.muncul:nth-child(4) { animation-delay: .15s; }
.muncul:nth-child(5) { animation-delay: .19s; }
.muncul:nth-child(6) { animation-delay: .23s; }

.berdenyut { animation: berdenyut 1.6s ease-in-out infinite; }

.skeleton {
    background: linear-gradient(
        90deg,
        var(--permukaan-2) 30%,
        var(--garis-halus) 50%,
        var(--permukaan-2) 70%
    );
    background-size: 200% 100%;
    animation: kilauSkeleton 1.35s linear infinite;
    border-radius: 7px;
    color: transparent;
}

/* Konfeti waktu target tabungan tercapai */
.konfeti {
    position: fixed;
    inset: 0;
    pointer-events: none;
    z-index: 95;
    overflow: hidden;
}

.konfeti i {
    position: absolute;
    top: -12px;
    width: 8px;
    height: 13px;
    opacity: 0;
    animation: jatuhKonfeti 2.6s ease-in forwards;
}

@keyframes jatuhKonfeti {
    0%   { opacity: 1; transform: translateY(0) rotate(0deg); }
    100% { opacity: 0; transform: translateY(104vh) rotate(680deg); }
}

/* ---------------------------------------------------------------------
   Hormati pengaturan perangkat.
   Sebagian orang pusing melihat gerakan; kalau mereka mematikannya di
   pengaturan HP, aplikasi ini ikut diam.
   --------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: .01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: .01ms !important;
        scroll-behavior: auto !important;
    }

    .pindai::before { animation: none; opacity: .5; }
}

/* Layar lebih besar: naikkan sedikit lebarnya */
@media (min-width: 720px) {
    .bungkus { padding-bottom: 40px; }

    .nav {
        max-width: 640px;
        left: 50%;
        transform: translateX(-50%);
        border-radius: var(--radius-lg) var(--radius-lg) 0 0;
        border: 1px solid var(--garis);
        border-bottom: none;
    }
}

/* Kotak catatan log di halaman diagnosa.
   Baris log panjang dan tidak boleh dipotong — dibiarkan menggulir
   ke samping supaya isinya tetap utuh waktu disalin. */
.log-kotak {
    margin: 0;
    padding: 10px 12px;
    border-radius: 12px;
    background: var(--permukaan-2);
    border: 1px solid var(--garis);
    font: 11px/1.55 ui-monospace, SFMono-Regular, Menlo, monospace;
    color: var(--tinta-lembut);
    max-height: 240px;
    overflow: auto;
    white-space: pre;
    -webkit-overflow-scrolling: touch;
}

/* Area scan waktu berkas sedang diseret di atasnya (laptop). */
.scan-area-seret {
    border-color: var(--aksen);
    background: var(--aksen-terang);
}

/* =====================================================================
   ALOKASI BULANAN

   Warna bar mengikuti empat tingkat pemakaian, bukan dua. Peringatan
   yang baru muncul setelah pagu terlampaui datang terlambat — uangnya
   sudah keluar. Kuning di 70% dan oranye di 90% memberi waktu untuk
   mengubah keputusan selagi masih bisa.
   ===================================================================== */

.bar-tebal { height: 11px; }

.bar-aman   { background: var(--bagus); }
.bar-hati   { background: #C79A2E; }
.bar-kritis { background: #C97B2E; }
.bar-jebol  { background: var(--bahaya); }

/* Bar kategori memakai kelas yang sama; warnanya diterapkan ke <span>
   di dalamnya, jadi selektornya perlu disebut terpisah. */
.kategori-bar span.bar-aman   { background: var(--bagus); }
.kategori-bar span.bar-hati   { background: #C79A2E; }
.kategori-bar span.bar-kritis { background: #C97B2E; }
.kategori-bar span.bar-jebol  { background: var(--bahaya); }

.sorotan-bahaya { background: var(--bahaya-bg); color: var(--bahaya); }

/* Kartu ringkas dua kolom di Beranda: pemasukan, pengeluaran, sisa. */
.kisi-angka {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 1px;
    background: var(--garis-halus);
    border-radius: var(--radius-sm);
    overflow: hidden;
}

.kisi-angka > div {
    background: var(--permukaan);
    padding: 11px 9px;
    text-align: center;
}

/* Neraca bulanan: masuk, keluar, ditabung, sisa — DUA baris kali dua,
   bukan empat kolom.

   Dulu empat kolom, dan supaya nominal tujuh digit muat, angkanya
   dipendekkan jadi "Rp 5,7jt". Akibatnya satu layar memuat dua tulisan
   untuk angka yang sama: kartu di atasnya berkata "Rp 5.650.000", kotak
   ini berkata "Rp 5,7jt", jaraknya dua sentimeter. Yang membacanya harus
   berhenti sejenak untuk memastikan itu memang angka yang sama — dan
   ragu sesaat pada angka sendiri adalah harga yang terlalu mahal untuk
   menghemat satu baris.

   Dua kolom memberi ruang yang cukup untuk nominal penuh, jadi keempat
   angka ini sekarang bisa langsung dibandingkan dengan angka mana pun
   di halaman ini. */
.kisi-angka.kisi-empat { grid-template-columns: repeat(2, 1fr); }
.kisi-angka.kisi-empat > div { padding: 11px 10px; text-align: start; }
.kisi-angka.kisi-empat .kisi-nilai { font-size: .95rem; }

/* Dua kolom, dipakai kartu yang hanya punya dua angka. Tanpa ini,
   kisi tiga kolom menyisakan satu kotak kosong yang terlihat seperti
   data yang gagal dimuat. */
.kisi-dua { grid-template-columns: repeat(2, 1fr); }

.kisi-angka .label-kecil { margin-bottom: 3px; }

.kisi-nilai {
    font-weight: 700;
    font-size: .84rem;
    font-variant-numeric: tabular-nums;
    letter-spacing: -.01em;
}

/* Titik warna kecil untuk keterangan grafik. */
.titik-warna {
    display: inline-block;
    width: 8px;
    height: 8px;
    border-radius: 999px;
    margin-right: 3px;
    vertical-align: baseline;
}

/* =====================================================================
   TOMBOL HAPUS YANG TERBACA

   Versi sebelumnya memakai gaya samar: latar bening, huruf abu-abu,
   tanpa garis tepi. Maksudnya supaya tidak tertekan tak sengaja, tapi
   akibatnya user tidak menemukannya sama sekali dan mengira fitur
   hapusnya memang tidak ada.

   Garis tepi merah membuatnya terbaca tanpa mengundang — jelas terlihat,
   tapi jelas juga bahwa ini bukan tombol yang ditekan sembarangan.
   ===================================================================== */

.tombol-garis-bahaya {
    background: transparent;
    color: var(--bahaya);
    border: 1px solid var(--bahaya);
}

.tombol-garis-bahaya:active {
    background: var(--bahaya-bg);
}

/* =====================================================================
   GESER BARIS UNTUK ARSIP / HAPUS

   Tombolnya duduk di belakang baris dan tersingkap waktu barisnya
   digeser ke kiri. Tidak menambah apa pun ke layar sampai memang
   dibutuhkan — yang penting di daftar panjang di layar HP.

   Barisnya sendiri tetap tautan biasa, jadi ketukan singkat tetap
   membuka form ubah seperti biasa.
   ===================================================================== */

.geser-bungkus {
    position: relative;
    overflow: hidden;
}

.geser-aksi {
    position: absolute;
    inset: 0 0 0 auto;
    display: flex;
    align-items: stretch;
}

.geser-tombol {
    border: none;
    padding: 0 16px;
    font-size: .82rem;
    font-weight: 700;
    color: #fff;
    cursor: pointer;
}

.geser-arsip { background: var(--tinta-samar); }
.geser-hapus { background: var(--bahaya); }

/* Barisnya WAJIB punya latar buram. Tombol di belakangnya duduk di
   lapisan yang sama; tanpa latar, tombol itu tembus pandang lewat baris
   dan terlihat permanen — persis yang tidak diinginkan. */
.geser-isi {
    position: relative;
    background: var(--permukaan);
    transition: transform .22s var(--halus);
    will-change: transform;
}

/* Baris terakhir di dalam .daftar tidak lagi jadi anak langsung karena
   dibungkus .geser-bungkus, jadi aturan :last-child yang lama tidak kena.
   Garisnya dirapikan dari pembungkusnya. */
.geser-bungkus:last-child .daftar-baris { border-bottom: none; }

/* Waktu sedang diseret, animasinya dimatikan supaya mengikuti jari. */
.geser-isi.menyeret { transition: none; }


/* =====================================================================
   Warna dominan pilihan tiap orang

   Cuma --aksen* yang ikut berubah. --bagus (pemasukan, di bawah pagu),
   --tabung, --aset, --nota, --bahaya, dan --hati TIDAK ikut: warna-warna
   itu BERARTI sesuatu. Kalau semuanya diseragamkan ke warna pilihan,
   orang yang memilih coral akan melihat pemasukan berwarna merah —
   angka yang bertambah terbaca sebagai peringatan.

   Tiap warna punya TIGA blok, dan urutannya penting:

     1. [data-aksen="x"]                          mode terang
     2. @media dark + :not([data-tema="terang"])  ikut HP, kecuali orangnya
                                                  memaksa terang
     3. [data-tema="gelap"][data-aksen="x"]       dipaksa gelap, menang
                                                  atas media query

   Tanpa blok ketiga, orang yang memaksa mode gelap di HP bermode terang
   akan mendapat latar gelap dengan aksen versi terang — teks gelap di
   atas gelap.
   ===================================================================== */

[data-aksen="emerald"] {
    --aksen:        #1F6F5C;
    --aksen-terang: #E2EFE9;
    --aksen-gelap:  #175449;
}

@media (prefers-color-scheme: dark) {
    [data-aksen="emerald"]:not([data-tema="terang"]) {
        --aksen:        #56C4A0;
        --aksen-terang: #16302A;
        --aksen-gelap:  #7DD9BC;
    }
}

[data-tema="gelap"][data-aksen="emerald"] {
    --aksen:        #56C4A0;
    --aksen-terang: #16302A;
    --aksen-gelap:  #7DD9BC;
}

[data-aksen="biru"] {
    --aksen:        #1D4F91;
    --aksen-terang: #E4ECF7;
    --aksen-gelap:  #163C6E;
}

@media (prefers-color-scheme: dark) {
    [data-aksen="biru"]:not([data-tema="terang"]) {
        --aksen:        #7FB2ED;
        --aksen-terang: #152538;
        --aksen-gelap:  #A6CCF5;
    }
}

[data-tema="gelap"][data-aksen="biru"] {
    --aksen:        #7FB2ED;
    --aksen-terang: #152538;
    --aksen-gelap:  #A6CCF5;
}

[data-aksen="nila"] {
    --aksen:        #4A3FBF;
    --aksen-terang: #EAE7F9;
    --aksen-gelap:  #372E93;
}

@media (prefers-color-scheme: dark) {
    [data-aksen="nila"]:not([data-tema="terang"]) {
        --aksen:        #A79BF0;
        --aksen-terang: #1E1A38;
        --aksen-gelap:  #C4BCF7;
    }
}

[data-tema="gelap"][data-aksen="nila"] {
    --aksen:        #A79BF0;
    --aksen-terang: #1E1A38;
    --aksen-gelap:  #C4BCF7;
}

[data-aksen="coklat"] {
    --aksen:        #6B4A3A;
    --aksen-terang: #EFE8E4;
    --aksen-gelap:  #523629;
}

@media (prefers-color-scheme: dark) {
    [data-aksen="coklat"]:not([data-tema="terang"]) {
        --aksen:        #D3A886;
        --aksen-terang: #2A211C;
        --aksen-gelap:  #E4C4AB;
    }
}

[data-tema="gelap"][data-aksen="coklat"] {
    --aksen:        #D3A886;
    --aksen-terang: #2A211C;
    --aksen-gelap:  #E4C4AB;
}

[data-aksen="coral"] {
    --aksen:        #C93A14;
    --aksen-terang: #FBE8E2;
    --aksen-gelap:  #A62F10;
}

@media (prefers-color-scheme: dark) {
    [data-aksen="coral"]:not([data-tema="terang"]) {
        --aksen:        #FF9270;
        --aksen-terang: #351D16;
        --aksen-gelap:  #FFB49B;
    }
}

[data-tema="gelap"][data-aksen="coral"] {
    --aksen:        #FF9270;
    --aksen-terang: #351D16;
    --aksen-gelap:  #FFB49B;
}

[data-aksen="batu"] {
    --aksen:        #4B5563;
    --aksen-terang: #E9EBEE;
    --aksen-gelap:  #374151;
}

@media (prefers-color-scheme: dark) {
    [data-aksen="batu"]:not([data-tema="terang"]) {
        --aksen:        #A3AEBE;
        --aksen-terang: #1C2128;
        --aksen-gelap:  #C3CBD8;
    }
}

[data-tema="gelap"][data-aksen="batu"] {
    --aksen:        #A3AEBE;
    --aksen-terang: #1C2128;
    --aksen-gelap:  #C3CBD8;
}

[data-aksen="arang"] {
    --aksen:        #26282E;
    --aksen-terang: #E8E9EB;
    --aksen-gelap:  #15171B;
}

@media (prefers-color-scheme: dark) {
    [data-aksen="arang"]:not([data-tema="terang"]) {
        --aksen:        #C9CDD4;
        --aksen-terang: #22242A;
        --aksen-gelap:  #E3E6EA;
    }
}

[data-tema="gelap"][data-aksen="arang"] {
    --aksen:        #C9CDD4;
    --aksen-terang: #22242A;
    --aksen-gelap:  #E3E6EA;
}

/* Tautan bergaris bawah untuk warna yang nyaris netral.

   Abu batu dan Pearl black jaraknya terlalu dekat dengan warna teks
   biasa — tautan yang cuma dibedakan warna berhenti terlihat seperti
   tautan, dan orang berhenti mengkliknya tanpa pernah tahu kenapa.
   Yang tidak bisa membedakan diri lewat rona, membedakan diri lewat
   bentuk.

   Yang dikecualikan elemen yang memang BUKAN tautan teks: tombol,
   tombol ikon, kartu yang bisa diklik, baris daftar, item menu bawah,
   pil periode, dan lencana.

   Daftar pengecualiannya panjang, dan itu memang bentuknya. Di aplikasi
   ini banyak <a> yang bukan tautan teks — dia tombol, kartu, atau item
   menu yang kebetulan ditulis sebagai tautan. Versi pertama aturan ini
   melupakan menu bawah, dan hasilnya seluruh label "Dashboard History
   Aset Profil" bergaris bawah seperti dokumen tahun 1998. */
[data-aksen="batu"] a:not(.tombol):not(.tombol-ikon):not(.kartu-klik):not(.daftar-baris):not(.nav-item):not(.nav-scan-tombol):not(.pil):not(.kartu):not(.lencana),
[data-aksen="arang"] a:not(.tombol):not(.tombol-ikon):not(.kartu-klik):not(.daftar-baris):not(.nav-item):not(.nav-scan-tombol):not(.pil):not(.kartu):not(.lencana) {
    text-decoration: underline;
    text-underline-offset: 2px;
}

/* Pemilih warna dominan di Profil.

   Bulatannya menampilkan warna aslinya, bukan cuma namanya: "Nila" dan
   "Abu batu" tidak berarti apa-apa sampai orangnya melihat warnanya.

   Yang terpilih ditandai cincin, BUKAN cuma warna — kalau tandanya
   warna, warna yang nyaris netral (Abu batu, Pearl black) tidak akan
   pernah terlihat terpilih. */
.pilih-warna {
    display: inline-flex;
    flex-direction: column;
    align-items: center;
    gap: 5px;
    cursor: pointer;
    width: 62px;
}

.pilih-warna span {
    width: 34px;
    height: 34px;
    border-radius: 50%;
    border: 2px solid var(--garis);
    box-shadow: 0 0 0 0 transparent;
    transition: box-shadow .15s var(--halus), transform .15s var(--halus);
}

.pilih-warna em {
    font-style: normal;
    font-size: .68rem;
    color: var(--tinta-samar);
    text-align: center;
    line-height: 1.2;
}

.pilih-warna input:checked + span {
    box-shadow: 0 0 0 3px var(--permukaan), 0 0 0 5px var(--tinta-lembut);
    transform: scale(1.05);
}

.pilih-warna input:checked ~ em {
    color: var(--tinta);
    font-weight: 600;
}

.pilih-warna input:focus-visible + span {
    box-shadow: 0 0 0 3px var(--permukaan), 0 0 0 5px var(--aksen);
}

/* ---------------------------------------------------------------------
   Tawaran pasang di layar HP

   Kartunya lahir dengan atribut hidden dari PHP dan cuma dibuka
   JavaScript — lihat app.js. Tidak ada aturan di sini yang boleh
   menampilkannya sendiri; kalau ada, orang yang aplikasinya sudah
   terpasang akan melihatnya berkedip sebelum JavaScript sempat jalan.
   --------------------------------------------------------------------- */

.kartu-pasang { border-left: 3px solid var(--aksen); }

/* Satu langkah di lembar panduan iPhone. */
.langkah-pasang {
    display: flex;
    gap: 12px;
    align-items: flex-start;
    padding: 11px 0;
    border-top: 1px solid var(--garis-halus);
}

.langkah-pasang:first-of-type { border-top: 0; }

.langkah-nomor {
    flex-shrink: 0;
    width: 24px;
    height: 24px;
    border-radius: 999px;
    background: var(--aksen);
    color: #fff;
    font-size: .78rem;
    font-weight: 700;
    display: flex;
    align-items: center;
    justify-content: center;
}

/* Kotak kecil tempat ikon Share dicontohkan. */
.ikon-contoh {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    border-radius: var(--radius-sm);
    border: 1px solid var(--garis);
    background: var(--permukaan-2);
    color: var(--tinta-lembut);
}

/* =====================================================================
   MODE DEMO
   =====================================================================

   Pita ini SENGAJA di aliran halaman, bukan position:fixed seperti
   kilat. Pita melayang akan menutupi isi di layar HP pendek, dan yang
   ketutup justru bagian atas beranda — tempat angka terpenting berada.

   Warnanya memakai token yang sudah ada, bukan warna baru. Pita demo
   yang punya paletnya sendiri akan berhenti cocok begitu ada aksen baru
   ditambahkan, dan tidak ada yang akan ingat memperbaruinya.
   ===================================================================== */

.pita-demo {
    background: var(--permukaan-2);
    border-bottom: 1px solid var(--garis);
    color: var(--tinta-lembut);
    font-size: .78rem;
    line-height: 1.45;
    text-align: center;
    padding: 7px 14px;
}

.kartu-demo {
    margin-top: 18px;
    padding: 14px;
    border: 1px dashed var(--garis);
    border-radius: var(--radius-sm);
    background: var(--permukaan-2);
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.kartu-demo code {
    font-size: .9rem;
    font-weight: 600;
    color: var(--tinta);

    /* Alamat email dan sandi dibacakan lewat WhatsApp dan diketik ulang
       orang lain. Yang boleh dipilih harus benar-benar bisa dipilih. */
    user-select: all;
}

/* =====================================================================
   INI ITU

   Halaman coretan. Semua yang di sini dibuat untuk DIGESER, dan
   digesernya di jempol, bukan di tetikus — jadi ukuran sentuh menang
   atas kerapian tampilan.
   ===================================================================== */

/* Ajakan yang tampil selama Posisi Kas dan pemasukan berulang dua-duanya
   masih kosong. Garis putus-putus, bukan warna peringatan: yang belum
   mengisi apa-apa tidak sedang melakukan kesalahan. */
.kartu-ajakan {
    border-style: dashed;
    background: var(--permukaan-2);
}

.kartu-ajakan .baris { margin-top: 10px; }

/*
   Angka sisa. Lebih besar dari .nilai-besar karena dia satu-satunya
   alasan halaman ini dibuka — yang lain cuma bahan untuk sampai ke sini.

   font-variant-numeric: tabular-nums penting di sini dan tidak di
   tempat lain: angkanya berubah tiap kali slider digeser, dan digit
   dengan lebar berbeda membuat seluruh baris bergoyang kiri-kanan
   selama jempol bergerak.
*/
.nilai-raksasa {
    font-size: 2.9rem;
    font-weight: 700;
    letter-spacing: -0.045em;
    line-height: 1.02;
    margin: 8px 0 12px;
    font-variant-numeric: tabular-nums;
    transition: color .18s var(--halus);
}

.meter-ini-itu {
    height: 8px;
    border-radius: 999px;
    background: var(--permukaan-2);
    overflow: hidden;
}

.meter-isi {
    display: block;
    height: 100%;
    width: 0;
    border-radius: 999px;
    background: var(--tinta-samar);
    transition: width .18s var(--halus), background .18s var(--halus);
}

[data-ini-itu-persen] { margin-top: 6px; }

/*
   TIGA WARNA, DAN SATU KEADAAN TANPA WARNA.

   Kelasnya dipasang di akar halaman, bukan di angkanya, supaya meter
   dan angka tidak pernah bisa berbeda pendapat. Kalau tidak ada satu
   pun kelas ini — yaitu waktu pemasukannya belum diketahui — angkanya
   tetap tampil dengan warna tinta biasa. Itu disengaja: persentase
   tanpa pembagi selalu jatuh ke merah, dan menyambut orang baru dengan
   merah adalah vonis atas sesuatu yang belum dia lakukan.
*/
.ini-itu-bagus  .nilai-raksasa { color: var(--bagus); }
.ini-itu-hati   .nilai-raksasa { color: var(--hati); }
.ini-itu-bahaya .nilai-raksasa { color: var(--bahaya); }

.ini-itu-bagus  .meter-isi { background: var(--bagus); }
.ini-itu-hati   .meter-isi { background: var(--hati); }
.ini-itu-bahaya .meter-isi { background: var(--bahaya); }

/* --- Centang kotak --------------------------------------------------- */

/* Dipakai baris pemasukan di kartu Masuk. Kartu "Wajib" yang dulu
   memakainya dibuang di v3.30 — tagihan berulang sekarang terhitung di
   dalam rata-rata kategorinya sendiri, jadi menampilkannya lagi sebagai
   baris terpisah berarti menghitungnya dua kali. */
.sakelar-kotak {
    width: 22px;
    height: 22px;
    flex-shrink: 0;
    accent-color: var(--aksen);
    cursor: pointer;
}

/* --- Slider per kategori --------------------------------------------- */

.baris-geser {
    padding: 10px 0;
    border-bottom: 1px solid var(--garis-halus);
}

.baris-geser:last-child { border-bottom: 0; }

/*
   Kolom ketik di kanan nama kategori.

   Lebarnya tetap dan rata kanan supaya deretan angkanya lurus ke bawah
   — daftar angka yang tepi kanannya bergerigi jauh lebih susah
   dibandingkan sekilas, dan membandingkan sekilas itulah gunanya
   halaman ini.

   width-nya ditulis ulang karena aturan umum kolom isian memakai
   width:100%, yang di dalam baris flex akan memakan seluruh sisa ruang
   dan mendorong nama kategorinya sampai terpotong.
*/
/*
   input.kolom-angka, bukan .kolom-angka.

   Aturan umum kolom isian ditulis sebagai daftar selektor elemen —
   input[type="text"], select, textarea — dan itu lebih kuat daripada
   satu kelas. Ditulis sebagai .kolom-angka saja, width:7.2em di sini
   KALAH oleh width:100% di sana: kotaknya memakan seluruh baris dan
   nama kategorinya terjepit jadi tiga baris. Nama elemennya ikut
   ditulis supaya bobotnya sama lalu menang karena urutan.
*/
input.kolom-angka {
    width: 7.2em;
    flex-shrink: 0;
    text-align: right;
    padding: 7px 10px;
    font-size: 16px;   /* tetap 16px: di bawah itu iOS memperbesar layar */
    font-variant-numeric: tabular-nums;
}

.geser {
    width: 100%;
    margin-top: 8px;
    accent-color: var(--aksen);

    /* Jalur setipis bawaannya susah dikenai jempol. Yang ditinggikan
       area sentuhnya, bukan garisnya. */
    height: 26px;
    background: transparent;
    cursor: pointer;
}

/* --- Ini Itu: kartu Masuk yang bisa dicoret-coret -------------------- */

.baris-masuk {
    padding: 8px 0;
    border-bottom: 1px solid var(--garis-halus);
    gap: 8px;
}

.baris-masuk:last-child { border-bottom: 0; }

/* Baris yang centangnya dilepas dipudarkan, sama perlakuannya dengan
   baris Wajib — bukan dicoret. Coretan terbaca "dibatalkan"; pemasukannya
   tidak dibatalkan apa-apa, cuma tidak ikut dihitung di coretan ini. */
.baris-masuk:has(input[type="checkbox"]:not(:checked)) {
    opacity: .45;
}

/* Nama pemasukan tambahan yang diketik sendiri.

   Sengaja tidak setebal kolom angka: yang dibandingkan orang waktu
   memindai kartu ini nominalnya, bukan namanya. */
input.kolom-judul {
    min-width: 0;
    padding: 7px 10px;
    font-size: 16px;   /* tetap 16px: di bawah itu iOS memperbesar layar */
}

/*
   Tombol buang.

   Ukurannya 30px, bukan sebesar tulisan "×" di dalamnya. Sasaran
   sentuh sekecil huruf akan sering meleset — dan yang meleset di baris
   ini mendarat di kolom angka sebelahnya, jadi orangnya malah mengetik
   di tempat yang tidak dia tuju.
*/
.tombol-buang {
    flex-shrink: 0;
    width: 30px;
    height: 30px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 1px solid var(--garis);
    border-radius: var(--radius-sm);
    background: var(--permukaan);
    color: var(--tinta-samar);
    font-size: 1.1rem;
    line-height: 1;
    cursor: pointer;
}

.tombol-buang:hover {
    border-color: var(--bahaya);
    color: var(--bahaya);
}
