/* ============================================================
   HURUF

   Plus Jakarta Sans, DIPASANG SENDIRI - bukan diambil dari Google
   Fonts. Alasannya bukan privasi melainkan tempat: berkas gaya ini
   ikut terbundel ke dalam APK, dan HP di dalam mobil yang sedang
   melewati daerah tanpa sinyal tidak bisa mengunduh apa pun. Huruf
   yang gagal dimuat membuat seluruh aplikasi jatuh ke Arial, persis
   pada keadaan yang paling sering dialami driver.

   Satu berkas untuk SELURUH bobot 400-800: ini variable font, 27 KB.
   Lima berkas terpisah akan berukuran lima kali lipat dan membuat
   tebal-tipisnya berdatangan tidak bersamaan.

   font-display: swap - tulisan tampil lebih dulu dengan huruf
   cadangan, lalu berganti. Yang menunggu huruf termuat sebelum
   menggambar teks akan menampilkan layar kosong di HP yang lambat.
   ============================================================ */

@font-face {
    font-family: 'Plus Jakarta Sans';
    src: url('fonts/plus-jakarta-sans.woff2') format('woff2');
    font-weight: 400 800;
    font-style: normal;
    font-display: swap;
}

html, body {
    /*
        Cadangannya Segoe UI lalu huruf sistem, bukan Arial. Kalau
        berkasnya kelak gagal termuat, yang menggantikan sebaiknya huruf
        yang metriknya berdekatan supaya tata letak tidak melompat.
    */
    font-family: 'Plus Jakarta Sans', 'Segoe UI', system-ui, -apple-system, sans-serif;
    background-color: var(--ams-bg, #f4f6fb);
    color: var(--ams-ink, #101a33);

    /*
        Perataan halus. Di layar HP ber-DPI tinggi, huruf tanpa ini
        tampak lebih tebal daripada seharusnya.
    */
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

a, .btn-link {
    color: #1d4ed8;
}

/* ============================================================
   TOMBOL — GAYA BAKU SELURUH APLIKASI

   Bentuknya diambil dari tombol aksi pada halaman Tugas Saya, yang memang
   dirancang untuk dipakai driver sambil berdiri di pinggir jalan: tinggi,
   sudut membulat, dan warna bergradasi yang terlihat jelas di bawah matahari.

   Ditulis sebagai penimpaan kelas Bootstrap, BUKAN sebagai kelas baru.
   Alasannya: seluruh halaman sudah memakai .btn-primary dan kawan-kawannya.
   Membuat kelas baru berarti menyunting puluhan berkas, dan satu tombol yang
   terlewat akan tetap tampil dengan gaya lama tanpa ada yang menyadarinya.
   Dengan cara ini, tombol yang belum ditulis pun otomatis ikut seragam.

   Berkas ini dimuat SETELAH bootstrap.min.css, sehingga aturan di sini menang
   tanpa perlu !important. CSS milik komponen dimuat setelahnya lagi, jadi
   penyesuaian setempat — tombol ikon pada baris tabel, tombol simpan yang
   melayang di form invoice — tetap bisa menimpanya.
   ============================================================ */

/*
    Warna tombol ditaruh di :root, bukan di dalam .btn. Halaman Tugas Saya
    menyusun tombolnya sendiri karena bentuknya khusus — melebar penuh dengan
    panah di ujung kanan — tetapi warnanya harus tetap sama persis. Token di
    sini yang memastikannya: mengubah warna tombol utama cukup di satu baris,
    dan tidak mungkin ada dua biru navy yang sedikit berbeda.
*/
:root {
    /*
        RATA, BUKAN BERGRADASI.

        Sebelumnya tiap warna tombol berupa gradasi 135 derajat dengan bayangan
        berwarna yang tebal - bahasa rupa tombol sekitar 2015. Yang membuatnya
        terbaca lawas bukan warnanya, melainkan gradasi dan bayangan itu:
        aplikasi ponsel masa kini memakai bidang warna rata dengan bayangan
        yang nyaris tidak terlihat.

        Warnanya sendiri tidak diubah jauh - biru dongker tetap biru dongker
        milik merek ini. Yang dilepas hanya kilau palsunya.

        Bayangannya kini NETRAL, bukan berwarna senada tombolnya. Bayangan
        berwarna meniru cahaya yang memantul dari benda berwarna, dan itu tepat
        pada tombol timbul; pada bidang rata ia hanya membuat tepinya tampak
        kotor.
    */
    --ams-navy: #1b4285;
    --ams-navy-hover: #17386f;
    --ams-navy-shadow: 0 .125rem .375rem rgba(11, 31, 63, .16);

    /*
        Dipekatkan dari amber-600 ke amber-700, dan itu bukan soal selera.
        Putih di atas #d97706 hanya beruntun 3,5:1 - di bawah ambang keterbacaan
        4,5:1 untuk ukuran huruf tombol ini. Warna ini mencapainya, dan tombol
        yang dipakai untuk hal mendesak justru yang paling tidak boleh sulit
        dibaca di bawah matahari.
    */
    --ams-amber: #b45309;
    --ams-amber-shadow: 0 .125rem .375rem rgba(11, 31, 63, .14);

    --ams-green: #16a34a;
    --ams-green-hover: #15803d;
    --ams-green-shadow: 0 .125rem .375rem rgba(11, 31, 63, .14);

    --ams-red: #dc2626;
    --ams-red-hover: #c11f1f;
    --ams-red-shadow: 0 .125rem .375rem rgba(11, 31, 63, .14);

    /*
        Sedikit lebih pekat daripada warna dasar halaman (#eef2f8). Kalau
        keduanya sama persis, tombol pendamping menghilang menjadi bidang tak
        bertepi - dan sesudah garis tepinya dilepas, isi inilah satu-satunya
        yang menandai bahwa itu tombol.
    */
    --ams-muted-bg: var(--ams-btn-soft);
    --ams-muted-ink: #33405e;

    /*
        TOKEN TOMBOL, dipakai bersama app.css dan CSS milik halaman.

        Ada karena aplikasi ini ternyata punya DUA dunia tombol: keluarga .btn
        di berkas ini, dan belasan tombol yang digambar sendiri di CSS tiap
        halaman - "Foto", "Berkas", "Muat ulang", pemilih tanggal. Setiap kali
        rupa tombol diperbarui di sini, dunia kedua tidak ikut, dan yang
        memakainya menemukan tombol lama di halaman yang justru paling sering
        dibuka.

        Sesudah ini, tombol halaman menunjuk token yang sama. Satu angka diubah
        di sini, keduanya ikut - dan tidak ada lagi tombol yang tertinggal
        karena kebetulan tidak memakai kelas .btn.
    */
    --ams-btn-radius: 999px;
    --ams-btn-icon: #2563eb;

    /*
        Sudut KARTU, bukan tombol.

        Ada karena bentuk pil sempat bocor ke kartu pilihan - "Perorangan" dan
        "Perusahaan" pada form pemesanan berubah menjadi lonjong. Keduanya
        memang <button>, tetapi yang dilihat orang adalah KARTU: berisi ikon,
        judul, dan keterangan di bawahnya. Kartu berbentuk pil terbaca seperti
        tombol raksasa yang kebetulan kebanyakan tulisan.
    */
    --ams-card-radius: 1rem;

    /*
        Isi tombol lembut: biru pucat, BUKAN kelabu.

        Kelabu adalah warna bawaan Bootstrap, dan itu yang membuat tombol
        terbaca lawas walaupun bentuk dan bayangannya sudah diperbarui. Biru
        pucat ini masih ringan - tidak bersaing dengan tombol utama - tetapi
        punya suhu warna, dan itu yang membedakan tampilan yang dirancang dari
        tampilan yang dibiarkan bawaan.
    */
    --ams-btn-soft: #eff5ff;
    --ams-btn-soft-hover: #e0ebfe;
}

.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    /* Jarak antara ikon dan tulisan. Hampir semua tombol di aplikasi ini
       berisi <i> diikuti teks; tanpa gap keduanya menempel. */
    gap: .5rem;

    /* 44px adalah ukuran sasaran sentuh terkecil yang masih nyaman bagi jari.
       min-height, bukan height, supaya tombol yang tulisannya membungkus ke
       dua baris ikut memanjang alih-alih terpotong. */
    min-height: 2.75rem;
    padding: .5rem 1.25rem;

    border: 1px solid transparent;

    /*
        BENTUK PIL, bukan persegi bersudut tumpul.

        Perubahan bentuk inilah yang paling menentukan tombol terbaca masa kini
        atau tidak - lebih menentukan daripada warnanya. Aman dipakai di sini
        karena aplikasi ini tidak punya satu pun tombol berkelompok
        (btn-group), yang memang akan tampak aneh bila tiap anggotanya bulat.
    */
    border-radius: var(--ams-btn-radius);
    font-size: .9375rem;
    font-weight: 600;
    line-height: 1.25;
    text-decoration: none;
    transition: background-color .15s ease, box-shadow .15s ease, opacity .15s ease, transform .1s ease;
}

.btn:disabled,
.btn.disabled {
    opacity: .6;
    box-shadow: none;
    cursor: not-allowed;
}

/*
    Ikon di dalam tombol.

    Ukurannya dikunci relatif terhadap tulisannya, bukan dibiarkan mengikuti
    ukuran bawaan font ikon. Tanpa itu, ikon pada tombol kecil tampak terlalu
    besar dan pada tombol besar tampak tenggelam - dan bedanya baru terlihat
    ketika dua ukuran tombol kebetulan bersebelahan.

    line-height 1 meluruskannya secara optis: glif ikon punya ruang atas-bawah
    sendiri, dan tanpa ini ikon duduk satu-dua piksel lebih rendah daripada
    tulisan di sebelahnya.
*/
.btn > .bi,
.btn > i {
    font-size: 1.0625em;
    line-height: 1;
}

/* ---------- Ikon berwarna pada tombol berlatar lembut ----------

   Ikon TIDAK lagi mengikuti warna tulisannya. Tombol dengan ikon dan tulisan
   sewarna terbaca sebagai satu blok huruf yang kebetulan diawali gambar; ikon
   berwarna memisahkan keduanya, dan yang dicari mata lebih dulu - gambarnya -
   menjadi yang paling cepat ditemukan.

   Hanya pada tombol berlatar LEMBUT. Pada tombol berisi warna penuh, ikon
   berwarna akan beradu dengan latarnya sendiri dan justru hilang; di sana ikon
   tetap putih bersama tulisannya.
*/

.btn-secondary > .bi,
.btn-secondary > i,
.btn-outline-secondary > .bi,
.btn-outline-secondary > i,
.btn-outline-primary > .bi,
.btn-outline-primary > i {
    color: var(--ams-btn-icon);
}

.btn-outline-danger > .bi,
.btn-outline-danger > i {
    color: #e11d48;
}

.btn-outline-success > .bi,
.btn-outline-success > i {
    color: #16a34a;
}

/* Tombol yang sedang tidak bisa ditekan tidak boleh tetap memancing lewat
   ikon berwarnanya. */
.btn:disabled > .bi,
.btn:disabled > i,
.btn.disabled > .bi,
.btn.disabled > i {
    color: inherit;
}

/*
    Ditekan sedikit turun, bukan berubah bayangan.

    Tombol rata tidak punya bayangan tebal untuk dikecilkan, jadi umpan balik
    sentuhnya diberikan lewat perpindahan satu piksel - cara yang dipakai
    aplikasi ponsel masa kini, dan yang tetap terasa walau jari menutupi
    tombolnya.
*/
.btn:active:not(:disabled) {
    transform: translateY(1px);
}

/* ---------- Tombol utama ---------- */

.btn-primary {
    color: #fff;
    background: var(--ams-navy);
    border-color: transparent;
    box-shadow: var(--ams-navy-shadow);
}

.btn-primary:hover,
.btn-primary:focus,
.btn-primary:active {
    color: #fff;
    background: var(--ams-navy-hover);
    border-color: transparent;
}

.btn-success {
    color: #fff;
    background: var(--ams-green);
    border-color: transparent;
    box-shadow: var(--ams-green-shadow);
}

.btn-success:hover,
.btn-success:focus,
.btn-success:active {
    color: #fff;
    background: var(--ams-green-hover);
    border-color: transparent;
}

.btn-danger {
    color: #fff;
    background: var(--ams-red);
    border-color: transparent;
    box-shadow: var(--ams-red-shadow);
}

.btn-danger:hover,
.btn-danger:focus,
.btn-danger:active {
    color: #fff;
    background: var(--ams-red-hover);
    border-color: transparent;
}

/* Dipakai untuk hal yang mendesak, seperti tugas yang belum dijawab driver. */
.btn-warning {
    color: #fff;
    background: var(--ams-amber);
    border-color: transparent;
    box-shadow: var(--ams-amber-shadow);
}

.btn-warning:hover,
.btn-warning:focus,
.btn-warning:active {
    color: #fff;
    background: #b45309;
    border-color: transparent;
}

/* ---------- Tombol pendamping ----------

   Rata, tanpa bayangan, tanpa gradasi. Bedanya dengan tombol utama harus
   terlihat sekilas: pada satu layar hanya boleh ada satu tindakan yang
   tampak paling menonjol, selebihnya mendampingi. Karena itu "Batal" dan
   "Kembali" sengaja tidak diberi warna penuh.
*/

/*
    PUTIH bergaris rambut, bukan bidang kelabu kebiruan.

    Isi kelabu adalah rupa tombol pendamping bawaan Bootstrap, dan itu yang
    membuatnya tetap terbaca lawas walaupun bentuknya sudah pil. Putih dengan
    garis setipis rambut dan bayangan hampir tak terlihat adalah bentuk yang
    dipakai aplikasi ponsel masa kini - dan di atas latar bergambar, putih
    justru yang paling tegas memisahkan tombol dari belakangnya.
*/
.btn-secondary,
.btn-outline-secondary {
    color: var(--ams-ink);
    background: var(--ams-surface);
    border-color: var(--ams-line);
    box-shadow: 0 .0625rem .125rem rgba(7, 22, 48, .06);
}

.btn-secondary:hover,
.btn-outline-secondary:hover,
.btn-secondary:focus,
.btn-outline-secondary:focus,
.btn-secondary:active,
.btn-outline-secondary:active {
    color: #12305e;
    background: #f4f7fc;
    border-color: rgba(18, 48, 94, .18);
}

.btn-outline-primary {
    color: #1b4285;
    background: #e7eefb;
    border-color: transparent;
    box-shadow: none;
}

.btn-outline-primary:hover,
.btn-outline-primary:focus,
.btn-outline-primary:active {
    color: #12305e;
    background: #d8e3f8;
    border-color: transparent;
}

/* Aksi merusak dibiarkan tenang sampai disentuh, supaya tidak menarik
   perhatian lebih dulu daripada aksi yang memang sering dipakai. */
.btn-outline-danger {
    color: #b42318;
    background: #fef3f2;
    border-color: transparent;
    box-shadow: none;
}

.btn-outline-danger:hover,
.btn-outline-danger:focus,
.btn-outline-danger:active {
    color: #fff;
    background: #b42318;
    border-color: transparent;
}

/* Kuning tidak pernah punya aturannya sendiri, dan itu terlihat: .btn di atas
   memasang `border: 1px solid transparent` untuk SEMUA tombol supaya kotaknya
   sama besar, sehingga varian yang tidak diberi warna tepi berakhir sebagai
   tulisan kuning yang mengambang tanpa bentuk. Di layar telepon, tempat tombol
   ini melebar sampai setengah baris, batasnya hilang sama sekali.

   Berbeda dari saudara-saudaranya, yang ini diberi tepi yang benar-benar
   terlihat - bukan transparan. Alasannya ada di papan jadwal: tombol keep kecil
   di dalam sel memakai tepi kuning yang sama, dan dua kendali yang mengerjakan
   hal yang sama harus terlihat sama. */
.btn-outline-warning {
    color: #7a5c05;
    background: #fdf6e3;
    border-color: #e3cd8a;
    box-shadow: none;
}

.btn-outline-warning:hover,
.btn-outline-warning:focus,
.btn-outline-warning:active {
    color: #fff;
    background: #8a6a09;
    border-color: #8a6a09;
}

/* ---------- Ukuran kecil ---------- */

.btn-sm {
    min-height: 2.25rem;
    padding: .3125rem .75rem;
    font-size: .8125rem;
}

/* ---------- Sorotan fokus ----------

   Diperlukan agar tombol tetap bisa ditelusuri dengan papan ketik. Memakai
   :focus-visible, bukan :focus, supaya cincinnya tidak muncul saat tombol
   ditekan dengan tetikus atau jari — di sana ia hanya terlihat seperti cacat.
*/

.btn:focus-visible,
.form-control:focus-visible,
.form-select:focus-visible,
.form-check-input:focus-visible {
    outline: none;
    box-shadow: 0 0 0 .1875rem rgba(37, 99, 235, .35);
}

h1:focus {
    outline: none;
}

.valid.modified:not([type=checkbox]) {
    outline: 1px solid #26b050;
}

.invalid {
    outline: 1px solid #e50000;
}

.validation-message {
    color: #e50000;
}

/*
    Tombol dan kolom isian diperbesar lagi di layar HP (aturan 6). Ukuran yang
    nyaman ditunjuk tetikus belum tentu nyaman ditekan ibu jari sambil berjalan.
*/
@media (max-width: 767.98px) {

    .btn {
        min-height: 3rem;
        font-size: .9375rem;
    }

    .btn-sm {
        min-height: 2.5rem;
        font-size: .875rem;
    }

    .form-control,
    .form-select {
        min-height: 2.875rem;
        /* 16px mencegah iOS otomatis memperbesar tampilan saat kolom disentuh. */
        font-size: 16px;
    }

    .table-responsive {
        font-size: 0.9rem;
    }
}

/* Kartu module pada Dashboard. */
.module-card {
    transition: transform 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
}

.module-card:hover {
    transform: translateY(-2px);
    box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.1) !important;
}

.module-card-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    border-radius: 0.5rem;
    background-color: #e0e7ff;
    color: #1d4ed8;
    font-size: 1.25rem;
    flex-shrink: 0;
}

.blazor-error-boundary {
    background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121;
    padding: 1rem 1rem 1rem 3.7rem;
    color: white;
}

    .blazor-error-boundary::after {
        content: "Terjadi kesalahan pada aplikasi."
    }

.darker-border-checkbox.form-check-input {
    border-color: #929292;
}

/* ==========================================================================
   Isi sel tabel
   ==========================================================================

   Kelas bantu untuk isi <td>. Ditaruh global, bukan di CSS masing-masing
   halaman, karena persoalannya sama di semua daftar: teks yang panjangnya
   tidak terduga harus dipotong pada lebar kolomnya, bukan melebarkan kolom.

   Bentuk pil ikon+teks TIDAK ada di sini melainkan di komponen DataChip.
   Yang di sini hanya yang tidak layak jadi komponen sendiri.
*/

/*
    Memotong teks pada lebar sel dengan elipsis.

    Perlu display:block karena <td> bukan flex container, sehingga span inline
    biasa tidak pernah mendapat lebar untuk dipotong — ia justru mendorong
    kolomnya melebar, persis kebalikan dari yang diinginkan.

    Selalu pasangkan dengan title= berisi teks lengkapnya. Isi yang terpotong
    tanpa cara melihat versi utuhnya bukan penghematan ruang, melainkan
    kehilangan informasi.
*/
.cell-clip {
    display: block;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Baris waktu: ikon jam kecil, lalu tanggal yang tidak boleh terpotong. */
.cell-time {
    display: flex;
    align-items: center;
    gap: 0.375rem;
    white-space: nowrap;
    font-weight: 500;
}

.cell-time > .bi {
    flex-shrink: 0;
    font-size: 0.8125rem;
    color: #667085;
}

/* Baris keterangan di bawah nilai utama: alamat, kode, nomor telepon. */
.cell-sub {
    display: flex;
    align-items: center;
    gap: 0.375rem;
    margin-top: 0.1875rem;
    min-width: 0;
    font-size: 0.8125rem;
    color: #667085;
}

.cell-sub > .bi {
    flex-shrink: 0;
    font-size: 0.8125rem;
    opacity: 0.8;
}

/* Angka di dalam tabel. Tabular figures membuat digit sejajar antar baris,
   sehingga ribuan bisa dibandingkan tanpa membacanya satu per satu. */
.cell-num {
    font-variant-numeric: tabular-nums;
    font-weight: 600;
    white-space: nowrap;
}

/* ============================================================
   PENYEGARAN TAMPILAN MENYELURUH

   Ditulis sebagai lapisan di atas Bootstrap, bukan sebagai penggantinya.
   Alasannya bukan kemalasan: aplikasi ini punya puluhan halaman yang sudah
   jadi, dan menyentuhnya satu per satu berarti puluhan kesempatan merusak
   halaman yang sudah bekerja. Yang diubah di sini hanya lapisan permukaannya —
   warna, jarak, sudut, bayangan — sehingga seluruh halaman lama ikut terangkat
   tanpa satu pun barisnya disunting.

   Prinsip warnanya satu: TINTA GELAP DI ATAS LATAR MUDA. Tulisan putih hanya
   dipakai di atas warna pekat yang kontrasnya memang cukup — tombol utama,
   tombol bahaya. Label berwarna dengan tulisan putih di atas kuning atau abu
   muda adalah sumber keluhan yang paling sering, dan di sini diperbaiki sekali
   untuk semua halaman.
   ============================================================ */

:root {
    /* ---- Permukaan dan garis ---- */
    --ams-bg: #f4f6fb;
    --ams-surface: #ffffff;
    --ams-surface-sunk: #f7f9fc;
    --ams-line: #e2e7f0;
    --ams-line-strong: #cdd7e6;

    /* ---- Tinta ----
       Abu di sini dibiaskan sedikit ke biru, mengikuti navy merek. Abu netral
       murni terlihat seperti warna bawaan yang tidak dipilih siapa pun. */
    --ams-ink: #101a33;
    --ams-ink-soft: #46536e;
    --ams-ink-faint: #7c879b;

    /*
        Aksen: warna tulisan yang menonjolkan diri - tautan, angka penting,
        judul beraksen. Biru dongker merek ini di mode terang; di mode gelap ia
        harus menjadi biru terang, sebab navy di atas latar gelap tidak terbaca
        sebagai warna melainkan sebagai tulisan yang redup.
    */
    --ams-accent: #1b4285;

    /* ---- Warna keadaan, sebagai pasangan latar + tinta ---- */
    --ams-ok-bg: #dcf6e6;
    --ams-ok-line: #a7e3c3;
    --ams-ok-ink: #10603b;

    --ams-info-bg: #e2eafc;
    --ams-info-line: #b6c9f2;
    --ams-info-ink: #1c3d78;

    --ams-warn-bg: #fdf0d6;
    --ams-warn-line: #f0d091;
    --ams-warn-ink: #7c4a03;

    --ams-bad-bg: #fbe4e4;
    --ams-bad-line: #e7bcbc;
    --ams-bad-ink: #8a1f1f;

    --ams-mute-bg: #e8ecf3;
    --ams-mute-line: #cdd5e2;
    --ams-mute-ink: #3b4661;

    /* ---- Bentuk ---- */
    --ams-radius: .75rem;
    --ams-radius-sm: .55rem;
    --ams-shadow: 0 .35rem 1rem rgba(18, 48, 94, .07);
    --ams-shadow-lift: 0 .6rem 1.5rem rgba(18, 48, 94, .12);
}

/* ============================================================
   MODE GELAP

   Mengikuti setelan perangkat, bukan tombol di dalam aplikasi. Yang
   menyalakan mode gelap sudah menyalakannya untuk seluruh HP-nya;
   menuntut ia menyalakannya sekali lagi di sini hanya menambah satu
   tempat yang bisa berbeda dari yang lain.

   Yang berubah HANYA nilai token. Tidak ada satu pun aturan tata letak
   di bawah sini - kalau ada, dua tampilan akan mulai berbeda bentuk,
   dan yang diperbaiki di satu mode tidak ikut di mode lain.

   Warna keadaan tidak dibalik menjadi gelap, melainkan diganti pasangan
   yang setara: latar tipis berwarna dan tinta terang. Hijau tua di atas
   latar gelap tidak terbaca sebagai "beres" - ia terbaca sebagai noda.
   ============================================================ */

@media (prefers-color-scheme: dark) {

    :root {
        /* ---- Permukaan dan garis ---- */
        --ams-bg: #0a1020;
        --ams-surface: #141c2e;
        --ams-surface-sunk: #1a2338;
        --ams-line: rgba(255, 255, 255, .08);
        --ams-line-strong: rgba(255, 255, 255, .16);

        /* ---- Tinta ----
           Tidak putih murni. Putih penuh di atas biru gelap menyilaukan
           pada layar HP yang dibuka di dalam mobil malam hari. */
        --ams-ink: #eaf0fb;
        --ams-ink-soft: #c2cde3;
        --ams-ink-faint: #93a1bd;

        /* ---- Warna keadaan ---- */
        --ams-ok-bg: rgba(74, 222, 128, .14);
        --ams-ok-line: rgba(74, 222, 128, .3);
        --ams-ok-ink: #86efac;

        --ams-info-bg: rgba(122, 179, 255, .14);
        --ams-info-line: rgba(122, 179, 255, .3);
        --ams-info-ink: #a8ceff;

        --ams-warn-bg: rgba(251, 191, 36, .14);
        --ams-warn-line: rgba(251, 191, 36, .32);
        --ams-warn-ink: #fcd34d;

        --ams-bad-bg: rgba(251, 113, 133, .14);
        --ams-bad-line: rgba(251, 113, 133, .3);
        --ams-bad-ink: #fda4af;

        --ams-mute-bg: rgba(255, 255, 255, .06);
        --ams-mute-line: rgba(255, 255, 255, .14);
        --ams-mute-ink: #b9c5dd;

        /* ---- Tombol ----
           Biru dongker merek ini nyaris menyatu dengan latar gelap, jadi
           tombol utama memakai biru yang lebih terang. Warnanya tetap
           biru yang sama keluarganya, bukan warna lain. */
        --ams-navy: #2563eb;
        --ams-navy-hover: #1d4ed8;
        --ams-navy-shadow: 0 .125rem .375rem rgba(0, 0, 0, .4);
        --ams-green-shadow: 0 .125rem .375rem rgba(0, 0, 0, .4);
        --ams-red-shadow: 0 .125rem .375rem rgba(0, 0, 0, .4);
        --ams-amber-shadow: 0 .125rem .375rem rgba(0, 0, 0, .4);

        --ams-accent: #7ab3ff;

        --ams-btn-soft: rgba(122, 179, 255, .12);
        --ams-btn-soft-hover: rgba(122, 179, 255, .2);
        --ams-btn-icon: #7ab3ff;
        --ams-muted-ink: #cbd6ea;

        --ams-shadow: 0 .35rem 1rem rgba(0, 0, 0, .45);
        --ams-shadow-lift: 0 .6rem 1.5rem rgba(0, 0, 0, .55);
    }

    /*
        Latar bergambar TETAP ADA di mode gelap, hanya diturunkan sedikit.

        Gambarnya pucat, dan di atas latar gelap ia bekerja terbalik: yang
        tadinya bayangan tipis menjadi cahaya. Diturunkan dari 25% ke 16% -
        cukup untuk tetap terasa sebagai latar bergambar, tidak sampai menjadi
        kabut kelabu yang menutupi seluruh layar.
    */
    body::before {
        opacity: .16;
    }
}

body {
    background: var(--ams-bg);
    color: var(--ams-ink);
    -webkit-font-smoothing: antialiased;
}

/* ---- Kartu ----
   border-radius dan bayangan saja. Lebar garis tepi sengaja tidak disetel,
   supaya utility .border-0 yang dipakai halaman-halaman lama tetap menang. */
.card {
    border-color: var(--ams-line);
    border-radius: var(--ams-radius);
    box-shadow: var(--ams-shadow);
}

.card.shadow-sm {
    box-shadow: var(--ams-shadow) !important;
}

/* ---- Isian ----
   Tinggi 2.75rem menyamai tombol. Kolom isian yang lebih pendek daripada
   tombol di sebelahnya membuat satu baris form terlihat miring. */
.form-control,
.form-select {
    min-height: 2.75rem;
    border-color: var(--ams-line-strong);
    border-radius: var(--ams-radius-sm);
    color: var(--ams-ink);
    transition: border-color .15s ease, box-shadow .15s ease;
}

.form-control:hover:not(:disabled),
.form-select:hover:not(:disabled) {
    border-color: #b3c1d8;
}

.form-control:focus,
.form-select:focus {
    border-color: #4f7fd4;
    box-shadow: 0 0 0 .1875rem rgba(37, 99, 235, .18);
}

.form-control::placeholder {
    color: #9aa5b8;
}

.form-label {
    margin-bottom: .3rem;
    font-size: .8rem;
    font-weight: 600;
    letter-spacing: .02em;
    color: var(--ams-ink-soft);
}

.form-text {
    font-size: .78rem;
    color: var(--ams-ink-faint);
}

/* ---- Label keadaan ----
   Seluruh varian text-bg-* dijadikan latar muda bertinta gelap. Bawaan
   Bootstrap menulisnya putih di atas warna penuh, dan hasilnya pada kuning
   maupun abu muda nyaris tidak terbaca. */
.badge {
    padding: .3rem .6rem;
    border: 1px solid transparent;
    border-radius: 2rem;
    font-size: .72rem;
    font-weight: 700;
    letter-spacing: .03em;
}

.badge.text-bg-success {
    background: var(--ams-ok-bg) !important;
    border-color: var(--ams-ok-line);
    color: var(--ams-ok-ink) !important;
}

.badge.text-bg-primary,
.badge.text-bg-info {
    background: var(--ams-info-bg) !important;
    border-color: var(--ams-info-line);
    color: var(--ams-info-ink) !important;
}

.badge.text-bg-warning {
    background: var(--ams-warn-bg) !important;
    border-color: var(--ams-warn-line);
    color: var(--ams-warn-ink) !important;
}

.badge.text-bg-danger {
    background: var(--ams-bad-bg) !important;
    border-color: var(--ams-bad-line);
    color: var(--ams-bad-ink) !important;
}

.badge.text-bg-secondary,
.badge.text-bg-light,
.badge.text-bg-dark {
    background: var(--ams-mute-bg) !important;
    border-color: var(--ams-mute-line);
    color: var(--ams-mute-ink) !important;
}

/* ---- Pemberitahuan ---- */
.alert {
    border-radius: var(--ams-radius-sm);
    border-width: 1px;
    font-size: .88rem;
}

.alert-success { background: var(--ams-ok-bg);   border-color: var(--ams-ok-line);   color: var(--ams-ok-ink); }
.alert-info    { background: var(--ams-info-bg); border-color: var(--ams-info-line); color: var(--ams-info-ink); }
.alert-warning { background: var(--ams-warn-bg); border-color: var(--ams-warn-line); color: var(--ams-warn-ink); }
.alert-danger  { background: var(--ams-bad-bg);  border-color: var(--ams-bad-line);  color: var(--ams-bad-ink); }

/* ---- Tabel ----
   Kepala tabel dibuat menempel saat digulir. Tabel panjang yang kehilangan
   nama kolomnya di tengah gulungan memaksa orang menggulir balik ke atas hanya
   untuk mengingat kolom keempat itu apa. */
.table {
    --bs-table-bg: transparent;
    margin-bottom: 0;
    color: var(--ams-ink);
}

.table > thead > tr > th {
    position: sticky;
    top: 0;
    z-index: 1;
    background: var(--ams-surface-sunk);
    border-bottom: 1px solid var(--ams-line);
    font-size: .74rem;
    font-weight: 700;
    letter-spacing: .05em;
    text-transform: uppercase;
    color: var(--ams-ink-faint);
    white-space: nowrap;
}

.table > tbody > tr > td {
    border-bottom: 1px solid #eef1f6;
    vertical-align: middle;
}

.table > tbody > tr:last-child > td {
    border-bottom: 0;
}

@media (hover: hover) {
    .table > tbody > tr:hover > td {
        background: #f7f9fd;
    }
}

/* Angka dalam kolom disejajarkan lebarnya. Kolom rupiah yang lebarnya
   berbeda-beda per baris tidak bisa dibandingkan sekilas. */
.table td,
.table th {
    font-variant-numeric: tabular-nums;
}

/* ---- Judul halaman ---- */
h1, h2, h3, h4, h5, h6 {
    color: var(--ams-ink);
    text-wrap: balance;

    /*
        Lebih tebal dan lebih rapat.

        Plus Jakarta Sans punya bobot 800 yang tegas, dan judul yang
        memakainya perlu jarak huruf dirapatkan sedikit - huruf tebal
        pada ukuran besar tampak renggang bila dibiarkan pada jarak
        bawaannya. Angkanya negatif kecil saja; lebih dari itu huruf
        mulai saling menempel di layar HP.
    */
    font-weight: 800;
    letter-spacing: -0.02em;
}


/* ============================================================
   TOKEN PAPAN JADWAL ARMADA

   Ditaruh di sini, bukan di berkas berlingkup milik halamannya, karena CSS
   berlingkup menambahkan penanda lingkup pada selektor terakhir - ":root" di
   sana akan menjadi ":root[b-xxxx]" dan tidak pernah cocok dengan elemen html.
   Tokennya akan mati diam-diam, dan halamannya kehilangan seluruh warna serta
   ukuran tanpa satu pun galat yang menandainya.
   ============================================================ */
:root {
    /* Tinggi sentuh. 2.75rem = 44px, ukuran terkecil yang masih nyaman ditekan
       ibu jari; 2.25rem untuk kendali sekunder di dalam sel yang padat. */
    --fs-touch: 2.75rem;
    --fs-touch-sm: 2.25rem;

    /* Lengkung: permukaan, kendali, pil. */
    --fs-r-surface: .85rem;
    --fs-r-control: .55rem;
    --fs-r-pill: 2rem;

    /* Bayangan: satu untuk permukaan diam, satu untuk yang mengambang. */
    --fs-shadow: 0 .2rem .7rem rgba(16, 26, 51, .06);
    --fs-shadow-float: 0 .5rem 1.1rem rgba(16, 26, 51, .12);

    --fs-line: #e4e9f2;
    --fs-line-soft: #eef1f6;
    --fs-ink: #101a33;
    --fs-ink-soft: #5b6478;
    --fs-ink-mute: #8a93a5;

    --fs-free: #0f7a4a;
    --fs-free-bg: #e8f5ee;
    --fs-rental: #1c3d78;
    --fs-rental-bg: #e6edfb;
    --fs-hold: #8a6a09;
    --fs-hold-bg: #fdf6e3;
    --fs-trip: #4c2f8f;
    --fs-trip-bg: #efeafc;
    --fs-off: #8a1c1c;
    --fs-off-bg: #fdecec;
    --fs-accent: #1d4ed8;

    /* Lebar kolom papan. Dipakai DUA pihak yang harus sepakat: berkas gaya
       halamannya, dan perhitungan lebar minimum tabel di markup. Dua angka
       terpisah yang harus sama cepat atau lambat akan berbeda - dan bedanya
       berupa kolom yang tidak lagi sama besar. */
    --fs-unit-col: 12rem;
    --fs-day-col: 7rem;
}

@media (max-width: 48rem) {
    :root {
        --fs-unit-col: 9rem;
        --fs-day-col: 6rem;
    }
}

/* ============================================================
   Vehicle Handover - daftar tugas dan bukti serah-terima

   Ditaruh di berkas global, bukan sebagai gaya berlingkup, karena DUA halaman
   memakainya: daftar tugas dan halaman buktinya. Gaya berlingkup menempel pada
   satu berkas komponen, sehingga dua halaman yang berbagi bentuk akan menuntut
   dua salinan aturan yang harus tetap sama - dan yang harus tetap sama, cepat
   atau lambat, tidak lagi sama.

   Dirancang untuk JEMPOL lebih dulu. Yang memakainya berdiri di halaman parkir
   sambil memegang kunci: tiap sasaran sentuh setinggi jempol, tulisan penting
   sebesar yang terbaca sambil bergerak, dan tidak ada kendali yang menuntut
   ketepatan lebih dari satu sentuhan.
   ============================================================ */

.hv__bar {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: .5rem .85rem;
    margin-bottom: .6rem;
    padding: .55rem .8rem;
    border: 1px solid #e4e9f2;
    border-radius: .85rem;
    background: #fff;
    box-shadow: 0 .2rem .7rem rgba(16, 26, 51, .06);
}

.hv__bar-title {
    flex: 1 1 14rem;
    min-width: 0;
}

.hv__bar-title h1 {
    margin: 0;
    font-size: 1.05rem;
    font-weight: 700;
    letter-spacing: -.01em;
    color: #101a33;
}

.hv__bar-title p {
    margin: 0;
    font-size: .78rem;
    color: #5b6478;
}

.hv__bar-tools {
    display: flex;
    align-items: center;
    gap: .4rem;
    flex: 1 1 16rem;
    justify-content: flex-end;
}

.hv__search {
    position: relative;
    flex: 1 1 auto;
    max-width: 18rem;
}

.hv__search i {
    position: absolute;
    top: 50%;
    left: .65rem;
    transform: translateY(-50%);
    color: #8a93a5;
    font-size: .85rem;
    pointer-events: none;
}

.hv__search .form-control {
    height: 2.75rem;
    padding-left: 2rem;
    border-radius: .55rem;
}

.hv__reload {
    flex: 0 0 auto;
    width: 2.75rem;
    height: 2.75rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 1px solid #cdd5e2;
    border-radius: .55rem;
    background: #fff;
    color: #101a33;
    cursor: pointer;
}

.hv__reload:hover:not(:disabled) {
    background: #f3f7ff;
    border-color: #9fb9ee;
}

/* ---- Dua arah, selalu terlihat ---- */

.hv__tabs {
    display: flex;
    gap: .3rem;
    margin-bottom: .7rem;
    padding: .3rem;
    border: 1px solid #e4e9f2;
    border-radius: 2rem;
    background: linear-gradient(180deg, #fbfcfe 0%, #f3f6fc 100%);
    box-shadow: inset 0 1px 2px rgba(16, 26, 51, .04);
    overflow-x: auto;
}

.hv__tab {
    display: inline-flex;
    align-items: center;
    gap: .4rem;
    flex: 1 1 auto;
    justify-content: center;
    min-height: 2.4rem;
    padding: .3rem .9rem;
    border: 1px solid transparent;
    border-radius: 2rem;
    color: #5b6478;
    font-size: .85rem;
    font-weight: 600;
    text-decoration: none;
    white-space: nowrap;
}

.hv__tab:hover {
    background: #eef3fd;
    color: #101a33;
}

.hv__tab.is-on {
    background: #fff;
    border-color: #b6c9f2;
    color: #1c3d78;
    box-shadow: 0 .15rem .5rem rgba(16, 26, 51, .1);
}

/* ---- Kabar tugas yang barusan selesai ---- */

.hv__done {
    display: flex;
    align-items: center;
    gap: .5rem;
    margin-bottom: .6rem;
    padding: .6rem .8rem;
    border: 1px solid #a9dcc3;
    border-radius: .6rem;
    background: #e8f5ee;
    color: #0f7a4a;
    font-size: .85rem;
}

/* ---- Daftar tugas ---- */

.hv__list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: .5rem;
}

.hv__row {
    display: grid;
    grid-template-columns: 4.5rem 1fr;
    gap: .3rem .75rem;
    padding: .7rem .8rem;
    border: 1px solid #e4e9f2;
    border-left: .3rem solid #cdd5e2;
    border-radius: .75rem;
    background: #fff;
    box-shadow: 0 .15rem .5rem rgba(16, 26, 51, .04);
}

/* Yang sudah lewat jamnya diberi tepi merah - satu-satunya warna kuat di
   daftar ini, supaya yang terlambat tidak pernah tenggelam di antara yang
   belum waktunya. */
.hv__row.is-late {
    border-left-color: #b42318;
    background: #fffbfa;
}

.hv__when {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
    line-height: 1.15;
}

.hv__when-day {
    font-size: .64rem;
    font-weight: 700;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: #8a93a5;
}

.hv__when-time {
    font-size: 1.35rem;
    font-weight: 700;
    color: #101a33;
    font-variant-numeric: tabular-nums;
}

.hv__when-date {
    font-size: .7rem;
    color: #5b6478;
}

.hv__row.is-late .hv__when-time {
    color: #b42318;
}

.hv__body {
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: .15rem;
}

.hv__unit {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: .4rem;
}

.hv__unit strong {
    font-size: 1.05rem;
    font-weight: 700;
    letter-spacing: .03em;
    color: #101a33;
}

.hv__unit span {
    font-size: .78rem;
    color: #5b6478;
}

.hv__who {
    display: flex;
    align-items: center;
    gap: .35rem;
    font-size: .85rem;
    color: #33405e;
}

.hv__who i {
    color: #8a93a5;
    font-size: .8rem;
}

.hv__late {
    display: flex;
    align-items: center;
    gap: .35rem;
    font-size: .76rem;
    font-weight: 600;
    color: #b42318;
}

.hv__contact {
    display: flex;
    flex-wrap: wrap;
    gap: .4rem;
    margin-top: .3rem;
}

.hv__call,
.hv__wa {
    display: inline-flex;
    align-items: center;
    gap: .35rem;
    min-height: 2.25rem;
    padding: .25rem .7rem;
    border: 1px solid;
    border-radius: 2rem;
    font-size: .8rem;
    font-weight: 600;
    text-decoration: none;
}

.hv__call {
    border-color: #b6c9f2;
    background: #eef3fd;
    color: #1c3d78;
}

.hv__wa {
    border-color: #a9dcc3;
    background: #e8f5ee;
    color: #0f7a4a;
}

.hv__call:hover { background: #dfe9fb; }
.hv__wa:hover   { background: #d6efe1; }

/* Tombol tugasnya selebar baris di telepon: satu sasaran besar, dan tidak ada
   yang perlu dibidik. */
.hv__go {
    grid-column: 1 / -1;
    display: inline-flex;
    align-items: center;
    gap: .5rem;
    min-height: 2.75rem;
    margin-top: .2rem;
    padding: .4rem .9rem;
    border-radius: .6rem;
    color: #fff;
    font-size: .9rem;
    font-weight: 700;
    text-decoration: none;
}

.hv__go span {
    flex: 1 1 auto;
    text-align: center;
}

.hv__go--out {
    background: #1d4ed8;
    box-shadow: 0 .125rem .375rem rgba(11, 31, 63, .16);
}

.hv__go--in {
    background: #0e7490;
    box-shadow: 0 .125rem .375rem rgba(11, 31, 63, .16);
}

.hv__go:hover {
    color: #fff;
    filter: brightness(1.06);
}

.hv__foot {
    margin: .7rem 0 0;
    font-size: .78rem;
    color: #6b7280;
}

.hv__empty {
    padding: 2rem 1rem;
    border: 1px dashed #cdd5e2;
    border-radius: .85rem;
    background: #fbfcfe;
    text-align: center;
    color: #5b6478;
}

.hv__empty i {
    font-size: 1.8rem;
    color: #9aa5b8;
}

.hv__empty p {
    margin: .5rem 0 0;
    font-size: .9rem;
}

/* ---- Halaman bukti ---- */

.hv__proof-top {
    margin-bottom: .5rem;
}

.hv__back {
    display: inline-flex;
    align-items: center;
    gap: .3rem;
    min-height: 2.4rem;
    padding: .3rem .7rem .3rem .5rem;
    border-radius: .55rem;
    color: #33405e;
    font-size: .85rem;
    font-weight: 600;
    text-decoration: none;
}

.hv__back:hover {
    background: #eef3fd;
    color: #1c3d78;
}

/* Kepala tugas: satu-satunya tempat kru memastikan ia berdiri di depan unit
   yang benar, jadi nopolnya dibuat sebesar mungkin. */
.hv__task {
    display: flex;
    flex-wrap: wrap;
    gap: .5rem 1.25rem;
    align-items: center;
    justify-content: space-between;
    margin-bottom: .8rem;
    padding: .8rem .9rem;
    border: 1px solid #e4e9f2;
    border-radius: .85rem;
    background: #fff;
    box-shadow: 0 .2rem .7rem rgba(16, 26, 51, .06);
}

.hv__task-label {
    display: block;
    font-size: .66rem;
    font-weight: 700;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: #8a93a5;
}

.hv__task-plate strong {
    display: block;
    font-size: 1.6rem;
    font-weight: 700;
    letter-spacing: .04em;
    line-height: 1.1;
    color: #101a33;
}

.hv__task-desc {
    display: block;
    font-size: .82rem;
    color: #5b6478;
}

.hv__task-facts {
    display: flex;
    flex-wrap: wrap;
    gap: .3rem .9rem;
}

.hv__fact {
    display: inline-flex;
    align-items: center;
    gap: .35rem;
    font-size: .82rem;
    color: #33405e;
    text-decoration: none;
}

.hv__fact i {
    color: #8a93a5;
    font-size: .8rem;
}

.hv__fact--call {
    min-height: 2.25rem;
    padding: .25rem .7rem;
    border: 1px solid #b6c9f2;
    border-radius: 2rem;
    background: #eef3fd;
    color: #1c3d78;
    font-weight: 600;
}

.hv__fact--call i { color: #1c3d78; }

.hv__wrong {
    display: flex;
    gap: .6rem;
    padding: .9rem 1rem;
    border: 1px solid #f0d9a8;
    border-radius: .75rem;
    background: #fffaf0;
    color: #8a5b00;
}

.hv__wrong i {
    font-size: 1.2rem;
}

.hv__wrong p {
    margin: .25rem 0 .6rem;
    font-size: .85rem;
}

.hv__grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
    gap: .6rem;
    margin-bottom: .6rem;
}

.hv__check {
    display: flex;
    align-items: center;
    gap: .5rem;
    min-height: 2.75rem;
    margin-bottom: .4rem;
}

/* Kotak jaminan dan peringatan keadaan unit: dua hal yang harus dibaca, bukan
   dilewati, jadi keduanya diberi permukaan sendiri. */
.hv__hold {
    margin-bottom: .7rem;
    padding: .7rem .8rem;
    border: 1px solid #e4e9f2;
    border-radius: .7rem;
    background: #f7f9fd;
}

.hv__hold--warn {
    border-color: #f0d9a8;
    background: #fffaf0;
    color: #8a5b00;
}

.hv__hold-head {
    display: flex;
    align-items: flex-start;
    gap: .5rem;
    font-size: .85rem;
}

.hv__hold-check {
    display: flex;
    align-items: center;
    gap: .5rem;
    min-height: 2.75rem;
    margin: .2rem 0 0;
    font-size: .85rem;
    font-weight: 600;
    cursor: pointer;
}

.hv__submit {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: .5rem;
    width: 100%;
    min-height: 3.25rem;
    margin-top: .3rem;
    border: 0;
    border-radius: .7rem;
    color: #fff;
    font-size: 1rem;
    font-weight: 700;
    cursor: pointer;
}

.hv__submit--out {
    background: #1d4ed8;
    box-shadow: 0 .1875rem .5rem rgba(11, 31, 63, .18);
}

.hv__submit--in {
    background: #0e7490;
    box-shadow: 0 .1875rem .5rem rgba(11, 31, 63, .18);
}

.hv__submit:disabled {
    opacity: .65;
    cursor: not-allowed;
}

.hv__submit-note {
    margin: .45rem 0 0;
    font-size: .76rem;
    color: #6b7280;
    text-align: center;
}

@media (min-width: 48rem) {
    .hv__row {
        grid-template-columns: 5rem 1fr auto;
        align-items: center;
    }

    /* Di layar lebar tombolnya kembali ke ujung kanan barisnya sendiri, tidak
       lagi melebar - jempol bukan lagi alat utamanya di sana. */
    .hv__go {
        grid-column: auto;
        margin-top: 0;
        min-width: 12rem;
    }
}
/* ============================================================
   WARNA IKON MENU

   Tiap menu punya warnanya sendiri, ditetapkan MenuIconPalette dari kode
   menunya. Kelasnya dipasang langsung pada elemen ikon, dan elemen itu
   membawa dua nilai sekaligus:

     --menu-ink   warna ikon di atas latar terang  (kartu menu di ponsel)
     --menu-tint  warna lingkaran di belakang ikon (kartu menu di ponsel)
     --menu-glow  warna ikon di atas latar gelap   (daftar menu di sisi kiri)

   Nilainya di sini, BERSAMA, bukan di dalam CSS bercakupan salah satu
   komponen: yang memakainya ada dua - NavMenu dan NavMenuCards - dan CSS
   bercakupan hanya berlaku bagi komponennya sendiri. Komponen kedua akan
   terkirim tanpa satu pun warna, tanpa galat maupun peringatan build.

   Dua warna dipisah untuk latar terang dan gelap karena satu warna tidak
   pernah cukup untuk keduanya: biru yang enak dibaca di atas kartu putih
   nyaris lenyap di atas biru dongker sidebar.
   ============================================================ */

.menu-ico--blue {
    --menu-ink: #2563eb;
    --menu-tint: #e7efff;
    --menu-glow: #7ab3ff;
}

.menu-ico--green {
    --menu-ink: #12855a;
    --menu-tint: #e0f5ea;
    --menu-glow: #4ade80;
}

.menu-ico--orange {
    --menu-ink: #b8760d;
    --menu-tint: #fdf1da;
    --menu-glow: #fbbf24;
}

.menu-ico--purple {
    --menu-ink: #6743d8;
    --menu-tint: #ece8fd;
    --menu-glow: #a78bfa;
}

.menu-ico--red {
    --menu-ink: #c33359;
    --menu-tint: #fde9ee;
    --menu-glow: #fb7185;
}

.menu-ico--teal {
    --menu-ink: #0e7490;
    --menu-tint: #ddf3f8;
    --menu-glow: #2dd4bf;
}


/* ============================================================
   LATAR LAYAR PONSEL

   Gambar latar hanya di layar kecil. Di layar besar isi halaman jauh lebih
   padat - tabel, papan jadwal, formulir panjang - dan gambar di belakangnya
   hanya membuat angka lebih sulit dibaca tanpa menambah apa pun.

   Dipasang pada PSEUDO-ELEMEN yang position: fixed, bukan sebagai background
   body biasa. Alasannya dua, dan keduanya soal yang benar-benar terjadi di HP:

     - background-size: cover pada body akan meregang setinggi SELURUH isi
       halaman. Pada halaman panjang gambarnya jadi melar dan gambar yang sama
       tampak berbeda di tiap halaman.
     - background-attachment: fixed diabaikan sebagian peramban ponsel dan
       mahal di sebagian lainnya. Pseudo-elemen yang fixed memberi hasil yang
       sama di semua, dan hanya digambar satu kali.

   Kecerahannya diatur lewat opacity, BUKAN dengan menyunting gambarnya. Dengan
   begitu satu berkas yang sama bisa dinaikkan atau diturunkan ketebalannya
   hanya dengan mengubah satu angka di sini.
   ============================================================ */

@media (max-width: 991.98px) {

    /*
        Warna dasar diserahkan ke html.

        Tanpa ini gambarnya TIDAK PERNAH terlihat, dan kekeliruannya halus:
        app.css memberi warna kepada html DAN body sekaligus. Karena html punya
        warna sendiri, warna body tidak lagi diteruskan ke kanvas - ia digambar
        sebagai kotak milik body, tepat DI ATAS pseudo-elemen ber-z-index
        negatif di bawah ini. Hasilnya bidang kelabu rata, tanpa satu pun galat
        yang menjelaskan ke mana perginya gambar.
    */
    body {
        background-color: transparent;
    }

    body::before {
        content: "";
        position: fixed;
        inset: 0;

        /*
            Di BELAKANG seluruh isi, tetapi di depan warna dasar body. Nilai
            negatif aman di sini karena body tidak membentuk konteks penumpukan
            sendiri - warna dasarnya diteruskan ke kanvas peramban.
        */
        z-index: -1;

        background-image: url("images/bg-mobile.jpg");
        background-position: center center;
        background-size: cover;
        background-repeat: no-repeat;

        /*
            Tipis, dan memang harus. Gambarnya penuh ikon dan garis; pada
            ketebalan penuh, tulisan kelabu di atas kartu tembus pandang tidak
            lagi terbaca sambil berjalan - dan itu keadaan yang paling sering
            dialami pemakainya.

            Gambarnya sendiri sudah dipotong bagian atasnya: aslinya memuat
            tulisan merek lain, dan latar aplikasi tidak boleh menyebut nama
            yang bukan miliknya.
        */
        opacity: .25;

        /* Tidak menghalangi sentuhan pada apa pun di atasnya. */
        pointer-events: none;
    }

    /*
        Kartu dibuat sedikit tembus pandang supaya latar terasa hadir, tetapi
        tetap 90% pekat: yang di baliknya gambar penuh garis, dan kartu yang
        terlalu bening membuat huruf beradu dengan setang sepeda di belakangnya.
    */
    .card {
        background-color: var(--ams-surface);
    }

    /*
        Judul dipekatkan menjadi hitam dan tebal.

        Sebagian judul berdiri LANGSUNG di atas latar bergambar, tanpa kartu di
        belakangnya - dan warna biru keabuan yang enak dibaca di atas bidang
        rata menjadi samar begitu ada ilustrasi di belakangnya. Yang paling
        sering terkena justru judul yang paling menentukan arah: nama halaman
        di kepala, dan nama bagian di antara dua kelompok kartu.
    */
    h1, h2, h3, h4, h5, h6,
    .h1, .h2, .h3, .h4, .h5, .h6 {
        /*
            Token, BUKAN warna harfiah.

            Sebelumnya #0b1220 ditulis langsung di sini demi kontras di atas
            latar bergambar - dan warna harfiah itu menang atas token, sehingga
            di mode gelap seluruh judul menjadi hitam di atas hitam. Tidak ada
            galat; judulnya sekadar lenyap.
        */
        color: var(--ams-ink);
        font-weight: 700;
    }

    /*
        Judul yang memakai utilitas warna Bootstrap harus dilawan setara.

        Utilitas seperti .text-secondary menuliskan warnanya dengan !important,
        sehingga aturan di atas TIDAK akan mengenainya - judul "Module yang
        tersedia untuk Anda" akan tetap kelabu samar di atas gambar. Hanya
        judul yang disasar di sini; tulisan kelabu di tempat lain memang
        seharusnya tetap kelabu.
    */
    h1.text-secondary, h2.text-secondary, h3.text-secondary,
    h4.text-secondary, h5.text-secondary, h6.text-secondary,
    h1.text-muted, h2.text-muted, h3.text-muted,
    h4.text-muted, h5.text-muted, h6.text-muted {
        color: var(--ams-ink) !important;
    }

    /*
        Keterangan kecil ikut dipekatkan.

        Yang paling terasa adalah kalimat di bawah judul halaman - "15 module
        aktif untuk akun Anda" dan sejenisnya. Ia dirender sebagai <small> abu
        dan berdiri LANGSUNG di atas latar bergambar; ukuran kecil ditambah
        warna pucat ditambah ilustrasi di belakangnya membuatnya nyaris tidak
        terbaca sambil berjalan.

        Sama seperti judul, warnanya harus dilawan setara: .text-secondary
        menuliskan warnanya dengan !important, dan tanpa itu justru tulisan
        kecil yang paling samar yang tidak akan berubah sama sekali.
    */
    small, .small {
        font-weight: 700;
        color: var(--ams-ink);
    }

    small.text-secondary, small.text-muted,
    .small.text-secondary, .small.text-muted {
        color: var(--ams-ink) !important;
    }

    /*
        KECUALI di dalam kartu dan tabel.

        Di sana tidak ada gambar di belakangnya - kartunya 90% pekat - sehingga
        tulisan kecil memang sudah terbaca. Menghitamkan dan menebalkannya di
        situ justru menghapus tingkatan: nama unit, nilai, dan keterangannya
        akan tampak sama penting, dan mata kehilangan urutan bacanya.
    */
    .card small, .card .small,
    .table small, .table .small {
        font-weight: 400;
    }
}


/* ============================================================
   KARTU BOOTSTRAP MENGIKUTI TOKEN

   .card dipakai hampir di seluruh halaman dan warnanya datang dari
   Bootstrap - putih mati. Tanpa baris ini, mode gelap menghasilkan
   halaman gelap berisi kartu putih menyala: bukan tampilan gelap,
   melainkan tampilan terang yang kebingungan.
   ============================================================ */

.card {
    background-color: var(--ams-surface);
    border-color: var(--ams-line);
    color: var(--ams-ink);
}

.card-body,
.card-header,
.card-footer {
    color: inherit;
}

.text-secondary,
.text-muted {
    color: var(--ams-ink-faint) !important;
}


/* ============================================================
   PALET IKON MENU - PASANGAN GELAPNYA

   Ditaruh DI SINI, sesudah definisi terangnya, dan bukan di dalam blok
   mode gelap di atas. Dua aturan yang kekuatannya sama dimenangkan oleh
   yang ditulis belakangan: selama pasangan gelap ini berada di atas,
   lingkaran ikon tetap pucat di mode gelap dan tampak seperti tambalan
   putih di atas kartu gelap.
   ============================================================ */

@media (prefers-color-scheme: dark) {

    .menu-ico--blue   { --menu-ink: #7ab3ff; --menu-tint: rgba(122, 179, 255, .14); }
    .menu-ico--green  { --menu-ink: #4ade80; --menu-tint: rgba(74, 222, 128, .14); }
    .menu-ico--orange { --menu-ink: #fbbf24; --menu-tint: rgba(251, 191, 36, .14); }
    .menu-ico--purple { --menu-ink: #a78bfa; --menu-tint: rgba(167, 139, 250, .14); }
    .menu-ico--red    { --menu-ink: #fb7185; --menu-tint: rgba(251, 113, 133, .14); }
    .menu-ico--teal   { --menu-ink: #2dd4bf; --menu-tint: rgba(45, 212, 191, .14); }

}

/* ============================================================
   KOMPONEN BAWAAN BOOTSTRAP DI MODE GELAP

   Bagian yang paling mudah terlupakan, dan yang paling merusak: kotak
   isian, tabel, dan dialog tidak digambar oleh berkas ini melainkan
   oleh Bootstrap, dengan warna putih yang ditulis di dalamnya. Tanpa
   blok ini, halaman gelap berisi formulir putih menyala - dan yang
   mengetik di dalamnya melihat tulisan gelap di atas putih di tengah
   layar yang seluruhnya gelap.

   Yang disetel hanya WARNA. Tidak ada ukuran maupun jarak di sini;
   bentuk kedua mode harus tetap sama persis.
   ============================================================ */

@media (prefers-color-scheme: dark) {

    /* ---------- Kotak isian ---------- */

    .form-control,
    .form-select,
    .input-group-text {
        color: var(--ams-ink);
        background-color: var(--ams-surface-sunk);
        border-color: var(--ams-line-strong);
    }

    .form-control:focus,
    .form-select:focus {
        color: var(--ams-ink);
        background-color: var(--ams-surface-sunk);
        border-color: var(--ams-accent);
    }

    /*
        Tulisan bayangan dibuat lebih redup daripada tulisan sungguhan,
        bukan sama. Di mode gelap keduanya mudah terbaca sama terang, dan
        yang membuka formulir mengira kolomnya sudah terisi.
    */
    .form-control::placeholder {
        color: var(--ams-ink-faint);
        opacity: .75;
    }

    .form-control:disabled,
    .form-select:disabled {
        background-color: rgba(255, 255, 255, .04);
        color: var(--ams-ink-faint);
    }

    .form-label,
    .col-form-label,
    .form-check-label {
        color: var(--ams-ink-soft);
    }

    .form-text {
        color: var(--ams-ink-faint);
    }

    .form-check-input {
        background-color: var(--ams-surface-sunk);
        border-color: var(--ams-line-strong);
    }

    .form-check-input:checked {
        background-color: var(--ams-accent);
        border-color: var(--ams-accent);
    }

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

    .table {
        --bs-table-bg: transparent;
        --bs-table-color: var(--ams-ink);
        color: var(--ams-ink);
        border-color: var(--ams-line);
    }

    .table > :not(caption) > * > * {
        background-color: transparent;
        color: var(--ams-ink);
        border-bottom-color: var(--ams-line);
    }

    .table thead th,
    .table > thead,
    .table-light,
    .table-light > th,
    .table-light > td {
        color: var(--ams-ink-soft);
        background-color: var(--ams-surface-sunk);
        border-color: var(--ams-line);
    }

    .table-hover > tbody > tr:hover > * {
        background-color: rgba(255, 255, 255, .04);
        color: var(--ams-ink);
    }

    /* ---------- Panel yang melayang ---------- */

    .dropdown-menu,
    .modal-content,
    .offcanvas,
    .list-group-item,
    .accordion-item,
    .accordion-button {
        color: var(--ams-ink);
        background-color: var(--ams-surface);
        border-color: var(--ams-line);
    }

    .dropdown-item {
        color: var(--ams-ink);
    }

    .dropdown-item:hover,
    .dropdown-item:focus {
        color: var(--ams-ink);
        background-color: rgba(255, 255, 255, .06);
    }

    .modal-header,
    .modal-footer {
        border-color: var(--ams-line);
    }

    /* ---------- Kabar ---------- */

    .alert-success { color: var(--ams-ok-ink);   background-color: var(--ams-ok-bg);   border-color: var(--ams-ok-line); }
    .alert-info,
    .alert-primary { color: var(--ams-info-ink); background-color: var(--ams-info-bg); border-color: var(--ams-info-line); }
    .alert-warning { color: var(--ams-warn-ink); background-color: var(--ams-warn-bg); border-color: var(--ams-warn-line); }
    .alert-danger  { color: var(--ams-bad-ink);  background-color: var(--ams-bad-bg);  border-color: var(--ams-bad-line); }
    .alert-secondary,
    .alert-light   { color: var(--ams-mute-ink); background-color: var(--ams-mute-bg); border-color: var(--ams-mute-line); }

    .text-bg-light,
    .badge.text-bg-light {
        color: var(--ams-mute-ink) !important;
        background-color: var(--ams-mute-bg) !important;
    }

    .text-bg-secondary,
    .badge.text-bg-secondary {
        color: var(--ams-mute-ink) !important;
        background-color: var(--ams-mute-bg) !important;
    }

    /* ---------- Pemisah dan tautan ---------- */

    hr {
        border-color: var(--ams-line);
        opacity: 1;
    }

    a,
    .btn-link {
        color: var(--ams-accent);
    }

    /*
        Dialog sweetalert2 - satu-satunya JavaScript yang dipakai aplikasi
        ini. Ia menggambar dirinya sendiri di atas seluruh halaman, dan
        putihnya paling menyilaukan justru karena muncul mendadak.
    */
    .swal2-popup {
        color: var(--ams-ink);
        background: var(--ams-surface);
    }

    .swal2-title,
    .swal2-html-container {
        color: var(--ams-ink);
    }
}

/* ============================================================
   PAPAN JADWAL ARMADA DI MODE GELAP

   Papan ini punya paletnya sendiri - dua puluh tujuh token yang
   dibuat khusus untuknya. Membalik permukaan aplikasi tanpa
   membalik palet ini menyisakan satu halaman terang menyilaukan di
   tengah aplikasi yang gelap, dan justru halaman yang paling lama
   ditatap orang saat menyusun jadwal.

   Warna KEADAAN tidak ditukar maknanya: hijau tetap bebas, biru tetap
   tersewa, merah tetap tidak bisa dipakai. Yang berubah hanya
   pasangannya - latar tipis berwarna dengan tinta terang.
   ============================================================ */

@media (prefers-color-scheme: dark) {

    :root {
        --fs-shadow: 0 .2rem .7rem rgba(0, 0, 0, .45);
        --fs-shadow-float: 0 .5rem 1.1rem rgba(0, 0, 0, .55);

        --fs-line: rgba(255, 255, 255, .1);
        --fs-line-soft: rgba(255, 255, 255, .06);
        --fs-ink: #eaf0fb;
        --fs-ink-soft: #b9c5dd;
        --fs-ink-mute: #93a1bd;

        --fs-free: #4ade80;
        --fs-free-bg: rgba(74, 222, 128, .16);
        --fs-rental: #a8ceff;
        --fs-rental-bg: rgba(122, 179, 255, .18);
        --fs-hold: #fcd34d;
        --fs-hold-bg: rgba(251, 191, 36, .16);
        --fs-trip: #c4b5fd;
        --fs-trip-bg: rgba(167, 139, 250, .18);
        --fs-off: #fda4af;
        --fs-off-bg: rgba(251, 113, 133, .16);
        --fs-accent: #7ab3ff;
    }

    /* Dua keping yang latarnya ditulis putih tembus, bukan lewat token.
       Di atas papan gelap keduanya menyala seperti kertas. */
    .fs__bar-label,
    .fs__cell-note {
        background: rgba(255, 255, 255, .1);
    }
}
