/* ============================================================
   nasabah.css — TEMA aplikasi NASABAH (mobile banking).

   Satu tempat untuk bentuk yang dipakai BERULANG di layar nasabah:
   judul halaman, kartu, baris kunci-nilai, kartu saldo, pintasan,
   kartu aksi, badge, kotak pesan, baris mutasi.

   Sebelumnya setiap halaman menyalin bentuk yang sama di blok <style>
   sendiri (nbr- / nbt- / nms- / npf- / …), jadi satu perubahan tema harus
   diulang di 13 berkas dan hasilnya mudah berbeda antar layar.

   ATURAN BERKAS INI
   1. SEMUA warna dari token tema (--accent, --surface, --border-light,
      --text-*, --radius-card, --shadow-card, --table-stripe). Tidak ada
      warna keras buatan sendiri: tema terang/gelap/MC perangkat harus
      tetap benar tanpa berkas kedua.
   2. Kelas berawalan `nb-` dipakai halaman nasabah; gaya yang hanya dipakai satu halaman boleh
      tetap di <style> halaman itu (awalan halamannya, mis. `npf-`). PENGECUALIAN di bagian
      12–14: komponen BERSAMA milik aplikasi (sp-btn, sp-input, form-group, empty-state,
      list-state) didefinisikan di `shared.css` yang tidak boleh disuntik tema (spec A.1),
      jadi bentuknya di dalam kerangka nasabah ditimpa lewat aturan ber-scope `.nb-shell` —
      area petugas (di luar `.nb-shell`) tidak menerima aturan ini sama sekali.
   3. Dimuat PALING AKHIR di index.html (sesudah mobile.css).

   Versi di index.html: naikkan `nasabah.css?v=` setiap berkas ini diubah,
   kalau tidak browser/WebView yang sudah pernah membuka aplikasi akan
   memakai versi lamanya (gaya baru tidak sampai).
   ============================================================ */

/* ── 1. Judul halaman & bagian ───────────────────────────────────────── */
/* 2026-10-17: `.nb-kepala` DIHAPUS — nama & nomor nasabah kini duduk di DALAM kartu
   hero (`nb-saldo .nb-hero` di bawah), bukan di baris kepala halaman. Kelas lama
   sengaja tidak dihapus dari berkas ini karena masih dipakai halaman lain;
   hanya di Beranda yang bentuknya berubah total. */

.nb-judul {
    margin: 0; font-size:var(--nb-fs-title); font-weight: 700; color: var(--text-primary); letter-spacing:var(--nb-ls-tight);
}
.nb-sub {
    margin:var(--nb-sp-1) 0 0; font-size:var(--nb-fs-label); color: var(--text-tertiary); line-height: 1.45;
}
.nb-kepala {
    display: flex; align-items: flex-start; justify-content: space-between; gap:var(--nb-sp-3); margin-bottom:var(--nb-sp-4);
}
.nb-bagian {
    margin:var(--nb-sp-4) 0 var(--nb-sp-2); font-size:var(--nb-fs-subtitle); font-weight: 700; color: var(--text-primary);
}
/* ── 1b. Kepala hero (dipakai layar pra-login: Masuk · Daftar) ───────── */
/* Pembungkus layar pra-login: isinya diletakkan di tengah tinggi layar. */
.nb-bungkus { display: flex; flex-direction: column; justify-content: center; min-height: 100%; }

.nb-hero {
    background: linear-gradient(135deg, var(--nb-hero-from, var(--accent)) 0%, var(--nb-hero-to, var(--accent-dark)) 100%);
    border-radius: var(--nb-hero-radius);
    padding:var(--nb-sp-5) var(--nb-gutter) var(--nb-sp-5); margin-bottom:var(--nb-sp-4);
    text-align: center; color: var(--on-accent); box-shadow: var(--nb-shadow-hero);
}
/* Pelat logo: logo apa pun tetap terbaca karena latarnya opaque, sedangkan gradien di
   belakangnya mengikuti warna tema lembaga (terang/gelap/MC). */
.nb-hero-plat {
    width:var(--nb-hero-plat); height:var(--nb-hero-plat); border-radius: 50%; padding:var(--nb-sp-2); margin:0 auto var(--nb-sp-3);
    display: flex; align-items: center; justify-content: center; background: var(--nb-hero-plat-bg);
}
.nb-hero-plat img { width: 100%; height: 100%; object-fit: contain; display: block; }
.nb-hero-judul { margin: 0; font-size:var(--nb-fs-title); font-weight: 700; letter-spacing:var(--nb-ls-tight); }
.nb-hero-sub { margin:var(--nb-sp-1) 0 0; font-size:var(--nb-fs-label); opacity: .9; }

/* ── 1d. HERO SALDO BERANDA (2026-10-17): baris nama + ikon aksi di dalam
   kartu saldo, menggantikan baris kepala halaman lama. 2026-10-17 (revisi):
   `nb-hero` dihapus karena terlalu tinggi — diganti `nb-saldo-nama` (baris
   nama saja, tanpa h2 besar, tanpa "Halo"), font-size standard label,
   lebih rapat dengan angka di bawahnya.
   Swipe-to-refresh: kartu hero menjadi zona sentuh; geser ke bawah ±90px
   memicu `SegarkanAsync` lewat event DOM (JS di code-behind Beranda.razor).
   Indikatornya adalah lingkaran memutar di tengah bawah kartu
   (`nb-saldo-refresh`), terlihat hanya saat sedang memuat (kelas aktif
   ditambahkan JS pada `data-ambil-data`). *@

/* Baris nama + ikon aksi di bawah angka saldo:
   - `.nb-saldo-nama` = baris flex: nama di kiri, ikon di kanan
   - `.nb-saldo-nama-nilai` = nama saja (tanpa label, tanpa sub — nomor &
     jumlah rekening sudah di kartu rekening di bawah, jangan diulang di sini)
   - `.nb-saldo-nama-aksi` = dua ikon di kanan (tema + mata)
   - Tinggi baris ≈ tinggi label standard, tidak membengkakkan kartu.
   2026-10-17 (revisi 2): hapus label "Nasabah" & sub (nomor + jumlah),
   saldo dipindah ke atas. */
.nb-saldo .nb-saldo-nama {
    display: flex; align-items: center; justify-content: space-between; gap:var(--nb-sp-3);
    margin-top:var(--nb-sp-3); position: relative; z-index: 1;
}
.nb-saldo .nb-saldo-nama-nilai {
    min-width: 0; font-size:var(--nb-fs-label); font-weight: 600; color: var(--on-accent);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.nb-saldo .nb-saldo-nama-aksi {
    display: flex; align-items: center; gap:var(--nb-sp-2); flex: 0 0 auto;
}
/* Tombol ganti tema di hero: lingkaran chip, sama ukurannya dengan tombol mata,
   sejajar di kanan kartu — ikon matahari/bulan 18 piksel. 2026-10-17. */
.nb-saldo .nb-tema {
    flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
    width:var(--nb-avatar); height:var(--nb-avatar); border-radius: 50%; cursor: pointer; font-family: inherit;
    background: var(--nb-on-brand-chip); border:var(--nb-hairline) solid var(--nb-on-brand-border); color: var(--on-accent);
}
.nb-saldo .nb-tema:disabled { opacity: .6; cursor: not-allowed; }
.nb-saldo .nb-tema svg { display: block; }
/* Lingkaran VISUAL 34 piksel, bidang sentuh 44 piksel — sama seperti tombol
   mata di sebelahnya (`.nb-saldo-mata::before` memakai inset sentuh; yang ini
   diulang biar konsisten). */
.nb-saldo .nb-tema { position: relative; }
.nb-saldo .nb-tema::before { content: ""; position: absolute; inset:var(--nb-sentuh-2); border-radius: 50%; }
/* Indikator swipe-to-refresh: lingkaran memutar di tengah bawah kartu, hanya
   ditampilkan saat kartu mendapat kelas `nb-saldo-memuat` (ditambah JS pada
   `data-ambil-data` saat `SegarkanAsync` berjalan). */
.nb-saldo .nb-saldo-refresh {
    position: absolute; left: 50%; bottom:var(--nb-sp-3); transform: translateX(-50%);
    width:22px; height:22px; border-radius: 50%; border:var(--nb-hairline) solid var(--nb-on-brand-divider);
    border-top-color: var(--on-accent); opacity: 0; pointer-events: none; z-index: 2;
}
.nb-saldo-memuat .nb-saldo-refresh {
    opacity: 1; animation: nb-refresh-putar .9s linear infinite;
}
@keyframes nb-refresh-putar { to { transform: translateX(-50%) rotate(360deg); } }
/* Kartu sedang memuat: isian hero sedikit meredup (bukan menyembunyikan — angka
   lama tetap terbaca, hanya memberi sinyal bahwa angka sedang disegarkan). */
.nb-saldo-memuat .nb-saldo-nilai { opacity: .55; }

/* Isian ber-tombol di kanan (mis. mata pada PIN). WAJIB dipasang pada elemen yang juga
   ber-kelas `input-trailing-wrapper`: m3-outline.js hanya mengenali pembungkus baku itu,
   jadi nama kelas bikinan sendiri membuat kotak isiannya kehilangan gaya M3 (label tidak
   mengambang) tanpa error apa pun. Ruang kanannya perlu dilebarkan agar teks tidak masuk
   ke bawah tombolnya. */
.nb-sandi .sp-input { padding-right:var(--nb-sp-12); }

/* ── 1c. Kotak daftar yang DIGULIR (katalog produk Topup & Tagihan) ──── */

/* Daftar produk di dalam kotak yang menggulung sendiri, TINGGINYA DIBATASI ±4 produk
   supaya kartu isian (pembelian / pembayaran tagihan) tidak terdorong jauh ke bawah layar
   (permintaan pemilik 2026-09-26: "bungkus dalam scrollable cukup tampilkan 4 data").

   Tingginya 226 piksel = **kepala kelompok** (± 37 piksel, ikut di dalam kotak) + **2 baris kartu
   produk penuh** (diukur: kartu tertinggi 90,3 piksel waktu namanya membungkus + celah kisi 8 piksel).
   Di kisi 2 kolom layar HP itu 4 produk yang terlihat utuh — kepala kelompoknya tetap terbaca
   saat digulir; di kerangka 480 piksel (3 kolom) 6. Angkanya dari
   `artifacts/uji-hp/ukur_daftar_gulir.py` (Chromium tanpa kepala, memuat berkas ini apa
   adanya), bukan perkiraan: `python artifacts/uji-hp/ukur_daftar_gulir.py`.
   `max-height` — kotak dengan 1 produk tetap setinggi isinya, bukan 226 piksel. */
.nb-daftar-gulir {
    max-height:var(--nb-gulir-h); overflow-y: auto; padding-right:var(--nb-sp-1);
    -webkit-overflow-scrolling: touch; overscroll-behavior: contain;
}

/* ── 2. Kartu ────────────────────────────────────────────────────────── */

.nb-kartu {
    background: var(--surface); border:var(--nb-hairline) solid var(--border-light);
    border-radius: var(--radius-card); padding: var(--nb-pad-kartu);
}
.nb-kartu + .nb-kartu { margin-top: var(--nb-gap-kartu); }
.nb-kartu-judul {
    display: flex; align-items: center; gap:var(--nb-sp-2); margin:0 0 var(--nb-sp-3);
    font-size:var(--nb-fs-overline); font-weight: 700; text-transform: uppercase; letter-spacing:var(--nb-ls-overline); color: var(--accent);
}
.nb-kartu-judul .material-symbols-rounded { font-size:var(--nb-fs-title); }
.nb-kartu-ket {
    margin:var(--nb-sp-2) 0 0; font-size:var(--nb-fs-caption); color: var(--text-tertiary); line-height: 1.5;
}
.nb-tumpuk { display: flex; flex-direction: column; gap: var(--nb-gap-kartu); }

/* ── 3. Baris kunci–nilai (identitas, limit, ringkasan) ──────────────── */

.nb-baris {
    display: flex; justify-content: space-between; gap:var(--nb-sp-3); padding:var(--nb-sp-2) 0;
    border-bottom:var(--nb-hairline) dashed var(--border-subtle);
}
.nb-baris:last-child { border-bottom: none; }
.nb-baris-kunci { font-size:var(--nb-fs-label); color: var(--text-tertiary); flex: 0 0 auto; }
.nb-baris-nilai {
    font-size:var(--nb-fs-label); font-weight: 600; color: var(--text-primary);
    text-align: right; overflow-wrap: anywhere;
}

/* ── 4. Kartu SALDO (hero) ───────────────────────────────────────────── */

.nb-saldo {
    position: relative; overflow: hidden; margin-bottom:var(--nb-sp-4);
    border-radius: var(--nb-hero-radius); padding:var(--nb-pad-hero) var(--nb-gutter) var(--nb-sp-4);
    color: var(--on-accent); background: linear-gradient(135deg, var(--nb-hero-from, var(--accent)) 0%, var(--nb-hero-to, var(--accent-dark)) 100%);
    box-shadow: var(--nb-shadow-hero);
}
/* Hiasan lembut di sudut — memberi kesan berdimensi tanpa gambar/aset. */
.nb-saldo::after {
    content: ""; position: absolute; right:var(--nb-dekor-kanan); top:var(--nb-dekor-atas); width:var(--nb-dekor-sudut); height:var(--nb-dekor-sudut);
    border-radius: 50%; background: var(--nb-on-brand-deco); pointer-events: none;
}
.nb-saldo-kepala {
    display: flex; align-items: flex-start; justify-content: space-between; gap:var(--nb-sp-3);
    position: relative; z-index: 1;
}
.nb-saldo-label {
    font-size:var(--nb-fs-overline); text-transform: uppercase; letter-spacing:var(--nb-ls-overline); opacity: .85;
}
.nb-saldo-nilai {
    margin-top:var(--nb-sp-1); font-size:var(--nb-fs-headline); font-weight: 700; line-height: 1.1;
    font-variant-numeric: tabular-nums; letter-spacing:var(--nb-ls-tighter);
}
/* Nominal hero naik ke skala `display` pada layar lebar-HP (≥390px, rujukan desain spec §4.2);
   di bawah itu tetap `headline` 30px (ukuran lama, dipertahankan). Angka di @media tidak bisa
   memakai var() — CSS custom property tidak terbaca di kondisi media. */
@media (min-width: 390px) {
    .nb-saldo-nilai { font-size:var(--nb-fs-display); }
}
.nb-saldo-sembunyi { letter-spacing:var(--nb-ls-sembunyi); }
.nb-saldo-norek {
    margin-top:var(--nb-sp-2); font-family: var(--font-mono); font-size:var(--nb-fs-label); opacity: .92; letter-spacing:var(--nb-ls-micro);
}
.nb-saldo-catatan {
    margin-top:var(--nb-sp-2); font-size:var(--nb-fs-caption); line-height: 1.45; opacity: .85; position: relative; z-index: 1;
}
.nb-saldo-mata {
    position: relative; flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center;
    width:var(--nb-avatar); height:var(--nb-avatar); border-radius: 50%; cursor: pointer; font-family: inherit;
    background: var(--nb-on-brand-chip); border:var(--nb-hairline) solid var(--nb-on-brand-border); color: var(--on-accent);
}
/* Lingkaran VISUAL 34 piksel, bidang sentuh 44 piksel (spec §11.3) — tanpa menambah lebar. */
.nb-saldo-mata::before { content: ""; position: absolute; inset:var(--nb-sentuh-2); border-radius: 50%; }
.nb-saldo-mata .material-symbols-rounded { font-size:var(--nb-ikon-18); }
.nb-saldo-kaki {
    display: flex; align-items: center; gap:var(--nb-sp-2); margin-top:var(--nb-sp-3);
    padding-top:var(--nb-sp-3); border-top:var(--nb-hairline) solid var(--nb-on-brand-divider);
    position: relative; z-index: 1;
}
.nb-saldo-kaki-item {
    flex: 1 1 0; min-width: 0; font-size:var(--nb-fs-caption); opacity: .9;
}
.nb-saldo-kaki-item b {
    display: block; font-size:var(--nb-fs-body-sm); font-weight: 700; opacity: 1;
    font-variant-numeric: tabular-nums; margin-top:var(--nb-sp-1);
}

/* ── 5. Kartu rekening ───────────────────────────────────────────────── */

.nb-rek {
    background: var(--surface); border:var(--nb-hairline) solid var(--border-light);
    border-radius: var(--radius-card); padding: var(--nb-pad-kartu);
}
.nb-rek + .nb-rek { margin-top:var(--nb-sp-3); }
.nb-rek.tutup { opacity: .72; }
.nb-rek-kepala {
    display: flex; align-items: center; justify-content: space-between; gap:var(--nb-sp-2);
}
.nb-rek-jenis {
    font-size:var(--nb-fs-overline); font-weight: 700; color: var(--accent);
    text-transform: uppercase; letter-spacing:var(--nb-ls-bagian);
}
.nb-rek-norek {
    font-family: var(--font-mono); font-size:var(--nb-fs-label); color: var(--text-secondary); margin-top:var(--nb-sp-1);
}
.nb-rek-saldo-label { font-size:var(--nb-fs-caption); color: var(--text-tertiary); margin-top:var(--nb-sp-2); }
.nb-rek-saldo {
    font-size:var(--nb-fs-title-lg); font-weight: 700; color: var(--text-primary);
    font-variant-numeric: tabular-nums; margin-top:var(--nb-sp-1); line-height: 1.15;
}

/* ── 6. Baris aksi (tombol di dalam kartu) ───────────────────────────── */

.nb-aksi { display: flex; gap:var(--nb-sp-2); margin-top:var(--nb-sp-3); flex-wrap: wrap; }
/* Ukuran tombol (font 14px, padding 12/20) diatur aturan bersama bagian 12;
   di sini cukup LEBAR PENUH — tindakan uang tidak boleh setengah lebar (spec §11.5). */
.nb-aksi .sp-btn { flex: 1 1 auto; justify-content: center; }

/* ── 7. Pintasan ikon (satu baris, membungkus 2×2 di layar sempit) ───── */

.nb-pintasan {
    display: grid; grid-template-columns:repeat(auto-fit, minmax(var(--nb-kisi-min-xs), 1fr));
    gap:var(--nb-sp-2); margin:var(--nb-sp-3) 0 var(--nb-sp-1);
}
.nb-pintasan a {
    display: flex; flex-direction: column; align-items: center; gap:var(--nb-sp-1);
    padding:var(--nb-sp-2) var(--nb-sp-1); border-radius: var(--nb-radius-md); text-decoration: none; text-align: center;
    background: var(--table-stripe); border:var(--nb-hairline) solid var(--border-light);
    color: var(--text-secondary); font-size:var(--nb-fs-micro); font-weight: 600; line-height: 1.15;
}
.nb-pintasan a:active { background: var(--accent-light); }
.nb-pintasan .material-symbols-rounded { font-size:var(--nb-ikon-19); color: var(--accent); }
.nb-pintasan-nama { overflow-wrap: anywhere; }

/* ── 8. Kisi kartu aksi (menu layanan, 2 kolom) ──────────────────────── */

.nb-kisi { display: grid; grid-template-columns: 1fr 1fr; gap: var(--nb-gap-kartu); }
.nb-aksi-kartu {
    display: flex; flex-direction: column; gap:var(--nb-sp-2); min-height:var(--nb-kosong-h);
    background: var(--surface); border:var(--nb-hairline) solid var(--border-light);
    border-radius: var(--radius-card); padding: var(--nb-pad-kartu);
    text-decoration: none; color: inherit;
}
.nb-aksi-kartu:active { background: var(--table-stripe); }
.nb-aksi-ikon { font-size:var(--nb-ikon-28); color: var(--accent); line-height: 1; }
.nb-aksi-nama { font-size:var(--nb-fs-body-sm); font-weight: 700; color: var(--text-primary); }
.nb-aksi-ket { font-size:var(--nb-fs-caption); color: var(--text-tertiary); line-height: 1.35; }

/* Kisi layanan ringkas (Beranda → "Layanan lainnya") */
.nb-layanan { display: grid; grid-template-columns:repeat(auto-fit, minmax(var(--nb-kisi-min-sm), 1fr)); gap:var(--nb-sp-2); }
.nb-layanan a {
    display: flex; flex-direction: column; gap:var(--nb-sp-1); min-height:var(--nb-kosong-h-sm);
    background: var(--surface); border:var(--nb-hairline) solid var(--border-light);
    border-radius: var(--radius-card); padding:var(--nb-sp-3) var(--nb-sp-3);
    text-decoration: none; color: inherit;
}
.nb-layanan a:active { background: var(--table-stripe); }
.nb-layanan .material-symbols-rounded { font-size:var(--nb-fs-title-lg); color: var(--accent); line-height: 1; }
.nb-layanan-nama { font-size:var(--nb-fs-label); font-weight: 700; color: var(--text-primary); }
.nb-layanan-ket { font-size:var(--nb-fs-caption); color: var(--text-tertiary); line-height: 1.3; }

/* ── 9. Baris mutasi / transaksi terakhir ────────────────────────────── */

.nb-mutasi-baris {
    display: flex; align-items: flex-start; justify-content: space-between; gap:var(--nb-sp-3);
    min-height:var(--nb-kosong-h-xs); padding:var(--nb-sp-3) 0; border-bottom:var(--nb-hairline) solid var(--border-subtle);
}
.nb-mutasi-baris:last-child { border-bottom: none; padding-bottom: 0; }
.nb-mutasi-teks { min-width: 0; }
.nb-mutasi-tgl { font-size:var(--nb-fs-caption); color: var(--text-tertiary); margin-top:var(--nb-sp-1); }
.nb-mutasi-uraian {
    font-size:var(--nb-fs-body-sm); font-weight: 600; color: var(--text-primary);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.nb-mutasi-nilai {
    font-size:var(--nb-fs-body-sm); font-weight: 700; white-space: nowrap;
    font-variant-numeric: tabular-nums; text-align: right;
}
.nb-mutasi-masuk { color: var(--accent-green); }
.nb-mutasi-keluar { color: var(--accent-red); }

/* ── 10. Badge & kotak pesan ─────────────────────────────────────────── */

/* Dasar badge = pasangan `badge.bg`/`badge.text` (spec §11.7); status pakai varian di bawah.
   Ukuran `micro` (10,5px/600 + `letter-spacing micro`) sesuai skala §4.2. */
.nb-badge {
    font-size:var(--nb-fs-micro); font-weight: 600; letter-spacing:var(--nb-ls-micro);
    padding:var(--nb-sp-1) var(--nb-sp-2); border-radius: var(--radius-pill);
    background: var(--badge-bg); color: var(--badge-text);
}
/* Varian lencana status — SATU kelas bersama untuk semua layar (spec §11.12).
   Sebelumnya 24 baris rgba hijau/merah/amber disalin di 6 blok <style> halaman;
   sekarang halaman hanya menulis `nb-badge nb-badge-sukses` dst. */
.nb-badge-sukses { background: var(--nb-success-soft); color: var(--accent-green); }
.nb-badge-galat { background: var(--nb-danger-soft); color: var(--accent-red); }
.nb-badge-peringatan { background: var(--nb-warning-soft); color: var(--nb-warning-text); }
.nb-badge-netral { background: var(--table-stripe); color: var(--text-secondary); }

.nb-info, .nb-ok, .nb-galat {
    display: flex; gap:var(--nb-sp-2); padding:var(--nb-sp-3) var(--nb-sp-4); border-radius: var(--nb-radius-md);
    font-size:var(--nb-fs-body-sm); line-height: 1.45; margin-bottom: var(--nb-gap-kartu);
}
.nb-info { background: var(--accent-light); border:var(--nb-hairline) solid var(--border-light); color: var(--text-primary); }
.nb-ok { background: var(--accent-light); border:var(--nb-hairline) solid var(--border-light); color: var(--accent-dark); }
.nb-galat {
    background: var(--nb-danger-soft); border:var(--nb-hairline) solid var(--nb-danger-border); color: var(--accent-red);
}
.nb-info .material-symbols-rounded,
.nb-ok .material-symbols-rounded,
.nb-galat .material-symbols-rounded { font-size:var(--nb-ikon-18); line-height: 1.2; flex: 0 0 auto; }

/* ── 11. Kaki halaman, tautan, utilitas ──────────────────────────────── */

.nb-kaki {
    margin:var(--nb-sp-4) 0 0; font-size:var(--nb-fs-caption); color: var(--text-tertiary);
    line-height: 1.5; text-align: center;
}
.nb-tautan { color: var(--accent); font-weight: 700; text-decoration: none; }
.nb-tautan:hover { text-decoration: underline; }
/* Kaki `.nb-kaki` & tautannya hanya berisi teks caption (13px) — bidang sentuh
   `--tap` (44px, spec §11.3) lewat `::before` (pola §15, tanpa menambah tinggi visual):
   kaki di semua 14 layar, tautan "Masuk/Daftar di sini" di Masuk & Daftar. */
.nb-shell .nb-kaki, .nb-shell .nb-tautan { position: relative; }
.nb-shell .nb-kaki::before, .nb-shell .nb-tautan::before {
    content: ""; position: absolute; inset: min(0px, calc((var(--tap) - 100%) / -2));
}
.nb-uang { font-variant-numeric: tabular-nums; }
.nb-mono { font-family: var(--font-mono); }
.nb-catatan {
    margin:var(--nb-sp-3) 0 0; font-size:var(--nb-fs-caption); color: var(--text-tertiary); line-height: 1.5;
}

/* ══════════════════════════════════════════════════════════════════════
   KOMPONEN BERSAMA APLIKASI — hanya di dalam kerangka nasabah (.nb-shell)

   Tombol, isian, dan keadaan daftar didefinisikan di `shared.css` karena
   dipakai bersama area petugas; berkas itu tidak boleh disuntik tema
   (spec A.1: "berkas tema tidak menyentuh shared.css"), jadi pemetaan ke
   token ditulis DI SINI dengan selektor ber-scope `.nb-shell`. Efeknya:
   di dalam kerangka nasabah semuanya memakai token Trust Blue, di luar
   kerangka (tulang petugas) tidak ada satu pun aturan yang berubah.

   Semua nilai dari token; angka mentah hanya muncul di dalam
   `nasabah-theme.css` (definisi token) dan di kondisi media
   (CSS tidak bisa memakai var() di dalam @media).
   ══════════════════════════════════════════════════════════════════════ */

/* ── 12. Tombol (spec §11.5) ─────────────────────────────────────────────
   shared.css menulis varian dengan warna keras buatan sendiri (nilai hover
   merah/oranye/ungu yang tidak ada di palet) dan `background: var(--accent)` —
   yang kedua salah di mode gelap (aksennya biru terang, teks putih cuma
   2,4:1, spec §0.4). Di sini varian dipetakan ke pasangan token "sebagai
   latar": `--nb-btn-*` / `--nb-warning-fill`. */
.nb-shell .sp-btn {
    border-radius: var(--nb-r-md);      /* radius.md — tombol modern, bukan pil (spec §6) */
    font-size: var(--nb-fs-body);       /* label tombol `body` 14px */
    font-weight: 600;
    transition: background-color var(--nb-motion-fast) var(--nb-ease-standard),
                border-color var(--nb-motion-fast) var(--nb-ease-standard),
                color var(--nb-motion-fast) var(--nb-ease-standard),
                box-shadow var(--nb-motion-fast) var(--nb-ease-standard),
                opacity var(--nb-motion-fast) var(--nb-ease-standard);
}
/* Tinggi `--nb-btn-h` 48px dipasang nasabah-theme.css pada lebar HP; padding ikut
   12/20 (spec §11.5). Di ≥900px kerangka ponsel memakai tinggi bawaan 38px
   shared.css — diizinkan spec §11.5, jadi padding tidak dipaksa di sana. */
@media (max-width: 56.1875em) {
    .nb-shell .sp-btn { padding: var(--nb-sp-3) var(--nb-sp-5); }
}
/* Varian kecil (tombol "Coba lagi" dsb.) tetap ringkas; tinggi 44px minimal
   datang dari mobile.css (`--tap`) di lebar HP. */
.nb-shell .sp-btn-sm { padding: var(--nb-sp-2) var(--nb-sp-4); font-size: var(--nb-fs-body-sm); }
/* `:disabled` = tanpa bayangan (spec §11.5); opacity & cursor sudah dari shared.css.
   Ditaruh sesudah varian supaya menang atas bayangan merek tombol primer. */
.nb-shell .sp-btn:disabled { box-shadow: none; }

/* Varian — `:hover` dikurung di `@media (hover: hover)` (spec §11.5: hover hanya
   untuk peranti penunjuk; di layar sentuh :hover menempel setelah ketukan).
   `:active` tetap berlaku di semua peranti. Nilai `:active` = latar `accent.soft`
   untuk varian bergaris/outline dan warna `:hover` untuk varian penuh. */

/* Primer — tindakan utama (Kirim, Bayar, Masuk). */
.nb-shell .sp-btn-primary { background: var(--nb-btn-primary); color: var(--on-accent); box-shadow: var(--nb-shadow-brand); }
@media (hover: hover) {
    .nb-shell .sp-btn-primary:hover:not(:disabled) { background: var(--nb-btn-primary-hover); }
}
.nb-shell .sp-btn-primary:active:not(:disabled) { background: var(--nb-btn-primary-hover); }

/* Sekunder — tindakan "aman/uang masuk"; teks memakai `on.secondary`
   (--nb-on-secondary): di mode gelap latarnya hijau muda, teks putih tidak lulus. */
.nb-shell .sp-btn-green { background: var(--nb-btn-secondary); color: var(--nb-on-secondary); }
@media (hover: hover) {
    .nb-shell .sp-btn-green:hover:not(:disabled) { background: var(--nb-btn-secondary-hover); }
}
.nb-shell .sp-btn-green:active:not(:disabled) { background: var(--nb-btn-secondary-hover); }

/* Amber — peringatan yang harus ditekan: teks `on.warning` (cokelat tua), bukan putih. */
.nb-shell .sp-btn-orange { background: var(--nb-warning-fill); color: var(--nb-on-warning); }

/* Bahaya — aksi merusak (Keluar, Blokir). */
.nb-shell .sp-btn-red { background: var(--nb-btn-danger); color: var(--on-accent); }
@media (hover: hover) {
    .nb-shell .sp-btn-red:hover:not(:disabled) { background: var(--nb-btn-danger-hover); }
}
.nb-shell .sp-btn-red:active:not(:disabled) { background: var(--nb-btn-danger-hover); }

/* Bahaya bergaris (varian lama shared.css, dipakai untuk aksi merusak ringan). */
.nb-shell .sp-btn-danger { background: transparent; border: var(--nb-hairline) solid var(--nb-danger-border); color: var(--accent-red); }
@media (hover: hover) {
    .nb-shell .sp-btn-danger:hover:not(:disabled) { background: var(--nb-danger-soft); }
}
.nb-shell .sp-btn-danger:active:not(:disabled) { background: var(--nb-danger-soft); }

/* Outline — tindakan alternatif (Batal, Kembali): tepi `border.control`, teks aksen. */
.nb-shell .sp-btn-outline { background: transparent; border: var(--nb-hairline) solid var(--border-medium); color: var(--accent); }
@media (hover: hover) {
    .nb-shell .sp-btn-outline:hover:not(:disabled) { background: var(--accent-light); }
}
.nb-shell .sp-btn-outline:active:not(:disabled) { background: var(--accent-light); }

/* ── 13. Isian (spec §11.6) ──────────────────────────────────────────────
   Tinggi `--tinggi-isian` (46px) TIDAK diubah — sudah ditentukan spec §10,
   dan font 16px di lebar HP datang dari mobile.css (anti-zoom iOS).
   Fokus tidak diberi ring tambahan: outline M3 sudah `2px solid accent`
   (shared.css blok "FOKUS") dan menambah ring justru membuat "double border"
   — catatan eksplisit snr-theme.css. Yang disunting di sini hanya latar &
   radius, keduanya token. */
.nb-shell .sp-input,
.nb-shell .sp-select,
.nb-shell textarea {
    background-color: var(--input-bg);      /* `input.bg` — kotak isian sedikit lebih terang dari kartu */
    border-radius: var(--nb-r-md);          /* radius.md 12px */
}
/* Label melayang menambal garis outline dengan `--m3-label-bg`; samakan dengan
   latar kotak supaya tambalan tidak terlihat sebagai kotak kedua di atas field. */
.nb-shell .form-group { --m3-label-bg: var(--input-bg); }
/* Hapus border pada label M3 di PWA Nasabah (request user 2026-10-17).
   shared.css memberi label floating border warna input/aksen; di PWA
   cukup bersih tanpa garis. */
.nb-shell .form-group:has(> .form-label) > .form-label,
.nb-shell .form-group.m3-auto > .form-label,
.nb-shell .form-group:focus-within > .form-label,
.nb-shell .dark .form-group:has(> .form-label) > .form-label {
    border: none !important;
    padding: 0 !important;
}
/* Di dalam `.form-group` bentuk datang dari pseudo-element M3 (`::before` = outline,
   field tanpa border) dengan spesifisitas tinggi. Selektor di bawah = selektor M3
   persis + `.nb-shell`, jadi menang tanpa `!important` dan tanpa menyunting
   `shared.css` (lihat aturan 2 di kepala berkas). */
.nb-shell .form-group:has(> .form-label):has(> .sp-input)::before,
.nb-shell .form-group:has(> .form-label):has(> .numinput)::before,
.nb-shell .form-group:has(> .form-label):has(> .sp-select)::before,
.nb-shell .form-group:has(> .form-label):has(> textarea)::before,
.nb-shell .form-group:has(> .form-label):has(> .input-trailing-wrapper)::before,
.nb-shell .form-group.m3-auto::before {
    border-radius: var(--nb-r-md);
}
.nb-shell .form-group:has(> .form-label):has(> .sp-input) > .sp-input,
.nb-shell .form-group:has(> .form-label):has(> .numinput) > .numinput,
.nb-shell .form-group:has(> .form-label):has(> .sp-select) > .sp-select,
.nb-shell .form-group:has(> .form-label):has(> textarea) > textarea,
.nb-shell .form-group:has(> .form-label):has(> .input-trailing-wrapper) > .input-trailing-wrapper .sp-input,
.nb-shell .form-group.m3-auto > .sp-input,
.nb-shell .form-group.m3-auto > .numinput,
.nb-shell .form-group.m3-auto > .sp-select,
.nb-shell .form-group.m3-auto > textarea,
.nb-shell .form-group.m3-auto > .input-trailing-wrapper .sp-input {
    background-color: var(--input-bg);
    border-radius: var(--nb-r-md);
}

/* ── 13b. Isian gaya sederhana ala AgenKilat (permintaan pemilik 2026-10-16) ──
   Di PWA/layar HP, notch + label melayang M3 terlihat ramai. Diganti: label
   STATIS di atas, kotak berbingkai 1px, fokus = bingkai aksen + ring lembut.
   Ini OVERRIDE di atas blok 13 & shared.css — semua ber-scope `.nb-shell`
   dengan `!important` karena aturan M3 memakai rantai `:has()` berspesifisitas
   tinggi dan `shared.css` sengaja tidak disentuh (dipakai bersama area petugas). */

/* (a) Outline pseudo M3 dimatikan — kotak isian sendiri yang punya bingkai. */
.nb-shell .form-group:has(> .form-label)::before,
.nb-shell .form-group.m3-auto::before { content: none !important; }

/* (b) Label STATIS di atas kotak: selalu terlihat, huruf kecil normal (bkan notch). */
.nb-shell .form-group:has(> .form-label) > .form-label,
.nb-shell .form-group.m3-auto > .form-label {
    position: static !important;
    top: auto !important;
    left: auto !important;
    transform: none !important;
    visibility: visible !important;
    display: block !important;
    margin: 0 0 var(--nb-sp-2) !important;
    padding: 0 !important;
    background: none !important;
    pointer-events: auto;
    white-space: normal !important;
    font-size: 13px !important;
    font-weight: 500 !important;
    letter-spacing: normal !important;
    text-transform: none !important;
    color: var(--text-secondary) !important;
    opacity: 1 !important;
}

/* (c) Bingkai kotak: 1px + latar isian + radius.md. */
.nb-shell .form-group:has(> .form-label) > .sp-input,
.nb-shell .form-group:has(> .form-label) > .numinput,
.nb-shell .form-group:has(> .form-label) > .sp-select,
.nb-shell .form-group:has(> .form-label) > textarea,
.nb-shell .form-group:has(> .form-label) > .input-trailing-wrapper .sp-input,
.nb-shell .form-group.m3-auto > .sp-input,
.nb-shell .form-group.m3-auto > .numinput,
.nb-shell .form-group.m3-auto > .sp-select,
.nb-shell .form-group.m3-auto > textarea,
.nb-shell .form-group.m3-auto > .input-trailing-wrapper .sp-input {
    border: var(--nb-hairline) solid var(--input-border) !important;
    background-color: var(--input-bg) !important;
    border-radius: var(--nb-r-md) !important;
}

/* (d) Hover: bingkai menggelap (peranti penunjuk saja). */
@media (hover: hover) {
    .nb-shell .form-group:has(> .form-label):not(:focus-within):hover > .sp-input,
    .nb-shell .form-group:has(> .form-label):not(:focus-within):hover > .numinput,
    .nb-shell .form-group:has(> .form-label):not(:focus-within):hover > .sp-select,
    .nb-shell .form-group:has(> .form-label):not(:focus-within):hover > textarea {
        border-color: var(--input-border-hover) !important;
    }
}

/* (e) Fokus: bingkai aksen + ring lembut (tanpa outline ganda). */
.nb-shell .form-group:has(> .form-label):focus-within > .sp-input,
.nb-shell .form-group:has(> .form-label):focus-within > .numinput,
.nb-shell .form-group:has(> .form-label):focus-within > .sp-select,
.nb-shell .form-group:has(> .form-label):focus-within > textarea,
.nb-shell .form-group:has(> .form-label):focus-within > .input-trailing-wrapper .sp-input,
.nb-shell .form-group.m3-auto:focus-within > .sp-input,
.nb-shell .form-group.m3-auto:focus-within > .numinput,
.nb-shell .form-group.m3-auto:focus-within > .sp-select,
.nb-shell .form-group.m3-auto:focus-within > textarea,
.nb-shell .form-group.m3-auto:focus-within > .input-trailing-wrapper .sp-input {
    border-color: var(--accent) !important;
    box-shadow: 0 0 0 3px var(--focus-ring) !important;
    outline: none !important;
    background-color: var(--input-bg) !important;
}

/* (f) Placeholder tetap terlihat saat fokus (label sudah di atas, jadi tidak perlu
   disembunyikan seperti gaya floating-label). */
.nb-shell .form-group:has(> .form-label):focus-within > .sp-input::placeholder,
.nb-shell .form-group:has(> .form-label):focus-within > .numinput::placeholder,
.nb-shell .form-group:has(> .form-label):focus-within > textarea::placeholder,
.nb-shell .form-group:has(> .form-label):focus-within > .input-trailing-wrapper .sp-input::placeholder,
.nb-shell .form-group.m3-auto:focus-within > .sp-input::placeholder,
.nb-shell .form-group.m3-auto:focus-within > textarea::placeholder {
    opacity: 1 !important;
}

/* ── 14. Keadaan kosong, gagal, memuat (spec §11.8 / §11.11) ─────────────
   `empty-state` & `list-state` juga didefinisikan shared.css (padding 60/20,
   ikon 34px, teks 12px). Di sini dipakai susunan spec: ikon 40px `text.tertiary`
   → judul `subtitle` → kalimat `body-sm` → padding 40px/16px, celah `space.2`.
   Markup komponen tidak diubah — hanya ditata ulang lewat CSS. */
.nb-shell .empty-state,
.nb-shell .list-state {
    display: flex; flex-direction: column; align-items: center; gap: var(--nb-sp-2);
    padding: var(--nb-sp-10) var(--nb-gutter);   /* 40px 16px (spec §11.8) */
    color: var(--text-tertiary);
}
.nb-shell .empty-state p {                       /* judul keadaan */
    margin: 0; font-size: var(--nb-fs-subtitle); font-weight: 700; color: var(--text-primary);
}
.nb-shell .empty-state-icon {
    font-size: var(--nb-ikon-40);                /* 40px, satu warna — bukan ilustrasi */
    color: var(--text-tertiary); opacity: .8; margin-bottom: 0;  /* .7 → .8: kontras ikon 2.87:1 → ~3.3:1 (syarat 3.0, audit t_b9507863) */
}

/* ═══ Perbaikan minor hasil audit visual 112 sel (t_b9507863) ════════════════
   Semua di bawah ini di-scoping ke .nb-shell sehingga area non-Nasabah tidak
   berubah. Bukti pengukuran per sel ada di audit.jsonl workspace tugas. */

/* Kontras — sub-judul kepala halaman & sub QR: terang 3.82:1 (syarat 4.5).
   Asal: warna text.tertiary dengan opacity .85 di atas bg #F4F7FB. */
.nb-shell .nb-kepala .nb-sub,
.nb-shell .nq-sub { opacity: 1; }

/* Kontras — pemisah "·" kaki dialog deposito: terang 1.28:1 / gelap 1.77:1.
   Shared.css memakai border-medium (garis, bukan teks); untuk teks pakai tertiary. */
.nb-shell .dk-pemisah { color: var(--text-tertiary); }

/* Radius — badge mengikuti spesifikasi §7 (pill), bukan 10px bawaan shared.css
   (nilai 10px di luar skala radius token 6/8/12/16/20/26/pill). */
.nb-shell .badge { border-radius: var(--nb-r-pill); }

/* Bidang sentuh ≥44×44 (spesifikasi §11.3, --nb-tap) — pola sama dengan
   .nb-saldo-mata::before yang sudah ada (inset negatif = perluasan bidang sentuh
   tanpa mengubah ukuran visual). */
.nb-shell .catatan__tanda { position: relative; }
.nb-shell .catatan__tanda::before {
    content: ""; position: absolute; inset: min(0px, calc((var(--tap) - 100%) / -2));   /* sentuh ikut --tap, tanpa literal px */
    border-radius: 50%;
}
.nb-shell .nbr-segarkan { position: relative; }
.nb-shell .nbr-segarkan::before {
    content: ""; position: absolute; inset: var(--nb-sentuh-2);  /* 34px → 44px */
    border-radius: 50%;
}
.nb-shell .nms-mata::before {
    content: ""; position: absolute; inset: var(--nb-sentuh-2);  /* 34px → 44px */
    border-radius: 50%;
}
/* Kontrol selektor/segmen yang tingginya di bawah 44px (34px & 42px & 31px). */
.nb-shell .ntf-seg { min-height: var(--nb-tap); }
.nb-shell .nkr-seg { min-height: var(--nb-tap); }
.nb-shell select.pp-pilih { box-sizing: border-box; min-height: var(--nb-tap); }
.nb-shell .empty-state p.empty-state-hint {       /* kalimat penjelas: maksimal 2 baris */
    margin: 0; max-width: var(--nb-teks-max); opacity: 1;
    font-size: var(--nb-fs-body-sm); font-weight: 400; color: var(--text-secondary); text-align: center;
}
.nb-shell .list-state p { margin: 0; font-size: var(--nb-fs-body-sm); color: var(--text-secondary); }

/* ══════════════════════════════════════════════════════════════════════
   15. SASARAN SENTUH ≥44px di dalam kerangka nasabah (spec §10)

   Beberapa komponen bersama sengaja kecil demi tampilan (tanda "?" catatan 17px,
   tombol mata isian 32/34px, pil pilih periode) — ukuran VISUAL dipertahankan,
   yang dinaikkan hanya bidang yang bisa ditekan. Polanya sama dengan spec
   §11.1/§11.3: lingkaran tak terlihat `::before`.

   Rumus `inset: min(0px, calc((var(--tap) - 100%) / -2))` = (44 − ukuran elemen)/2:
   bidang sentuh selalu pas `--tap` berapa pun ukuran visualnya, tanpa angka mentah
   baru. `min(0px, …)` menahan inset agar tak pernah positif (bila kelak ada elemen
   ≥44px, bidangnya tidak menyusut). Klik pada ::before mengenai elemennya sendiri
   (pseudo-element bagian dari kotak induk) — pola yang sudah terbukti pada
   `.nb-keluar`/`.nb-saldo-mata`.
   ══════════════════════════════════════════════════════════════════════ */

/* Tanda "?" keterangan (Shared/Catatan.razor — Topup · Tagihan · QRIS · TBB · PPOB). */
.nb-shell .catatan__tanda { position: relative; }
.nb-shell .catatan__tanda::before {
    content: ""; position: absolute;
    inset: min(0px, calc((var(--tap) - 100%) / -2));
    border-radius: 50%;
}
/* Tombol mata PIN (Masuk · Daftar): `.trailing-icon-btn` sudah `position:absolute`
   dari snr-theme.css — jangan ditimpa; hanya lingkaran sentuhnya yang dilebarkan. */
.nb-shell .input-trailing-wrapper .trailing-icon-btn::before {
    content: ""; position: absolute;
    inset: min(0px, calc((var(--tap) - 100%) / -2));
    border-radius: 50%;
}
/* Pil pilih periode (Shared/PeriodePilih.razor — dipakai Mutasi): tinggi sentuh `--tap`,
   lebar ikut isi (pil persegi panjang, bukan bulatan 44px). */
.nb-shell .pp-pilih { min-height: var(--tap); }

/* Gagal ≠ kosong: keadaan gagal ditampilkan sebagai kotak pesan galat
   (`nb-galat`) + tombol "Coba lagi" (spec §11.8) — role=alert tetap dari markup. */
.nb-shell .list-state-error {
    background: var(--nb-danger-soft);
    border: var(--nb-hairline) solid var(--nb-danger-border);
    border-radius: var(--nb-radius-md);
    padding: var(--nb-sp-4);
    color: var(--accent-red);
}
.nb-shell .list-state-error .list-state-icon { font-size: var(--nb-ikon-40); }
.nb-shell .list-state-error p { font-size: var(--nb-fs-body); font-weight: 700; color: var(--accent-red); }
.nb-shell .list-state-error .list-state-detail {
    font-size: var(--nb-fs-caption); font-weight: 400; color: var(--accent-red); opacity: .85;
}
.nb-shell .list-state-retry { margin-top: var(--nb-sp-1); }
