/* ==========================================================================
   Absensi Online — sistem desain
   Warna utama biru tua, dasar putih, aksen oranye dan hijau.
   ========================================================================== */

:root {
  --biru-900: #0f2557;
  --biru-800: #17306b;
  --biru-700: #1e3a8a;
  --biru-600: #2547a8;
  --biru-500: #3b62c9;
  --biru-100: #dbe6ff;
  --biru-50:  #eff4ff;

  --oranye-700: #c2410c;
  --oranye-600: #ea580c;
  --oranye-500: #f97316;
  --oranye-100: #ffedd5;

  --hijau-700: #15803d;
  --hijau-600: #16a34a;
  --hijau-100: #dcfce7;

  --merah-600: #dc2626;
  --merah-100: #fee2e2;
  --kuning-600: #ca8a04;
  --kuning-100: #fef3c7;
  --ungu-600: #7c3aed;
  --ungu-100: #ede9fe;

  --abu-900: #0f172a;
  --abu-700: #334155;
  --abu-600: #475569;
  --abu-500: #64748b;
  --abu-400: #94a3b8;
  --abu-300: #cbd5e1;
  --abu-200: #e2e8f0;
  --abu-100: #f1f5f9;
  --abu-50:  #f8fafc;
  --putih: #ffffff;

  /* Warna semantik yang berbeda antar-tema — lihat blok [data-tema="cerah"] di bawah. */
  --judul: var(--biru-900);
  --aksen-teks: var(--biru-700);

  /* Tint PERMUKAAN (hover baris tabel, chip jam, panel lembut, dsb.). Sengaja dipisah dari tint
     LENCANA (--biru-100, --hijau-100, dst.) meski di tema terang nilainya sama: hanya yang di sini
     yang boleh ikut berubah per tema. Tint lencana sengaja dibiarkan pastel terang di semua tema
     agar status tetap terbaca sama di mana pun. Pakai token ini untuk apa pun yang berperan
     sebagai BIDANG, dan --*-100 hanya untuk lencana/status. */
  --lembut-biru: var(--biru-50);
  --lembut-biru-kuat: var(--biru-100);
  --lembut-merah: var(--merah-100);

  /* Warna status sebagai TEKS di atas permukaan biasa (pesan galat, nominal potongan, dsb.).
     Berbeda dari --merah-600/--hijau-700 yang dipakai di dalam lencana: di sana latarnya selalu
     pastel terang sehingga merah pekat justru benar, sedangkan di sini latarnya adalah permukaan
     bertema yang kontrasnya bisa berbeda per tema. */
  --merah-teks: var(--merah-600);
  --hijau-teks: var(--hijau-700);

  --radius-sm: 8px;
  --radius: 12px;
  --radius-lg: 18px;
  --bayang-sm: 0 1px 2px rgba(15, 37, 87, .06), 0 1px 3px rgba(15, 37, 87, .08);
  --bayang: 0 4px 6px -1px rgba(15, 37, 87, .07), 0 2px 4px -2px rgba(15, 37, 87, .06);
  --bayang-lg: 0 12px 28px -8px rgba(15, 37, 87, .18);

  /*
   * Material "kaca" untuk LAPISAN KONTROL — permukaan yang mengambang di atas konten. Saat ini
   * baru dipakai .dock-bawah sebagai uji coba; dinamai umum supaya topbar, modal, toast, dan panel
   * chat kelak tinggal ikut memakainya tanpa mendefinisikan ulang nilainya masing-masing.
   *
   * JANGAN pakai untuk kartu, ubin, tabel, atau formulir. Teks panjang di atas latar yang ikut
   * berubah mengikuti apa pun yang lewat di baliknya adalah cara paling mudah merusak keterbacaan;
   * kaca hanya untuk permukaan yang memang melayang.
   *
   * Opasitas .85 bukan angka selera — di bawah itu label dock jatuh di bawah 4,5:1 begitu konten
   * gelap tergulir di baliknya (panel pindai patroli #0f172a turun ke 4,07:1 pada .72). Yang
   * membuat permukaan ini TERBACA sebagai kaca adalah saturate(), bukan tembus pandangnya:
   * warna di baliknya menyembul lebih pekat, persis seperti material Apple. Jadi bila kelak perlu
   * kaca yang lebih "terasa", naikkan --kaca-jenuh, jangan turunkan opasitas --kaca-bg.
   */
  --kaca-bg: rgba(255, 255, 255, .85);
  /*
   * Dock TRANSPARAN PENUH — varian "clear", bukan "frosted". Diminta begitu, dan konsekuensinya
   * perlu tercatat di sini karena tidak terlihat dari kodenya:
   *
   * Tanpa lapisan putih, warna di belakang label adalah konten yang sedang tergulir itu sendiri.
   * Terukur pada label --abu-600: 7,58:1 di atas kartu putih, tetapi hanya 1,25:1 saat kartu biru
   * dashboard lewat dan 2,36:1 di atas panel pindai patroli — jauh di bawah ambang 4,5:1.
   * brightness() pada backdrop-filter sudah dicoba dan TIDAK menolong: menaikkannya menggeser latar
   * gelap melewati luminansi teksnya sendiri, jadi kurvanya berbalik turun (terbaik hanya 1,76:1).
   *
   * Yang dipakai sebagai gantinya adalah halo di sekeliling teks & ikon (lihat .dock-tautan).
   * Halo memulihkan keterbacaan di mata, tetapi TIDAK diakui rumus kontras WCAG — jadi ini memang
   * pengecualian yang disengaja, bukan sesuatu yang lolos ambang. Jalan keluarnya ada pada kedua
   * media query aksesibilitas di bawah, yang mengembalikan dock menjadi opak.
   *
   * Ingin frosted lagi? Cukup ubah satu nilai ini kembali ke rgba(255, 255, 255, .78) — batas
   * terendah yang masih lolos 4,5:1 di seluruh latar.
   */
  --kaca-bg-dock: transparent;
  --kaca-blur: 18px;
  --kaca-jenuh: 180%;
  --kaca-tepi: rgba(15, 37, 87, .10);
  --kaca-kilau: rgba(255, 255, 255, .9);
  /* Bayangan topbar: menurun, karena topbar menempel di tepi ATAS layar dan sisi yang menghadap
     konten ada di bawahnya. Permukaan yang mengambang bebas — toast, modal, dan kini dock —
     memakai bayangan yang menyebar ke segala arah, bukan token ini. */
  --kaca-bayang-bawah: 0 8px 24px -12px rgba(15, 37, 87, .22);

  --lebar-sidebar: 264px;
  --tinggi-topbar: 64px;
  --tinggi-dock: 60px;
  /* Jarak dock mengambang dari ketiga tepi layar. Dijadikan token karena dipakai di EMPAT tempat
     yang harus sepakat: margin dock itu sendiri, padding bawah isi halaman, posisi widget chat,
     dan posisi area toast. */
  --dock-tepi: .8rem;
  --transisi: 180ms cubic-bezier(.4, 0, .2, 1);
}

/* ==========================================================================
   Tema cerah — varian terang yang lebih lapang: netral condong biru, sudut lebih
   membulat, bayangan lembut kebiruan, dan latar halaman bergradasi.

   Ditulis sebagai tema KETIGA, bukan penggantian tema terang: keduanya hidup
   berdampingan, jadi pengguna yang sudah nyaman dengan tampilan lama tidak ikut
   berubah. Warna aksen (biru, oranye, hijau, dst.) dan tint lencana dibiarkan
   apa adanya supaya status tetap terbaca sama di mana pun.
   ========================================================================== */
:root[data-tema="cerah"] {
  /* Netral sengaja dicondongkan ke biru, bukan abu murni — inilah yang membuat
     seluruh halaman terasa "sejuk" tanpa perlu satu pun aturan tambahan. */
  --abu-50:  #edf4ff;
  --abu-100: #e3edfb;
  --abu-200: #d8e5f6;
  --abu-300: #bacfee;
  --abu-400: #93a9c8;
  /* Sedikit lebih gelap dari #64748b milik tema terang. Teks redup di sini banyak yang duduk
     langsung di atas latar halaman yang kebiruan (bukan di atas kartu putih), dan di sana
     #64748b tinggal ±4.3:1 — di bawah ambang AA. */
  --abu-500: #5b6b82;
  --abu-600: #475569;
  --abu-700: #334155;
  --abu-900: #0f172a;
  --putih: #ffffff;

  --judul: #102b5e;
  --aksen-teks: #1d6fe0;

  --lembut-biru: #e8f1fd;
  --lembut-biru-kuat: #d5e6fb;
  --lembut-merah: #fdeaea;

  /* Varian pekat --aksen-teks, khusus TEKS KECIL di atas --lembut-biru: aksen biasa (#1d6fe0)
     di atas tint itu hanya 4,19:1 — cukup untuk teks besar & ikon, kurang untuk label tombol
     dan tab yang ukurannya di bawah 18px. */
  --aksen-pekat: #1a56b8;

  /* Sudut lebih membulat dari tema terang (8/12/18) — ini pembeda bentuk utamanya. */
  --radius-sm: 10px;
  --radius: 14px;
  --radius-lg: 22px;

  /* Bayangan diberi rona biru, bukan abu netral: bayangan kelabu di atas latar kebiruan
     terbaca kotor, seperti kartu yang menempel di kaca berdebu. */
  --bayang-sm: 0 1px 2px rgba(23, 64, 138, .05), 0 2px 6px rgba(23, 64, 138, .06);
  --bayang: 0 6px 16px -4px rgba(23, 64, 138, .13);
  --bayang-lg: 0 18px 40px -12px rgba(23, 64, 138, .22);

  /* Kaca ikut dirona biru dengan alasan yang sama seperti bayangan di atas. Opasitas --kaca-bg
     sengaja TIDAK ditimpa di sini: .85 adalah ambang keterbacaannya, bukan pilihan rupa. */
  --kaca-tepi: rgba(23, 64, 138, .12);
  --kaca-bayang-bawah: 0 8px 24px -12px rgba(23, 64, 138, .26);
}

/* Latar halaman bergradasi. Harus di <body> (bukan di --abu-50) karena gradasi bukan warna:
   token yang sama juga dipakai sebagai latar sel tabel, bilah alat, dan modal-kaki, yang
   semuanya mengharapkan satu warna datar. `fixed` supaya gradasinya tidak ikut bergulir dan
   berulang di halaman panjang. */
:root[data-tema="cerah"] body {
  background: linear-gradient(180deg, #e8f1fe 0%, #f3f8ff 42%, #eaf2fe 100%) fixed;
}

/* Tombol berbentuk pil — ciri bentuk kedua tema cerah, setelah sudut kartu yang lebih membulat.
   Hanya tombol, bukan input: kotak isian berbentuk pil membuat teks yang diketik terlihat
   menempel ke tepi lengkung, dan tanda sisip di awal baris jadi sulit ditemukan mata. */
:root[data-tema="cerah"] .tbl { border-radius: 999px; }

/* Kartu hero absen: aksi utamanya dijadikan pil putih selebar panel, meniru tombol besar
   "Absen Masuk" pada rancangan. Dipilih lewat [data-aksi="masuk"] — sama seperti yang dipakai
   panelAbsen() di absensi.js untuk memasang penanganan kliknya, jadi keduanya tidak bisa
   berpisah diam-diam. */
:root[data-tema="cerah"] .panel-absen .aksi-cepat [data-aksi="masuk"] {
  grid-column: 1 / -1;
  background: #fff; color: var(--biru-700);
  padding: .9rem 1.4rem; font-size: .98rem;
  box-shadow: 0 6px 18px -6px rgba(8, 30, 79, .45);
}
:root[data-tema="cerah"] .panel-absen .aksi-cepat [data-aksi="masuk"]:hover:not(:disabled) {
  background: #f4f8ff;
}

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

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

body {
  margin: 0;
  font-family: "Segoe UI", system-ui, -apple-system, "Helvetica Neue", Arial, sans-serif;
  font-size: 15px;
  line-height: 1.55;
  color: var(--abu-900);
  background: var(--abu-50);
  transition: background-color var(--transisi), color var(--transisi);
}

h1, h2, h3, h4 { margin: 0; line-height: 1.25; font-weight: 700; color: var(--judul); }
p { margin: 0 0 .75rem; }
a { color: var(--aksen-teks); text-decoration: none; }
a:hover { text-decoration: underline; }
img { max-width: 100%; display: block; }

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

/* ---- Layar pemuatan awal ------------------------------------------------ */
.app-loading { min-height: 100vh; display: grid; place-items: center; }
.boot-screen { text-align: center; color: var(--abu-500); }
.boot-logo {
  width: 64px; height: 64px; margin: 0 auto 1rem; border-radius: 18px;
  background: var(--biru-700); color: #fff; display: grid; place-items: center;
  font-weight: 800; font-size: 1.5rem; letter-spacing: .5px;
  animation: denyut 1.4s ease-in-out infinite;
}
/* Saat logo perusahaan sungguhan dipasang (lihat merek-awal.js), kotaknya berhenti menjadi
   lambang huruf: latar birunya dilepas supaya logo berlatar terang tidak tenggelam, dan sudutnya
   dibiarkan mengikuti gambar. */
.boot-logo-gambar {
  width: auto; max-width: 190px; height: 64px; background: none; border-radius: 0;
}
.boot-logo-gambar img { width: auto; height: 100%; max-width: 100%; object-fit: contain; }

@keyframes denyut { 0%, 100% { transform: scale(1); opacity: 1; } 50% { transform: scale(.92); opacity: .7; } }

/* ==========================================================================
   Halaman autentikasi
   ========================================================================== */
.auth-layar { min-height: 100vh; background: var(--putih); }

/* Variasi statis (Lupa Sandi, Atur Ulang Sandi): dua kolom tetap berdampingan, tanpa switch. */
.auth-layar.auth-statis { display: grid; grid-template-columns: 1.05fr .95fr; }
.auth-panel {
  background: linear-gradient(150deg, var(--biru-900) 0%, var(--biru-700) 55%, var(--biru-600) 100%);
  color: #fff;
  padding: 3rem;
  display: flex;
  flex-direction: column;
  justify-content: center;
  position: relative;
  overflow: hidden;
}
.auth-panel::after {
  content: '';
  position: absolute; inset: auto -80px -120px auto;
  width: 380px; height: 380px; border-radius: 50%;
  background: rgba(249, 115, 22, .22);
}
.auth-panel::before {
  content: '';
  position: absolute; inset: -100px auto auto -80px;
  width: 230px; height: 230px; border-radius: 50%;
  background: rgba(255, 255, 255, .07);
}
.auth-panel > * { position: relative; z-index: 1; }
.auth-panel h1 { color: #fff; font-size: 2.1rem; margin-bottom: .75rem; }
.auth-panel p { color: rgba(255, 255, 255, .82); max-width: 44ch; }
.auth-fitur { list-style: none; padding: 0; margin: 2rem 0 0; display: grid; gap: .9rem; }
.auth-fitur li { display: flex; gap: .75rem; align-items: flex-start; color: rgba(255, 255, 255, .9); }
.auth-fitur .tik {
  flex: 0 0 22px; height: 22px; border-radius: 50%; background: var(--oranye-500);
  display: grid; place-items: center; font-size: .7rem; color: #fff; margin-top: 2px;
}
.auth-isi { position: relative; padding: 3rem; display: flex; flex-direction: column; justify-content: center; overflow-y: auto; }

.auth-merek { display: flex; align-items: center; gap: .75rem; margin-bottom: 2.5rem; }
.auth-merek .logo-kotak { background: rgba(255, 255, 255, .16); }

.auth-kotak { width: 100%; max-width: 420px; margin: 0 auto; }
.auth-kotak h2 { font-size: 1.6rem; margin-bottom: .35rem; }
.auth-kotak > p.sub { color: var(--abu-500); margin-bottom: 1.6rem; }
.auth-kaki { margin-top: 1.5rem; text-align: center; color: var(--abu-500); font-size: .9rem; }

/* ---- Kotak kode OTP (verifikasi email) — satu input per digit, auto-lompat fokus ---------- */
.otp-kotak { display: flex; gap: .6rem; justify-content: center; }
.otp-digit {
  width: 3rem; height: 3.5rem; text-align: center; font-size: 1.5rem; font-weight: 700;
  border: 1.5px solid var(--abu-200); border-radius: var(--radius-sm); background: var(--putih);
  color: var(--judul); transition: border-color var(--transisi), box-shadow var(--transisi);
}
.otp-digit:focus { outline: none; border-color: var(--biru-600); box-shadow: 0 0 0 3px rgba(37, 71, 168, .14); }
.otp-digit.galat { border-color: var(--merah-600); }
.otp-kirim-ulang {
  width: 100%; display: flex; align-items: center; justify-content: space-between;
  padding: .75rem 1rem; border: 1px solid var(--abu-200); border-radius: var(--radius-sm);
  background: var(--putih); font: inherit; font-size: .88rem; font-weight: 600; color: var(--abu-400);
  cursor: not-allowed; transition: color var(--transisi), border-color var(--transisi), background var(--transisi);
}
.otp-kirim-ulang:not(:disabled) { color: var(--aksen-teks); border-color: var(--lembut-biru-kuat); cursor: pointer; }
.otp-kirim-ulang:not(:disabled):hover { background: var(--lembut-biru); }
.otp-kirim-ulang .otp-hitung { font-variant-numeric: tabular-nums; }
@media (max-width: 420px) {
  .otp-digit { width: 2.5rem; height: 3.1rem; font-size: 1.3rem; }
  .otp-kotak { gap: .4rem; }
}

.logo-gambar { display: block; width: auto; max-width: 220px; object-fit: contain; border-radius: 8px; }
.auth-logo-form {
  display: flex; flex-direction: column; align-items: center; gap: .6rem; margin-bottom: 1.75rem;
}
.auth-logo-form .nama-perusahaan-form { font-weight: 700; color: var(--judul); font-size: 1.05rem; text-align: center; }

/* ---- Variasi switcher (Masuk <-> Daftar): panel warna "membesar menutupi" lalu mengecil lagi
   di sisi sebaliknya, meniru animasi liquid pada komponen acuan — bukan sekadar geser lurus.
   Tiga lapisan bertumpuk (lihat gantiModeAuth() di auth.js untuk koreografi waktunya):
     1. .auth-putih   — latar putih penuh, selalu 100% (form ada di dalamnya, sisi kiri/kanan
                        diatur lewat kelas .sisi-kiri/.sisi-kanan pada .auth-kotak-wadah).
     2. .auth-warna-bg — kotak warna bergradasi, lebar & posisinya dianimasikan lewat @keyframes
                         dari 50% di satu sisi -> 100% menutupi seluruh kartu -> 50% di sisi lain.
     3. .auth-warna-teks — ajakan & logo, kotak 50% yang bergeser polos lewat transisi `left`;
                         isinya diganti via JS tepat saat kotak warna sedang menutupi penuh,
                         supaya pergantiannya tidak pernah terlihat "meloncat". ---------------- */
.auth-layar.auth-tukar { position: relative; overflow: hidden; }

.auth-putih {
  position: absolute; inset: 0; z-index: 1; background: var(--putih);
  display: flex; align-items: center; padding: 0 3rem; overflow-y: auto;
}
.auth-putih.sisi-kiri { justify-content: flex-start; }
.auth-putih.sisi-kanan { justify-content: flex-end; }
/* Timpa margin:0 auto dari .auth-kotak umum — di sini posisinya diatur justify-content
   pada .auth-putih (flex-start/flex-end), margin otomatis akan membatalkan itu. */
.auth-putih > .auth-kotak { width: 100%; max-width: 420px; padding: 3rem 0; margin: 0; }

.auth-warna-bg {
  position: absolute; top: 0; bottom: 0; z-index: 2;
  background: linear-gradient(150deg, var(--biru-900) 0%, var(--biru-700) 55%, var(--biru-600) 100%);
}
.auth-tukar.mode-masuk .auth-warna-bg { left: 0; width: 50%; border-radius: 0 32% 32% 0 / 0 42% 42% 0; }
.auth-tukar.mode-daftar .auth-warna-bg { left: 50%; width: 50%; border-radius: 32% 0 0 32% / 42% 0 0 42%; }
.auth-warna-bg.animasi-kanan { animation: warna-bg-kanan .8s cubic-bezier(.65, 0, .35, 1) forwards; }
.auth-warna-bg.animasi-kiri { animation: warna-bg-kiri .8s cubic-bezier(.65, 0, .35, 1) forwards; }
@keyframes warna-bg-kanan {
  0%   { left: 0%;  width: 50%;  border-radius: 0 32% 32% 0 / 0 42% 42% 0; }
  50%  { left: 0%;  width: 100%; border-radius: 0; }
  100% { left: 50%; width: 50%;  border-radius: 32% 0 0 32% / 42% 0 0 42%; }
}
@keyframes warna-bg-kiri {
  0%   { left: 50%; width: 50%;  border-radius: 32% 0 0 32% / 42% 0 0 42%; }
  50%  { left: 0%;  width: 100%; border-radius: 0; }
  100% { left: 0%;  width: 50%;  border-radius: 0 32% 32% 0 / 0 42% 42% 0; }
}

.auth-warna-teks {
  position: absolute; top: 0; bottom: 0; width: 50%; z-index: 3; color: #fff;
  padding: 3rem; display: flex; flex-direction: column; justify-content: center;
  transition: left .8s cubic-bezier(.65, 0, .35, 1), top .8s cubic-bezier(.65, 0, .35, 1);
}
.auth-tukar.mode-masuk .auth-warna-teks { left: 0; }
.auth-tukar.mode-daftar .auth-warna-teks { left: 50%; }
/* Rata kanan di Masuk, rata kiri di Daftar (desktop saja — lihat override .rata-tengah-m di
   media query mobile di bawah). Kelas .rata-kanan/.rata-kiri (bukan kelas mode) supaya
   perataan hanya berganti tepat di titik tengah animasi (lihat gantiModeAuth() di auth.js),
   sinkron dengan pergantian konten, bukan meloncat instan begitu tombol diklik. */
.auth-warna-teks.rata-kanan { align-items: flex-end; text-align: right; }
.auth-warna-teks.rata-kiri { align-items: flex-start; text-align: left; }
/* Sengaja TIDAK position:absolute di sudut — kurva border-radius mengempis (tidak menutup
   penuh) tepat di area sudut atas/bawah, jadi logo diikutkan ke alur flex-center yang sama
   dengan ajakan supaya selalu berada di pita vertikal tengah yang selalu tertutup warna penuh,
   berapa pun sisi kurvanya menghadap. */
.auth-warna-teks .auth-merek { margin-bottom: 2rem; }
.auth-warna-teks.rata-kanan .auth-merek { flex-direction: row-reverse; }
.auth-warna-isi h2 { color: #fff; font-size: 1.7rem; margin-bottom: .75rem; }
.auth-warna-isi p { color: rgba(255, 255, 255, .82); max-width: 32ch; margin-bottom: 1.7rem; }
.auth-warna-teks.rata-kanan .auth-warna-isi p { margin-left: auto; }
.auth-warna-isi [data-tab-auth] {
  padding: .7rem 2.1rem; border-radius: 999px; border: 2px solid rgba(255, 255, 255, .85);
  background: transparent; color: #fff; font-weight: 700; font-size: .85rem; letter-spacing: .03em;
  cursor: pointer; transition: background var(--transisi), color var(--transisi);
}
.auth-warna-isi [data-tab-auth]:hover { background: #fff; color: var(--biru-700); }

/* ---- Mobile (<=1024px): susunan vertikal, bukan disembunyikan begitu saja ----------------
   Sumbu digeser 90°: yang di desktop "kiri/kanan" (left/width) di sini jadi "atas/bawah"
   (top/height), memakai pola matematis yang sama (tumbuh menutup penuh lalu mengecil di sisi
   sebaliknya) supaya arah kurtainnya bisa dijaga: Masuk turun dari atas ke bawah, Daftar naik
   dari bawah ke atas — makanya panel warna Masuk berakhir DI BAWAH dan Daftar DI ATAS (bukan
   kebalikannya seperti di desktop), supaya arah tumbuhnya sesuai. Kelas .sisi-kiri/.sisi-kanan
   yang sama dipakai lagi, hanya maknanya berubah jadi atas/bawah lewat flex-direction:column. */
@media (max-width: 1024px) {
  /* Tinggi tetap (px, bukan %) supaya bisa dicocokkan persis dengan padding pengaman di
     .auth-putih — kalau pakai % keduanya sulit disinkronkan dan konten form yang panjang
     (mis. formulir daftar bertahap) berisiko masuk ke bawah panel warna. */
  .auth-tukar .auth-putih {
    flex-direction: column; align-items: stretch; padding: 1.25rem; overflow-y: auto;
  }
  /* flex-start/flex-end (bukan center) + padding sesisi saja (bukan dua sisi) supaya konten
     tumbuh menjauhi panel warna berapa pun panjangnya, alih-alih dipaksa "rata tengah" penuh
     yang bisa membuat konten panjang meluber ke belakang panel warna. */
  /* Keduanya flex-start (bukan flex-end untuk Daftar) — flex-end pada kontainer overflow:auto
     membuat overflow terjadi di ATAS titik scrollTop=0, jadi bagian atas konten panjang
     (judul, deskripsi) tidak akan pernah bisa dijangkau lewat scroll. flex-start selalu aman:
     konten tumbuh ke bawah dari titik setelah padding, overflow-nya normal & bisa di-scroll. */
  .auth-tukar .auth-putih.sisi-kanan { justify-content: flex-start; padding-bottom: 230px; } /* Masuk: warna di bawah */
  .auth-tukar .auth-putih.sisi-kiri { justify-content: flex-start; padding-top: 230px; }      /* Daftar: warna di atas */
  .auth-tukar .auth-putih > .auth-kotak { padding: 1.25rem 0; }

  /* left/width digabung ke selector bermode (bukan selector polos) supaya spesifisitasnya
     menyamai — kalau tidak, aturan left/width dari versi desktop di atas tetap menang meski
     berada di dalam media query ini, karena spesifisitas CSS tidak peduli urutan media query.
     Ini juga berlaku untuk .auth-warna-teks: desktop punya `.mode-daftar .auth-warna-teks
     { left: 50% }` yang spesifisitasnya lebih tinggi dari selector polos `.auth-tukar
     .auth-warna-teks` — kalau left tidak ikut digabung ke sini, kotak teks di mode Daftar
     mobile hanya menempati separuh kanan layar (bukan penuh), membuat teksnya "meloncat"
     ke kanan alih-alih benar-benar rata tengah. */
  .auth-tukar.mode-masuk .auth-warna-bg {
    left: 0; right: 0; width: auto; top: calc(100% - 230px); height: 230px;
    border-radius: 46% 46% 0 0 / 30% 30% 0 0;
  }
  .auth-tukar.mode-daftar .auth-warna-bg {
    left: 0; right: 0; width: auto; top: 0; height: 230px;
    border-radius: 0 0 46% 46% / 0 0 30% 30%;
  }
  .auth-warna-bg.animasi-turun { animation: warna-bg-turun-m .8s cubic-bezier(.65, 0, .35, 1) forwards; }
  .auth-warna-bg.animasi-naik { animation: warna-bg-naik-m .8s cubic-bezier(.65, 0, .35, 1) forwards; }
  @keyframes warna-bg-turun-m {
    0%   { top: 0;                    height: 230px;  border-radius: 0 0 46% 46% / 0 0 30% 30%; }
    50%  { top: 0;                    height: 100%;    border-radius: 0; }
    100% { top: calc(100% - 230px);   height: 230px;  border-radius: 46% 46% 0 0 / 30% 30% 0 0; }
  }
  @keyframes warna-bg-naik-m {
    0%   { top: calc(100% - 230px);   height: 230px;  border-radius: 46% 46% 0 0 / 30% 30% 0 0; }
    50%  { top: 0;                    height: 100%;    border-radius: 0; }
    100% { top: 0;                    height: 230px;  border-radius: 0 0 46% 46% / 0 0 30% 30%; }
  }

  .auth-tukar.mode-masuk .auth-warna-teks { left: 0; right: 0; width: auto; top: calc(100% - 230px); height: 230px; }
  .auth-tukar.mode-daftar .auth-warna-teks { left: 0; right: 0; width: auto; top: 0; height: 230px; }
  .auth-tukar .auth-warna-teks { padding: 1.1rem 1.5rem; justify-content: center; }
  /* Di mobile SELALU rata tengah, berapa pun modenya — beda dari desktop (rata kanan/kiri
     tetap dipakai di atas 1024px). Menimpa .rata-kanan/.rata-kiri lewat selector yang sama
     spesifisitasnya + urutan sesudahnya di file ini. */
  .auth-tukar .auth-warna-teks.rata-kanan,
  .auth-tukar .auth-warna-teks.rata-kiri { align-items: center; text-align: center; }
  .auth-tukar .auth-warna-teks.rata-kanan .auth-merek { flex-direction: row; }
  .auth-tukar .auth-warna-teks.rata-kanan .auth-warna-isi p,
  .auth-tukar .auth-warna-teks.rata-kiri .auth-warna-isi p { margin-left: auto; margin-right: auto; }
  .auth-tukar .auth-warna-teks .auth-merek { margin-bottom: .5rem; }
  .auth-tukar .auth-warna-isi h2 { font-size: 1.2rem; margin-bottom: .25rem; }
  .auth-tukar .auth-warna-isi p { font-size: .82rem; margin-bottom: .6rem; }
  .auth-tukar .auth-warna-isi [data-tab-auth] { padding: .5rem 1.5rem; font-size: .8rem; }
}

/* Konten formulir masuk/daftar meluncur masuk dari arah sisi switch yang dipilih. */
@keyframes auth-isi-kiri { from { opacity: 0; transform: translateX(-18px); } to { opacity: 1; transform: none; } }
@keyframes auth-isi-kanan { from { opacity: 0; transform: translateX(18px); } to { opacity: 1; transform: none; } }
.auth-konten-kiri { animation: auth-isi-kiri .32s cubic-bezier(.2, .9, .3, 1); }
.auth-konten-kanan { animation: auth-isi-kanan .32s cubic-bezier(.2, .9, .3, 1); }

/*
 * Kartu pilihan jalur pengiriman kode OTP (email/WhatsApp) — dipakai identik di formulir Daftar
 * dan Lupa Kata Sandi. Radio aslinya disembunyikan lewat opacity (BUKAN display:none) supaya
 * tetap bisa dijangkau keyboard (Tab) dan diklik lewat <label> yang membungkusnya; status
 * terpilih ditandai murni lewat selector `:checked + .otp-opsi-tampilan`, tanpa JavaScript.
 */
/* Kelompok saklar notifikasi WhatsApp, dipisah menurut penerimanya. */
.wa-notif-kelompok {
  padding: .85rem 1rem; border: 1px solid var(--abu-200); border-radius: var(--radius);
  background: var(--abu-50); margin-top: .7rem;
}
.wa-notif-kelompok .wa-notif-judul { font-weight: 700; color: var(--judul); font-size: .92rem; }
.wa-notif-kelompok .petunjuk { margin-bottom: .35rem; }

.otp-langkah-kepala { margin-bottom: 1.1rem; }
.otp-langkah-kepala h3 { font-size: 1.15rem; color: var(--judul); margin: 0 0 .35rem; }
.otp-langkah-kepala p { color: var(--abu-500); font-size: .88rem; line-height: 1.5; margin: 0; }
.otp-pilihan { display: grid; gap: .7rem; margin-top: .4rem; }
.otp-opsi { display: block; position: relative; cursor: pointer; }
.otp-opsi-masukan { position: absolute; opacity: 0; width: 1px; height: 1px; pointer-events: none; }
.otp-opsi-tampilan {
  display: flex; align-items: flex-start; gap: .85rem; padding: .9rem 1rem;
  border: 1.5px solid var(--abu-200); border-radius: var(--radius-lg);
  background: var(--putih); transition: border-color var(--transisi), box-shadow var(--transisi);
}
.otp-opsi:hover .otp-opsi-tampilan { border-color: var(--abu-300); }
.otp-opsi-masukan:checked + .otp-opsi-tampilan { border-color: var(--biru-500); box-shadow: 0 0 0 3px var(--biru-50); }
.otp-opsi-masukan:focus-visible + .otp-opsi-tampilan { outline: 2px solid var(--biru-500); outline-offset: 2px; }
.otp-opsi-lambang { flex: 0 0 46px; width: 46px; height: 46px; border-radius: 50%; display: grid; place-items: center; }
.otp-opsi-lambang.email { background: var(--biru-50); color: var(--biru-700); }
.otp-opsi-lambang.whatsapp { background: var(--hijau-100); color: var(--hijau-700); }
.otp-opsi-isi { flex: 1; min-width: 0; padding-top: .1rem; }
.otp-opsi-judul { display: block; font-weight: 700; color: var(--judul); margin-bottom: .15rem; }
.otp-opsi-ket { display: block; font-size: .84rem; color: var(--abu-500); line-height: 1.4; }
.otp-opsi-panah { flex: 0 0 auto; align-self: center; color: var(--abu-400); }
.otp-opsi.nonaktif { cursor: not-allowed; }
.otp-opsi.nonaktif .otp-opsi-tampilan { background: var(--abu-50); opacity: .65; }
.otp-info {
  display: flex; gap: .65rem; align-items: flex-start; margin-top: .7rem;
  padding: .8rem .9rem; border-radius: var(--radius); background: var(--biru-50);
}
.otp-info-lambang { flex: 0 0 auto; color: var(--biru-700); }
.otp-info-isi { font-size: .84rem; color: var(--abu-600); line-height: 1.4; }
.otp-info-isi strong { display: block; color: var(--biru-700); margin-bottom: .1rem; }

/* Indikator tahap pada formulir pendaftaran bertahap */
.langkah-indikator { display: flex; list-style: none; margin: 0 0 1.6rem; padding: 0; }
.langkah-indikator .langkah {
  position: relative; flex: 1; display: flex; flex-direction: column; align-items: center;
  gap: .45rem; text-align: center;
}
/* Garis penghubung antar bulatan; ikut biru begitu tahapnya aktif/selesai. */
.langkah-indikator .langkah:not(:first-child)::before {
  content: ''; position: absolute; top: 20px; right: 50%; left: -50%; height: 2px; background: var(--abu-200);
}
.langkah-indikator .langkah.aktif::before,
.langkah-indikator .langkah.selesai::before { background: var(--biru-700); }
.langkah-indikator .bulat {
  position: relative; z-index: 1; width: 42px; height: 42px; border-radius: 50%;
  display: grid; place-items: center; font-weight: 700; font-size: .95rem;
  background: var(--putih); border: 2px solid var(--abu-200); color: var(--abu-400);
  transition: background var(--transisi), border-color var(--transisi), color var(--transisi);
}
.langkah-indikator .langkah.aktif .bulat,
.langkah-indikator .langkah.selesai .bulat { background: var(--biru-700); border-color: var(--biru-700); color: #fff; }
.langkah-indikator .teks { font-size: .78rem; font-weight: 600; color: var(--abu-500); line-height: 1.25; }
.langkah-indikator .langkah.aktif .teks { color: var(--aksen-teks); }

.langkah-kaki { display: flex; align-items: center; gap: .6rem; margin-top: 1.5rem; }
.langkah-kaki .langkah-hitung {
  flex: 1; text-align: center; font-size: .8rem; font-weight: 600; color: var(--abu-500);
}
/* Di layar sempit ketiganya tidak muat sebaris — penghitung dinaikkan ke barisnya sendiri
   agar kedua tombol tidak terpotong di tepi layar. */
@media (max-width: 480px) {
  .langkah-kaki { flex-wrap: wrap; justify-content: space-between; }
  .langkah-kaki .langkah-hitung { order: -1; flex: 1 0 100%; margin-bottom: .15rem; }
  .langkah-kaki .tbl { padding-left: .75rem; padding-right: .75rem; }
}

.akun-demo {
  margin-top: 1.5rem; padding: .9rem 1rem; border-radius: var(--radius);
  background: var(--lembut-biru); border: 1px dashed var(--lembut-biru-kuat); font-size: .85rem; color: var(--abu-600);
}
.akun-demo strong { color: var(--judul); display: block; margin-bottom: .35rem; }
.akun-demo code { background: var(--putih); color: var(--abu-900); padding: .1rem .35rem; border-radius: 5px; border: 1px solid var(--abu-200); }
.akun-demo button {
  margin-top: .6rem; background: none; border: none; color: var(--aksen-teks);
  font: inherit; font-size: .85rem; font-weight: 600; cursor: pointer; padding: 0; text-decoration: underline;
}

/* ==========================================================================
   Tata letak utama
   ========================================================================== */
.tata-letak { min-height: 100vh; }

.sidebar {
  position: fixed; inset: 0 auto 0 0; width: var(--lebar-sidebar); z-index: 60;
  background: linear-gradient(180deg, var(--biru-900), var(--biru-800));
  color: rgba(255, 255, 255, .85);
  display: flex; flex-direction: column;
  transition: transform var(--transisi);
}
.sidebar-merek {
  display: flex; align-items: center; gap: .7rem;
  padding: 1.15rem 1.25rem; border-bottom: 1px solid rgba(255, 255, 255, .1);
  min-height: var(--tinggi-topbar);
}
.logo-kotak {
  width: 38px; height: 38px; flex: 0 0 38px; border-radius: 11px;
  background: var(--oranye-500); color: #fff;
  display: grid; place-items: center; font-weight: 800; font-size: .95rem;
}
.sidebar-merek .nama { color: #fff; font-weight: 700; font-size: 1rem; line-height: 1.2; }
.sidebar-merek .peran { font-size: .74rem; color: var(--biru-100); text-transform: uppercase; letter-spacing: .06em; }

.sidebar-nav { flex: 1; overflow-y: auto; padding: 1rem .75rem 1.5rem; }
.sidebar-nav::-webkit-scrollbar { width: 6px; }
.sidebar-nav::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, .18); border-radius: 3px; }

.nav-judul {
  font-size: .68rem; text-transform: uppercase; letter-spacing: .1em;
  color: rgba(219, 230, 255, .55); padding: 1.1rem .75rem .4rem; font-weight: 700;
}
.nav-tautan {
  display: flex; align-items: center; gap: .7rem;
  padding: .58rem .75rem; border-radius: var(--radius-sm);
  color: rgba(255, 255, 255, .82); font-size: .9rem; font-weight: 500;
  transition: background var(--transisi), color var(--transisi);
}
.nav-tautan:hover { background: rgba(255, 255, 255, .09); color: #fff; text-decoration: none; }
.nav-tautan.aktif { background: var(--oranye-500); color: #fff; box-shadow: 0 4px 12px -4px rgba(249, 115, 22, .8); }
.nav-tautan .ikon { flex: 0 0 18px; display: grid; place-items: center; }
.nav-tautan .lencana {
  margin-left: auto; background: var(--merah-600); color: #fff;
  font-size: .68rem; font-weight: 700; padding: .05rem .4rem; border-radius: 99px; min-width: 20px; text-align: center;
}
.nav-tautan.aktif .lencana { background: rgba(0, 0, 0, .28); }

.sidebar-kaki { padding: 1rem .75rem; border-top: 1px solid rgba(255, 255, 255, .1); }
.sidebar-kaki .versi { font-size: .72rem; color: rgba(219, 230, 255, .45); text-align: center; margin: .5rem 0 0; }

.tirai {
  position: fixed; inset: 0; background: rgba(15, 37, 87, .5);
  z-index: 55; opacity: 0; pointer-events: none; transition: opacity var(--transisi);
}
.tirai.tampil { opacity: 1; pointer-events: auto; }

.wadah-utama { margin-left: var(--lebar-sidebar); min-height: 100vh; display: flex; flex-direction: column; }

.topbar {
  position: sticky; top: 0; z-index: 40;
  min-height: var(--tinggi-topbar);
  /* Material kaca — lihat --kaca-* di :root. Menggantikan token --topbar-bg (kini dihapus, tidak
     perlu dicari) berikut blur(8px)-nya yang berdiri
     sendiri sebelumnya: satu definisi material untuk semua permukaan mengambang, bukan satu nilai
     khusus topbar yang kelak menyimpang dari sisanya. Kilau ada di tepi ATAS pada dock (yang
     menempel di dasar layar) dan di tepi BAWAH di sini — cahaya selalu datang dari sisi yang
     menghadap konten. */
  background: var(--kaca-bg);
  -webkit-backdrop-filter: blur(var(--kaca-blur)) saturate(var(--kaca-jenuh));
  backdrop-filter: blur(var(--kaca-blur)) saturate(var(--kaca-jenuh));
  border-bottom: 1px solid var(--kaca-tepi);
  box-shadow: var(--kaca-bayang-bawah), inset 0 -1px 0 var(--kaca-kilau);
  display: flex; align-items: center; gap: 1rem; padding: .6rem 1.5rem;
  transition: background-color var(--transisi), border-color var(--transisi);
}
.tombol-menu {
  display: none; background: none; border: 1px solid var(--abu-200); border-radius: var(--radius-sm);
  width: 40px; height: 40px; cursor: pointer; color: var(--aksen-teks);
}

/* Judul halaman kini di KANAN topbar (merek perusahaan menempati sisi kiri), jadi teksnya ikut
   rata kanan — judul rata kiri di dalam kotak yang didorong ke kanan terbaca menggantung. */
.topbar-judul { flex: 1; min-width: 0; text-align: right; }
/* Disembunyikan dari MATA saja (pola .hanya-layar-pembaca): <h1> tetap harus ada bagi pembaca
   layar. Dipakai dashboard karyawan — lihat aturJudulHalaman() di app.js. */
.topbar-judul.judul-tersembunyi .jejak,
.topbar-judul.judul-tersembunyi h1 {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}

/* Merek perusahaan di kiri: lambang + wordmark dua baris. */
/* max-width 58%: merek boleh memakan ruang sebanyak yang ia butuhkan, tapi tidak sampai
   menghabiskan baris — judul halaman di sisi kanan harus selalu kebagian tempat. Sisanya diurus
   ellipsis pada wordmark. */
.topbar-merek { display: flex; align-items: center; gap: .55rem; flex: 0 1 auto; min-width: 0; max-width: 58%; }
.topbar-merek:hover { text-decoration: none; }
.topbar-merek .logo-gambar { flex: 0 0 auto; max-width: 120px; }
/* Wordmark dua baris: nama besar, keterangan "by …" kecil di bawahnya. line-height rapat supaya
   keduanya terbaca sebagai satu lambang merek, bukan dua baris teks yang kebetulan bertumpuk. */
.topbar-merek-teks { display: flex; flex-direction: column; min-width: 0; line-height: 1.08; }
/* Warna kedua baris digelapkan satu tingkat sejak topbar menjadi kaca: latar di baliknya kini ikut
   berubah mengikuti apa pun yang tergulir lewat. --aksen-teks hanya mencapai 3,48:1 dan --abu-500
   3,96:1 saat konten gelap lewat — keduanya gagal. --aksen-pekat & --abu-600 lolos di seluruh latar
   yang mungkin. */
.topbar-merek-teks .utama {
  font-weight: 800; font-size: 1.28rem; letter-spacing: -.02em; color: var(--aksen-pekat);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.topbar-merek-teks .sub {
  font-size: .72rem; font-weight: 600; color: var(--abu-600);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
@media (max-width: 560px) {
  /* Di layar sempit wordmark DISUSUTKAN, bukan disembunyikan: nama perusahaan adalah penanda
     "aplikasi siapa ini" dan harus terbaca di setiap halaman. Lambangnya ikut dikecilkan supaya
     teksnya yang mendapat sisa ruang, dan ellipsis mengurus nama yang terlalu panjang. */
  .topbar-merek .logo-gambar { max-width: 40px; }
  .topbar-merek-teks .utama { font-size: 1rem; }
  .topbar-merek-teks .sub { font-size: .66rem; }
  .topbar-judul h1 { font-size: 1rem; }
  .topbar-judul .jejak { font-size: .72rem; }
}
.topbar-judul h1 { font-size: 1.15rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* Pintasan foto profil (hanya dashboard karyawan — lihat #topbar-profil di pages/dashboard.js).
   Cincin tipis memisahkan foto dari latar topbar yang sama-sama terang; tanpa itu foto berlatar
   putih terlihat mengambang tanpa tepi. */
.topbar-profil {
  flex: 0 0 auto; display: block; border-radius: 50%; line-height: 0;
  box-shadow: 0 0 0 2px var(--abu-200);
  transition: box-shadow var(--transisi);
}
.topbar-profil:hover { box-shadow: 0 0 0 2px var(--biru-500); text-decoration: none; }
#topbar-profil:empty { display: none; }
/* --abu-600 dengan alasan yang sama seperti wordmark di atas: jejak duduk langsung di atas kaca. */
.topbar-judul .jejak { font-size: .78rem; color: var(--abu-600); }
.topbar-jam {
  font-variant-numeric: tabular-nums; font-weight: 600; color: var(--aksen-teks);
  background: var(--lembut-biru); padding: .35rem .7rem; border-radius: var(--radius-sm); font-size: .85rem;
  white-space: nowrap;
}

.avatar {
  width: 38px; height: 38px; flex: 0 0 38px; border-radius: 50%; object-fit: cover;
  background: var(--biru-700); color: #fff; display: grid; place-items: center;
  font-weight: 700; font-size: .85rem; overflow: hidden;
}
.avatar.besar { width: 96px; height: 96px; flex-basis: 96px; font-size: 1.8rem; }
.avatar.kecil { width: 32px; height: 32px; flex-basis: 32px; font-size: .72rem; }

.isi-halaman { flex: 1; padding: 1.5rem; max-width: 1440px; width: 100%; }

/* Dock navigasi bawah (mobile, karyawan) — tersembunyi di lebar layar desktop/tablet, lihat @media di bawah. */
.dock-bawah {
  display: none;
  position: fixed; inset: auto 0 0 0; z-index: 80;
  /*
   * Material kaca — lihat --kaca-* di :root. Dock adalah permukaan pertama yang memakainya.
   *
   * Pasangan -webkit- WAJIB ada dan ditulis LEBIH DULU: Safari baru mendukung backdrop-filter
   * tanpa prefiks sejak Safari 18. Tanpa pasangan itu, iOS yang lebih lama hanya melihat putih
   * 85% tembus pandang TANPA blur — konten di baliknya menembus dan label dock jadi bacaan
   * berbayang. Blok @supports di bagian aksesibilitas menangani peramban yang tidak mendukung
   * keduanya sama sekali.
   *
   * Garis tepi + kilau: --kaca-tepi menegaskan batas dock, inset putih tepat di dalamnya meniru
   * pantulan cahaya di bibir kaca. Keduanya bukan hiasan yang bisa ditukar — tanpa salah satunya
   * tepi atas dock lenyap begitu latar di baliknya kebetulan seterang kaca itu sendiri.
   */
  background: var(--kaca-bg-dock);
  /* Blur diperkuat (bukan --kaca-blur 18px): tanpa lapisan putih, blur dan saturate adalah
     satu-satunya yang menyisakan kesan permukaan. Pada 18px tanpa veil, dock hanya terbaca sebagai
     bingkai melayang tanpa isi. */
  -webkit-backdrop-filter: blur(26px) saturate(var(--kaca-jenuh));
  backdrop-filter: blur(26px) saturate(var(--kaca-jenuh));
  /*
   * MENGAMBANG, tidak lagi menempel di tepi layar: dock dilepas dari ketiga sisinya oleh
   * --dock-tepi dan dibulatkan penuh, sehingga konten terlihat lewat di bawahnya. Ini juga alasan
   * bayangannya menyebar ke segala arah — benda yang mengambang tidak punya sisi yang menempel.
   *
   * Kalau --dock-tepi diubah, padding bawah .isi-halaman ikut berubah dengan sendirinya: ketiga
   * perhitungannya (isi halaman, widget chat, area toast) sama-sama menjumlahkan token ini.
   *
   * Jarak bawah SAMA DENGAN jarak samping — satu nilai untuk keempat sisi, tanpa tambahan
   * env(safe-area-inset-bottom). Dengan safe-area dijumlahkan, dock terangkat 34pt di iPhone
   * berponi dan jarak bawahnya terlihat tiga kali lipat jarak sampingnya. Pada .8rem, batang
   * indikator beranda iOS justru jatuh pas di dalam celah itu tanpa bertumpuk dengan docknya.
   */
  margin: var(--dock-tepi);
  border: 1px solid var(--kaca-tepi);
  border-radius: 999px;
  box-shadow: 0 14px 32px -12px rgba(15, 37, 87, .3), inset 0 1px 0 var(--kaca-kilau);
  padding: .3rem .3rem;
  /*
   * Paksa dock menjadi lapisan kompositnya sendiri (GPU), jangan dihapus.
   *
   * Safari iOS tidak menggambar ulang elemen `position: fixed` pada tiap bingkai saat jari
   * menggeser layar — posisinya baru disegarkan setelah gerakan berhenti. Akibatnya dock sempat
   * "tertinggal" melayang di tengah layar selama scroll meluncur, seolah lepas dari dasar layar.
   * Dengan lapisan sendiri, dock digeser oleh compositor mengikuti viewport, bukan digambar ulang
   * bersama isi halaman, sehingga ia tetap menempel di bawah selama scroll.
   *
   * translateZ(0) dipilih ketimbang `will-change: transform`: efek lapisannya sama, tanpa memaksa
   * peramban menyiapkan cadangan memori tambahan untuk elemen yang toh selalu tampil.
   * Aman terhadap tata letak — dock tidak memuat elemen `position: fixed` lain yang bisa berubah
   * acuannya gara-gara transform ini.
   */
  transform: translateZ(0);
}
.dock-tautan {
  flex: 1 1 0; display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: .2rem; padding: .35rem .2rem; border: none; background: none; cursor: pointer;
  /* --abu-600, bukan --abu-500 seperti permukaan lain: dock kini tembus pandang, jadi latar di
     balik label ikut berubah mengikuti apa pun yang tergulir lewat. Diukur pada kaca .85, --abu-500
     turun ke 3,96:1 saat panel gelap lewat di baliknya — gagal. --abu-600 lolos di seluruh latar
     yang mungkin (terburuk 5,53:1). */
  color: var(--abu-600); font: inherit; font-size: .68rem; font-weight: 600; border-radius: var(--radius-sm);
  transition: color var(--transisi), transform .15s cubic-bezier(.4, 0, .2, 1);
  -webkit-tap-highlight-color: transparent;
}
/* Label dock tidak boleh membungkus. Dock karyawan lapangan berisi lima–enam entri, bukan empat,
   sehingga lebar per entri menyusut; tanpa ini "Slip Gaji" pecah jadi dua baris dan seluruh dock
   ikut meninggi, menggeser isi halaman di atasnya. */
.dock-tautan span:not(.ikon) {
  max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* --judul, bukan --aksen-teks: di atas kaca yang menembus konten gelap, --aksen-teks hanya
   mencapai 3,48:1. Menggelap ke arah warna label aktif juga membaca lebih masuk akal — hover
   seolah mengintip keadaan sesudah ditekan. */
.dock-tautan:hover { color: var(--judul); text-decoration: none; }
/* Animasi tekan — mengecil sesaat setiap tombol dock ditekan/disentuh. */
.dock-tautan:active { transform: scale(.86); }
.dock-tautan .ikon {
  position: relative; display: grid; place-items: center;
  /* Warna ikon berpindah bertahap, seiring kapsul yang meluncur (.38s) — bukan seketika. Sejak
     kapsulnya abu netral dan bukan bidang pekat, ikon di kedua keadaan sama-sama terbaca, jadi
     durasinya soal kehalusan belaka, bukan soal keterbacaan. */
  transition: transform .18s cubic-bezier(.4, 0, .2, 1), color .24s ease;
}
/*
 * Kapsul penanda menu aktif — SATU elemen yang meluncur, ditempatkan oleh posisikanSorotDock()
 * di app.js. Menggantikan pil per-ikon yang hanya bisa memudar di tempat.
 *
 * Kenapa oranye pekat dan bukan kaca terang seperti pada rujukannya: di dock yang gelap, kapsul
 * abu terang menonjol dengan sendirinya. Dock ini terang, dan kapsul terang di atasnya hanya
 * mencapai 1,08:1 terhadap permukaan sekelilingnya — praktis tidak terlihat. Yang tersisa sebagai
 * pembeda hanyalah warna yang lebih PEKAT dari docknya (3,78:1), dengan ikon & label putih di
 * atasnya (5,18:1).
 *
 * Kapsul dilukis DI BAWAH isi item (.dock-tautan diberi z-index), sehingga ikon dan label tetap
 * tajam — tidak ikut terkena kaca.
 */
/*
 * Pembagian tugas antara elemen dan pseudo-elemennya disengaja: .dock-sorot HANYA menempatkan
 * (transform: translateX + width), ::before yang MENGGAMBAR kapsulnya. Keduanya perlu transform
 * sendiri-sendiri — geseran posisi dan renggangan saat melesat — dan dua animasi transform pada
 * satu elemen akan saling menimpa.
 */
.dock-sorot {
  /*
   * Ukuran & posisi SEPENUHNYA dari posisikanSorotDock(), tidak satu pun ditulis di sini.
   *
   * Sebelumnya top/bottom dipatok .3rem + env(safe-area-inset-bottom) menyalin padding dock. Begitu
   * dock berubah jadi mengambang, safe-area-nya pindah dari padding ke margin — dan kapsulnya
   * tetap memotong 34pt yang sudah tidak ada di sana, jadi tingginya kurang ~100px di perangkat
   * berponi. Nilai yang MENYALIN nilai lain seperti itu akan menyimpang lagi pada perubahan tata
   * letak berikutnya; diukur dari itemnya, ia tidak bisa.
   */
  position: absolute; left: 0; top: 0;
  width: 0; height: 0; pointer-events: none;
  /* Sampai posisi sahihnya terukur, kapsul disembunyikan — lihat catatan offsetWidth di
     posisikanSorotDock(). Tanpa ini ia sempat terlihat menempel di pojok kiri. */
  opacity: 0;
  /* Kurva berpantul: kapsul sedikit melewati sasaran lalu kembali — inilah yang membuat geraknya
     terbaca "berbobot" alih-alih meluncur datar. */
  transition: transform .38s cubic-bezier(.34, 1.24, .5, 1),
              width .38s cubic-bezier(.34, 1.24, .5, 1),
              opacity .2s ease;
}
.dock-bawah.sorot-siap .dock-sorot { opacity: 1; }

/*
 * Kapsul ABU NETRAL, bukan oranye pekat.
 *
 * Diukur dari rekaman rujukannya: docknya #ffffff, kapsulnya #efefef — batas keduanya hanya
 * 1,15:1, jauh di bawah 3:1. Kapsul itu memang BUKAN penanda status yang berdiri sendiri di sana;
 * yang memikul status adalah ikonnya, yang berubah dari garis luar menjadi terisi penuh. Kapsulnya
 * cuma penegas. Itu sebabnya .dock-tautan.aktif di bawah menebalkan goresan ikon dan menggelapkan
 * labelnya — tanpa keduanya, satu-satunya penanda "kamu di sini" tinggal bidang 1,15:1 yang di
 * bawah matahari tidak akan terlihat sama sekali.
 *
 * Hitam tembus pandang, bukan abu mati: dock ini kaca, warnanya ikut apa pun yang lewat di
 * baliknya. Kapsul berwarna tetap akan menyimpang begitu latar di belakangnya berubah.
 */
.dock-sorot::before {
  content: ''; position: absolute; inset: 0; border-radius: 999px;
  background: rgba(15, 23, 42, .07);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .5);
  transition: opacity .2s ease;
}
/*
 * Saat melesat kapsulnya MENJADI BENING berbingkai cahaya, lalu memadat lagi setibanya — di
 * rujukannya ia berubah jadi tetesan kaca yang membiaskan tulisan di bawahnya. Pembiasannya tidak
 * bisa ditiru CSS (perlu feDisplacementMap/WebGL), jadi yang diambil adalah tiga isyarat lain yang
 * bisa: memudar jadi bening, merenggang, dan tepinya menyala.
 *
 * scaleY ikut sedikit — di rekaman, tetesannya memang menyembul keluar dari pil docknya saat
 * melintas, bukan tetap terkurung rapi di dalamnya.
 */
.dock-sorot.melesat::before { animation: sorot-melesat .38s cubic-bezier(.34, 1.24, .5, 1); }
@keyframes sorot-melesat {
  0% {
    transform: scaleX(1) scaleY(1);
    background: rgba(15, 23, 42, .07);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .5);
  }
  45% {
    transform: scaleX(1.16) scaleY(1.07);
    background: rgba(15, 23, 42, .02);
    box-shadow: inset 0 0 0 1.5px rgba(255, 255, 255, .95),
                0 6px 18px -6px rgba(15, 37, 87, .35);
  }
  100% {
    transform: scaleX(1) scaleY(1);
    background: rgba(15, 23, 42, .07);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .5);
  }
}

/* Isi item di ATAS kapsul. Tanpa ini kapsul menutupi ikon dan labelnya sendiri. */
.dock-tautan { position: relative; z-index: 1; }

/*
 * Halo putih di sekeliling label & ikon — penopang keterbacaan sejak dock menjadi transparan.
 *
 * Empat bayangan pada arah berlawanan, bukan satu: satu bayangan hanya menebalkan sisi tertentu
 * dan huruf tetap lebur di sisi lainnya. Radiusnya kecil (2px) supaya terbaca sebagai tepian
 * huruf, bukan sebagai kabut di sekeliling teks.
 *
 * Halo memulihkan keterbacaan DI MATA, tetapi tidak diakui rumus kontras WCAG — lihat catatan
 * pada --kaca-bg-dock. Karena itu ia bukan pengganti permukaan opak, melainkan penolong; yang
 * benar-benar memulihkan kontras adalah kedua media query aksesibilitas.
 */
.dock-tautan span:not(.ikon) {
  text-shadow:
    0 0 2px rgba(255, 255, 255, .95), 0 1px 2px rgba(255, 255, 255, .9),
    0 -1px 2px rgba(255, 255, 255, .9), 1px 0 2px rgba(255, 255, 255, .9);
}
/* Ikon adalah SVG bergores, jadi ditolong drop-shadow — text-shadow tidak berlaku padanya. */
.dock-tautan .ikon-svg {
  filter:
    drop-shadow(0 0 1.5px rgba(255, 255, 255, .95))
    drop-shadow(0 1px 1.5px rgba(255, 255, 255, .85));
}
/* Ikon aktif duduk di atas kapsul oranye pekat, bukan di atas konten — halonya justru mengotori
   tepi glifnya di sana. */
.dock-tautan.aktif .ikon-svg { filter: none; }
/*
 * INILAH penanda status yang sebenarnya, bukan kapsulnya (lihat catatan di .dock-sorot::before).
 * Rujukannya menukar ikon garis-luar dengan ikon terisi penuh; ikon di aplikasi ini semuanya
 * bergores tanpa varian terisi, jadi padanannya adalah goresan yang menebal — isyarat "lebih
 * berbobot" yang sama, tanpa perlu satu set ikon kedua.
 *
 * stroke-width sebagai PROPERTI CSS sengaja: ikon() di ui.js menuliskannya sebagai atribut
 * presentasi (stroke-width="1.9"), dan properti CSS selalu menang atas atribut presentasi —
 * jadi tidak perlu menyentuh pembuat ikonnya sama sekali.
 */
.dock-tautan.aktif { color: var(--abu-900); font-weight: 700; }
.dock-tautan.aktif .ikon-svg { stroke-width: 2.6; }
/* Goresan ikut menebal bertahap supaya perpindahannya tidak "meletik" — sejalan dengan kapsul
   yang meluncur, bukan mendahuluinya. */
.dock-tautan .ikon-svg { transition: stroke-width .24s ease; }
/* Animasi perpindahan menu — ikon "melompat" setiap kali ditandai aktif (lihat tandaiDockAktif di app.js). */
.dock-tautan.aktif .ikon { animation: dock-aktif-masuk .42s cubic-bezier(.34, 1.56, .64, 1); }

@keyframes dock-aktif-masuk {
  0% { transform: scale(.55) translateY(3px); }
  60% { transform: scale(1.2) translateY(-3px); }
  100% { transform: scale(1) translateY(0); }
}

/* ---- Rona ubin fitur ----------------------------------------------------
   Tiap fitur punya satu warna pekat (--ubin-warna, ditetapkan lewat kelas .ubin-* dari properti
   `warna` pada definisi navigasi di app.js). Latar ubinnya TIDAK ditulis sebagai pastel tetap,
   melainkan dicampur dari warna itu ke --putih lewat color-mix. Dengan begitu satu aturan melayani
   setiap tema sekaligus: hasilnya selalu tint lembut di atas warna permukaan tema itu, tanpa perlu
   daftar warna terpisah per tema yang pasti akan ketinggalan begitu ada rona baru ditambahkan.
   Kalau kelak ada tema bertema gelap lagi, aturan ini sudah benar dengan sendirinya. */
/* Tiap rona punya DUA nilai, dan keduanya wajib ada:
     --ubin-warna  warna cerah, HANYA untuk mencampur tint latar lewat color-mix.
     --ubin-kuat   varian pekatnya, untuk apa pun yang harus terbaca — bidang ikon berlambang
                   putih, angka, dan panah.
   Dipisah karena warna cerahnya tidak bisa dipakai dua-duanya: lambang putih di atas kuning
   #eab308 hanya 1.9:1 dan di atas toska #06b6d4 hanya 2.4:1, dua-duanya di bawah ambang 3:1 untuk
   elemen non-teks; sementara angka rekap di atas tint-nya sendiri cuma 1.8:1. Rona yang varian
   pekatnya sama dengan warna cerahnya (biru, ungu) tetap ditulis dua kali dengan sengaja, supaya
   penambahan rona baru tidak bisa lupa memikirkannya. */
.ubin-biru   { --ubin-warna: #2563eb; --ubin-kuat: #2563eb; }
.ubin-hijau  { --ubin-warna: #16a34a; --ubin-kuat: #15803d; }
.ubin-ungu   { --ubin-warna: #7c3aed; --ubin-kuat: #7c3aed; }
.ubin-oranye { --ubin-warna: #f97316; --ubin-kuat: #ea580c; }
.ubin-merah  { --ubin-warna: #f43f5e; --ubin-kuat: #e11d48; }
.ubin-kuning { --ubin-warna: #eab308; --ubin-kuat: #a16207; }
.ubin-toska  { --ubin-warna: #06b6d4; --ubin-kuat: #0e7490; }

/* Halaman Menu (mobile) — grid seluruh fitur, dibuka lewat item Menu pada dock. */
.menu-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: .7rem; padding: .25rem 0 .5rem; }
.menu-kartu {
  position: relative; display: flex; flex-direction: column; align-items: flex-start; gap: .1rem;
  padding: .85rem .8rem 2.1rem; border-radius: var(--radius-lg);
  background: color-mix(in srgb, var(--ubin-warna, var(--biru-600)) 9%, var(--putih));
  color: var(--abu-600); text-align: left;
  transition: transform var(--transisi), box-shadow var(--transisi);
}
.menu-kartu:hover { transform: translateY(-2px); box-shadow: var(--bayang); text-decoration: none; }
.menu-kartu:active { transform: scale(.98); }
.menu-kartu .lambang {
  position: relative; width: 46px; height: 46px; border-radius: var(--radius);
  display: grid; place-items: center; margin-bottom: .5rem;
  background: var(--ubin-kuat, var(--biru-700)); color: #fff;
}
.menu-kartu .judul { font-size: .88rem; font-weight: 700; color: var(--abu-900); line-height: 1.25; }
/* --abu-600, bukan --abu-500: keterangan ini duduk di atas ubin ber-tint, bukan di atas kartu
   putih polos, dan abu-500 di sana tinggal ±4.2:1 untuk teks sekecil ini. */
.menu-kartu .ket { font-size: .74rem; line-height: 1.3; color: var(--abu-600); margin-top: .15rem; }
/* Panah dijangkarkan ke sudut kanan-bawah (padding-bottom ubin sudah menyediakan ruangnya) supaya
   letaknya sama di semua kartu — kalau ikut alur teks, panjang keterangan yang berbeda-beda membuat
   panahnya naik-turun dan barisan kartu terlihat goyah. */
.menu-kartu .panah {
  position: absolute; right: .7rem; bottom: .7rem;
  width: 26px; height: 26px; border-radius: 50%; display: grid; place-items: center;
  background: var(--putih); color: var(--ubin-kuat, var(--biru-700)); box-shadow: var(--bayang-sm);
}

@media (max-width: 560px) {
  .menu-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (min-width: 900px) {
  .menu-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

/* ==========================================================================
   Komponen
   ========================================================================== */
.kartu {
  background: var(--putih); border: 1px solid var(--abu-200); border-radius: var(--radius-lg);
  box-shadow: var(--bayang-sm);
}
.kartu-kepala {
  display: flex; align-items: center; gap: 1rem; flex-wrap: wrap;
  padding: 1.1rem 1.25rem; border-bottom: 1px solid var(--abu-200);
}
.kartu-kepala h2, .kartu-kepala h3 { font-size: 1rem; }
.kartu-kepala .sub { font-size: .8rem; color: var(--abu-500); margin: .15rem 0 0; }
.kartu-kepala .aksi { margin-left: auto; display: flex; gap: .5rem; flex-wrap: wrap; }
.kartu-isi { padding: 1.25rem; }
.kartu-isi.rapat { padding: .75rem; }
.kartu-isi.nol { padding: 0; }

.grid { display: grid; gap: 1rem; grid-template-columns: minmax(0, 1fr); }
.grid-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grid-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.grid-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.grid-auto { grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); }
.grid-sisi { grid-template-columns: minmax(0, 2fr) minmax(0, 1fr); align-items: start; }

/*
 * Dua kolom setara untuk halaman admin yang isinya dibaca bergantian — kalender & daftarnya,
 * misalnya. Beda dari .grid-sisi yang 2fr/1fr: di sini keduanya sama penting, dan kolom 2fr
 * justru membuat kalender (yang selnya ber-aspect-ratio 1) membengkak seperti saat lebar penuh.
 *
 * auto-fit + minmax, bukan ambang media query: lebar isi halaman admin bergantung pada lebar
 * jendela DAN apakah sidebar sedang tampil. Dengan minmax, keduanya berdampingan tepat ketika
 * masing-masing kebagian >=380px, dan jatuh menumpuk dengan sendirinya begitu tidak.
 */
.admin-sisi {
  display: grid; gap: 1rem;
  grid-template-columns: repeat(auto-fit, minmax(380px, 1fr));
  align-items: start;
}

/*
 * Varian untuk kartu yang isinya TABEL. Ambangnya jauh lebih besar (500px) karena tabel lima–enam
 * kolom di kolom sempit akan menggulung mendatar di dalam kartunya — menukar gulir vertikal dengan
 * gulir mendatar yang lebih menyusahkan. Dengan 500px, keduanya baru berdampingan pada layar yang
 * memang cukup lebar; di bawah itu tetap menumpuk seperti semula.
 */
.admin-sisi-lebar {
  display: grid; gap: 1rem;
  grid-template-columns: repeat(auto-fit, minmax(500px, 1fr));
  align-items: start;
}

/* Kartu statistik */
.stat {
  background: var(--putih); border: 1px solid var(--abu-200); border-radius: var(--radius-lg);
  padding: 1.1rem 1.2rem; box-shadow: var(--bayang-sm);
  display: flex; gap: .9rem; align-items: flex-start;
  transition: transform var(--transisi), box-shadow var(--transisi);
}
.stat:hover { transform: translateY(-2px); box-shadow: var(--bayang); }
.stat .lambang {
  width: 44px; height: 44px; flex: 0 0 44px; border-radius: var(--radius);
  display: grid; place-items: center; font-size: 1.15rem;
}
.stat .nilai { font-size: 1.6rem; font-weight: 800; color: var(--judul); line-height: 1.15; font-variant-numeric: tabular-nums; }
.stat .label { font-size: .82rem; color: var(--abu-500); font-weight: 500; }
.stat .catatan { font-size: .74rem; color: var(--abu-400); margin-top: .2rem; }
.stat.biru   .lambang { background: var(--biru-50);    color: var(--biru-700); }
.stat.hijau  .lambang { background: var(--hijau-100);  color: var(--hijau-700); }
.stat.oranye .lambang { background: var(--oranye-100); color: var(--oranye-600); }
.stat.merah  .lambang { background: var(--merah-100);  color: var(--merah-600); }
.stat.kuning .lambang { background: var(--kuning-100); color: var(--kuning-600); }
.stat.ungu   .lambang { background: var(--ungu-100);   color: var(--ungu-600); }

/* Lencana status */
.lencana {
  display: inline-flex; align-items: center; gap: .35rem;
  padding: .2rem .6rem; border-radius: 99px; font-size: .76rem; font-weight: 600; white-space: nowrap;
}
.lencana::before { content: ''; width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
.lencana.polos::before { display: none; }
.lencana.hadir, .lencana.disetujui, .lencana.aktif, .lencana.terbit { background: var(--hijau-100); color: var(--hijau-700); }
.lencana.terlambat, .lencana.menunggu, .lencana.draft { background: var(--kuning-100); color: var(--kuning-600); }
.lencana.izin { background: var(--biru-50); color: var(--biru-700); }
.lencana.sakit { background: var(--ungu-100); color: var(--ungu-600); }
.lencana.dinas { background: var(--oranye-100); color: var(--oranye-600); }
.lencana.alpa, .lencana.ditolak, .lencana.nonaktif { background: var(--merah-100); color: var(--merah-600); }
.lencana.netral { background: var(--abu-100); color: var(--abu-600); }

/* Kode ringkas shift (mis. "PAG") di daftar shift, kalender jadwal, dan rekap bulanan */
.kode-shift {
  display: inline-block; padding: .1rem .35rem; border-radius: 6px;
  background: var(--biru-50); color: var(--biru-700);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: .68rem; font-weight: 800; letter-spacing: .04em; line-height: 1.5; white-space: nowrap;
}
.kode-shift.libur { background: var(--merah-100); color: var(--merah-600); }
.kode-shift.redup { background: var(--abu-100); color: var(--abu-500); }

/* Tombol */
.tbl {
  display: inline-flex; align-items: center; justify-content: center; gap: .5rem;
  padding: .58rem 1.1rem; border-radius: var(--radius-sm); border: 1px solid transparent;
  font: inherit; font-size: .88rem; font-weight: 600; cursor: pointer;
  transition: background var(--transisi), color var(--transisi), transform var(--transisi), box-shadow var(--transisi);
  white-space: nowrap; text-decoration: none;
}
.tbl:hover { text-decoration: none; }
.tbl:active { transform: translateY(1px); }
.tbl:disabled { opacity: .55; cursor: not-allowed; transform: none; }
.tbl-utama { background: var(--biru-700); color: #fff; }
.tbl-utama:hover:not(:disabled) { background: var(--biru-800); box-shadow: var(--bayang); }
.tbl-aksen { background: var(--oranye-500); color: #fff; }
.tbl-aksen:hover:not(:disabled) { background: var(--oranye-600); box-shadow: var(--bayang); }
.tbl-sukses { background: var(--hijau-600); color: #fff; }
.tbl-sukses:hover:not(:disabled) { background: var(--hijau-700); box-shadow: var(--bayang); }
.tbl-bahaya { background: var(--merah-600); color: #fff; }
.tbl-bahaya:hover:not(:disabled) { background: #b91c1c; }
.tbl-garis { background: var(--putih); border-color: var(--abu-300); color: var(--abu-700); }
.tbl-garis:hover:not(:disabled) { background: var(--abu-100); border-color: var(--abu-400); }
.tbl-halus { background: var(--lembut-biru); color: var(--aksen-teks); }
.tbl-halus:hover:not(:disabled) { background: var(--lembut-biru-kuat); }
.tbl-kecil { padding: .35rem .7rem; font-size: .8rem; }
.tbl-blok { width: 100%; }
.tbl-besar { padding: .8rem 1.4rem; font-size: .95rem; }
.tbl-ikon { padding: .4rem; width: 34px; height: 34px; }

.tbl.memuat { position: relative; color: transparent !important; pointer-events: none; }
.tbl.memuat::after {
  content: ''; position: absolute; width: 16px; height: 16px; border-radius: 50%;
  border: 2px solid rgba(255, 255, 255, .4); border-top-color: #fff; animation: putar .6s linear infinite;
}
/* --aksen-teks, bukan biru-700 yang dipatok: kedua tombol ini berlatar permukaan bertema, jadi
   warna spinnernya harus ikut tema agar tidak pernah senada dengan latarnya sendiri.
   (currentColor tidak bisa dipakai — .tbl.memuat menyetel color jadi transparent.) */
.tbl-garis.memuat::after, .tbl-halus.memuat::after { border-color: rgba(127, 143, 178, .3); border-top-color: var(--aksen-teks); }
@keyframes putar { to { transform: rotate(360deg); } }

/* Formulir */
.form-grup { margin-bottom: 1.05rem; }
.form-grup > label, .label {
  display: block; font-size: .84rem; font-weight: 600; color: var(--abu-700); margin-bottom: .35rem;
}
.form-grup .wajib { color: var(--merah-teks); }
.kendali {
  width: 100%; padding: .62rem .8rem; font: inherit; font-size: .9rem;
  border: 1px solid var(--abu-300); border-radius: var(--radius-sm);
  background: var(--putih); color: var(--abu-900); transition: border-color var(--transisi), box-shadow var(--transisi);
}
.kendali:hover:not(:disabled) { border-color: var(--abu-400); }
.kendali:focus { outline: none; border-color: var(--biru-600); box-shadow: 0 0 0 3px rgba(37, 71, 168, .14); }
.kendali:disabled { background: var(--abu-100); color: var(--abu-500); cursor: not-allowed; }
.kendali.galat { border-color: var(--merah-600); }
.kendali.galat:focus { box-shadow: 0 0 0 3px rgba(220, 38, 38, .14); }
/* Safari iOS & Chrome Android menerapkan gaya bawaan pada input date/time yang punya lebar
   intrinsik sendiri dan bisa melebihi kotak (width:100%) di layar sempit — appearance:none
   membuatnya sepenuhnya mengikuti gaya kustom di atas, tanpa menghilangkan date/time picker asli. */
.kendali[type="date"], .kendali[type="time"], .kendali[type="datetime-local"] {
  -webkit-appearance: none;
  appearance: none;
  min-width: 0;
}
textarea.kendali { min-height: 108px; resize: vertical; }
select.kendali {
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2364748b' stroke-width='2.5' stroke-linecap='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right .65rem center; background-size: 16px;
  padding-right: 2.2rem;
}
.pesan-galat { display: block; color: var(--merah-teks); font-size: .78rem; margin-top: .3rem; font-weight: 500; }
.petunjuk { display: block; color: var(--abu-500); font-size: .78rem; margin-top: .3rem; }

.input-sandi { position: relative; }
.input-sandi .kendali { padding-right: 2.8rem; }
.input-sandi button {
  position: absolute; right: .35rem; top: 50%; transform: translateY(-50%);
  background: none; border: none; cursor: pointer; color: var(--abu-500); padding: .35rem; border-radius: 6px;
}
.input-sandi button:hover { color: var(--aksen-teks); background: var(--abu-100); }

.berkas-drop {
  display: flex; flex-direction: column; align-items: center; gap: .35rem;
  border: 2px dashed var(--abu-300); border-radius: var(--radius); padding: 1.3rem;
  text-align: center; background: var(--abu-50); cursor: pointer; transition: border-color var(--transisi), background var(--transisi);
}
.berkas-drop:hover { border-color: var(--biru-500); background: var(--lembut-biru); }
.berkas-drop input { display: none; }
.berkas-drop .nama-berkas { font-weight: 600; color: var(--aksen-teks); font-size: .88rem; }
.berkas-drop .keterangan { font-size: .78rem; color: var(--abu-500); }

.baris-form { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 1rem; }
.baris-form-3 { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 0 1rem; }

/* Bagian bertajuk di dalam formulir panjang — mis. Data Pribadi / Kepegawaian / Kontak Darurat
   pada formulir karyawan. Garis pemisah di atas judul, bukan kotak: formulir ini sudah berada di
   dalam modal, dan kotak di dalam kotak membuat kedalamannya sulit dibaca. */
.form-bagian { margin: 1.5rem 0 0; padding-top: 1.1rem; border-top: 1px solid var(--abu-200); }
.form-bagian-judul {
  display: flex; align-items: center; gap: .45rem; margin: 0 0 .2rem;
  font-size: .84rem; font-weight: 700; color: var(--abu-600);
  text-transform: uppercase; letter-spacing: .04em;
}
.form-bagian > .petunjuk { margin: 0 0 .75rem; }

/* Tabel */
.bungkus-tabel { overflow-x: auto; -webkit-overflow-scrolling: touch; }
table.tabel { width: 100%; border-collapse: collapse; font-size: .875rem; min-width: 640px; }
table.tabel thead th {
  background: var(--abu-50); color: var(--abu-600); text-align: left; font-weight: 700;
  font-size: .74rem; text-transform: uppercase; letter-spacing: .045em;
  padding: .75rem 1rem; border-bottom: 1px solid var(--abu-200); white-space: nowrap;
}
table.tabel tbody td { padding: .8rem 1rem; border-bottom: 1px solid var(--abu-100); vertical-align: middle; }
table.tabel tbody tr:last-child td { border-bottom: none; }
table.tabel tbody tr:hover { background: var(--lembut-biru); }
table.tabel .angka { text-align: right; font-variant-numeric: tabular-nums; }
table.tabel .tengah { text-align: center; }
table.tabel tfoot td { padding: .8rem 1rem; font-weight: 700; background: var(--abu-50); border-top: 2px solid var(--abu-200); }
.sel-orang { display: flex; align-items: center; gap: .65rem; }
.sel-orang .nama { font-weight: 600; color: var(--abu-900); }
.sel-orang .sub { font-size: .76rem; color: var(--abu-500); }

.bilah-alat {
  display: flex; gap: .65rem; flex-wrap: wrap; align-items: flex-end;
  padding: 1rem 1.25rem; border-bottom: 1px solid var(--abu-200); background: var(--abu-50);
  border-radius: var(--radius-lg) var(--radius-lg) 0 0;
}
.bilah-alat .bidang { display: flex; flex-direction: column; gap: .25rem; min-width: 140px; }
.bilah-alat .bidang label { font-size: .74rem; font-weight: 600; color: var(--abu-500); text-transform: uppercase; letter-spacing: .04em; }
.bilah-alat .tumbuh { flex: 1 1 220px; }
.bilah-alat .kanan { margin-left: auto; display: flex; gap: .5rem; align-items: flex-end; }

.kotak-cari { position: relative; }
.kotak-cari .kendali { padding-left: 2.3rem; }
.kotak-cari .ikon { position: absolute; left: .7rem; top: 50%; transform: translateY(-50%); color: var(--abu-400); pointer-events: none; }

.penomoran {
  display: flex; align-items: center; justify-content: space-between; gap: 1rem; flex-wrap: wrap;
  padding: .9rem 1.25rem; border-top: 1px solid var(--abu-200); font-size: .84rem; color: var(--abu-500);
}
.penomoran .tombol-halaman { display: flex; gap: .3rem; }
.penomoran .tombol-halaman button {
  min-width: 34px; height: 34px; border: 1px solid var(--abu-300); background: var(--putih);
  border-radius: var(--radius-sm); cursor: pointer; font: inherit; font-size: .84rem; color: var(--abu-700);
}
.penomoran .tombol-halaman button:hover:not(:disabled) { background: var(--abu-100); }
.penomoran .tombol-halaman button.aktif { background: var(--biru-700); border-color: var(--biru-700); color: #fff; font-weight: 700; }
.penomoran .tombol-halaman button:disabled { opacity: .45; cursor: not-allowed; }

/* Keadaan kosong / galat / memuat */
.keadaan { text-align: center; padding: 3rem 1.5rem; color: var(--abu-500); }
.keadaan .lambang {
  width: 66px; height: 66px; margin: 0 auto 1rem; border-radius: 50%;
  display: grid; place-items: center; background: var(--abu-100); color: var(--abu-400); font-size: 1.7rem;
}
.keadaan h3 { font-size: 1.02rem; margin-bottom: .35rem; color: var(--abu-700); }
.keadaan p { max-width: 42ch; margin: 0 auto .9rem; font-size: .88rem; }
.keadaan.galat .lambang { background: var(--merah-100); color: var(--merah-600); }

.rangka { background: linear-gradient(90deg, var(--abu-100) 25%, var(--abu-200) 37%, var(--abu-100) 63%); background-size: 400% 100%; animation: geser 1.3s ease infinite; border-radius: 6px; }
@keyframes geser { 0% { background-position: 100% 50%; } 100% { background-position: 0 50%; } }
.rangka-baris { height: 14px; margin-bottom: .65rem; }
.rangka-kartu { height: 92px; border-radius: var(--radius-lg); }

/* Toast */
.toast-area {
  position: fixed; top: 1rem; right: 1rem; z-index: 200;
  display: flex; flex-direction: column; gap: .6rem; max-width: min(380px, calc(100vw - 2rem));
}
.toast {
  display: flex; gap: .75rem; align-items: flex-start;
  /* Material kaca — lihat --kaca-* di :root. Toast mengambang bebas di atas konten (bukan menempel
     di tepi layar seperti topbar/dock), jadi bayangannya tetap --bayang-lg yang menyebar ke segala
     arah; yang ditambahkan hanya kilau tepi atas. Garis kiri berwarna DIPERTAHANKAN penuh sebagai
     penanda jenis pesan — ia satu-satunya bagian toast yang tidak boleh ikut menembus. */
  background: var(--kaca-bg);
  -webkit-backdrop-filter: blur(var(--kaca-blur)) saturate(var(--kaca-jenuh));
  backdrop-filter: blur(var(--kaca-blur)) saturate(var(--kaca-jenuh));
  border: 1px solid var(--kaca-tepi); border-left: 4px solid var(--biru-700);
  border-radius: var(--radius);
  box-shadow: var(--bayang-lg), inset 0 1px 0 var(--kaca-kilau);
  padding: .85rem 1rem;
  animation: masuk-kanan .28s cubic-bezier(.2, .9, .3, 1);
}
.toast.keluar { animation: keluar-kanan .22s ease forwards; }
/* Garis kiri digelapkan sejak toast menjadi kaca: sebagai penanda jenis pesan ia harus mencapai
   3:1 terhadap permukaannya, dan --hijau-600 (2,40:1) maupun --oranye-500 tidak sampai begitu ada
   konten gelap menembus di baliknya. */
.toast.sukses { border-left-color: var(--hijau-700); }
.toast.galat { border-left-color: var(--merah-600); }
.toast.peringatan { border-left-color: var(--oranye-700); }
.toast .lambang { flex: 0 0 22px; height: 22px; border-radius: 50%; display: grid; place-items: center; font-size: .72rem; color: #fff; margin-top: 1px; }
.toast.sukses .lambang { background: var(--hijau-600); }
.toast.galat .lambang { background: var(--merah-600); }
.toast.peringatan .lambang { background: var(--oranye-500); }
.toast.info .lambang { background: var(--biru-700); }
.toast .teks { flex: 1; font-size: .87rem; color: var(--abu-700); }
.toast .teks strong { display: block; color: var(--abu-900); margin-bottom: .1rem; }
/* --abu-400 hanya 1,75:1 di atas kaca — tombol tutupnya praktis lenyap. Ini sudah gagal 3:1
   sejak sebelum kaca (2,39:1 di atas putih); kaca yang membuatnya tak lagi bisa diabaikan. */
.toast .tutup { background: none; border: none; color: var(--abu-600); cursor: pointer; padding: 0 .2rem; font-size: 1.1rem; line-height: 1; }
@keyframes masuk-kanan { from { opacity: 0; transform: translateX(28px); } to { opacity: 1; transform: none; } }
@keyframes keluar-kanan { to { opacity: 0; transform: translateX(28px); } }

/* Modal */
.modal-latar {
  position: fixed; inset: 0; background: rgba(15, 37, 87, .45); z-index: 150;
  /* Scrim ikut mengabur — inilah bagian paling terasa dari seluruh perubahan kaca. Warnanya
     DITURUNKAN .55 → .45 justru karena blurnya kini yang memisahkan modal dari konten, bukan
     kepekatan tirainya; dipertahankan di .55 hasilnya cuma gelap, bukan berkaca. */
  -webkit-backdrop-filter: blur(var(--kaca-blur));
  backdrop-filter: blur(var(--kaca-blur));
  display: grid; place-items: center; padding: 1rem; animation: pudar .2s ease;
  overflow-y: auto;
}
@keyframes pudar { from { opacity: 0; } to { opacity: 1; } }
/*
 * Material kaca — lihat --kaca-* di :root.
 *
 * Modal adalah kasus paling ramah bagi kaca justru karena ia TIDAK mengambang langsung di atas
 * konten: di bawahnya selalu ada .modal-latar yang menyeragamkan apa pun yang lewat. Rentang latar
 * efektifnya jadi sempit (#dbdce2–#ebedf1) apa pun isi halaman di belakangnya, sehingga teks
 * panjang di dalam modal tetap aman — sesuatu yang tidak berlaku bagi toast atau topbar.
 */
.modal {
  background: var(--kaca-bg);
  -webkit-backdrop-filter: blur(var(--kaca-blur)) saturate(var(--kaca-jenuh));
  backdrop-filter: blur(var(--kaca-blur)) saturate(var(--kaca-jenuh));
  border: 1px solid var(--kaca-tepi);
  border-radius: var(--radius-lg);
  box-shadow: var(--bayang-lg), inset 0 1px 0 var(--kaca-kilau);
  width: 100%; max-width: 520px; margin: auto; animation: naik .24s cubic-bezier(.2, .9, .3, 1);
}
.modal.lebar { max-width: 760px; }
/*
 * Modal layar penuh — dipakai kamera absen wajah agar bingkai wajah sebesar mungkin, terutama di
 * ponsel. Tinggi memakai dvh (dengan cadangan vh untuk peramban lama) supaya tombol di kaki modal
 * tidak tertutup bilah alamat peramban seluler yang muncul-hilang saat digulir.
 */
.modal-latar.penuh { padding: 0; overflow: hidden; }
.modal.penuh {
  width: 100%; max-width: none; margin: 0; border-radius: 0;
  height: 100vh; height: 100dvh;
  display: flex; flex-direction: column;
}
.modal.penuh .modal-isi {
  flex: 1; min-height: 0; max-height: none; padding: .85rem;
  display: flex; flex-direction: column; gap: .5rem;
}
.modal.penuh .modal-kaki { border-radius: 0; }
@keyframes naik { from { opacity: 0; transform: translateY(16px) scale(.98); } to { opacity: 1; transform: none; } }
.modal-kepala { display: flex; align-items: flex-start; gap: 1rem; padding: 1.2rem 1.35rem; border-bottom: 1px solid var(--abu-200); }
.modal-kepala h3 { font-size: 1.05rem; }
/* --abu-600/--abu-500: keduanya digelapkan satu tingkat sejak modal menjadi kaca. Tombol tutup
   sebelumnya --abu-400 — 1,77:1 di atas kaca, dan sudah gagal 3:1 bahkan di atas putih. */
.modal-kepala .sub { font-size: .82rem; color: var(--abu-600); margin: .15rem 0 0; }
.modal-kepala .tutup { margin-left: auto; background: none; border: none; font-size: 1.3rem; color: var(--abu-600); cursor: pointer; line-height: 1; padding: 0 .2rem; }
.modal-isi { padding: 1.35rem; max-height: min(62vh, 560px); overflow-y: auto; }
/* Latar kaki dibuat setengah tembus, bukan --abu-50 pekat: kaki menutupi seluruh lebar dasar
   modal, jadi latar opak di sini mematikan kaca justru di tempat yang paling terlihat (tepi bawah
   yang membulat). color-mix mempertahankan rona --abu-50 yang membedakan kaki dari badan modal,
   hanya saja kini ikut menembus. */
.modal-kaki { display: flex; gap: .6rem; justify-content: flex-end; padding: 1rem 1.35rem; border-top: 1px solid var(--abu-200); background: color-mix(in srgb, var(--abu-50) 55%, transparent); border-radius: 0 0 var(--radius-lg) var(--radius-lg); flex-wrap: wrap; }
.modal-lambang { width: 46px; height: 46px; flex: 0 0 46px; border-radius: 50%; display: grid; place-items: center; font-size: 1.2rem; }
.modal-lambang.bahaya { background: var(--merah-100); color: var(--merah-600); }
.modal-lambang.peringatan { background: var(--oranye-100); color: var(--oranye-600); }
.modal-lambang.info { background: var(--biru-50); color: var(--biru-700); }
.modal-lambang.sukses { background: var(--hijau-100); color: var(--hijau-700); }

/* Panel jam absensi */
.panel-absen {
  background: linear-gradient(135deg, var(--biru-800), var(--biru-600));
  color: #fff; border-radius: var(--radius-lg); padding: 1.75rem; position: relative; overflow: hidden;
}
.panel-absen::after {
  content: ''; position: absolute; right: -60px; top: -60px; width: 220px; height: 220px;
  border-radius: 50%; background: rgba(249, 115, 22, .18);
}
.panel-absen > * { position: relative; z-index: 1; }
.panel-absen .jam-besar { font-size: 3rem; font-weight: 800; font-variant-numeric: tabular-nums; line-height: 1.05; letter-spacing: -.02em; }
.panel-absen .tanggal { color: rgba(255, 255, 255, .8); font-size: .92rem; }
.panel-absen .status-kini {
  display: inline-flex; align-items: center; gap: .5rem; margin-top: 1rem;
  background: rgba(255, 255, 255, .16); padding: .4rem .9rem; border-radius: 99px; font-size: .85rem; font-weight: 600;
}
.panel-absen .status-kini .titik { width: 8px; height: 8px; border-radius: 50%; background: var(--hijau-100); animation: denyut-titik 1.8s ease-in-out infinite; }
@keyframes denyut-titik { 0%, 100% { opacity: 1; } 50% { opacity: .35; } }
.aksi-cepat { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: .75rem; margin-top: 1.5rem; }
.aksi-cepat .tbl { padding: .75rem 1rem; }
.aksi-cepat .tbl-garis { background: rgba(255, 255, 255, .14); border-color: rgba(255, 255, 255, .3); color: #fff; }
.aksi-cepat .tbl-garis:hover:not(:disabled) { background: rgba(255, 255, 255, .24); border-color: rgba(255, 255, 255, .5); }

.linimasa-absen { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: .8rem; margin-top: 1.4rem; }
.linimasa-absen .butir { background: rgba(255, 255, 255, .12); border-radius: var(--radius); padding: .8rem .9rem; }
.linimasa-absen .butir .l { font-size: .74rem; color: rgba(255, 255, 255, .72); text-transform: uppercase; letter-spacing: .05em; }
.linimasa-absen .butir .n { font-size: 1.15rem; font-weight: 700; font-variant-numeric: tabular-nums; }

/* ==========================================================================
   Dashboard karyawan — profil ringkas, jadwal hari ini, aksi cepat
   ========================================================================== */
.profil-ringkas { display: flex; align-items: center; gap: .85rem; }
.profil-ringkas .avatar { width: 52px; height: 52px; flex-basis: 52px; font-size: 1.1rem; border: 2px solid var(--putih); box-shadow: var(--bayang-sm); }
.profil-ringkas .profil-info { flex: 1; min-width: 0; }
.profil-ringkas .jabatan { font-size: .8rem; color: var(--abu-500); font-weight: 600; }
.profil-ringkas .nama { font-size: 1.25rem; font-weight: 800; color: var(--judul); line-height: 1.25; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.profil-lonceng {
  position: relative; flex: 0 0 auto; width: 44px; height: 44px; border-radius: 50%;
  background: var(--putih); border: 1px solid var(--abu-200); box-shadow: var(--bayang-sm);
  display: grid; place-items: center; color: var(--abu-700); transition: background var(--transisi), color var(--transisi);
}
.profil-lonceng:hover { background: var(--lembut-biru); color: var(--aksen-teks); text-decoration: none; }

/* Lonceng versi topbar — duduk di antara tombol tema dan menu pengguna, jadi ukuran DAN
   bentuknya disamakan dengan tombol tema di sebelahnya (kotak membulat, bukan lingkaran seperti
   lonceng kartu yang lebih besar). */
.topbar-lonceng {
  position: relative; flex: 0 0 auto; display: grid; place-items: center; width: 38px; height: 38px;
  border-radius: var(--radius-sm); border: 1px solid var(--abu-200); background: none;
  color: var(--aksen-teks); transition: background var(--transisi), border-color var(--transisi);
}
.topbar-lonceng:hover { background: var(--abu-100); border-color: var(--abu-300); text-decoration: none; }
#topbar-lonceng:empty { display: none; }
.lonceng-lencana {
  position: absolute; top: -3px; right: -3px; min-width: 18px; height: 18px; padding: 0 4px;
  border-radius: 999px; background: var(--merah-600); color: #fff; font-size: .64rem; font-weight: 800;
  display: grid; place-items: center; border: 2px solid var(--putih);
}

.kartu-jadwal .jadwal-kop { font-size: .74rem; font-weight: 700; color: var(--abu-500); text-transform: uppercase; letter-spacing: .07em; }
.kartu-jadwal .jadwal-tanggal { font-size: .86rem; font-weight: 700; color: var(--judul); }
/* ---- Baris kartu yang dapat digeser (gaji, cuaca) ----------------------- */
.geser-kartu { position: relative; }
.geser-trek {
  display: flex; gap: .9rem; overflow-x: auto; scroll-snap-type: x mandatory;
  /* Sembunyikan batang gulir: gesernya sudah ditandai titik indikator di bawah, dan batang gulir
     mendatar di dalam kartu terbaca seperti cacat tampilan pada layar sentuh. */
  scrollbar-width: none; -ms-overflow-style: none;
}
.geser-trek::-webkit-scrollbar { display: none; }
/* Tiap slot selebar penuh trek supaya satu geseran = tepat satu kartu. */
.geser-slot { flex: 0 0 100%; scroll-snap-align: start; min-width: 0; }
.geser-slot > .kartu { height: 100%; margin: 0; }
.geser-titik { display: flex; justify-content: center; gap: .4rem; margin-top: .6rem; }
.geser-titik button {
  width: 7px; height: 7px; padding: 0; border: none; border-radius: 50%; cursor: pointer;
  background: var(--abu-300); transition: background var(--transisi), width var(--transisi);
}
.geser-titik button.aktif { background: var(--biru-600); width: 18px; border-radius: 99px; }

/* ---- Kartu cuaca -------------------------------------------------------- */
.kartu-cuaca {
  position: relative; overflow: hidden;
  background: linear-gradient(150deg, #0e7490, #0891b2);
  border: none; color: #fff;
}
/* Gradasi per suasana — dipisah dari animasinya supaya kartu tetap "terasa benar" bahkan bila
   pengguna mematikan animasi lewat prefers-reduced-motion. */
.kartu-cuaca.cuaca-cerah { background: linear-gradient(150deg, #0284c7, #38bdf8 70%, #7dd3fc); }
.kartu-cuaca.cuaca-berawan { background: linear-gradient(150deg, #475569, #64748b 70%, #94a3b8); }
.kartu-cuaca.cuaca-hujan { background: linear-gradient(150deg, #1e3a5f, #334e68 70%, #486581); }
.kartu-cuaca.cuaca-petir { background: linear-gradient(150deg, #1e293b, #334155 70%, #475569); }

/* Malam: gradasi yang jauh lebih gelap untuk tiap suasana. Ditulis sebagai kelas TAMBAHAN
   (.cuaca-cerah.cuaca-malam), bukan suasana tersendiri, supaya satu-satunya yang berubah adalah
   warnanya — benda dan animasi yang dipilih JavaScript tetap sama persis. Hujan malam tetap hujan. */
.kartu-cuaca.cuaca-cerah.cuaca-malam { background: linear-gradient(150deg, #0b1b3f, #16307a 62%, #2a4ba8); }
.kartu-cuaca.cuaca-berawan.cuaca-malam { background: linear-gradient(150deg, #16203a, #27324f 70%, #3b4763); }
.kartu-cuaca.cuaca-hujan.cuaca-malam { background: linear-gradient(150deg, #0a1526, #16273f 70%, #21374f); }
.kartu-cuaca.cuaca-petir.cuaca-malam { background: linear-gradient(150deg, #0b1120, #1b2434 70%, #2b3547); }
/* Awan malam memantulkan lebih sedikit cahaya — tanpa ini gumpalan putih terang terlihat seperti
   kabut yang menyala sendiri di atas langit gelap. */
.kartu-cuaca.cuaca-malam .c-awan { background: rgba(226, 232, 240, .13); }

/* Lapisan hiasan: di belakang teks, tidak menangkap sentuhan, dan tidak pernah meluber keluar
   kartu (overflow:hidden pada .kartu-cuaca). */
.kartu-cuaca .c-latar { position: absolute; inset: 0; pointer-events: none; z-index: 0; overflow: hidden; }
.kartu-cuaca .kartu-isi { position: relative; z-index: 1; }

/* Matahari: satu bola bercahaya yang berdenyut pelan. */
.c-surya {
  position: absolute; top: -34px; right: -26px; width: 132px; height: 132px; border-radius: 50%;
  background: radial-gradient(circle, rgba(255, 236, 170, .95) 0%, rgba(255, 214, 102, .55) 42%, rgba(255, 214, 102, 0) 70%);
  animation: cuaca-denyut 5s ease-in-out infinite;
}
@keyframes cuaca-denyut {
  0%, 100% { transform: scale(1); opacity: .9; }
  50% { transform: scale(1.12); opacity: 1; }
}

/* Bulan sabit: lingkaran BERLATAR TRANSPARAN yang bentuk sabitnya dibuat satu inset box-shadow
   bergeser. Bukan dua lingkaran bertumpuk — cara itu menuntut lingkaran penutup berwarna sama
   dengan latar, padahal latarnya gradasi yang berbeda tiap suasana.

   Diletakkan di BAWAH baris ikon, bukan di sudut seperti matahari: matahari adalah cahaya kabur
   tanpa tepi sehingga boleh menyelinap di belakang ikon, sedangkan sabit bertepi tegas di tempat
   yang sama hanya terlihat seperti dua bulan yang bertabrakan.

   Denyutnya jauh lebih pelan daripada matahari — bulan yang berdenyut secepat matahari terbaca
   seperti lampu yang berkedip. */
.c-bulan {
  position: absolute; top: 66px; right: 30px; width: 52px; height: 52px; border-radius: 50%;
  background: transparent;
  box-shadow: inset -14px 5px 0 0 #f6f2d9;
  animation: cuaca-sinar 9s ease-in-out infinite;
}
@keyframes cuaca-sinar {
  0%, 100% { filter: drop-shadow(0 0 5px rgba(246, 242, 217, .35)); }
  50% { filter: drop-shadow(0 0 13px rgba(246, 242, 217, .6)); }
}

/* Bintang: titik kecil yang berkelip bergantian. Posisi & jeda ditetapkan lewat nth-child supaya
   susunannya sama pada tiap render — langit yang berpindah-pindah tiap kali kartu digambar ulang
   justru menarik perhatian ke tempat yang salah. */
.c-bintang { position: absolute; inset: 0; }
.c-bintang i {
  position: absolute; width: 3px; height: 3px; border-radius: 50%; background: #fff;
  opacity: .25; animation: cuaca-kelip ease-in-out infinite;
}
.c-bintang i:nth-child(1) { top: 18%; left: 12%; animation-duration: 3.1s; animation-delay: -.2s; }
.c-bintang i:nth-child(2) { top: 9%; left: 30%; animation-duration: 2.4s; animation-delay: -1.1s; }
.c-bintang i:nth-child(3) { top: 27%; left: 47%; animation-duration: 3.8s; animation-delay: -.6s; }
.c-bintang i:nth-child(4) { top: 13%; left: 62%; animation-duration: 2.8s; animation-delay: -1.7s; width: 2px; height: 2px; }
.c-bintang i:nth-child(5) { top: 41%; left: 20%; animation-duration: 3.4s; animation-delay: -2.3s; }
.c-bintang i:nth-child(6) { top: 52%; left: 68%; animation-duration: 2.6s; animation-delay: -.9s; width: 2px; height: 2px; }
.c-bintang i:nth-child(7) { top: 64%; left: 38%; animation-duration: 4.1s; animation-delay: -1.4s; }
.c-bintang i:nth-child(8) { top: 74%; left: 84%; animation-duration: 3s; animation-delay: -2.8s; width: 2px; height: 2px; }
.c-bintang i:nth-child(9) { top: 35%; left: 88%; animation-duration: 3.6s; animation-delay: -.4s; }
@keyframes cuaca-kelip {
  0%, 100% { opacity: .2; transform: scale(.85); }
  50% { opacity: .95; transform: scale(1); }
}

/* Awan: gumpalan lembut yang hanyut mendatar. Ukuran & ketinggian dibedakan supaya tidak terlihat
   seperti satu bentuk yang diulang. */
.c-awan {
  position: absolute; border-radius: 999px; background: rgba(255, 255, 255, .22);
  filter: blur(1px); animation: cuaca-hanyut linear infinite;
}
.c-awan-1 { width: 120px; height: 34px; top: 14px; left: -130px; animation-duration: 26s; }
.c-awan-2 { width: 86px; height: 26px; top: 58px; left: -100px; animation-duration: 34s; animation-delay: -8s; opacity: .8; }
.c-awan-3 { width: 150px; height: 40px; top: 96px; left: -160px; animation-duration: 44s; animation-delay: -18s; opacity: .55; }
@keyframes cuaca-hanyut {
  from { transform: translateX(0); }
  to { transform: translateX(calc(100% + 100vw)); }
}

/* Hujan: garis tipis yang jatuh miring. Sepuluh tetes dengan jarak & jeda berbeda lewat nth-child
   — nilainya tetap, jadi tampilannya sama pada tiap render. */
.c-hujan { position: absolute; inset: 0; }
.c-hujan i {
  position: absolute; top: -18%; width: 1.5px; height: 16px; border-radius: 2px;
  background: linear-gradient(to bottom, rgba(255, 255, 255, 0), rgba(255, 255, 255, .55));
  animation: cuaca-tetes linear infinite;
}
.c-hujan i:nth-child(1) { left: 6%; animation-duration: 1.1s; animation-delay: 0s; }
.c-hujan i:nth-child(2) { left: 16%; animation-duration: .9s; animation-delay: -.4s; }
.c-hujan i:nth-child(3) { left: 26%; animation-duration: 1.3s; animation-delay: -.8s; }
.c-hujan i:nth-child(4) { left: 36%; animation-duration: 1s; animation-delay: -.2s; }
.c-hujan i:nth-child(5) { left: 46%; animation-duration: 1.2s; animation-delay: -.6s; }
.c-hujan i:nth-child(6) { left: 56%; animation-duration: .95s; animation-delay: -1s; }
.c-hujan i:nth-child(7) { left: 66%; animation-duration: 1.25s; animation-delay: -.3s; }
.c-hujan i:nth-child(8) { left: 76%; animation-duration: 1.05s; animation-delay: -.7s; }
.c-hujan i:nth-child(9) { left: 86%; animation-duration: 1.15s; animation-delay: -.5s; }
.c-hujan i:nth-child(10) { left: 94%; animation-duration: .85s; animation-delay: -.9s; }
@keyframes cuaca-tetes {
  from { transform: translate3d(0, 0, 0); opacity: 0; }
  10% { opacity: 1; }
  to { transform: translate3d(-14px, 190px, 0); opacity: 0; }
}

/* Kilat: seluruh kartu berkedip sekejap, dengan jeda panjang di antaranya. */
.c-kilat {
  position: absolute; inset: 0; background: rgba(255, 255, 255, .5); opacity: 0;
  animation: cuaca-kilat 7s ease-out infinite;
}
@keyframes cuaca-kilat {
  0%, 92%, 100% { opacity: 0; }
  93% { opacity: .55; }
  94% { opacity: 0; }
  95% { opacity: .35; }
  96% { opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .c-surya, .c-awan, .c-hujan i, .c-kilat, .c-bulan, .c-bintang i { animation: none; }
  /* Berbeda dengan hujan, bintang yang diam tetap terbaca sebagai bintang — jadi hanya kelipnya
     yang dihentikan, dan opasitasnya disetel ke nilai tengah agar tidak nyaris tak terlihat. */
  .c-bintang i { opacity: .7; }
  /* Tanpa animasi, tetes hujan yang membeku di satu tempat terbaca seperti goresan pada layar. */
  .c-hujan, .c-kilat { display: none; }
}
.kartu-cuaca .c-lokasi {
  display: inline-flex; align-items: center; gap: .35rem; font-size: .82rem; font-weight: 600; opacity: .9;
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.kartu-cuaca .c-ikon { flex: 0 0 auto; opacity: .95; }
.kartu-cuaca .c-suhu { font-size: 2.1rem; font-weight: 800; line-height: 1.1; margin-top: .35rem; font-variant-numeric: tabular-nums; }
.kartu-cuaca .c-satuan { font-size: 1.1rem; font-weight: 700; opacity: .85; margin-left: .1rem; }
.kartu-cuaca .c-deskripsi { font-size: .86rem; font-weight: 600; opacity: .9; margin-top: .1rem; }
/* Didorong ke dasar kartu supaya tinggi kartu cuaca dan kartu gaji tetap sama tanpa menyisakan
   ruang kosong menganga di bawah — keduanya berbagi satu trek geser. */
.kartu-cuaca .kartu-isi { display: flex; flex-direction: column; height: 100%; }
.kartu-cuaca .c-catatan { margin: auto 0 0; padding-top: .7rem; font-size: .72rem; line-height: 1.4; opacity: .78; }

/* ---- Kartu gaji dashboard karyawan (nominal dapat disembunyikan) -------- */
.kartu-gaji {
  background: linear-gradient(150deg, var(--biru-800), var(--biru-600));
  border: none; color: #fff;
}
.kartu-gaji .g-label { font-size: .82rem; font-weight: 600; opacity: .85; }
.kartu-gaji .g-mata {
  border: none; background: rgba(255, 255, 255, .18); color: #fff; cursor: pointer;
  width: 34px; height: 34px; border-radius: 50%; display: grid; place-items: center;
  transition: background var(--transisi);
}
.kartu-gaji .g-mata:hover { background: rgba(255, 255, 255, .3); }
.kartu-gaji .g-mata:active { transform: scale(.92); }

/* ---- Animasi buka/tutup ikon mata --------------------------------------
   Keadaan BAWAAN = tertutup (nominal tersembunyi), sesuai keadaan awal kartu:
   kelopak menyipit, pupil menciut, dan garis coret tergambar penuh melintang.
   Kelas .terbuka pada tombolnya membalik ketiganya sekaligus. */
.ikon-mata .m-kelopak,
.ikon-mata .m-pupil,
.ikon-mata .m-coret { transition: all 260ms cubic-bezier(.4, 0, .2, 1); transform-origin: 12px 12px; }

/* Garis coret "ditarik" memakai dasharray: panjang penuh diagonalnya ±24. */
.ikon-mata .m-coret { stroke-dasharray: 24; stroke-dashoffset: 0; }
.ikon-mata .m-kelopak { transform: scaleY(.55); }
.ikon-mata .m-pupil { transform: scale(.45); opacity: .45; }

/* Terbuka: coret ditarik habis ke luar, kelopak & pupil kembali penuh. */
.g-mata.terbuka .ikon-mata .m-coret { stroke-dashoffset: 24; }
.g-mata.terbuka .ikon-mata .m-kelopak { transform: scaleY(1); }
.g-mata.terbuka .ikon-mata .m-pupil { transform: scale(1); opacity: 1; }

/* Nominal ikut muncul/menghilang dengan lembut, bukan berkedip. */
.kartu-gaji .g-angka,
.kartu-gaji .g-titik { animation: gaji-muncul 260ms cubic-bezier(.4, 0, .2, 1); }
@keyframes gaji-muncul {
  from { opacity: 0; transform: translateY(4px); }
  to { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  .ikon-mata .m-kelopak,
  .ikon-mata .m-pupil,
  .ikon-mata .m-coret { transition: none; }
  .kartu-gaji .g-angka,
  .kartu-gaji .g-titik { animation: none; }
}
/* Tinggi dikunci supaya kartu tidak melompat saat nominal dibuka/ditutup — titik dan angka
   punya tinggi baris yang berbeda. */
.kartu-gaji .g-nominal { margin: .55rem 0 .15rem; min-height: 2.1rem; display: flex; align-items: center; }
.kartu-gaji .g-titik { font-size: 1.5rem; letter-spacing: .18em; line-height: 1; }
.kartu-gaji .g-angka { font-size: 1.55rem; font-weight: 800; font-variant-numeric: tabular-nums; }
.kartu-gaji .g-tautan {
  display: flex; align-items: center; justify-content: space-between; gap: .5rem;
  margin-top: .7rem; padding-top: .7rem; border-top: 1px solid rgba(255, 255, 255, .22);
  color: #fff; font-weight: 700; font-size: .9rem;
}
.kartu-gaji .g-tautan:hover { text-decoration: none; opacity: .85; }
.kartu-gaji .g-catatan { margin: .5rem 0 0; font-size: .72rem; line-height: 1.4; opacity: .78; }

.grid-jadwal { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .8rem; margin-top: 1rem; }
/* Ubin ini adalah BIDANG berwarna bertulisan putih, sekelas .panel-absen — jadi gradasinya
   dipatok dan TIDAK boleh memakai skala abu bertema. Skala abu dimaksudkan untuk teks & garis
   di atas permukaan, bukan sebagai permukaan itu sendiri; memakainya di sini membuat kontras
   tulisan putihnya bergantung pada tema yang sedang aktif. Nilai di bawah = slate-500/600, aman
   untuk teks putih. */
.jadwal-tile {
  border-radius: var(--radius-lg); padding: 1.1rem .9rem; text-align: center; color: #fff;
  background: linear-gradient(160deg, #64748b, #475569);
  transition: transform var(--transisi);
}
.jadwal-tile.aktif { background: linear-gradient(160deg, var(--biru-700), var(--biru-500)); box-shadow: var(--bayang); }
.jadwal-tile.selesai { background: linear-gradient(160deg, var(--hijau-700), var(--hijau-600)); }
.jadwal-tile .j-label { font-size: .8rem; font-weight: 600; opacity: .9; }
.jadwal-tile .j-jam { font-size: 1.55rem; font-weight: 800; margin: .3rem 0 .15rem; font-variant-numeric: tabular-nums; }
.jadwal-tile .j-tombol {
  /* Pil putih di atas ubin berwarna — putih & teksnya sama-sama dipatok, mengikuti ubinnya.
     Warna teks bertema tidak boleh dipakai di sini: latarnya putih tetap, bukan permukaan tema. */
  margin-top: .55rem; background: #fff; border: none; border-radius: 999px; padding: .45rem 1rem;
  font: inherit; font-size: .78rem; font-weight: 700; color: #475569; cursor: pointer;
  display: inline-flex; align-items: center; gap: .3rem; transition: transform var(--transisi);
}
.jadwal-tile .j-tombol:hover:not(:disabled) { transform: translateY(-1px); }
.jadwal-tile .j-tombol:disabled { opacity: .65; cursor: not-allowed; }
.jadwal-tile.aktif .j-tombol { color: var(--biru-700); }
.jadwal-tile.tile-lembur.aktif .j-tombol { color: var(--oranye-600); }
.jadwal-tile .j-selesai {
  display: inline-flex; align-items: center; gap: .3rem; margin-top: .55rem;
  background: rgba(255, 255, 255, .22); padding: .4rem .85rem; border-radius: 999px; font-size: .76rem; font-weight: 700;
}
/* Ubin lembur: membentang kedua kolom lalu dipersempit dan dipusatkan, sehingga tampak duduk
   tepat di tengah bawah ubin Absen Masuk & Absen Pulang. Lebarnya mengikuti satu ubin ditambah
   separuh jarak antar-ubin agar tepiannya tidak sejajar dengan ubin mana pun di atasnya. */
.jadwal-tile.tile-lembur {
  grid-column: 1 / -1;
  width: min(100%, calc(50% + 2.4rem));
  margin-inline: auto;
}
.jadwal-tile.tile-lembur.aktif { background: linear-gradient(160deg, var(--oranye-600), var(--oranye-500)); }

.aksi-ikon-baris { display: flex; justify-content: space-between; gap: .4rem; }
.aksi-ikon {
  flex: 1 1 0; display: flex; flex-direction: column; align-items: center; gap: .5rem;
  color: var(--abu-700); font-size: .78rem; font-weight: 600; text-align: center;
}
.aksi-ikon:hover { color: var(--biru-700); text-decoration: none; }
/* Tombol "Atur" memakai kerangka .aksi-ikon yang sama supaya sejajar dengan pintasan di
   sebelahnya, tetapi dibedakan sebagai bulatan berbingkai putus-putus — ia mengatur baris ini,
   bukan salah satu isinya. */
.aksi-ikon.aksi-atur { border: none; background: none; font: inherit; cursor: pointer; padding: 0; }
.aksi-ikon.aksi-atur .bulat {
  background: none; color: var(--abu-500); border: 1.5px dashed var(--abu-300);
}
.aksi-ikon.aksi-atur:hover .bulat { color: var(--biru-700); border-color: var(--biru-500); }

.tumpuk-rapat { display: flex; flex-direction: column; gap: .35rem; }
.pilihan-pintasan {
  display: flex; align-items: center; gap: .7rem; padding: .55rem .7rem; cursor: pointer;
  border: 1px solid var(--abu-200); border-radius: var(--radius-sm); transition: background var(--transisi);
}
.pilihan-pintasan:hover { background: var(--abu-50); }
.pilihan-pintasan .lambang {
  width: 32px; height: 32px; flex: 0 0 32px; border-radius: 9px; display: grid; place-items: center;
  background: var(--lembut-biru); color: var(--aksen-teks);
}
.pilihan-pintasan .teks { font-size: .88rem; font-weight: 600; color: var(--abu-700); }
.pilihan-pintasan:has(input:checked) { border-color: var(--biru-500); background: var(--lembut-biru); }
.pilihan-pintasan:has(input:disabled) { opacity: .5; cursor: not-allowed; }

.aksi-ikon .bulat {
  position: relative; width: 52px; height: 52px; border-radius: 50%; display: grid; place-items: center;
  background: linear-gradient(150deg, var(--biru-700), var(--biru-500)); color: #fff;
  box-shadow: var(--bayang-sm); transition: transform var(--transisi), box-shadow var(--transisi);
}
.aksi-ikon:hover .bulat { transform: translateY(-3px); box-shadow: var(--bayang); }
.lencana-mini {
  position: absolute; top: -3px; right: -4px; min-width: 18px; height: 18px; padding: 0 4px;
  border-radius: 999px; background: var(--merah-600); color: #fff; font-size: .62rem; font-weight: 800;
  display: grid; place-items: center; border: 2px solid var(--putih);
}

.statistik-kop { display: flex; align-items: baseline; gap: .5rem; margin-bottom: .9rem; }
.statistik-kop .judul { font-size: 1.05rem; font-weight: 800; color: var(--judul); }
.statistik-kop .judul .bulan { font-weight: 500; color: var(--abu-500); margin-left: .3rem; }
.statistik-kop .tahun { margin-left: auto; font-weight: 700; color: var(--judul); font-size: .92rem; }

.grid-statistik { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .85rem; }
.kartu-mini-stat {
  display: flex; align-items: center; gap: .9rem; background: var(--putih); border: 1px solid var(--abu-200);
  border-radius: var(--radius-lg); padding: 1rem 1.05rem; box-shadow: var(--bayang-sm);
}
.kartu-mini-stat .lambang { width: 54px; height: 54px; flex: 0 0 54px; border-radius: 50%; display: grid; place-items: center; }
.kartu-mini-stat .label { font-weight: 700; font-size: .98rem; color: var(--judul); }
.kartu-mini-stat .nilai { font-size: .84rem; color: var(--abu-500); margin-top: .15rem; font-variant-numeric: tabular-nums; }
.kartu-mini-stat.biru   .lambang { background: var(--biru-50);    color: var(--biru-700); }
.kartu-mini-stat.hijau  .lambang { background: var(--hijau-100);  color: var(--hijau-700); }
.kartu-mini-stat.oranye .lambang { background: var(--oranye-100); color: var(--oranye-600); }
.kartu-mini-stat.kuning .lambang { background: var(--kuning-100); color: var(--kuning-600); }
.kartu-mini-stat.merah  .lambang { background: var(--merah-100);  color: var(--merah-600); }
.kartu-mini-stat.ungu   .lambang { background: var(--ungu-100);   color: var(--ungu-600); }

/* Daftar aktivitas & pengumuman */
.daftar-garis { list-style: none; margin: 0; padding: 0; }
.daftar-garis li { display: flex; gap: .85rem; padding: .85rem 1.25rem; border-bottom: 1px solid var(--abu-100); }
.daftar-garis li:last-child { border-bottom: none; }
.daftar-garis .lambang { width: 34px; height: 34px; flex: 0 0 34px; border-radius: 50%; display: grid; place-items: center; font-size: .8rem; background: var(--lembut-biru); color: var(--aksen-teks); }
.daftar-garis .isi { flex: 1; min-width: 0; }
.daftar-garis .isi .judul { font-weight: 600; font-size: .89rem; color: var(--abu-900); }
.daftar-garis .isi .meta { font-size: .77rem; color: var(--abu-500); }

.kartu-pengumuman {
  display: block; border: 1px solid var(--abu-200); border-radius: var(--radius);
  padding: 1.1rem 1.2rem; background: var(--putih); transition: border-color var(--transisi), box-shadow var(--transisi), transform var(--transisi);
  height: 100%;
}
.kartu-pengumuman:hover { border-color: var(--biru-500); box-shadow: var(--bayang); transform: translateY(-2px); text-decoration: none; }
.kartu-pengumuman .judul { font-weight: 700; color: var(--judul); margin: .5rem 0 .35rem; font-size: 1rem; }
.kartu-pengumuman .ringkas { font-size: .86rem; color: var(--abu-600); display: -webkit-box; -webkit-line-clamp: 3; line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
.kartu-pengumuman .kaki { display: flex; gap: .75rem; align-items: center; margin-top: .9rem; font-size: .77rem; color: var(--abu-500); flex-wrap: wrap; }

.isi-artikel { font-size: .95rem; color: var(--abu-700); line-height: 1.75; white-space: pre-wrap; }

/* Grafik */
.grafik { width: 100%; height: auto; display: block; }
.legenda { display: flex; gap: 1rem; flex-wrap: wrap; justify-content: center; margin-top: .9rem; font-size: .8rem; color: var(--abu-600); }
.legenda span { display: inline-flex; align-items: center; gap: .4rem; }
.legenda i { width: 11px; height: 11px; border-radius: 3px; display: inline-block; }

.bilah-maju { height: 8px; background: var(--abu-200); border-radius: 99px; overflow: hidden; }
.bilah-maju > i { display: block; height: 100%; border-radius: 99px; background: var(--hijau-600); transition: width .5s ease; }
.bilah-maju.oranye > i { background: var(--oranye-500); }
.bilah-maju.merah > i { background: var(--merah-600); }

/* Rincian gaji */
.rincian { list-style: none; margin: 0; padding: 0; }
.rincian li { display: flex; justify-content: space-between; gap: 1rem; padding: .6rem 0; border-bottom: 1px dashed var(--abu-200); font-size: .89rem; }
.rincian li:last-child { border-bottom: none; }
.rincian li .k { color: var(--abu-600); }
.rincian li .v { font-weight: 600; font-variant-numeric: tabular-nums; }
.rincian li.tambah .v { color: var(--hijau-teks); }
.rincian li.kurang .v { color: var(--merah-teks); }
.rincian li.total { border-top: 2px solid var(--abu-200); border-bottom: none; margin-top: .4rem; padding-top: .8rem; font-size: 1.02rem; }
.rincian li.total .k, .rincian li.total .v { font-weight: 800; color: var(--judul); }

/* Tab */
.tab { display: flex; gap: .25rem; border-bottom: 1px solid var(--abu-200); overflow-x: auto; }
.tab button {
  background: none; border: none; padding: .7rem 1rem; font: inherit; font-size: .88rem; font-weight: 600;
  color: var(--abu-500); cursor: pointer; border-bottom: 2px solid transparent; white-space: nowrap;
}
.tab button:hover { color: var(--aksen-teks); }
.tab button.aktif { color: var(--aksen-teks); border-bottom-color: var(--oranye-500); }

/* Utilitas */
/* grid-template-columns: minmax(0, 1fr) mencegah kolom implisit melebar mengikuti konten
   (mis. tabel lebar di .bungkus-tabel) yang memaksa seluruh halaman perlu di-zoom out di mobile —
   pola yang sama seperti .grid-2/3/4/sisi di bawah, hanya belum diterapkan di sini sebelumnya. */
.tumpuk { display: grid; gap: 1rem; grid-template-columns: minmax(0, 1fr); }
.tumpuk-kecil { display: grid; gap: .5rem; grid-template-columns: minmax(0, 1fr); }
.baris { display: flex; gap: .6rem; align-items: center; flex-wrap: wrap; }
.baris-antara { display: flex; gap: 1rem; align-items: center; justify-content: space-between; flex-wrap: wrap; }
.kanan { margin-left: auto; }
.teks-kecil { font-size: .82rem; }
.teks-redup { color: var(--abu-500); }
.teks-tebal { font-weight: 700; }
.teks-kanan { text-align: right; }
.teks-tengah { text-align: center; }
.mt-0 { margin-top: 0; } .mt-1 { margin-top: .5rem; } .mt-2 { margin-top: 1rem; } .mt-3 { margin-top: 1.5rem; }
.mb-0 { margin-bottom: 0; } .mb-1 { margin-bottom: .5rem; } .mb-2 { margin-bottom: 1rem; } .mb-3 { margin-bottom: 1.5rem; }
.sembunyi { display: none !important; }
.hanya-layar-pembaca {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}

/* ==========================================================================
   Kamera (absen wajah)
   ========================================================================== */
.kamera-wadah {
  position: relative; width: 100%; aspect-ratio: 4 / 3; max-width: 420px; margin: 0 auto;
  border-radius: var(--radius); overflow: hidden; background: #0f172a;
}
.kamera-wadah video, .kamera-wadah img {
  width: 100%; height: 100%; object-fit: cover; display: block;
  transform: scaleX(-1); /* efek cermin — kamera depan terasa lebih alami dipakai seperti bercermin */
}
/*
 * `display: block` di atas adalah aturan penulis, sehingga menang atas `[hidden] { display: none }`
 * bawaan peramban (spesifisitas sama, aturan penulis diprioritaskan). Tanpa aturan ini, men-set
 * `video.hidden = true` saat pindah ke pratinjau tidak benar-benar menyembunyikan video — video tetap
 * memenuhi bingkai dan foto hasil jepretan terdorong ke bawah lalu terpotong `overflow: hidden`.
 * Bandingkan dengan catatan serupa pada .chat-panel di bawah.
 */
.kamera-wadah video[hidden], .kamera-wadah img[hidden] { display: none; }
/*
 * Kanvas penanda wajah ditumpuk persis di atas video. Ikut dicerminkan seperti videonya supaya
 * kotak penanda mendarat di posisi yang sama dengan wajah yang dilihat pengguna — koordinat dari
 * model dihitung pada bingkai asli (belum dicermin), jadi pencerminannya diserahkan ke CSS.
 */
.kamera-bingkai {
  position: absolute; inset: 0; width: 100%; height: 100%;
  pointer-events: none; transform: scaleX(-1);
  /*
   * WAJIB sama dengan object-fit videonya. Kanvas termasuk elemen replaced dan punya ukuran
   * intrinsik dari atribut width/height (= ukuran bingkai video asli), jadi dengan `cover` yang
   * sama ia dipotong persis seperti video. Tanpa ini kanvas diregangkan penuh sementara video
   * dipotong, sehingga kotak penanda melenceng dari wajah — paling kentara di modal layar penuh
   * yang rasio wadahnya jauh berbeda dari rasio bingkai kamera.
   */
  object-fit: cover;
}
.kamera-bingkai[hidden] { display: none; }
/*
 * Kamera belakang untuk foto OBJEK (bukti patroli/kunjungan): tidak dicerminkan. Cermin hanya
 * masuk akal ketika pengguna melihat dirinya sendiri — memotret pintu atau papan nama dengan
 * pratinjau terbalik membuat pengguna salah membidik dan tulisannya tidak terbaca.
 */
.kamera-wadah.tanpa-cermin video, .kamera-wadah.tanpa-cermin img { transform: none; }
/*
 * Bingkai bidik pemindai QR. Murni penuntun mata — jsQR memindai SELURUH bingkai, bukan hanya
 * bagian dalam kotak ini. Kotaknya ada supaya pengguna tahu harus mendekat seberapa, karena
 * kesalahan paling umum saat memindai adalah berdiri terlalu jauh.
 */
/* --------------------------------------------------------------------------
   Pilihan berbentuk kartu (hasil kunjungan sales) — lihat js/pages/kunjungan.js
   Warna tiap pilihan berbeda-beda, jadi diambil dari properti kustom `--warna-pilihan` yang
   dipasang inline per opsi. Dengan begitu satu aturan CSS melayani semua pilihan tanpa perlu
   satu kelas untuk tiap warna.
   -------------------------------------------------------------------------- */
.pilihan-kartu {
  position: relative; flex: 1; min-width: 150px;
  display: flex; gap: .5rem; align-items: flex-start;
  padding: .7rem .8rem; border: 1.5px solid var(--abu-200); border-radius: var(--radius);
  cursor: pointer; background: var(--putih);
  transition: border-color .18s ease, background-color .18s ease, box-shadow .18s ease, transform .12s ease;
}
.pilihan-kartu:hover { border-color: var(--warna-pilihan, var(--abu-400)); }
/* Umpan balik sentuh: mengecil sesaat saat ditekan, sama seperti tombol dock. */
.pilihan-kartu:active { transform: scale(.97); }
.pilihan-kartu:has(input:checked) {
  border-color: var(--warna-pilihan);
  background: color-mix(in srgb, var(--warna-pilihan) 8%, var(--putih));
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--warna-pilihan) 18%, transparent);
}
/* Keyboard tetap terlihat: :has(:focus-visible) menandai kartu, bukan radio kecilnya. */
.pilihan-kartu:has(input:focus-visible) { outline: 3px solid var(--oranye-500); outline-offset: 2px; }
/*
 * Denyut singkat sekali jalan saat pilihan berpindah. Sengaja pendek dan hanya pada bayangan —
 * animasi yang menggeser tata letak membuat tiga kartu bersebelahan terlihat goyah setiap kali
 * pengguna berganti pikiran.
 */
.pilihan-kartu:has(input:checked) .pilihan-tanda {
  animation: pilihan-masuk .32s cubic-bezier(.34, 1.56, .64, 1);
}
.pilihan-tanda {
  position: absolute; top: .55rem; right: .6rem;
  width: 18px; height: 18px; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--warna-pilihan); color: #fff;
  opacity: 0; transform: scale(.4);
  transition: opacity .18s ease, transform .22s cubic-bezier(.34, 1.56, .64, 1);
}
.pilihan-kartu:has(input:checked) .pilihan-tanda { opacity: 1; transform: scale(1); }
@keyframes pilihan-masuk {
  0% { box-shadow: 0 0 0 0 var(--warna-pilihan); }
  100% { box-shadow: 0 0 0 10px transparent; }
}
/* Radio aslinya disembunyikan dari mata tetapi tetap ada untuk pembaca layar & keyboard. */
.pilihan-kartu input[type="radio"] { margin-top: .2rem; accent-color: var(--warna-pilihan); }

.qr-sasaran {
  position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
  width: min(62%, 260px); aspect-ratio: 1; pointer-events: none;
  border: 3px solid rgba(255, 255, 255, .9); border-radius: 18px;
  box-shadow: 0 0 0 100vmax rgba(15, 23, 42, .35);
}
/*
 * Di dalam modal layar penuh, bingkai kamera ikut meregang mengisi sisa ruang alih-alih dikunci
 * rasio 4:3 selebar 420px. `min-height: 0` wajib ada, tanpa itu flex item tidak boleh menyusut di
 * bawah tinggi kontennya sehingga video mendorong tombol Ambil Foto keluar layar.
 */
.modal.penuh .kamera-wadah {
  flex: 1; min-height: 0; width: 100%; max-width: none; aspect-ratio: auto;
}

/* --------------------------------------------------------------------------
   Verifikasi gerakan wajah (liveness) — lihat js/liveness.js
   Instruksinya harus terbaca sekilas sambil karyawan menggerakkan kepala, jadi sengaja dibuat
   besar, di tengah, dan dengan tinggi tetap agar teks yang berganti-ganti tidak menggeser tata
   letak (pergeseran kecil pun mengganggu saat mata sedang mengikuti bingkai kamera).
   -------------------------------------------------------------------------- */
.lv-langkah { display: flex; gap: .4rem; justify-content: center; margin-top: .9rem; }
.lv-titik {
  width: 26px; height: 5px; border-radius: 999px; background: var(--abu-200);
  transition: background .2s ease;
}
.lv-titik.aktif { background: var(--oranye-500); }
.lv-titik.selesai { background: var(--hijau-600); }
.lv-instruksi {
  margin: .6rem 0 .5rem; text-align: center; font-weight: 700; font-size: 1.05rem;
  line-height: 1.35; min-height: 2.7em;
}
.lv-bar {
  width: min(320px, 100%); height: 8px; margin: 0 auto; border-radius: 999px;
  background: var(--abu-200); overflow: hidden;
}
.lv-bar > span {
  display: block; width: 0; height: 100%; border-radius: 999px;
  background: var(--hijau-600); transition: width .12s linear;
}

/* ==========================================================================
   Widget chat mengambang
   ========================================================================== */
/*
 * Leaflet mengatur .leaflet-container jadi position:relative tapi TANPA z-index eksplisit,
 * sehingga elemen itu tidak membentuk stacking context sendiri — pane & kontrol internalnya
 * (z-index bawaan sampai 1000, lihat leaflet.css) ikut dibandingkan langsung dengan elemen lain
 * di halaman seperti widget chat (z-index 70) dan bisa "menutupinya". Memberi z-index eksplisit
 * di sini mengurung seluruh isi peta ke stacking context-nya sendiri agar tidak pernah bocor
 * menutupi elemen lain di luar peta (mis. peta karyawan menutupi pop-up chat).
 */
.leaflet-container { z-index: 0; }
/* Label nama permanen di atas penanda Peta Karyawan (lihat admin-peta.js).
   Warna dipatok, BUKAN var(--abu-900): latarnya datang dari leaflet.css (.leaflet-tooltip
   { background-color: #fff }) yang selalu putih apa pun temanya — beserta warna panah tooltipnya.
   Memakai warna teks bertema di sini membuat labelnya bergantung pada tema padahal latarnya tidak.
   Ubin petanya sendiri juga terang, jadi tooltip putih memang yang senada di sini. */
.peta-label-nama { font-size: .74rem; font-weight: 700; padding: 2px 8px; color: #0f172a; }
/*
 * JANGAN beri `transform` (atau filter/perspective/will-change) pada .chat-widget.
 *
 * Elemen ini adalah INDUK dari .chat-latar yang ber-`position: fixed; inset: 0`. Begitu induknya
 * punya transform, ia berubah jadi containing block bagi si anak — `inset: 0` tidak lagi berarti
 * "seluruh layar" melainkan "sebesar kotak tombol chat 56px", dan panel chat langsung terpotong.
 * Trik lapisan komposit yang dipakai .dock-bawah aman di sana justru karena dock tidak memuat
 * elemen `position: fixed` apa pun di dalamnya.
 */
.chat-widget {
  position: fixed; right: 1.4rem; bottom: 1.4rem; z-index: 70;
  display: flex; flex-direction: column; align-items: flex-end; gap: .8rem;
}
/*
 * Dinaikkan hanya SELAMA panel terbuka (kelas dipasang bukaPanel() di chat-widget.js).
 *
 * `.chat-latar` di bawah memang sudah diberi z-index 150, tetapi angka itu tidak pernah berlaku
 * secara global: karena induknya (.chat-widget) punya position + z-index sendiri, ia membentuk
 * stacking context, sehingga seisi widget dibandingkan dengan elemen lain memakai angka INDUKNYA
 * — yaitu 70. Padahal dock bawah bernilai 80, jadi dock menimpa panel chat dan menutupi bagian
 * paling bawahnya: tepat di kotak ketik pesan.
 *
 * Dinaikkan lewat kelas, bukan permanen, supaya di luar keadaan terbuka tombol chat tetap berada
 * di bawah tirai (85) dan sidebar mobile (90) seperti sebelumnya.
 */
.chat-widget.chat-terbuka { z-index: 150; }
.chat-fab {
  width: 56px; height: 56px; flex: 0 0 56px; border-radius: 50%; border: none; cursor: grab;
  /* FAB tetap biru PEKAT, tidak ikut menembus: ikonnya putih, dan latar tembus pandang berarti
     kontras ikon berubah-ubah mengikuti apa pun yang lewat di baliknya — pada tombol sebesar 56px
     yang melayang di sembarang tempat, itu taruhan yang tidak perlu. Yang diambil dari bahasa kaca
     hanya kilau tepinya, supaya ia terbaca sebagai benda yang sama dengan topbar dan dock. */
  background: var(--biru-700); color: #fff; display: grid; place-items: center; position: relative;
  box-shadow: 0 10px 26px rgba(15, 23, 42, .28), inset 0 1px 0 rgba(255, 255, 255, .25);
  transition: transform .15s ease, background .15s ease;
  touch-action: none; -webkit-user-select: none; user-select: none;
}
.chat-fab:hover { transform: translateY(-2px); background: var(--biru-800); }
.chat-fab:active { cursor: grabbing; }
.chat-fab.aktif {
  /*
   * Tombol bulat disembunyikan total selagi panel terbuka (panel kini mengambang di tengah layar,
   * lihat .chat-latar di bawah) — bukan cuma diberi warna aktif seperti semula, supaya logo telepon
   * tidak lagi menumpuk di atas isi panel (dilaporkan lewat tangkapan layar).
   */
  display: none;
}
/*
 * Ditambahkan begitu pengguna pertama kali menggeser tombol chat (lihat pasangGeserFab() di
 * chat-widget.js) — posisi berpindah dari jangkar kanan-bawah bawaan ke left/top bebas yang
 * diatur lewat inline style, jadi transform hover di atas sengaja dimatikan agar tidak dianggap
 * ikut menggeser posisi saat idle.
 */
.chat-widget-geser .chat-fab:hover { transform: none; }
.chat-fab-lencana {
  display: none; /* ditampilkan lewat .tampil — sama seperti .chat-latar, lihat catatan di bawah */
  position: absolute; top: -3px; right: -3px; min-width: 20px; height: 20px; padding: 0 5px;
  border-radius: 99px; background: var(--merah-600); color: #fff; font-size: .68rem; font-weight: 700;
  place-items: center; border: 2px solid var(--putih);
}
.chat-fab-lencana.tampil { display: grid; }
/*
 * Latar mengambang: panel chat tidak lagi menempel di pojok kanan-bawah dekat tombol, melainkan
 * ditumpangkan di tengah layar seperti modal (lihat pola .modal-latar di atas) — supaya posisinya
 * konsisten di mana pun tombol digeser, dan tidak perlu perhitungan left/top manual seperti
 * sebelumnya (yang rawan terpotong di dekat tepi layar).
 */
/*
 * Tinggi latar mengikuti area yang BENAR-BENAR terlihat, bukan 100vh.
 *
 * Di Safari iOS, `100vh` selalu berarti tinggi layar seolah-olah bilah alamat sedang tersembunyi —
 * jadi nilainya lebih besar daripada yang sungguh terlihat, dan panel setinggi itu bagian bawahnya
 * (justru kotak ketik pesan) terdorong ke luar layar. Keyboard yang muncul memperparahnya lagi:
 * area terlihat menyusut drastis sementara 100vh tidak berubah sama sekali.
 *
 * Karena itu tinggi & posisi atas diambil dari visualViewport lewat --chat-tinggi/--chat-atas yang
 * disetel chat-widget.js. 100vh hanya cadangan bila skripnya gagal jalan.
 */
.chat-latar {
  display: none; position: fixed; left: 0; right: 0; z-index: 150; place-items: center; padding: 1rem;
  top: var(--chat-atas, 0px);
  height: var(--chat-tinggi, 100vh);
  /* Ikut mengabur seperti .modal-latar, dengan alasan yang sama. Warnanya diturunkan .45 → .38
     karena blur kini yang memisahkan panel dari konten.

     Yang TIDAK diberi kaca adalah .chat-panel itu sendiri: seluruh anaknya opak
     (.chat-panel-kepala biru, .chat-panel-isi/-daftar, .chat-panel-input), jadi latar panel
     tertutup rapat dan kaca di sana hanya akan terlihat sebagai sesobek di sudut membulat —
     biaya backdrop-filter tanpa hasil yang terlihat. Membuat anak-anaknya ikut menembus bukan
     pilihan: itu berarti percakapan panjang dibaca di atas apa pun yang kebetulan lewat. */
  background: rgba(15, 37, 87, .38);
  -webkit-backdrop-filter: blur(var(--kaca-blur));
  backdrop-filter: blur(var(--kaca-blur));
  animation: pudar-chat .18s ease;
}
.chat-latar.tampil { display: grid; }
@keyframes pudar-chat { from { opacity: 0; } to { opacity: 1; } }
/*
 * Ukuran panel dinyatakan sebagai persentase petak grid induknya (yang sudah dikurangi padding 1rem),
 * bukan lagi hitungan `calc(100vh - 7rem)`. Dengan begitu panel mustahil melebihi ruang yang tersedia
 * berapa pun tinggi layar sesungguhnya — tidak ada lagi angka ajaib yang harus ditebak-tebak.
 */
.chat-panel {
  /* height + max-height, bukan min(500px, 100%): kalau persentasenya sampai tidak terselesaikan
     peramban, panel jatuh ke 500px yang wajar — bukan ke ukuran aneh hasil min() yang gagal. */
  width: min(360px, 100%); height: 500px; max-height: 100%;
  background: var(--putih); border: 1px solid var(--abu-200); border-radius: var(--radius-lg);
  box-shadow: 0 22px 55px rgba(15, 23, 42, .28); display: flex; flex-direction: column; overflow: hidden;
  animation: chat-panel-masuk .18s ease;
}
@keyframes chat-panel-masuk {
  from { opacity: 0; transform: scale(.97); }
  to { opacity: 1; transform: none; }
}
.chat-panel-kepala {
  flex: 0 0 auto; display: flex; align-items: center; gap: .6rem; padding: .8rem 1rem;
  background: var(--biru-700); color: #fff;
}
.chat-panel-kepala .judul { flex: 1; min-width: 0; }
.chat-panel-kepala .judul .nama {
  font-weight: 700; font-size: .92rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.chat-panel-kepala .judul .sub {
  font-size: .74rem; color: rgba(255, 255, 255, .75); white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.chat-panel-kepala button {
  flex: 0 0 auto; width: 28px; height: 28px; border-radius: 8px; border: none; cursor: pointer;
  background: rgba(255, 255, 255, .16); color: #fff; display: grid; place-items: center; font-size: 1.1rem; line-height: 1;
}
.chat-panel-kepala button:hover { background: rgba(255, 255, 255, .3); }
.chat-panel-isi, .chat-panel-daftar {
  flex: 1; overflow-y: auto; background: var(--abu-50);
}
.chat-panel-isi { padding: 1rem; display: flex; flex-direction: column; gap: .55rem; }
.chat-panel-daftar { background: var(--putih); }
.chat-bubble-baris { display: flex; }
.chat-bubble-baris.kanan { justify-content: flex-end; }
.chat-bubble-baris.kiri { justify-content: flex-start; }
.chat-bubble {
  max-width: 82%; background: var(--putih); border: 1px solid var(--abu-200); border-radius: var(--radius);
  padding: .5rem .75rem; box-shadow: 0 1px 2px rgba(15, 23, 42, .04);
}
.chat-bubble.milik-saya { background: var(--biru-700); border-color: var(--biru-700); color: #fff; }
.chat-bubble .isi { white-space: pre-wrap; word-break: break-word; font-size: .87rem; line-height: 1.42; }
.chat-bubble .waktu { margin-top: .2rem; font-size: .66rem; opacity: .7; }
.chat-panel-input {
  flex: 0 0 auto; display: flex; gap: .5rem; align-items: flex-end; padding: .65rem .75rem;
  border-top: 1px solid var(--abu-200); background: var(--putih);
}
.chat-panel-input textarea {
  flex: 1; resize: none; min-height: 38px; max-height: 96px; padding: .5rem .7rem; font-size: .86rem;
  border: 1px solid var(--abu-200); border-radius: var(--radius-sm); font-family: inherit;
  background: var(--putih); color: var(--abu-900);
}
.chat-panel-input textarea:focus { outline: 2px solid var(--biru-500); outline-offset: -1px; }
.chat-panel-input button {
  flex: 0 0 auto; width: 38px; height: 38px; border-radius: var(--radius-sm); border: none; cursor: pointer;
  background: var(--biru-700); color: #fff; display: grid; place-items: center;
}
.chat-panel-input button:hover { background: var(--biru-800); }
.chat-panel-input button:disabled { opacity: .6; cursor: default; }

.chat-daftar-item {
  display: flex; gap: .65rem; align-items: center; width: 100%; padding: .7rem .9rem;
  border: none; border-bottom: 1px solid var(--abu-100); background: none; cursor: pointer; text-align: left; font: inherit;
}
.chat-daftar-item:hover { background: var(--abu-50); }
.chat-daftar-item .isi { min-width: 0; flex: 1; }
.chat-daftar-item .nama { font-weight: 600; font-size: .86rem; color: var(--abu-900); display: flex; gap: .4rem; align-items: center; }
.chat-daftar-item .nama .lencana { background: var(--merah-600); color: #fff; border-radius: 99px; padding: 0 .4rem; font-size: .68rem; }
.chat-daftar-item .pesan { font-size: .78rem; color: var(--abu-500); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ==========================================================================
   Kalender hari libur / riwayat absensi harian
   ========================================================================== */
.legenda-status { display: flex; gap: .9rem; flex-wrap: wrap; font-size: .78rem; color: var(--abu-600); }
.legenda-status span { display: inline-flex; align-items: center; gap: .35rem; }
.legenda-status i { width: 10px; height: 10px; border-radius: 3px; display: inline-block; }
.kalender-grid { border: 1px solid var(--abu-200); border-radius: var(--radius); overflow: hidden; }
.kalender-kepala-hari {
  display: grid; grid-template-columns: repeat(7, 1fr); background: var(--abu-50);
  font-size: .78rem; font-weight: 700; color: var(--abu-500); text-align: center;
}
.kalender-kepala-hari > div { padding: .5rem 0; }
.kalender-badan { display: grid; grid-template-columns: repeat(7, 1fr); }
.kalender-sel {
  aspect-ratio: 1; border: 1px solid var(--abu-100); border-radius: 0; background: var(--putih);
  display: flex; flex-direction: column; align-items: center; justify-content: flex-start;
  gap: .2rem; padding: .35rem .2rem; cursor: pointer; font: inherit; overflow: hidden;
}
.kalender-sel:hover { background: var(--abu-50); }
.kalender-sel.kosong { background: var(--abu-50); cursor: default; border: 1px solid var(--abu-100); }
.kalender-sel .angka { font-size: .82rem; font-weight: 600; color: var(--abu-700); }
.kalender-sel.hari-ini .angka { color: var(--aksen-teks); font-weight: 800; }
/* Sel libur adalah BIDANG selebar sel, bukan lencana — pakai tint permukaan supaya tidak menyala
   sendirian di tengah kalender gelap. Warna angka & nama tetap merah-600 (tidak pernah di-remap). */
.kalender-sel.libur { background: var(--lembut-merah); }
.kalender-sel.libur .angka { color: var(--merah-teks); }
.kalender-sel .nama-libur { font-size: .64rem; line-height: 1.15; color: var(--merah-teks); text-align: center; }
/* Sel kalender jadwal shift: tinggi menyesuaikan isi (bukan kotak kaku) agar kode gabungan
   dobel shift (mis. "PAG+MLM") tetap utuh terlihat, tidak terpotong ellipsis. */
.kalender-sel.sel-jadwal { aspect-ratio: auto; min-height: 64px; overflow: visible; }
.kalender-sel .kode-shift {
  max-width: 100%; font-size: .62rem; padding: .1rem .3rem;
  white-space: normal; word-break: break-word; line-height: 1.2; text-align: center;
}
.sel-jadwal .nama-libur { max-width: 100%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

@media (max-width: 640px) {
  .chat-widget { right: 1rem; bottom: 1rem; }
  /* Di layar sempit panel mengisi seluruh ruang yang tersisa di dalam latar (sudah dikurangi
     padding 1rem), jadi kotak ketik pesan selalu ikut terlihat. */
  .chat-panel { width: 100%; height: 100%; }
  .kalender-sel .nama-libur { display: none; }
}

/* ==========================================================================
   Responsif
   ========================================================================== */
@media (max-width: 1200px) {
  .grid-4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .grid-sisi { grid-template-columns: minmax(0, 1fr); }
}

@media (max-width: 1024px) {
  .sidebar { transform: translateX(-100%); box-shadow: var(--bayang-lg); z-index: 90; }
  .sidebar.buka { transform: none; }
  .tirai { z-index: 85; }
  .wadah-utama { margin-left: 0; }
  .tombol-menu { display: grid; place-items: center; }
  .grid-3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  /* .auth-layar.auth-statis (2 kelas) lebih spesifik dari .auth-layar polos (1 kelas), jadi
     grid-template-columns 2 kolomnya tetap menang tanpa override ini — form Atur Ulang/Lupa
     Sandi jadi terjepit di kolom sempit (~separuh lebar) alih-alih memenuhi layar. */
  .auth-layar.auth-statis { grid-template-columns: 1fr; }
  .auth-panel { display: none; }
  .auth-isi { padding: 2rem 1.25rem; min-height: 100vh; }

  /* .dock-aktif ditandai di <div id="app"> untuk kedua peran (lihat kerangkaAplikasi()) — pada
     lebar mobile ini sidebar+hamburger diganti dock bawah, baik untuk admin maupun karyawan. */
  .dock-bawah { display: flex; }
  .dock-aktif .tombol-menu { display: none; }
  .dock-aktif .isi-halaman { padding-bottom: calc(var(--tinggi-dock) + var(--dock-tepi) + 1rem); }
  /* Tombol chat mengambang tetap tampil di atas dock — chat tidak lagi menjadi item dock. */
  .dock-aktif .chat-widget { bottom: calc(var(--tinggi-dock) + var(--dock-tepi) + .75rem); }
  /* Panel chat kini mengambang di tengah layar (.chat-latar menutupi seluruh viewport, termasuk
     dock) sehingga tidak perlu lagi menyisakan ruang khusus untuk dock di bawahnya seperti dulu. */
}

@media (max-width: 768px) {
  body { font-size: 14.5px; }
  /* Ukuran huruf field input di bawah 16px membuat Safari/Chrome mobile otomatis zoom
     saat fokus (keyboard muncul). Kunci ke 16px hanya di lebar layar ini agar tidak
     mengubah tampilan desktop. */
  .kendali, .chat-panel-input textarea { font-size: 16px; }
  .isi-halaman { padding: 1rem; }
  .dock-aktif .isi-halaman { padding-bottom: calc(var(--tinggi-dock) + var(--dock-tepi) + 1rem); }
  .topbar { padding: .5rem .9rem; }
  .topbar-jam { display: none; }
  .grid-2, .grid-3, .grid-4 { grid-template-columns: minmax(0, 1fr); }
  .baris-form, .baris-form-3 { grid-template-columns: minmax(0, 1fr); }
  .panel-absen { padding: 1.25rem; }
  .panel-absen .jam-besar { font-size: 2.3rem; }
  .bilah-alat { padding: .85rem; }
  .bilah-alat .bidang { min-width: 0; flex: 1 1 100%; }
  /* flex-wrap + min-width (bukan flex:1 kaku) supaya kelompok tombol yang lebih dari 2 buah
     (mis. Terapkan / Pola Rotasi / Reset ke Default di Jadwal Bulanan) turun ke baris baru
     alih-alih dipaksa muat sepertiga lebar layar dan teksnya terpotong. */
  .bilah-alat .kanan { margin-left: 0; width: 100%; flex-wrap: wrap; }
  .bilah-alat .kanan .tbl { flex: 1 1 auto; min-width: 140px; }
  .kartu-kepala { padding: 1rem; }
  .kartu-isi { padding: 1rem; }
  .modal-kaki { flex-direction: column-reverse; }
  .modal-kaki .tbl { width: 100%; }
  .toast-area { top: auto; bottom: 1rem; left: 1rem; right: 1rem; max-width: none; }
  .dock-aktif .toast-area { bottom: calc(var(--tinggi-dock) + var(--dock-tepi) + 1rem); }
}

@media (max-width: 420px) {
  .stat { padding: .9rem; }
  .stat .nilai { font-size: 1.35rem; }
  .aksi-cepat { grid-template-columns: minmax(0, 1fr); }
  .jadwal-tile .j-jam { font-size: 1.3rem; }
  .aksi-ikon { font-size: .72rem; }
  .aksi-ikon .bulat { width: 46px; height: 46px; }
  .kartu-mini-stat { padding: .8rem; gap: .6rem; }
  .kartu-mini-stat .lambang { width: 44px; height: 44px; flex-basis: 44px; }
  .kartu-mini-stat .label { font-size: .88rem; }
}

/* ---- Tur onboarding (spotlight + kartu penjelasan) ---------------------- */
/* pointer-events: auto — sengaja memblokir seluruh interaksi dengan halaman di baliknya selama
   tur berjalan; hanya tombol Lewati/Kembali/Lanjut pada .tur-kartu yang bisa ditekan. */
.tur-overlay { position: fixed; inset: 0; z-index: 1200; pointer-events: auto; }
.tur-sorot {
  position: fixed;
  border-radius: 14px;
  box-shadow: 0 0 0 9999px rgba(15, 23, 42, .62);
  transition: top .25s ease, left .25s ease, width .25s ease, height .25s ease, opacity .2s ease;
  pointer-events: none;
}
.tur-kartu {
  position: fixed;
  width: 320px;
  max-width: calc(100vw - 32px);
  background: var(--putih);
  border-radius: var(--radius-lg);
  box-shadow: var(--bayang-lg);
  padding: 1rem 1.1rem;
  pointer-events: auto;
  transition: top .25s ease, bottom .25s ease, left .25s ease;
  /* Jaring pengaman terakhir: pada layar pendek (ponsel mendatar, papan ketik terbuka) sebuah
     langkah berteks panjang bisa lebih tinggi dari layarnya sendiri, dan tidak ada penempatan yang
     bisa menyelamatkannya. Dengan batas ini kartunya menggulung di dalam dirinya — tombol
     Lanjut/Lewati selalu terjangkau.
     dvh lebih dulu gagal-diam di peramban lama, lalu vh sebagai jatuhan; dvh dipakai karena bilah
     alamat Safari iOS menyusut-memuai dan vh saja akan menyisakan kartu terpotong di baliknya. */
  max-height: calc(100vh - 32px);
  max-height: calc(100dvh - 32px);
  overflow-y: auto;
}
.tur-progres { display: flex; gap: .3rem; margin-bottom: .7rem; }
.tur-progres span { width: 6px; height: 6px; border-radius: 50%; background: var(--abu-200); transition: all .2s ease; }
.tur-progres span.aktif { background: var(--biru-600); width: 16px; border-radius: 4px; }
.tur-kartu h4 { margin: 0 0 .35rem; font-size: .98rem; color: var(--judul); }
.tur-kartu p { margin: 0 0 .9rem; font-size: .85rem; color: var(--abu-600); line-height: 1.45; }
.tur-aksi { display: flex; align-items: center; justify-content: space-between; gap: .6rem; }
.tur-lewati { background: none; border: none; color: var(--abu-500); font-size: .8rem; cursor: pointer; padding: .3rem 0; }
.tur-lewati:hover { color: var(--abu-700); text-decoration: underline; }
.tur-nav { display: flex; gap: .5rem; }

/* ---- Tautan koordinat (Riwayat Absensi Harian) — buka pop-up peta saat diklik ---------------- */
.tautan-koordinat {
  display: inline-flex; align-items: center; gap: .25rem;
  background: none; border: none; padding: 0; cursor: pointer;
  color: var(--biru-600); font-size: inherit; font-variant-numeric: tabular-nums;
  text-decoration: underline; text-decoration-style: dotted; text-underline-offset: 2px;
}
.tautan-koordinat:hover { color: var(--biru-700); }
.tautan-koordinat .ikon-svg { flex: 0 0 auto; }

@media print {
  /* Cetak memakai warna netral di atas kertas putih, apa pun rupa tema di layar.
     Selektor bertema WAJIB ikut disebut: `:root` polos bernilai (0,1,0) dan kalah dari
     `:root[data-tema="…"]` (0,2,0), sehingga aturan di sini tidak akan pernah berlaku kalau hanya
     `:root` yang ditulis. Dengan keduanya disebut, spesifisitasnya menyamai dan posisi blok ini
     yang lebih belakang yang menentukan. */
  :root, :root[data-tema="cerah"] {
    --abu-900: #0f172a; --abu-700: #334155; --abu-600: #475569; --abu-500: #64748b;
    --abu-400: #94a3b8; --abu-300: #cbd5e1; --abu-200: #e2e8f0; --abu-100: #f1f5f9; --abu-50: #f8fafc;
    --putih: #ffffff; --judul: var(--biru-900); --aksen-teks: var(--biru-700);
    --lembut-biru: var(--biru-50); --lembut-biru-kuat: var(--biru-100); --lembut-merah: var(--merah-100);
    --merah-teks: var(--merah-600); --hijau-teks: var(--hijau-700);
  }
  .sidebar, .topbar, .bilah-alat, .tirai, .toast-area, .chat-widget, .chat-latar, .dock-bawah { display: none !important; }
  .wadah-utama { margin-left: 0; }
  .kartu { box-shadow: none; border-color: var(--abu-300); }
  body { background: #fff; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .01ms !important; animation-iteration-count: 1 !important; transition-duration: .01ms !important; }
}

/* ==========================================================================
   Material kaca — cadangan & preferensi aksesibilitas
   --------------------------------------------------------------------------
   Ketiga blok di bawah memulihkan permukaan berkaca menjadi opak. Semuanya memakai daftar selektor
   yang SAMA — .topbar, .dock-bawah, .modal, .toast — plus kedua scrim (.modal-latar, .chat-latar)
   yang cuma perlu blurnya dilepas, bukan latarnya diganti. Permukaan baru yang kelak ikut memakai
   --kaca-* harus ditambahkan ke ketiganya sekaligus, bukan hanya ke satu; kacacek.mjs memeriksa
   justru hal ini, karena lupa di sini tidak terlihat sampai ada pengguna yang menyalakan
   "Kurangi Transparansi".

   Warna teks yang digelapkan (--abu-600, --aksen-pekat, pil --oranye-700 berikon putih) TIDAK ikut
   dikembalikan di sini: semuanya lolos ambang kontras di latar opak maupun di atas kaca, jadi
   membiarkannya satu nilai berarti satu hal lebih sedikit yang bisa meleset.
   ========================================================================== */

/* Peramban tanpa dukungan backdrop-filter sama sekali. Tanpa blok ini permukaannya tampil putih
   85% tembus pandang TANPA blur — konten di baliknya terbaca menembus teks. Scrim tidak perlu
   disebut: tanpa blur ia tetap tirai berwarna yang berfungsi. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .topbar, .dock-bawah, .modal, .toast { background: var(--putih); }
  .topbar { border-bottom-color: var(--abu-200); }
  .dock-bawah { border-color: var(--abu-200); }
  .modal { border-color: var(--abu-200); }
  /* Sisi kiri toast SENGAJA dilewati: itu garis penanda jenis pesan, bukan tepi permukaan.
     `border-color` yang menyapu keempat sisi akan menghapusnya pada varian .info, yang warnanya
     datang dari aturan .toast dasar dengan spesifisitas yang sama seperti blok ini. */
  .toast { border-top-color: var(--abu-200); border-right-color: var(--abu-200); border-bottom-color: var(--abu-200); }
  /* Sama seperti kedua blok di bawah: tanpa blur, dock kembali opak dan halonya tak berguna. */
  .dock-tautan span:not(.ikon) { text-shadow: none; }
  .dock-tautan .ikon-svg { filter: none; }
}

/* iOS/macOS: Aksesibilitas → Kurangi Transparansi. Apple memperlakukan ini sebagai bagian dari
   Liquid Glass, bukan tambahan — pengguna yang menyalakannya memang meminta permukaan yang tenang.
   Scrim ikut kehilangan blur di sini, tapi warnanya dikembalikan lebih pekat supaya pemisahan
   modal dari konten tidak hilang bersama blurnya. */
@media (prefers-reduced-transparency: reduce) {
  .topbar, .dock-bawah, .modal, .toast {
    background: var(--putih);
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }
  .topbar { border-bottom-color: var(--abu-200); }
  .dock-bawah { border-color: var(--abu-200); }
  .modal { border-color: var(--abu-200); }
  /* sisi kiri dilewati — lihat catatan di blok @supports di atas */
  .toast { border-top-color: var(--abu-200); border-right-color: var(--abu-200); border-bottom-color: var(--abu-200); }
  .modal-latar, .chat-latar {
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    background: rgba(15, 37, 87, .62);
  }
  /* Halo dilepas: di atas permukaan opak ia tidak menolong apa pun dan justru mengaburkan
     tepi huruf. Kontras aslinya sudah pulih dari latar putihnya sendiri. */
  .dock-tautan span:not(.ikon) { text-shadow: none; }
  .dock-tautan .ikon-svg { filter: none; }
  .modal-kaki { background: var(--abu-50); }
}

/* Kontras tinggi: selain opak, tepinya ditegaskan supaya batas tiap permukaan terhadap konten
   tidak bergantung pada bayangan yang halus. */
@media (prefers-contrast: more) {
  .topbar, .dock-bawah, .modal, .toast {
    background: var(--putih);
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }
  .topbar { border-bottom-color: var(--abu-400); }
  .dock-bawah { border-color: var(--abu-400); }
  .modal { border-color: var(--abu-400); }
  /* sisi kiri dilewati — lihat catatan di blok @supports di atas */
  .toast { border-top-color: var(--abu-400); border-right-color: var(--abu-400); border-bottom-color: var(--abu-400); }
  .modal-latar, .chat-latar {
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    background: rgba(15, 37, 87, .7);
  }
  /* Halo dilepas: di atas permukaan opak ia tidak menolong apa pun dan justru mengaburkan
     tepi huruf. Kontras aslinya sudah pulih dari latar putihnya sendiri. */
  .dock-tautan span:not(.ikon) { text-shadow: none; }
  .dock-tautan .ikon-svg { filter: none; }
  .modal-kaki { background: var(--abu-50); }
}

/* ==========================================================================
   Dashboard karyawan — susunan khusus tema CERAH
   --------------------------------------------------------------------------
   Seluruh blok ini dikurung :root[data-tema="cerah"] dengan sengaja. Markup-nya hanya digambar
   pada tema cerah (lihat tataCerah() di js/pages/dashboard.js), jadi secara teknis pengurungan
   ini tidak wajib — tetapi tanpa pagar itu, aturan sebanyak ini akan menjadi ranjau bagi siapa pun
   yang kelak memakai ulang kelas .cerah-* di tema lain dan bertanya-tanya kenapa bentuknya ikut
   terbawa. Tema terang & gelap tidak tersentuh satu baris pun oleh blok ini.
   ========================================================================== */

/* ---- Sapaan pembuka ---- */
:root[data-tema="cerah"] .cerah-sapa {
  display: flex; align-items: flex-start; gap: 1rem; flex-wrap: wrap; justify-content: space-between;
}
:root[data-tema="cerah"] .cerah-sapa h2 { font-size: 1.6rem; letter-spacing: -.02em; }
:root[data-tema="cerah"] .cerah-sapa p { margin: .25rem 0 0; color: var(--abu-500); font-size: .92rem; line-height: 1.45; }
:root[data-tema="cerah"] .cerah-sapa-kanan { text-align: right; flex: 0 0 auto; }
:root[data-tema="cerah"] .cerah-sapa-kanan .tanggal { font-weight: 700; color: var(--judul); font-size: .95rem; }
:root[data-tema="cerah"] .cerah-sapa-kanan .perusahaan {
  display: inline-flex; align-items: center; gap: .35rem; margin-top: .2rem;
  color: var(--abu-500); font-size: .85rem;
}

/* ---- Kartu hero absensi ---- */
:root[data-tema="cerah"] .cerah-hero {
  position: relative; overflow: hidden;
  border-radius: 24px; padding: 1.4rem; color: #fff;
  /* Stop tercerahnya #1a5fc4, bukan #2f86f2: seluruh teks di kartu ini putih (sebagian 85%
     opasitas), dan di atas biru yang lebih cerah teks kecilnya tinggal ~3,6:1. */
  background: linear-gradient(145deg, #1a5fc4 0%, #1657bb 45%, #0f4494 100%);
  box-shadow: 0 16px 34px -14px rgba(15, 68, 148, .65);
}
:root[data-tema="cerah"] .cerah-hero-atas { display: flex; gap: 1rem; align-items: flex-start; justify-content: space-between; flex-wrap: wrap; }
:root[data-tema="cerah"] .cerah-hero-jam .l { font-size: .95rem; color: rgba(255, 255, 255, .85); }
:root[data-tema="cerah"] .cerah-hero-jam .jam {
  font-size: 3rem; font-weight: 800; line-height: 1.05; letter-spacing: -.03em;
  font-variant-numeric: tabular-nums;
}
:root[data-tema="cerah"] .cerah-hero-jam .tgl { font-size: .92rem; color: rgba(255, 255, 255, .85); margin-top: .15rem; }

:root[data-tema="cerah"] .cerah-hero-info {
  position: relative; overflow: hidden; flex: 0 1 250px; min-width: 190px;
  /* .10, bukan .16: makin putih latarnya makin turun kontras teks putih di atasnya. */
  background: rgba(255, 255, 255, .10); border-radius: 16px; padding: .8rem .9rem;
}
:root[data-tema="cerah"] .cerah-hero-info .j { font-weight: 700; font-size: 1rem; }
/* Putih penuh: teks sekecil ini di atas kotak semi-transparan hanya 3,6:1 kalau ikut diredupkan. */
:root[data-tema="cerah"] .cerah-hero-info .k { font-size: .82rem; color: #fff; line-height: 1.35; max-width: 22ch; }
/* Ikon peta raksasa sebagai cap air. Ditaruh di bawah teks lewat z-index & dipotong overflow
   kotaknya, jadi ia mengisi sudut kosong tanpa pernah mengganggu keterbacaan. */
:root[data-tema="cerah"] .cerah-hero-pin {
  position: absolute; right: -14px; bottom: -22px; z-index: 0;
  color: rgba(255, 255, 255, .22); pointer-events: none;
}
:root[data-tema="cerah"] .cerah-hero-info > .j,
:root[data-tema="cerah"] .cerah-hero-info > .k { position: relative; z-index: 1; }

/* Baris shift & baris lokasi memakai susunan yang sama persis — "kapan" lalu "di mana", dua
   keterangan sederajat. Jaraknya beda: shift menempel di bawah panel "Siap Absen?" (1.1rem),
   lokasi menyusul lebih rapat (.55rem) supaya keduanya terbaca sebagai satu kelompok. */
:root[data-tema="cerah"] .cerah-hero-shift,
:root[data-tema="cerah"] .cerah-hero-lokasi {
  display: flex; align-items: center; gap: .5rem; flex-wrap: wrap;
  margin-top: 1.1rem; font-size: .88rem;
}
:root[data-tema="cerah"] .cerah-hero-lokasi { margin-top: .55rem; }
:root[data-tema="cerah"] .cerah-hero-shift .bulat {
  width: 26px; height: 26px; flex: 0 0 26px; border-radius: 50%;
  display: grid; place-items: center; background: rgba(255, 255, 255, .2);
}
:root[data-tema="cerah"] .cerah-hero-shift .n { font-weight: 600; }
/* Jam dibedakan dari chip keadaan (.cerah-chip) dengan sengaja: ia DATA, bukan status. Angka
   tabular supaya "08:00 – 17:00" tidak bergoyang lebarnya saat jam berganti. */
/* Latar chip MENGGELAPKAN hero, tidak memutihkannya seperti .cerah-chip di sekitarnya. Chip putih
   .18 mencerahkan biru di baliknya sampai teks putihnya tinggal 4,18:1 pada ujung tercerah gradasi
   — gagal. Menggelapkan justru menambah kontras (7,9:1 pada stop terburuk) sekaligus membuat chip
   terbaca sebagai bidang yang cekung, bukan tempelan terang di atas kartu yang sudah terang. */
:root[data-tema="cerah"] .cerah-hero-shift .jam {
  padding: .25rem .7rem; border-radius: 999px;
  background: rgba(0, 0, 0, .18); border: 1px solid rgba(255, 255, 255, .22);
  font-size: .82rem; font-weight: 700; font-variant-numeric: tabular-nums; white-space: nowrap;
}
:root[data-tema="cerah"] .cerah-hero-shift .jam small {
  font-size: .68em; font-weight: 800; opacity: .85; margin-left: .15rem;
}
:root[data-tema="cerah"] .cerah-hero-lokasi .bulat {
  width: 26px; height: 26px; flex: 0 0 26px; border-radius: 50%;
  display: grid; place-items: center; background: rgba(255, 255, 255, .2);
}
:root[data-tema="cerah"] .cerah-hero-lokasi .n { font-weight: 600; }

:root[data-tema="cerah"] .cerah-chip {
  padding: .25rem .7rem; border-radius: 999px; font-size: .78rem; font-weight: 700; white-space: nowrap;
}
:root[data-tema="cerah"] .cerah-chip.netral { background: rgba(255, 255, 255, .22); color: #fff; }
:root[data-tema="cerah"] .cerah-chip.hijau { background: #10b981; color: #04291d; }
:root[data-tema="cerah"] .cerah-chip.merah { background: #fecdd3; color: #9f1239; }

/* Tombol aksi utama: pil putih selebar kartu. */
:root[data-tema="cerah"] .cerah-hero-aksi {
  display: flex; align-items: center; gap: .9rem; width: 100%;
  margin-top: 1.1rem; padding: .8rem 1rem; border: none; border-radius: 999px;
  background: #fff; color: var(--biru-700); font: inherit; text-align: left; cursor: pointer;
  box-shadow: 0 8px 20px -8px rgba(6, 33, 84, .5);
  transition: transform var(--transisi), box-shadow var(--transisi);
}
:root[data-tema="cerah"] .cerah-hero-aksi:hover:not(:disabled) { transform: translateY(-2px); }
:root[data-tema="cerah"] .cerah-hero-aksi:active:not(:disabled) { transform: scale(.985); }
:root[data-tema="cerah"] .cerah-hero-aksi:disabled { opacity: .78; cursor: not-allowed; box-shadow: none; }
:root[data-tema="cerah"] .cerah-hero-aksi .lambang { flex: 0 0 auto; display: grid; place-items: center; color: #1d6fe0; }
:root[data-tema="cerah"] .cerah-hero-aksi .teks { flex: 1; min-width: 0; }
:root[data-tema="cerah"] .cerah-hero-aksi .teks .j { display: block; font-size: 1.12rem; font-weight: 700; line-height: 1.2; }
/* #475569 dipatok, bukan var(--abu-600): pil ini selalu putih di tema apa pun (ia duduk di atas
   kartu biru, bukan di atas permukaan bertema), jadi warna teksnya tidak boleh ikut token netral. */
:root[data-tema="cerah"] .cerah-hero-aksi .teks .k { display: block; font-size: .8rem; color: #475569; line-height: 1.3; }
:root[data-tema="cerah"] .cerah-hero-aksi .panah {
  flex: 0 0 auto; width: 38px; height: 38px; border-radius: 50%;
  display: grid; place-items: center; background: #1d6fe0; color: #fff;
}
:root[data-tema="cerah"] .cerah-hero-aksi:disabled .panah { background: #94a3b8; }

:root[data-tema="cerah"] .cerah-hero-lembur {
  display: inline-flex; align-items: center; gap: .4rem; margin-top: .7rem;
  padding: .45rem .9rem; border-radius: 999px; cursor: pointer; font: inherit; font-size: .82rem; font-weight: 600;
  background: rgba(255, 255, 255, .16); border: 1px solid rgba(255, 255, 255, .3); color: #fff;
}
:root[data-tema="cerah"] .cerah-hero-lembur:hover:not(:disabled) { background: rgba(255, 255, 255, .26); }
:root[data-tema="cerah"] .cerah-hero-lembur:disabled { opacity: .6; cursor: not-allowed; }

/* ---- Ubin pintasan ---- */
:root[data-tema="cerah"] .cerah-pintasan {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(112px, 1fr)); gap: .7rem;
}
:root[data-tema="cerah"] .cerah-ubin {
  display: flex; flex-direction: column; align-items: center; gap: .55rem;
  padding: 1rem .6rem; border-radius: var(--radius-lg); border: none; cursor: pointer;
  background: color-mix(in srgb, var(--ubin-warna, var(--biru-600)) 10%, var(--putih));
  font: inherit; font-size: .82rem; font-weight: 700; color: var(--abu-900); text-align: center;
  transition: transform var(--transisi), box-shadow var(--transisi);
}
:root[data-tema="cerah"] .cerah-ubin:hover { transform: translateY(-2px); box-shadow: var(--bayang); text-decoration: none; }
:root[data-tema="cerah"] .cerah-ubin .lambang {
  position: relative; width: 46px; height: 46px; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--ubin-kuat, var(--biru-700)); color: #fff;
}
:root[data-tema="cerah"] .cerah-ubin .teks { line-height: 1.25; }
/* Kop baris pintasan: judul di kiri, tombol pengatur sebagai pil kecil di kanan — bentuk yang
   sama dengan .profil-aksi ("Ubah Data") di halaman Profil. */
:root[data-tema="cerah"] .cerah-pintasan-blok { display: grid; gap: .55rem; }
:root[data-tema="cerah"] .cerah-pintasan-kop {
  display: flex; align-items: center; justify-content: space-between; gap: .6rem;
}
:root[data-tema="cerah"] .cerah-pintasan-kop .j { font-weight: 800; font-size: 1rem; color: var(--judul); }
:root[data-tema="cerah"] .cerah-atur {
  flex: 0 0 auto; display: inline-flex; align-items: center; gap: .35rem;
  padding: .4rem .85rem; border-radius: 999px; border: none; cursor: pointer;
  background: var(--lembut-biru); color: var(--aksen-pekat); font: inherit; font-size: .82rem; font-weight: 700;
}
:root[data-tema="cerah"] .cerah-atur:hover { background: var(--lembut-biru-kuat); }

/* ---- Kartu (rekap & linimasa) ---- */
:root[data-tema="cerah"] .cerah-kartu { padding: 1.1rem; }
:root[data-tema="cerah"] .cerah-kartu-kepala { display: flex; align-items: center; gap: .6rem; margin-bottom: .9rem; }
:root[data-tema="cerah"] .cerah-kartu-kepala h3 { font-size: 1.02rem; flex: 1; min-width: 0; }
:root[data-tema="cerah"] .cerah-kartu-kepala .lambang {
  width: 30px; height: 30px; flex: 0 0 30px; border-radius: 9px; display: grid; place-items: center;
  background: color-mix(in srgb, var(--ubin-warna) 16%, var(--putih)); color: var(--ubin-kuat);
}
:root[data-tema="cerah"] .cerah-kartu-kepala .tautan {
  display: inline-flex; align-items: center; gap: .25rem; flex: 0 0 auto;
  font-size: .84rem; font-weight: 600; color: var(--aksen-teks);
}

:root[data-tema="cerah"] .cerah-rekap {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(128px, 1fr)); gap: .6rem;
}
:root[data-tema="cerah"] .cerah-rekap-ubin {
  position: relative; padding: .8rem .9rem; border-radius: var(--radius);
  background: color-mix(in srgb, var(--ubin-warna) 11%, var(--putih));
}
:root[data-tema="cerah"] .cerah-rekap-ubin .nilai {
  font-size: 1.5rem; font-weight: 800; line-height: 1.1; color: var(--ubin-kuat);
  font-variant-numeric: tabular-nums;
}
:root[data-tema="cerah"] .cerah-rekap-ubin .label { font-size: .8rem; font-weight: 600; color: var(--abu-600); margin-top: .1rem; }
:root[data-tema="cerah"] .cerah-rekap-ubin .lambang {
  position: absolute; top: .7rem; right: .7rem;
  width: 26px; height: 26px; border-radius: 50%; display: grid; place-items: center;
  background: var(--ubin-kuat); color: #fff;
}

/* ---- Linimasa hari ini ---- */
:root[data-tema="cerah"] .cerah-linimasa { list-style: none; margin: 0; padding: 0; }
:root[data-tema="cerah"] .cerah-linimasa li {
  position: relative; display: flex; align-items: flex-start; gap: .75rem;
  padding: 0 0 1.1rem 0;
}
:root[data-tema="cerah"] .cerah-linimasa li:last-child { padding-bottom: 0; }
/* Garis penghubung digambar dari titiknya ke bawah, dan dimatikan pada baris terakhir supaya
   tidak menjuntai melewati butir terakhir. */
:root[data-tema="cerah"] .cerah-linimasa li::before {
  content: ''; position: absolute; left: 6px; top: 16px; bottom: 0; width: 2px; background: var(--abu-200);
}
:root[data-tema="cerah"] .cerah-linimasa li:last-child::before { display: none; }
:root[data-tema="cerah"] .cerah-linimasa .titik {
  position: relative; z-index: 1; flex: 0 0 14px; width: 14px; height: 14px; margin-top: 3px;
  border-radius: 50%; background: var(--abu-300);
}
:root[data-tema="cerah"] .cerah-linimasa li.selesai .titik { background: var(--hijau-600); }
:root[data-tema="cerah"] .cerah-linimasa .jam {
  flex: 0 0 auto; min-width: 3.4rem; font-size: .86rem; font-weight: 700;
  color: var(--abu-900); font-variant-numeric: tabular-nums;
}
:root[data-tema="cerah"] .cerah-linimasa li.menunggu .jam { font-weight: 600; color: var(--abu-500); }
:root[data-tema="cerah"] .cerah-linimasa .isi { flex: 1; min-width: 0; display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; }
:root[data-tema="cerah"] .cerah-linimasa .isi .j { font-size: .89rem; font-weight: 700; color: var(--abu-900); }
:root[data-tema="cerah"] .cerah-linimasa li.menunggu .isi .j { font-weight: 500; color: var(--abu-500); }
:root[data-tema="cerah"] .cerah-linimasa .tanda { flex: 0 0 auto; color: var(--abu-400); }

/* ---- Spanduk penutup ---- */
:root[data-tema="cerah"] .cerah-spanduk {
  display: flex; align-items: center; gap: .9rem;
  padding: .9rem 1.1rem; border-radius: var(--radius-lg);
  background: var(--lembut-biru); color: var(--abu-600);
}
:root[data-tema="cerah"] .cerah-spanduk:hover { text-decoration: none; box-shadow: var(--bayang-sm); }
:root[data-tema="cerah"] .cerah-spanduk .lambang { font-size: 2rem; line-height: 1; flex: 0 0 auto; }
:root[data-tema="cerah"] .cerah-spanduk .isi { flex: 1; min-width: 0; }
:root[data-tema="cerah"] .cerah-spanduk .isi .j { display: block; font-weight: 700; color: var(--judul); }
:root[data-tema="cerah"] .cerah-spanduk .isi .k { display: block; font-size: .84rem; line-height: 1.35; }
:root[data-tema="cerah"] .cerah-spanduk .panah { flex: 0 0 auto; color: var(--abu-400); }

@media (max-width: 560px) {
  :root[data-tema="cerah"] .cerah-sapa { flex-direction: column; gap: .5rem; }
  :root[data-tema="cerah"] .cerah-sapa-kanan { text-align: left; }
  :root[data-tema="cerah"] .cerah-sapa h2 { font-size: 1.35rem; }
  :root[data-tema="cerah"] .cerah-hero { padding: 1.1rem; }
  :root[data-tema="cerah"] .cerah-hero-jam .jam { font-size: 2.5rem; }
  :root[data-tema="cerah"] .cerah-hero-info { flex: 1 1 100%; }
  :root[data-tema="cerah"] .cerah-pintasan { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  :root[data-tema="cerah"] .cerah-ubin { padding: .8rem .35rem; font-size: .72rem; }
  :root[data-tema="cerah"] .cerah-ubin .lambang { width: 40px; height: 40px; }
}

/* ==========================================================================
   Halaman Slip Gaji — susunan khusus tema CERAH
   Dikurung [data-tema="cerah"] dengan alasan yang sama seperti blok dashboard di atas.
   ========================================================================== */

/* ---- Kartu puncak ---- */
:root[data-tema="cerah"] .slip-hero {
  display: flex; align-items: center; gap: 1.1rem; flex-wrap: wrap;
  padding: 1.3rem; border-radius: var(--radius-lg);
  background: linear-gradient(135deg, #dbeafe 0%, #eaf3ff 55%, #e3edfd 100%);
  border: 1px solid #cfe0fb;
}
:root[data-tema="cerah"] .slip-hero-gambar {
  flex: 0 0 auto; width: 96px; height: 96px; border-radius: 50%;
  display: grid; place-items: center; color: #2563eb; background: rgba(255, 255, 255, .65);
}
:root[data-tema="cerah"] .slip-hero-isi { flex: 1; min-width: 200px; }
:root[data-tema="cerah"] .slip-hero-isi .l { font-size: .92rem; color: var(--abu-600); }
:root[data-tema="cerah"] .slip-hero-isi .n {
  font-size: 2.1rem; font-weight: 800; letter-spacing: -.03em; line-height: 1.1;
  color: var(--judul); font-variant-numeric: tabular-nums;
}
:root[data-tema="cerah"] .slip-hero-isi .p { font-size: 1rem; font-weight: 600; color: var(--abu-700); margin-top: .1rem; }
/* --abu-600, bukan --abu-500: latarnya gradasi biru muda (bukan kartu putih), dan di stop
   tergelapnya abu-500 tinggal 4,45:1 — meleset tipis dari ambang AA. */
:root[data-tema="cerah"] .slip-hero-isi .k { font-size: .8rem; color: var(--abu-600); margin-top: .35rem; }
:root[data-tema="cerah"] .slip-hero-isi .slip-chip { margin-top: .5rem; }

:root[data-tema="cerah"] .slip-chip {
  display: inline-flex; align-items: center; gap: .3rem;
  padding: .25rem .65rem; border-radius: 999px; font-size: .76rem; font-weight: 700; white-space: nowrap;
}
:root[data-tema="cerah"] .slip-chip.hijau { background: #d1fae5; color: #065f46; }
:root[data-tema="cerah"] .slip-chip.kuning { background: #fef3c7; color: #854d0e; }

/* ---- Kerangka kartu bersama ---- */
:root[data-tema="cerah"] .slip-kartu { padding: 1.1rem; }
:root[data-tema="cerah"] .slip-kartu-kepala { display: flex; align-items: flex-start; gap: .7rem; margin-bottom: 1rem; }
:root[data-tema="cerah"] .slip-kartu-kepala h3 { font-size: 1.02rem; }
:root[data-tema="cerah"] .slip-kartu-kepala .sub { font-size: .82rem; color: var(--abu-500); margin: .1rem 0 0; }
:root[data-tema="cerah"] .slip-kartu-kepala .lambang,
:root[data-tema="cerah"] .slip-periode > .lambang {
  flex: 0 0 36px; width: 36px; height: 36px; border-radius: 11px; display: grid; place-items: center;
  background: color-mix(in srgb, var(--ubin-warna) 16%, var(--putih)); color: var(--ubin-kuat);
}

/* ---- Pemilih periode ---- */
:root[data-tema="cerah"] .slip-periode { display: flex; align-items: center; gap: .7rem; flex-wrap: wrap; }
:root[data-tema="cerah"] .slip-periode .isi { flex: 1; min-width: 160px; }
:root[data-tema="cerah"] .slip-periode .isi h3 { font-size: 1.02rem; }
:root[data-tema="cerah"] .slip-periode .isi .sub { font-size: .82rem; color: var(--abu-500); margin: .1rem 0 0; }
:root[data-tema="cerah"] .slip-periode .pilih { display: flex; gap: .5rem; flex: 0 0 auto; }
:root[data-tema="cerah"] .slip-periode .pilih .kendali { width: auto; min-width: 108px; font-weight: 600; }

/* ---- Rincian dua kolom ---- */
:root[data-tema="cerah"] .slip-dua-kolom {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .9rem;
}
:root[data-tema="cerah"] .slip-kolom { min-width: 0; }
:root[data-tema="cerah"] .slip-kolom .kepala {
  display: flex; align-items: center; gap: .5rem;
  padding: .5rem .7rem; border-radius: var(--radius-sm); margin-bottom: .5rem;
}
:root[data-tema="cerah"] .slip-kolom .kepala .bulat {
  width: 22px; height: 22px; flex: 0 0 22px; border-radius: 50%;
  display: grid; place-items: center; color: #fff;
}
:root[data-tema="cerah"] .slip-kolom .kepala .j { font-weight: 700; font-size: .9rem; }
:root[data-tema="cerah"] .slip-kolom-masuk .kepala { background: #e6f7ee; }
:root[data-tema="cerah"] .slip-kolom-masuk .kepala .bulat { background: var(--hijau-700); }
:root[data-tema="cerah"] .slip-kolom-masuk .kepala .j { color: var(--hijau-700); }
:root[data-tema="cerah"] .slip-kolom-keluar .kepala { background: #fdeaea; }
:root[data-tema="cerah"] .slip-kolom-keluar .kepala .bulat { background: #be123c; }
:root[data-tema="cerah"] .slip-kolom-keluar .kepala .j { color: #be123c; }

:root[data-tema="cerah"] .slip-baris { list-style: none; margin: 0; padding: 0; }
:root[data-tema="cerah"] .slip-baris li {
  display: flex; justify-content: space-between; gap: .6rem; padding: .32rem .2rem; font-size: .85rem;
}
:root[data-tema="cerah"] .slip-baris .k { color: var(--abu-600); min-width: 0; }
:root[data-tema="cerah"] .slip-baris .v { font-weight: 600; color: var(--abu-900); white-space: nowrap; font-variant-numeric: tabular-nums; }
:root[data-tema="cerah"] .slip-baris .kosong .k,
:root[data-tema="cerah"] .slip-baris .kosong .v { color: var(--abu-400); font-weight: 500; }
:root[data-tema="cerah"] .slip-kolom .total {
  display: flex; justify-content: space-between; gap: .6rem; align-items: baseline;
  margin-top: .45rem; padding-top: .5rem; border-top: 1px solid var(--abu-200);
  font-weight: 700; font-size: .88rem;
}
:root[data-tema="cerah"] .slip-kolom .total .v { white-space: nowrap; font-variant-numeric: tabular-nums; }
:root[data-tema="cerah"] .slip-kolom-masuk .total { color: var(--hijau-700); }
:root[data-tema="cerah"] .slip-kolom-keluar .total { color: #be123c; }

:root[data-tema="cerah"] .slip-bersih {
  display: flex; align-items: center; gap: .8rem; flex-wrap: wrap;
  margin-top: 1rem; padding: .9rem 1rem; border-radius: var(--radius);
  background: var(--lembut-biru);
}
:root[data-tema="cerah"] .slip-bersih .lambang {
  width: 34px; height: 34px; flex: 0 0 34px; border-radius: 10px; display: grid; place-items: center;
  background: var(--putih); color: var(--aksen-teks);
}
:root[data-tema="cerah"] .slip-bersih .isi { flex: 1; min-width: 140px; }
:root[data-tema="cerah"] .slip-bersih .isi .j { display: block; font-weight: 700; color: var(--judul); }
:root[data-tema="cerah"] .slip-bersih .isi .k { display: block; font-size: .79rem; color: var(--abu-500); }
:root[data-tema="cerah"] .slip-bersih .n {
  font-size: 1.4rem; font-weight: 800; color: var(--aksen-teks);
  white-space: nowrap; font-variant-numeric: tabular-nums;
}

/* ---- Riwayat ---- */
/*
 * Tombol unduh slip periode terpilih. Menggantikan daftar riwayat yang sebelumnya menempati ruang
 * ini — dulu satu-satunya jalan mengunduh dari halaman ini adalah ikon kecil pada tiap baris
 * riwayat, sehingga slip periode yang SEDANG dibuka justru tidak punya tombolnya sendiri.
 *
 * Lebar penuh dan bergaya tombol utama karena inilah satu-satunya aksi di halaman ini; keadaan
 * matinya dibuat jelas terlihat, sebab tombol ini memang mati selama slipnya belum termuat.
 */
:root[data-tema="cerah"] .slip-unduh {
  display: flex; align-items: center; justify-content: center; gap: .5rem;
  width: 100%; padding: .85rem 1rem; border: none; border-radius: var(--radius-lg); cursor: pointer;
  background: var(--biru-700); color: #fff; font: inherit; font-weight: 700; font-size: .95rem;
  box-shadow: var(--bayang);
  transition: background var(--transisi), transform var(--transisi);
}
:root[data-tema="cerah"] .slip-unduh:hover:not(:disabled) { background: var(--biru-800); }
:root[data-tema="cerah"] .slip-unduh:active:not(:disabled) { transform: scale(.99); }
:root[data-tema="cerah"] .slip-unduh:disabled {
  background: var(--abu-200); color: var(--abu-500); cursor: not-allowed; box-shadow: none;
}

/* ---- Spanduk informasi ---- */
:root[data-tema="cerah"] .slip-info {
  display: flex; align-items: flex-start; gap: .8rem;
  padding: .9rem 1.1rem; border-radius: var(--radius-lg); background: var(--lembut-biru);
}
:root[data-tema="cerah"] .slip-info .lambang {
  width: 30px; height: 30px; flex: 0 0 30px; border-radius: 50%; display: grid; place-items: center;
  background: var(--aksen-teks); color: #fff;
}
:root[data-tema="cerah"] .slip-info .isi .j { display: block; font-weight: 700; color: var(--judul); }
:root[data-tema="cerah"] .slip-info .isi .k { display: block; font-size: .84rem; line-height: 1.4; color: var(--abu-600); }

@media (max-width: 620px) {
  /* Dua kolom pada layar sempit membuat nominal terpotong di tengah angka — ditumpuk saja. */
  :root[data-tema="cerah"] .slip-dua-kolom { grid-template-columns: minmax(0, 1fr); }
  :root[data-tema="cerah"] .slip-periode .pilih { width: 100%; }
  :root[data-tema="cerah"] .slip-periode .pilih .kendali { flex: 1; min-width: 0; }
  :root[data-tema="cerah"] .slip-hero-gambar { width: 64px; height: 64px; }
  :root[data-tema="cerah"] .slip-hero-isi .n { font-size: 1.75rem; }
}

/* ==========================================================================
   Halaman Profil — susunan khusus tema CERAH
   ========================================================================== */

/* ---- Kartu puncak ---- */
:root[data-tema="cerah"] .profil-hero {
  display: flex; align-items: center; gap: 1.2rem; flex-wrap: wrap;
  padding: 1.3rem; border-radius: var(--radius-lg);
  background: linear-gradient(135deg, #dbeafe 0%, #eaf3ff 55%, #e3edfd 100%);
  border: 1px solid #cfe0fb;
}
:root[data-tema="cerah"] .profil-hero-foto { position: relative; flex: 0 0 auto; }
:root[data-tema="cerah"] .profil-hero-foto .avatar {
  width: 104px; height: 104px; flex-basis: 104px; font-size: 2rem;
  border: 4px solid #fff; box-shadow: var(--bayang);
}
/* Tombol kamera menumpang <label for="foto">, bukan <button>: itu membuat satu-satunya cara
   membuka pemilih berkas tetap milik input aslinya, sehingga penangan #foto di halamanProfil()
   berlaku apa adanya tanpa kode tambahan. */
:root[data-tema="cerah"] .profil-kamera {
  position: absolute; right: 0; bottom: 4px;
  width: 34px; height: 34px; border-radius: 50%; cursor: pointer;
  display: grid; place-items: center;
  background: var(--biru-600); color: #fff; border: 3px solid #fff;
  box-shadow: var(--bayang-sm); transition: background var(--transisi);
}
:root[data-tema="cerah"] .profil-kamera:hover { background: var(--biru-700); }
:root[data-tema="cerah"] .profil-kamera input { display: none; }

:root[data-tema="cerah"] .profil-hero-isi { flex: 1 1 200px; min-width: 0; }
:root[data-tema="cerah"] .profil-hero-isi h2 { font-size: 1.5rem; letter-spacing: -.02em; }
:root[data-tema="cerah"] .profil-hero-isi .peran { color: var(--abu-600); font-size: .92rem; }
:root[data-tema="cerah"] .profil-hero-isi .l { margin-top: .6rem; font-size: .82rem; color: var(--abu-600); }
:root[data-tema="cerah"] .profil-hero-isi .id-baris { display: flex; align-items: center; gap: .5rem; }
:root[data-tema="cerah"] .profil-hero-isi .nip {
  font-weight: 700; font-size: 1.05rem; color: var(--judul); font-variant-numeric: tabular-nums;
}
:root[data-tema="cerah"] .profil-salin {
  width: 30px; height: 30px; flex: 0 0 30px; border-radius: 9px; cursor: pointer;
  display: grid; place-items: center;
  background: var(--putih); border: 1px solid var(--abu-200); color: var(--aksen-teks);
}
:root[data-tema="cerah"] .profil-salin:hover { background: var(--lembut-biru); }

:root[data-tema="cerah"] .profil-chip {
  display: inline-flex; align-items: center; gap: .4rem; margin-top: .55rem;
  padding: .28rem .75rem; border-radius: 999px; font-size: .8rem; font-weight: 700; white-space: nowrap;
}
:root[data-tema="cerah"] .profil-chip .titik { width: 8px; height: 8px; border-radius: 50%; background: currentColor; }
:root[data-tema="cerah"] .profil-chip.polos { margin-top: 0; }
:root[data-tema="cerah"] .profil-chip.hijau { background: #d1fae5; color: #065f46; }
:root[data-tema="cerah"] .profil-chip.kuning { background: #fef3c7; color: #854d0e; }
:root[data-tema="cerah"] .profil-chip.abu { background: var(--abu-100); color: var(--abu-600); }

:root[data-tema="cerah"] .profil-kutipan {
  position: relative; flex: 0 1 300px; min-width: 170px;
  padding: .9rem 1rem; border-radius: var(--radius);
  background: rgba(255, 255, 255, .55); border: 1px solid rgba(255, 255, 255, .9);
}
:root[data-tema="cerah"] .profil-kutipan .tanda {
  font-size: 1.8rem; line-height: 1; color: var(--aksen-teks); font-weight: 800;
}
:root[data-tema="cerah"] .profil-kutipan p {
  margin: .1rem 0 0; font-style: italic; font-weight: 600; font-size: .92rem;
  line-height: 1.35; color: var(--judul);
}

/* ---- Tab ---- */
:root[data-tema="cerah"] .profil-tab {
  background: var(--putih); border: 1px solid var(--abu-200); border-radius: var(--radius-lg);
  padding: .3rem; gap: .2rem; box-shadow: var(--bayang-sm);
}
:root[data-tema="cerah"] .profil-tab button {
  flex: 1; display: flex; flex-direction: column; align-items: center; gap: .25rem;
  padding: .6rem .4rem; border-radius: var(--radius); border-bottom: none;
  font-size: .8rem; white-space: nowrap;
}
:root[data-tema="cerah"] .profil-tab button.aktif { background: var(--lembut-biru); color: var(--aksen-pekat); }

/* ---- Kartu ---- */
:root[data-tema="cerah"] .profil-kartu { padding: 1.1rem; }
:root[data-tema="cerah"] .profil-kartu-kepala {
  display: flex; align-items: flex-start; gap: .7rem; flex-wrap: wrap; margin-bottom: .9rem;
}
:root[data-tema="cerah"] .profil-kartu-kepala .isi { flex: 1; min-width: 140px; }
:root[data-tema="cerah"] .profil-kartu-kepala h3 { font-size: 1.02rem; }
:root[data-tema="cerah"] .profil-kartu-kepala .sub { font-size: .82rem; color: var(--abu-500); margin: .1rem 0 0; }
:root[data-tema="cerah"] .profil-kartu-kepala .lambang {
  flex: 0 0 36px; width: 36px; height: 36px; border-radius: 11px; display: grid; place-items: center;
  background: var(--ubin-kuat); color: #fff;
}
:root[data-tema="cerah"] .profil-aksi {
  flex: 0 0 auto; display: inline-flex; align-items: center; gap: .35rem;
  padding: .45rem .9rem; border-radius: 999px; border: none; cursor: pointer;
  background: var(--lembut-biru); color: var(--aksen-pekat); font: inherit; font-size: .84rem; font-weight: 700;
}
:root[data-tema="cerah"] .profil-aksi:hover { background: var(--lembut-biru-kuat); }
:root[data-tema="cerah"] .profil-versi {
  flex: 0 0 auto; padding: .4rem .85rem; border-radius: 999px;
  background: var(--lembut-biru); color: var(--aksen-pekat); font-size: .82rem; font-weight: 700;
}

/* ---- Daftar baris data ---- */
:root[data-tema="cerah"] .profil-baris { list-style: none; margin: 0; padding: 0; }
:root[data-tema="cerah"] .profil-baris li {
  display: flex; align-items: center; gap: .7rem; padding: .55rem 0; font-size: .9rem;
}
:root[data-tema="cerah"] .profil-baris li + li { border-top: 1px solid var(--abu-100); }
/* --abu-500, bukan --abu-400: ikon penanda jenis kolom masih membawa makna, dan abu-400 di atas
   kartu putih hanya 2,40:1 — di bawah ambang 3:1 untuk elemen non-teks. */
:root[data-tema="cerah"] .profil-baris .ikon { flex: 0 0 20px; display: grid; place-items: center; color: var(--abu-500); }
:root[data-tema="cerah"] .profil-baris .k { flex: 0 0 40%; max-width: 190px; color: var(--abu-500); }
:root[data-tema="cerah"] .profil-baris .v { flex: 1; min-width: 0; font-weight: 600; color: var(--abu-900); overflow-wrap: anywhere; }

/* ---- Tentang aplikasi ---- */
:root[data-tema="cerah"] .profil-tentang { display: flex; align-items: center; gap: .8rem; }
:root[data-tema="cerah"] .profil-tentang .lambang {
  width: 38px; height: 38px; flex: 0 0 38px; border-radius: 11px; display: grid; place-items: center;
  background: var(--lembut-biru); color: var(--aksen-teks);
}
:root[data-tema="cerah"] .profil-tentang .isi .j { display: block; font-weight: 700; color: var(--judul); }
:root[data-tema="cerah"] .profil-tentang .isi .k { display: block; font-size: .84rem; color: var(--abu-500); }

/* ---- Keluar ---- */
:root[data-tema="cerah"] .profil-keluar {
  display: flex; align-items: center; justify-content: center; gap: .5rem; width: 100%;
  padding: .9rem 1rem; border-radius: var(--radius-lg); cursor: pointer;
  background: #fdeaea; border: 1px solid #fbd0d0; color: #be123c;
  font: inherit; font-size: .95rem; font-weight: 700;
  transition: background var(--transisi);
}
:root[data-tema="cerah"] .profil-keluar:hover { background: #fbd5d5; }

@media (max-width: 620px) {
  :root[data-tema="cerah"] .profil-hero { justify-content: center; text-align: center; }
  :root[data-tema="cerah"] .profil-hero-isi { text-align: left; }
  :root[data-tema="cerah"] .profil-kutipan { flex: 1 1 100%; }
  :root[data-tema="cerah"] .profil-tab button span:not(.ikon-svg) { font-size: .72rem; }
  :root[data-tema="cerah"] .profil-baris li { flex-wrap: wrap; }
  :root[data-tema="cerah"] .profil-baris .k { flex: 0 0 auto; }
  :root[data-tema="cerah"] .profil-baris .v { flex: 1 1 100%; margin-left: 1.7rem; }
}

/* ==========================================================================
   Riwayat & Rekap Absensi — susunan khusus tema CERAH
   ========================================================================== */

/* ---- Kartu puncak ---- */
:root[data-tema="cerah"] .rekap-hero {
  display: flex; align-items: center; gap: 1.1rem; flex-wrap: wrap;
  padding: 1.1rem; border-radius: var(--radius-lg);
  background: linear-gradient(135deg, #dbeafe 0%, #eaf3ff 55%, #e3edfd 100%);
  border: 1px solid #cfe0fb;
}
:root[data-tema="cerah"] .rekap-hero-kiri { display: flex; align-items: center; gap: .9rem; flex: 0 1 auto; }
:root[data-tema="cerah"] .rekap-hero-kiri .lambang {
  width: 72px; height: 72px; flex: 0 0 72px; border-radius: 18px; display: grid; place-items: center;
  background: rgba(255, 255, 255, .7); color: #2563eb;
}
:root[data-tema="cerah"] .rekap-hero-kiri .l { font-size: .88rem; color: var(--abu-600); }
:root[data-tema="cerah"] .rekap-hero-kiri .n {
  font-size: 1.75rem; font-weight: 800; letter-spacing: -.02em; line-height: 1.15; color: var(--judul);
}
:root[data-tema="cerah"] .rekap-hero-kiri .k { font-size: .8rem; color: var(--abu-600); }

:root[data-tema="cerah"] .rekap-hero-angka {
  /* auto-fit, bukan angka tetap: jumlah statusnya bertambah (kini tujuh dengan dinas & cuti),
     dan kolom yang dipatok akan memotong angka begitu ada status baru ditambahkan. */
  flex: 1 1 320px; display: grid; grid-template-columns: repeat(auto-fit, minmax(62px, 1fr));
  background: var(--putih); border-radius: var(--radius); padding: .6rem .3rem;
}
:root[data-tema="cerah"] .rekap-hero-angka .butir {
  display: flex; flex-direction: column; align-items: center; gap: .2rem; padding: 0 .2rem; min-width: 0;
}
:root[data-tema="cerah"] .rekap-hero-angka .butir + .butir { border-left: 1px solid var(--abu-100); }
:root[data-tema="cerah"] .rekap-hero-angka .bulat {
  width: 26px; height: 26px; border-radius: 50%; display: grid; place-items: center;
  background: var(--ubin-kuat); color: #fff;
}
:root[data-tema="cerah"] .rekap-hero-angka .l {
  font-size: .7rem; color: var(--abu-500); text-align: center; line-height: 1.2;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100%;
}
:root[data-tema="cerah"] .rekap-hero-angka .v {
  font-size: 1.05rem; font-weight: 800; color: var(--ubin-kuat); font-variant-numeric: tabular-nums;
}

/* ---- Kartu & navigasi bulan ---- */
:root[data-tema="cerah"] .rekap-kartu { padding: 1.1rem; }
:root[data-tema="cerah"] .rekap-nav {
  display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; margin-bottom: .9rem;
}
:root[data-tema="cerah"] .rekap-nav .judul {
  flex: 1; text-align: center; font-weight: 800; font-size: 1.1rem; color: var(--judul); min-width: 130px;
}
:root[data-tema="cerah"] .rekap-nav-tbl {
  width: 38px; height: 38px; flex: 0 0 38px; border-radius: var(--radius); border: none; cursor: pointer;
  display: grid; place-items: center; background: var(--lembut-biru); color: var(--aksen-pekat);
}
:root[data-tema="cerah"] .rekap-nav-tbl:hover { background: var(--lembut-biru-kuat); }
/* Panah kiri memakai ikon panah kanan yang dibalik — satu ikon melayani dua arah. */
:root[data-tema="cerah"] #bln-mundur { transform: scaleX(-1); }
:root[data-tema="cerah"] .rekap-hari-ini {
  flex: 0 0 auto; padding: .5rem 1rem; border-radius: var(--radius); border: none; cursor: pointer;
  background: var(--lembut-biru); color: var(--aksen-pekat); font: inherit; font-size: .85rem; font-weight: 700;
}
:root[data-tema="cerah"] .rekap-hari-ini:hover { background: var(--lembut-biru-kuat); }

/* ---- Kisi kalender ---- */
:root[data-tema="cerah"] .rekap-kepala-hari {
  display: grid; grid-template-columns: repeat(7, minmax(0, 1fr));
  font-size: .78rem; font-weight: 600; color: var(--abu-500); text-align: center; margin-bottom: .3rem;
}
:root[data-tema="cerah"] .rekap-badan { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: .15rem; }
:root[data-tema="cerah"] .rekap-sel {
  aspect-ratio: 1; display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: .2rem; border: none; background: none; border-radius: var(--radius); cursor: pointer; font: inherit;
  transition: background var(--transisi);
}
:root[data-tema="cerah"] .rekap-sel.kosong { cursor: default; }
:root[data-tema="cerah"] .rekap-sel .angka { font-size: .95rem; font-weight: 600; color: var(--abu-900); line-height: 1; }
/* Titik selalu memakan ruang meski tidak berwarna, supaya angka tanggal pada baris yang sama
   tetap sejajar — tanpa ini tanggal bertitik dan tanpa titik saling bergeser naik-turun. */
:root[data-tema="cerah"] .rekap-sel .titik { width: 7px; height: 7px; border-radius: 50%; background: transparent; }
:root[data-tema="cerah"] .rekap-sel:hover:not(.kosong) { background: var(--lembut-biru); }
/* --abu-500, bukan --abu-400: tanggal libur & yang belum terjadi memang sengaja diredupkan,
   tetapi tetap angka yang harus terbaca — abu-400 di atas kartu putih hanya 2,40:1. */
:root[data-tema="cerah"] .rekap-sel.redup .angka { color: var(--abu-500); font-weight: 500; }
:root[data-tema="cerah"] .rekap-sel.hari-ini .angka { color: var(--aksen-pekat); font-weight: 800; }
:root[data-tema="cerah"] .rekap-sel.dipilih { background: var(--biru-600); }
:root[data-tema="cerah"] .rekap-sel.dipilih .angka { color: #fff; font-weight: 800; }

:root[data-tema="cerah"] .rekap-legenda {
  display: flex; justify-content: center; gap: .9rem; flex-wrap: wrap;
  margin-top: .9rem; padding-top: .9rem; border-top: 1px solid var(--abu-100);
  font-size: .78rem; color: var(--abu-600);
}

/* ---- Kalender berdampingan dengan detail & rekap bulanan ------------------
   Di layar sempit keduanya sekadar tumpukan biasa dengan jarak yang sama seperti .tumpuk, jadi
   susunan lamanya tidak berubah sama sekali. */
:root[data-tema="cerah"] .rekap-kolom,
:root[data-tema="cerah"] .rekap-sisi {
  display: grid; gap: 1rem; grid-template-columns: minmax(0, 1fr);
  align-content: start;
}
/* Kotak detail baru terisi sesudah sebuah tanggal dipilih. Selama masih kosong ia tetap memakan
   satu jarak kisi dan menyisakan lubang di atas Rekap Bulanan. */
:root[data-tema="cerah"] #rekap-detail:empty { display: none; }

/*
 * Kotak Rekap Bulan Ini & Tren 4 Bulan: berdampingan begitu ruangnya cukup, menumpuk bila tidak.
 *
 * auto-fit + minmax, BUKAN media query berambang tetap. Kedua kotak ini tinggal di dalam kolom
 * samping yang lebarnya sendiri bergantung pada lebar jendela, lebar sidebar, dan apakah susunan
 * dua kolom sedang berlaku — satu angka ambang tidak akan pernah benar untuk semua gabungan itu.
 * Dengan minmax, keduanya berdampingan tepat ketika masing-masing kebagian ≥260px dan jatuh
 * menumpuk dengan sendirinya begitu tidak.
 */
:root[data-tema="cerah"] .rekap-grafik {
  display: grid; gap: 1rem;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  align-items: start;
}
/* Donat dikecilkan lewat parameter ukuran di rekap.js; batas ini menjaga agar ia tidak melar
   memenuhi kotak yang kebetulan lebar dan membuat kedua kotak jadi timpang tingginya. */
:root[data-tema="cerah"] .rekap-grafik .grafik { max-height: 200px; }
/* Legenda dirapatkan: di kotak selebar ~280px, jarak 1rem bawaannya memecah tujuh status
   menjadi terlalu banyak baris. */
:root[data-tema="cerah"] .rekap-grafik .legenda { gap: .5rem .8rem; font-size: .76rem; margin-top: .7rem; }

/*
 * Sel kalender ber-aspect-ratio 1 pada kisi tujuh kolom: lebarnya mengikuti lebar wadahnya, dan
 * tingginya mengikuti lebarnya. Tanpa batas ini, kalender selebar 850px menghasilkan sel 120px dan
 * kalender setinggi hampir seribu piksel. Batasnya disetel supaya ukuran selnya kurang lebih sama
 * seperti di ponsel — di sanalah ukuran itu memang dirancang.
 */
@media (min-width: 640px) {
  /* 420px, bukan 360px seperti kolom kalender di PC: pada lebar menengah kartunya masih membentang
     penuh, dan kalender 360px yang terpusat di dalamnya menyisakan kartu yang terlihat kosong.
     Di ≥1024px batas ini tidak lagi berlaku — kolomnya sendiri sudah selebar kalendernya. */
  :root[data-tema="cerah"] .rekap-kepala-hari,
  :root[data-tema="cerah"] .rekap-badan {
    max-width: 420px; margin-inline: auto;
  }
}

/*
 * 1024px: ambang yang sama dengan munculnya sidebar (lihat .dock-aktif). Di bawah itu ruang mendatar
 * sudah habis dipakai kalender sendiri, dan memaksa dua kolom hanya akan menyempitkan kotak detail
 * sampai tabelnya tidak terbaca.
 */
@media (min-width: 1024px) {
  :root[data-tema="cerah"] .rekap-kolom {
    grid-template-columns: minmax(0, 360px) minmax(0, 1fr);
    align-items: start;
  }
  /* Kalender tidak lagi perlu dipusatkan: kolomnya sendiri sudah selebar kalendernya. */
  :root[data-tema="cerah"] .rekap-kolom .rekap-kepala-hari,
  :root[data-tema="cerah"] .rekap-kolom .rekap-badan { max-width: none; margin-inline: 0; }
}
:root[data-tema="cerah"] .rekap-legenda span { display: inline-flex; align-items: center; gap: .35rem; }
:root[data-tema="cerah"] .rekap-legenda i { width: 9px; height: 9px; border-radius: 50%; display: inline-block; }
:root[data-tema="cerah"] .rekap-unduh { display: flex; gap: .5rem; justify-content: center; margin-top: .8rem; }

/* ---- Detail satu tanggal ---- */
:root[data-tema="cerah"] .rekap-detail-kepala {
  display: flex; align-items: center; gap: .8rem; flex-wrap: wrap; margin-bottom: .9rem;
}
:root[data-tema="cerah"] .rekap-detail-tgl {
  flex: 0 0 auto; display: flex; flex-direction: column; align-items: center; justify-content: center;
  min-width: 74px; padding: .5rem .7rem; border-radius: var(--radius); background: var(--lembut-biru);
}
:root[data-tema="cerah"] .rekap-detail-tgl .hari { font-size: .74rem; color: var(--abu-600); }
:root[data-tema="cerah"] .rekap-detail-tgl .angka { font-size: 1.5rem; font-weight: 800; line-height: 1.1; color: var(--judul); }
:root[data-tema="cerah"] .rekap-detail-tgl .bln { font-size: .74rem; color: var(--abu-600); }
:root[data-tema="cerah"] .rekap-detail-kepala .isi { flex: 1; min-width: 150px; }
:root[data-tema="cerah"] .rekap-detail-kepala h3 { font-size: 1.02rem; }
:root[data-tema="cerah"] .rekap-detail-kepala .sub { font-size: .82rem; color: var(--abu-500); margin: .1rem 0 0; }

:root[data-tema="cerah"] .rekap-chip {
  flex: 0 0 auto; display: inline-flex; align-items: center; gap: .3rem;
  padding: .3rem .8rem; border-radius: 999px; font-size: .8rem; font-weight: 700; white-space: nowrap;
}
:root[data-tema="cerah"] .rekap-chip.hijau { background: #d1fae5; color: #065f46; }
:root[data-tema="cerah"] .rekap-chip.oranye { background: #fef3c7; color: #854d0e; }
:root[data-tema="cerah"] .rekap-chip.biru { background: var(--lembut-biru); color: var(--aksen-pekat); }
:root[data-tema="cerah"] .rekap-chip.merah { background: #fee2e2; color: #991b1b; }
:root[data-tema="cerah"] .rekap-chip.abu { background: var(--abu-100); color: var(--abu-600); }

:root[data-tema="cerah"] .rekap-detail-blok {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: .7rem;
}
:root[data-tema="cerah"] .rekap-blok {
  display: flex; gap: .7rem; padding: .8rem; border-radius: var(--radius);
  border: 1px solid var(--abu-200); background: var(--putih);
}
:root[data-tema="cerah"] .rekap-blok .lambang {
  width: 34px; height: 34px; flex: 0 0 34px; border-radius: 10px; display: grid; place-items: center;
}
:root[data-tema="cerah"] .rekap-blok-masuk .lambang { background: #d1fae5; color: #065f46; }
:root[data-tema="cerah"] .rekap-blok-pulang .lambang { background: var(--lembut-biru); color: var(--aksen-pekat); }
:root[data-tema="cerah"] .rekap-blok .isi { flex: 1; min-width: 0; }
:root[data-tema="cerah"] .rekap-blok .l { font-size: .82rem; color: var(--abu-500); }
:root[data-tema="cerah"] .rekap-blok .baris-jam { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; }
:root[data-tema="cerah"] .rekap-blok .jam {
  font-size: 1.25rem; font-weight: 800; color: var(--abu-900); font-variant-numeric: tabular-nums;
}
/*
 * Baris bukti: foto wajah di kiri, keterangan lokasi di kanan.
 *
 * align-items: flex-start, bukan center — nama lokasi bisa membungkus dua baris, dan foto yang
 * dipusatkan terhadapnya akan melayang turun menjauh dari jam absennya.
 */
:root[data-tema="cerah"] .rekap-bukti {
  display: flex; align-items: flex-start; gap: .6rem; margin-top: .5rem;
}
/* Foto tidak ikut menyusut saat nama lokasinya panjang. */
:root[data-tema="cerah"] .rekap-bukti .tautan-foto-wajah { flex: 0 0 auto; }
/* Keterangan lokasi mengisi sisa lebar; margin kirinya dinolkan karena tombol lokasi punya
   margin negatif untuk merapat ke tepi kartu — di sini ia tidak lagi berada di tepi. */
:root[data-tema="cerah"] .rekap-bukti .lokasi { flex: 1; min-width: 0; margin-left: 0; }

:root[data-tema="cerah"] .rekap-blok .lokasi {
  display: flex; gap: .35rem; margin-top: .4rem; font-size: .78rem; color: var(--abu-600); line-height: 1.35;
}
:root[data-tema="cerah"] .rekap-blok .lokasi .ikon { flex: 0 0 auto; color: var(--abu-400); margin-top: 1px; }
:root[data-tema="cerah"] .rekap-blok .lokasi .teks { flex: 1; min-width: 0; }
:root[data-tema="cerah"] .rekap-blok .lokasi .jarak { color: var(--abu-500); }

/*
 * Baris lokasi yang PUNYA koordinat menjadi tombol pembuka peta.
 *
 * Digambar sebagai <button> agar dapat difokus papan ketik dan terbaca sebagai kontrol oleh
 * pembaca layar — bukan <div> ber-onclick. Sebaliknya, baris tanpa koordinat tetap <div> biasa:
 * absensi lama, absensi lewat mesin, dan absensi saat pembatasan area dimatikan bisa tercatat
 * tanpa titik sama sekali, dan menampilkannya seolah dapat ditekan berarti menjanjikan peta yang
 * tidak akan pernah terbuka.
 *
 * text-align kiri disetel eksplisit: tombol memusatkan teksnya secara bawaan, dan tanpa ini nama
 * lokasi yang membungkus ke baris kedua terbaca miring sendiri di tengah.
 */
:root[data-tema="cerah"] .rekap-lokasi {
  width: 100%; padding: .35rem .45rem; margin-left: -.45rem;
  border: none; border-radius: var(--radius-sm); background: none;
  font: inherit; font-size: .78rem; color: var(--abu-600); text-align: left; cursor: pointer;
  align-items: flex-start;
  transition: background var(--transisi);
}
:root[data-tema="cerah"] .rekap-lokasi:hover { background: var(--lembut-biru); }
:root[data-tema="cerah"] .rekap-lokasi:hover .ikon,
:root[data-tema="cerah"] .rekap-lokasi:hover .buka { color: var(--aksen-pekat); }
:root[data-tema="cerah"] .rekap-lokasi .buka {
  flex: 0 0 auto; margin-top: 1px; color: var(--abu-400);
  transition: color var(--transisi), transform var(--transisi);
}
:root[data-tema="cerah"] .rekap-lokasi:hover .buka { transform: translateX(2px); }

:root[data-tema="cerah"] .rekap-catatan {
  display: flex; align-items: center; gap: .7rem; margin-top: .7rem;
  padding: .7rem .9rem; border-radius: var(--radius); background: var(--lembut-biru);
}
:root[data-tema="cerah"] .rekap-catatan .lambang {
  width: 30px; height: 30px; flex: 0 0 30px; border-radius: 9px; display: grid; place-items: center;
  background: var(--putih); color: var(--aksen-pekat);
}
:root[data-tema="cerah"] .rekap-catatan .j { display: block; font-weight: 700; font-size: .85rem; color: var(--aksen-pekat); }
:root[data-tema="cerah"] .rekap-catatan .k { display: block; font-size: .84rem; color: var(--abu-600); overflow-wrap: anywhere; }

/* ---- Rekap bulanan ---- */
:root[data-tema="cerah"] .rekap-kartu-kepala { display: flex; align-items: center; gap: .7rem; margin-bottom: .9rem; }
:root[data-tema="cerah"] .rekap-kartu-kepala .garis {
  flex: 0 0 4px; width: 4px; height: 34px; border-radius: 99px; background: var(--aksen-teks);
}
:root[data-tema="cerah"] .rekap-kartu-kepala h3 { font-size: 1.02rem; }
:root[data-tema="cerah"] .rekap-kartu-kepala .sub { font-size: .82rem; color: var(--abu-500); margin: .1rem 0 0; }

/* Persentase memakai netral, bukan --ubin-kuat seperti angka di atasnya: ukurannya di bawah
   18px sehingga ambangnya 4,5:1, dan pada rona oranye/merah --ubin-kuat hanya 3,2-4,1:1. Angka
   besar & ikon di ubin yang sama sudah membawa ronanya. */

@media (max-width: 700px) {
  :root[data-tema="cerah"] .rekap-detail-blok { grid-template-columns: minmax(0, 1fr); }
  :root[data-tema="cerah"] .rekap-hero-kiri .lambang { width: 56px; height: 56px; flex-basis: 56px; }
}
@media (max-width: 520px) {
  /* Lima ubin sebaris di layar sempit menyisakan ~60px per ubin — angkanya terpotong. */
  :root[data-tema="cerah"] .rekap-ubin-baris { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  :root[data-tema="cerah"] .rekap-hero-angka { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: .4rem 0; padding: .5rem .1rem; }
  /* Tujuh butir dalam empat kolom berarti baris kedua tidak penuh — garis pemisah kirinya
     dimatikan pada butir pertama tiap baris supaya tidak ada garis menggantung di tepi. */
  :root[data-tema="cerah"] .rekap-hero-angka .butir:nth-child(4n+1) { border-left: none; }
  :root[data-tema="cerah"] .rekap-hero-angka .l { font-size: .62rem; }
  :root[data-tema="cerah"] .rekap-sel .angka { font-size: .85rem; }
}

/* ==========================================================================
   Absen Masuk / Pulang / Lembur — susunan khusus tema CERAH
   ========================================================================== */

/* ---- Kartu puncak ---- */
:root[data-tema="cerah"] .absen-hero {
  display: flex; align-items: center; gap: 1rem; flex-wrap: wrap;
  padding: 1.2rem; border-radius: var(--radius-lg);
  background: linear-gradient(135deg, #dbeafe 0%, #eaf3ff 55%, #e3edfd 100%);
  border: 1px solid #cfe0fb;
}
:root[data-tema="cerah"] .absen-hero-lambang {
  width: 60px; height: 60px; flex: 0 0 60px; border-radius: 50%; display: grid; place-items: center;
  background: rgba(255, 255, 255, .7); color: #d97706;
}
:root[data-tema="cerah"] .absen-hero-isi { flex: 1 1 200px; min-width: 0; }
:root[data-tema="cerah"] .absen-hero-isi .tgl { font-size: .9rem; color: var(--abu-600); }
:root[data-tema="cerah"] .absen-hero-isi .jam {
  font-size: 2.4rem; font-weight: 800; letter-spacing: -.03em; line-height: 1.1;
  color: var(--judul); font-variant-numeric: tabular-nums;
}
:root[data-tema="cerah"] .absen-hero-isi .salam { font-size: 1rem; font-weight: 700; color: var(--abu-700); }
:root[data-tema="cerah"] .absen-hero-kutipan {
  flex: 0 1 200px; min-width: 150px; padding: .7rem .9rem; border-radius: var(--radius);
  background: rgba(255, 255, 255, .55); border: 1px solid rgba(255, 255, 255, .9);
  font-style: italic; font-weight: 600; font-size: .88rem; line-height: 1.35; color: var(--aksen-pekat);
}

/* ---- Kartu umum ---- */
:root[data-tema="cerah"] .absen-kartu { padding: 1.1rem; }
:root[data-tema="cerah"] .absen-kartu-kepala {
  display: flex; align-items: flex-start; gap: .75rem; flex-wrap: wrap; margin-bottom: .9rem;
}
:root[data-tema="cerah"] .absen-kartu-kepala .isi { flex: 1; min-width: 150px; }
:root[data-tema="cerah"] .absen-kartu-kepala .atas { font-size: .84rem; color: var(--abu-500); margin: 0 0 .1rem; }
:root[data-tema="cerah"] .absen-kartu-kepala h3 { font-size: 1.05rem; }
:root[data-tema="cerah"] .absen-kartu-kepala .sub { font-size: .84rem; color: var(--abu-500); margin: .15rem 0 0; line-height: 1.35; }
:root[data-tema="cerah"] .absen-kartu-kepala .lambang {
  flex: 0 0 38px; width: 38px; height: 38px; border-radius: 50%; display: grid; place-items: center; color: #fff;
}
:root[data-tema="cerah"] .absen-kartu-kepala .lambang.biru { background: var(--biru-600); }
:root[data-tema="cerah"] .absen-kartu-kepala .lambang.ungu { background: #7c3aed; }
:root[data-tema="cerah"] .absen-kartu-kepala .lambang.abu { background: var(--abu-400); }
:root[data-tema="cerah"] .absen-aksi {
  flex: 0 0 auto; display: inline-flex; align-items: center; gap: .35rem;
  padding: .45rem .9rem; border-radius: 999px; border: none; cursor: pointer;
  background: var(--lembut-biru); color: var(--aksen-pekat); font: inherit; font-size: .84rem; font-weight: 700;
}
:root[data-tema="cerah"] .absen-aksi:hover { background: var(--lembut-biru-kuat); text-decoration: none; }

/* ---- Peta kecil ---- */
:root[data-tema="cerah"] .absen-peta {
  height: 190px; border-radius: var(--radius); overflow: hidden;
  background: var(--abu-100); border: 1px solid var(--abu-200);
}

/* ---- Spanduk jangkauan ---- */
:root[data-tema="cerah"] .absen-jangkauan {
  display: flex; align-items: center; gap: .85rem;
  padding: .9rem 1.1rem; border-radius: var(--radius-lg); border: 1px solid transparent;
}
:root[data-tema="cerah"] .absen-jangkauan .lambang {
  width: 42px; height: 42px; flex: 0 0 42px; border-radius: 50%; display: grid; place-items: center; color: #fff;
}
:root[data-tema="cerah"] .absen-jangkauan .isi { min-width: 0; }
:root[data-tema="cerah"] .absen-jangkauan .j { display: block; font-weight: 700; font-size: 1rem; }
:root[data-tema="cerah"] .absen-jangkauan .k { display: block; font-size: .85rem; line-height: 1.35; }
:root[data-tema="cerah"] .absen-jangkauan.hijau { background: #e6f7ee; border-color: #bbeacd; }
:root[data-tema="cerah"] .absen-jangkauan.hijau .lambang { background: var(--hijau-700); }
:root[data-tema="cerah"] .absen-jangkauan.hijau .j { color: #065f46; }
:root[data-tema="cerah"] .absen-jangkauan.hijau .k { color: var(--abu-600); }
:root[data-tema="cerah"] .absen-jangkauan.merah { background: #fdeaea; border-color: #fbd0d0; }
:root[data-tema="cerah"] .absen-jangkauan.merah .lambang { background: #be123c; }
:root[data-tema="cerah"] .absen-jangkauan.merah .j { color: #be123c; }
:root[data-tema="cerah"] .absen-jangkauan.merah .k { color: var(--abu-600); }
:root[data-tema="cerah"] .absen-jangkauan.netral { background: var(--lembut-biru); border-color: var(--lembut-biru-kuat); }
:root[data-tema="cerah"] .absen-jangkauan.netral .lambang { background: var(--biru-600); }
:root[data-tema="cerah"] .absen-jangkauan.netral .j { color: var(--aksen-pekat); }
:root[data-tema="cerah"] .absen-jangkauan.netral .k { color: var(--abu-600); }

/* ---- Kartu selfie ---- */
:root[data-tema="cerah"] .absen-selfie { display: flex; gap: 1rem; align-items: center; flex-wrap: wrap; }
:root[data-tema="cerah"] .absen-selfie .bingkai {
  position: relative; flex: 0 0 auto; width: 150px; height: 150px; border-radius: var(--radius-lg);
  display: grid; place-items: center; background: var(--abu-100); color: var(--abu-400);
}
/* Empat siku bracket, meniru bingkai bidik kamera. */
:root[data-tema="cerah"] .absen-selfie .sudut {
  position: absolute; width: 22px; height: 22px; border: 3px solid var(--biru-500);
}
:root[data-tema="cerah"] .absen-selfie .sudut.ka { top: 12px; left: 12px; border-right: none; border-bottom: none; border-radius: 8px 0 0 0; }
:root[data-tema="cerah"] .absen-selfie .sudut.kb { top: 12px; right: 12px; border-left: none; border-bottom: none; border-radius: 0 8px 0 0; }
:root[data-tema="cerah"] .absen-selfie .sudut.kc { bottom: 12px; left: 12px; border-right: none; border-top: none; border-radius: 0 0 0 8px; }
:root[data-tema="cerah"] .absen-selfie .sudut.kd { bottom: 12px; right: 12px; border-left: none; border-top: none; border-radius: 0 0 8px 0; }
:root[data-tema="cerah"] .absen-selfie .teks { flex: 1; min-width: 180px; }
:root[data-tema="cerah"] .absen-selfie .teks .j { display: block; font-weight: 700; font-size: 1.02rem; color: var(--judul); }
:root[data-tema="cerah"] .absen-selfie .teks .k { display: block; font-size: .86rem; line-height: 1.45; color: var(--abu-600); margin-top: .2rem; }

/* ---- Catatan ---- */
:root[data-tema="cerah"] .absen-catatan { display: flex; align-items: center; gap: .75rem; flex-wrap: wrap; }
:root[data-tema="cerah"] .absen-catatan > .lambang {
  flex: 0 0 38px; width: 38px; height: 38px; border-radius: 50%; display: grid; place-items: center;
  background: var(--biru-600); color: #fff;
}
:root[data-tema="cerah"] .absen-catatan .isi { flex: 0 1 auto; min-width: 140px; }
:root[data-tema="cerah"] .absen-catatan .isi label { display: block; font-weight: 700; font-size: .95rem; color: var(--judul); }
:root[data-tema="cerah"] .absen-catatan .isi .sub { display: block; font-size: .82rem; color: var(--abu-500); }
:root[data-tema="cerah"] .absen-catatan .kendali { flex: 1 1 220px; width: auto; }

/* ---- Tombol aksi utama ---- */
:root[data-tema="cerah"] .absen-cta {
  display: flex; align-items: center; gap: 1rem; width: 100%;
  padding: 1.05rem 1.2rem; border: none; border-radius: 999px; cursor: pointer; font: inherit; text-align: left;
  background: linear-gradient(135deg, #1a5fc4, #0f4494); color: #fff;
  box-shadow: 0 12px 28px -10px rgba(15, 68, 148, .8);
  transition: transform var(--transisi), box-shadow var(--transisi);
}
:root[data-tema="cerah"] .absen-cta:hover:not(:disabled) { transform: translateY(-2px); }
:root[data-tema="cerah"] .absen-cta:active:not(:disabled) { transform: scale(.99); }
:root[data-tema="cerah"] .absen-cta:disabled {
  background: var(--abu-300); color: var(--abu-700); box-shadow: none; cursor: not-allowed;
}
:root[data-tema="cerah"] .absen-cta .lambang { flex: 0 0 auto; display: grid; place-items: center; }
:root[data-tema="cerah"] .absen-cta .teks { flex: 1; min-width: 0; }
:root[data-tema="cerah"] .absen-cta .teks .j { display: block; font-size: 1.25rem; font-weight: 800; line-height: 1.2; }
:root[data-tema="cerah"] .absen-cta .teks .k { display: block; font-size: .84rem; opacity: .9; }
:root[data-tema="cerah"] .absen-cta .panah {
  flex: 0 0 auto; width: 42px; height: 42px; border-radius: 50%; display: grid; place-items: center;
  background: #fff; color: var(--biru-700);
}
:root[data-tema="cerah"] .absen-cta:disabled .panah { background: var(--abu-100); color: var(--abu-600); }

@media (max-width: 560px) {
  :root[data-tema="cerah"] .absen-hero-isi .jam { font-size: 2rem; }
  :root[data-tema="cerah"] .absen-hero-kutipan { flex: 1 1 100%; }
  :root[data-tema="cerah"] .absen-selfie { justify-content: center; }
  :root[data-tema="cerah"] .absen-cta { padding: .9rem 1rem; }
  :root[data-tema="cerah"] .absen-cta .teks .j { font-size: 1.1rem; }
}

/* ==========================================================================
   Tukar Shift — susunan khusus tema CERAH
   ========================================================================== */

:root[data-tema="cerah"] .ts-hero {
  display: flex; align-items: center; gap: 1.1rem; flex-wrap: wrap;
  padding: 1.2rem; border-radius: var(--radius-lg);
  background: linear-gradient(135deg, #dbeafe 0%, #eaf3ff 55%, #e3edfd 100%);
  border: 1px solid #cfe0fb;
}
:root[data-tema="cerah"] .ts-hero-lambang {
  width: 68px; height: 68px; flex: 0 0 68px; border-radius: 50%; display: grid; place-items: center;
  background: rgba(255, 255, 255, .7); color: #1d6fe0;
}
:root[data-tema="cerah"] .ts-hero-isi { flex: 1 1 220px; min-width: 0; }
:root[data-tema="cerah"] .ts-hero-isi h2 { font-size: 1.4rem; letter-spacing: -.02em; }
:root[data-tema="cerah"] .ts-hero-isi p { margin: .25rem 0 0; font-size: .9rem; line-height: 1.4; color: var(--abu-600); }
:root[data-tema="cerah"] .ts-hero-kutipan {
  flex: 0 1 195px; min-width: 150px; padding: .7rem .9rem; border-radius: var(--radius);
  background: rgba(255, 255, 255, .55); border: 1px solid rgba(255, 255, 255, .9);
  font-style: italic; font-weight: 600; font-size: .86rem; line-height: 1.35; color: var(--aksen-pekat);
}

/* ---- Tab ---- */
:root[data-tema="cerah"] .ts-tab {
  background: var(--putih); border: 1px solid var(--abu-200); border-radius: var(--radius-lg);
  padding: .3rem; gap: .2rem; box-shadow: var(--bayang-sm);
}
:root[data-tema="cerah"] .ts-tab button {
  flex: 1; display: inline-flex; align-items: center; justify-content: center; gap: .4rem;
  padding: .65rem .5rem; border-radius: var(--radius); border-bottom: none; font-size: .84rem;
}
:root[data-tema="cerah"] .ts-tab button.aktif { background: var(--biru-600); color: #fff; }

/* ---- Kartu ---- */
:root[data-tema="cerah"] .ts-kartu { padding: 1.1rem; }
:root[data-tema="cerah"] .ts-kartu-kepala {
  display: flex; align-items: flex-start; gap: .7rem; flex-wrap: wrap; margin-bottom: 1rem;
}
:root[data-tema="cerah"] .ts-kartu-kepala .isi { flex: 1; min-width: 150px; }
:root[data-tema="cerah"] .ts-kartu-kepala h3 { font-size: 1.02rem; }
:root[data-tema="cerah"] .ts-kartu-kepala .sub { font-size: .82rem; color: var(--abu-500); margin: .1rem 0 0; }
:root[data-tema="cerah"] .ts-kartu-kepala .lambang {
  flex: 0 0 36px; width: 36px; height: 36px; border-radius: 11px; display: grid; place-items: center; color: #fff;
}
:root[data-tema="cerah"] .ts-kartu-kepala .lambang.biru { background: var(--biru-600); }
:root[data-tema="cerah"] .ts-kartu-kepala .lambang.ungu { background: #7c3aed; }
:root[data-tema="cerah"] .ts-kartu-kepala .lambang.oranye { background: #ea580c; }
:root[data-tema="cerah"] .ts-kartu-kepala .lambang.toska { background: #0e7490; }

/* ---- Baris tukar (shift saya <-> shift target) ---- */
:root[data-tema="cerah"] .ts-tukar-baris {
  display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  gap: .7rem; align-items: end; margin-bottom: 1.05rem;
}
:root[data-tema="cerah"] .ts-sisi { min-width: 0; }
:root[data-tema="cerah"] .ts-sisi > label {
  display: block; font-size: .82rem; font-weight: 600; color: var(--abu-500); margin-bottom: .3rem;
}
:root[data-tema="cerah"] .ts-panah {
  width: 38px; height: 38px; flex: 0 0 38px; border-radius: 50%; display: grid; place-items: center;
  background: var(--lembut-biru); color: var(--aksen-pekat); margin-bottom: .5rem;
}
:root[data-tema="cerah"] .ts-shift {
  display: flex; align-items: center; gap: .6rem; margin-top: .45rem;
  padding: .6rem .7rem; border-radius: var(--radius); min-height: 58px;
}
:root[data-tema="cerah"] .ts-shift .lambang {
  width: 34px; height: 34px; flex: 0 0 34px; border-radius: 10px; display: grid; place-items: center;
}
:root[data-tema="cerah"] .ts-shift .teks { min-width: 0; }
:root[data-tema="cerah"] .ts-shift .j { display: block; font-weight: 700; font-size: .92rem; color: var(--abu-900); }
:root[data-tema="cerah"] .ts-shift .k { display: block; font-size: .82rem; color: var(--abu-600); font-variant-numeric: tabular-nums; }
:root[data-tema="cerah"] .ts-shift.pagi { background: #fdf3e0; }
:root[data-tema="cerah"] .ts-shift.pagi .lambang { background: #fbe3b8; color: #a16207; }
:root[data-tema="cerah"] .ts-shift.malam { background: var(--lembut-biru); }
:root[data-tema="cerah"] .ts-shift.malam .lambang { background: #cfe0fb; color: #1a56b8; }
:root[data-tema="cerah"] .ts-shift.libur { background: #fdeaea; }
:root[data-tema="cerah"] .ts-shift.libur .lambang { background: #fbd0d0; color: #be123c; }
:root[data-tema="cerah"] .ts-shift.kosong {
  background: var(--abu-50); border: 1px dashed var(--abu-300); justify-content: center;
}
:root[data-tema="cerah"] .ts-shift.kosong .teks { font-size: .84rem; color: var(--abu-500); }

/* ---- Jenis tukar ---- */
:root[data-tema="cerah"] .ts-jenis { display: flex; gap: .5rem; flex-wrap: wrap; margin-top: .3rem; }
:root[data-tema="cerah"] .ts-jenis label {
  display: inline-flex; align-items: center; gap: .4rem; cursor: pointer;
  padding: .45rem .8rem; border-radius: 999px; border: 1px solid var(--abu-200);
  font-size: .83rem; font-weight: 600; color: var(--abu-700); background: var(--putih);
}
:root[data-tema="cerah"] .ts-jenis label:has(input:checked) {
  border-color: var(--biru-500); background: var(--lembut-biru); color: var(--aksen-pekat);
}

:root[data-tema="cerah"] .ts-hitung {
  display: flex; justify-content: space-between; gap: .6rem; align-items: baseline; margin-top: .3rem;
}
:root[data-tema="cerah"] .ts-hitung > span:last-child {
  font-size: .78rem; color: var(--abu-500); font-variant-numeric: tabular-nums;
}

:root[data-tema="cerah"] .ts-kirim {
  display: flex; align-items: center; justify-content: center; gap: .5rem; width: 100%;
  padding: .85rem 1rem; border: none; border-radius: 999px; cursor: pointer; font: inherit;
  font-size: 1rem; font-weight: 700;
  background: linear-gradient(135deg, #1a5fc4, #0f4494); color: #fff;
  box-shadow: 0 10px 24px -10px rgba(15, 68, 148, .8);
  transition: transform var(--transisi);
}
:root[data-tema="cerah"] .ts-kirim:hover:not(:disabled) { transform: translateY(-2px); }
:root[data-tema="cerah"] .ts-kirim:disabled { background: var(--abu-300); color: var(--abu-700); box-shadow: none; cursor: not-allowed; }

/* ---- Keping tanggal ---- */
:root[data-tema="cerah"] .ts-keping-baris {
  display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: .3rem; margin-bottom: .9rem;
}
:root[data-tema="cerah"] .ts-keping {
  display: flex; flex-direction: column; align-items: center; gap: .1rem; min-width: 0;
  padding: .5rem .2rem; border-radius: var(--radius); cursor: pointer; font: inherit;
  border: 1px solid var(--abu-200); background: var(--putih); color: var(--abu-700);
}
:root[data-tema="cerah"] .ts-keping .h { font-size: .74rem; color: var(--abu-500); }
:root[data-tema="cerah"] .ts-keping .t { font-size: .82rem; font-weight: 700; white-space: nowrap; }
:root[data-tema="cerah"] .ts-keping.aktif { background: var(--biru-600); border-color: var(--biru-600); color: #fff; }
:root[data-tema="cerah"] .ts-keping.aktif .h { color: rgba(255, 255, 255, .85); }

/* Navigasi bulan kalender jadwal — memakai ulang tombol .rekap-nav-tbl dari halaman rekap. */
:root[data-tema="cerah"] .ts-bulan { display: flex; align-items: center; gap: .5rem; flex-wrap: wrap; margin-bottom: .8rem; }
:root[data-tema="cerah"] .ts-bulan .judul {
  flex: 1; text-align: center; font-weight: 800; font-size: 1rem; color: var(--judul); min-width: 130px;
}
:root[data-tema="cerah"] .ts-bulan .kendali { width: auto; max-width: 110px; flex: 0 0 auto; }
:root[data-tema="cerah"] #js-bln-mundur { transform: scaleX(-1); }

/* ---- Daftar rekan ---- */
:root[data-tema="cerah"] .ts-rekan { list-style: none; margin: 0; padding: 0; }
:root[data-tema="cerah"] .ts-rekan li {
  display: flex; align-items: center; gap: .7rem; flex-wrap: wrap;
  padding: .65rem 0; border-bottom: 1px solid var(--abu-100);
}
:root[data-tema="cerah"] .ts-rekan li:last-child { border-bottom: none; }
:root[data-tema="cerah"] .ts-rekan .isi { flex: 1 1 130px; min-width: 0; }
:root[data-tema="cerah"] .ts-rekan .isi .j { display: block; font-weight: 700; font-size: .9rem; color: var(--abu-900); }
:root[data-tema="cerah"] .ts-rekan .isi .k { display: block; font-size: .78rem; color: var(--abu-500); }
:root[data-tema="cerah"] .ts-rekan .shift { flex: 1 1 150px; min-width: 0; }
:root[data-tema="cerah"] .ts-rekan .shift .ts-shift { margin-top: 0; min-height: 0; padding: .4rem .6rem; }
:root[data-tema="cerah"] .ts-pilih {
  flex: 0 0 auto; padding: .45rem 1.1rem; border-radius: 999px; cursor: pointer; font: inherit;
  font-size: .84rem; font-weight: 700;
  border: 1px solid var(--biru-500); background: var(--putih); color: var(--aksen-pekat);
}
:root[data-tema="cerah"] .ts-pilih:hover { background: var(--lembut-biru); }

/* ---- Spanduk informasi ---- */
:root[data-tema="cerah"] .ts-info {
  display: flex; align-items: flex-start; gap: .8rem;
  padding: .9rem 1.1rem; border-radius: var(--radius-lg); background: var(--lembut-biru);
}
:root[data-tema="cerah"] .ts-info .lambang {
  width: 30px; height: 30px; flex: 0 0 30px; border-radius: 50%; display: grid; place-items: center;
  background: var(--aksen-teks); color: #fff;
}
:root[data-tema="cerah"] .ts-info .isi .j { display: block; font-weight: 700; color: var(--aksen-pekat); }
:root[data-tema="cerah"] .ts-info .isi .k { display: block; font-size: .84rem; line-height: 1.4; color: var(--abu-600); }

@media (max-width: 640px) {
  /* Tiga kolom di layar sempit membuat kartu shift terhimpit di bawah 100px. */
  :root[data-tema="cerah"] .ts-tukar-baris { grid-template-columns: minmax(0, 1fr); }
  :root[data-tema="cerah"] .ts-panah { transform: rotate(90deg); margin: 0 auto; }
  :root[data-tema="cerah"] .ts-tab button span:not(.ikon-svg) { display: none; }
  :root[data-tema="cerah"] .ts-keping-baris { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  :root[data-tema="cerah"] .ts-hero-kutipan { flex: 1 1 100%; }
}

/* ==========================================================================
   Pengajuan Izin / Sakit / Dinas / Cuti — susunan khusus tema CERAH
   ========================================================================== */

:root[data-tema="cerah"] .pj-hero {
  display: flex; align-items: center; gap: 1.1rem; flex-wrap: wrap;
  padding: 1.2rem; border-radius: var(--radius-lg);
  background: linear-gradient(135deg, #dbeafe 0%, #eaf3ff 55%, #e3edfd 100%);
  border: 1px solid #cfe0fb;
}
:root[data-tema="cerah"] .pj-hero-lambang {
  width: 68px; height: 68px; flex: 0 0 68px; border-radius: 20px; display: grid; place-items: center;
  background: rgba(255, 255, 255, .75); color: #1d6fe0;
}
:root[data-tema="cerah"] .pj-hero-isi { flex: 1 1 220px; min-width: 0; }
:root[data-tema="cerah"] .pj-hero-isi h2 { font-size: 1.35rem; letter-spacing: -.02em; }
:root[data-tema="cerah"] .pj-hero-isi p { margin: .25rem 0 0; font-size: .9rem; line-height: 1.4; color: var(--abu-600); }
:root[data-tema="cerah"] .pj-hero-kutipan {
  flex: 0 1 195px; min-width: 150px; padding: .7rem .9rem; border-radius: var(--radius);
  background: rgba(255, 255, 255, .55); border: 1px solid rgba(255, 255, 255, .9);
  font-style: italic; font-weight: 600; font-size: .86rem; line-height: 1.35; color: var(--aksen-pekat);
}

/* ---- Tab jenis ---- */
:root[data-tema="cerah"] .pj-tab {
  background: var(--putih); border: 1px solid var(--abu-200); border-radius: var(--radius-lg);
  padding: .3rem; gap: .2rem; box-shadow: var(--bayang-sm);
}
:root[data-tema="cerah"] .pj-tab button {
  flex: 1; display: inline-flex; align-items: center; justify-content: center; gap: .4rem;
  padding: .7rem .5rem; border-radius: var(--radius); border-bottom: none; font-size: .88rem;
}
:root[data-tema="cerah"] .pj-tab button.aktif { background: var(--biru-600); color: #fff; }

/* ---- Kartu ---- */
:root[data-tema="cerah"] .pj-kartu { padding: 1.1rem; }
:root[data-tema="cerah"] .pj-kartu-kepala {
  display: flex; align-items: flex-start; gap: .7rem; flex-wrap: wrap; margin-bottom: 1rem;
}
:root[data-tema="cerah"] .pj-kartu-kepala .isi { flex: 1; min-width: 150px; }
:root[data-tema="cerah"] .pj-kartu-kepala h3 { font-size: 1.02rem; }
:root[data-tema="cerah"] .pj-kartu-kepala .sub { font-size: .82rem; color: var(--abu-500); margin: .1rem 0 0; line-height: 1.35; }
:root[data-tema="cerah"] .pj-kartu-kepala .lambang {
  flex: 0 0 36px; width: 36px; height: 36px; border-radius: 11px; display: grid; place-items: center;
  background: var(--ubin-kuat); color: #fff;
}
:root[data-tema="cerah"] .pj-aksi {
  flex: 0 0 auto; display: inline-flex; align-items: center; gap: .25rem;
  font-size: .84rem; font-weight: 700; color: var(--aksen-pekat);
}

/* ---- Ringkasan sisa cuti ---- */
:root[data-tema="cerah"] .pj-cuti {
  display: flex; align-items: center; gap: 1rem; flex-wrap: wrap;
  padding: .85rem 1rem; border-radius: var(--radius); background: var(--lembut-biru); margin-bottom: 1rem;
}
:root[data-tema="cerah"] .pj-cuti .isi { flex: 1; min-width: 160px; }
:root[data-tema="cerah"] .pj-cuti .l { display: block; font-size: .82rem; color: var(--abu-600); }
:root[data-tema="cerah"] .pj-cuti .n { display: block; font-size: 1.5rem; font-weight: 800; color: var(--aksen-pekat); }
:root[data-tema="cerah"] .pj-cuti .n small { font-size: .85rem; font-weight: 500; color: var(--abu-600); }
:root[data-tema="cerah"] .pj-cuti .k { flex: 0 0 auto; font-size: .84rem; color: var(--abu-600); }

/* ---- Penghitung karakter ---- */
:root[data-tema="cerah"] .pj-hitung {
  display: flex; justify-content: space-between; gap: .6rem; align-items: baseline; margin-top: .3rem;
}
:root[data-tema="cerah"] .pj-hitung > span:last-child {
  font-size: .78rem; color: var(--abu-500); font-variant-numeric: tabular-nums; flex: 0 0 auto;
}

/* ---- Lampiran ---- */
:root[data-tema="cerah"] .pj-lampiran {
  display: flex; align-items: center; gap: .75rem; flex-wrap: wrap;
  padding: .8rem .9rem; border-radius: var(--radius); border: 1px solid var(--abu-200); margin-bottom: 1rem;
}
:root[data-tema="cerah"] .pj-lampiran .lambang {
  width: 36px; height: 36px; flex: 0 0 36px; border-radius: 10px; display: grid; place-items: center;
  background: var(--lembut-biru); color: var(--aksen-pekat);
}
:root[data-tema="cerah"] .pj-lampiran .isi { flex: 1; min-width: 140px; }
:root[data-tema="cerah"] .pj-lampiran .isi .j { display: block; font-weight: 700; font-size: .92rem; color: var(--judul); }
:root[data-tema="cerah"] .pj-lampiran .isi .k { display: block; font-size: .8rem; color: var(--abu-500); overflow-wrap: anywhere; }
:root[data-tema="cerah"] .pj-pilih-berkas {
  flex: 0 0 auto; display: inline-flex; align-items: center; gap: .35rem; cursor: pointer;
  padding: .5rem 1rem; border-radius: 999px;
  background: var(--lembut-biru); color: var(--aksen-pekat); font-size: .84rem; font-weight: 700;
}
:root[data-tema="cerah"] .pj-pilih-berkas:hover { background: var(--lembut-biru-kuat); }
:root[data-tema="cerah"] .pj-pilih-berkas input { display: none; }

:root[data-tema="cerah"] .pj-catatan {
  display: flex; align-items: flex-start; gap: .6rem; margin-bottom: 1rem;
  padding: .75rem .9rem; border-radius: var(--radius); background: var(--lembut-biru);
}
:root[data-tema="cerah"] .pj-catatan .lambang { flex: 0 0 auto; color: var(--aksen-pekat); margin-top: 1px; }
:root[data-tema="cerah"] .pj-catatan .k { font-size: .84rem; line-height: 1.4; color: var(--abu-600); }

:root[data-tema="cerah"] .pj-kirim {
  display: flex; align-items: center; justify-content: center; gap: .5rem; width: 100%;
  padding: .85rem 1rem; border: none; border-radius: 999px; cursor: pointer; font: inherit;
  font-size: 1rem; font-weight: 700;
  background: linear-gradient(135deg, #1a5fc4, #0f4494); color: #fff;
  box-shadow: 0 10px 24px -10px rgba(15, 68, 148, .8);
  transition: transform var(--transisi);
}
:root[data-tema="cerah"] .pj-kirim:hover:not(:disabled) { transform: translateY(-2px); }
:root[data-tema="cerah"] .pj-kirim:disabled { background: var(--abu-300); color: var(--abu-700); box-shadow: none; cursor: not-allowed; }

/* ---- Riwayat ---- */
:root[data-tema="cerah"] .pj-riwayat { list-style: none; margin: 0; padding: 0; }
:root[data-tema="cerah"] .pj-riwayat li + li { border-top: 1px solid var(--abu-100); }
:root[data-tema="cerah"] .pj-riwayat-baris {
  display: flex; align-items: center; gap: .75rem; width: 100%;
  padding: .8rem .2rem; border: none; background: none; cursor: pointer; font: inherit; text-align: left;
  border-radius: var(--radius); transition: background var(--transisi);
}
:root[data-tema="cerah"] .pj-riwayat-baris:hover { background: var(--lembut-biru); }
:root[data-tema="cerah"] .pj-riwayat-baris .lambang {
  width: 44px; height: 44px; flex: 0 0 44px; border-radius: var(--radius); display: grid; place-items: center;
  background: color-mix(in srgb, var(--ubin-warna) 14%, var(--putih)); color: var(--ubin-kuat);
}
:root[data-tema="cerah"] .pj-riwayat-baris .isi { flex: 1; min-width: 0; }
:root[data-tema="cerah"] .pj-riwayat-baris .isi .j { display: block; font-weight: 700; font-size: .95rem; color: var(--abu-900); }
:root[data-tema="cerah"] .pj-riwayat-baris .isi .t { display: block; font-size: .82rem; color: var(--abu-600); }
:root[data-tema="cerah"] .pj-riwayat-baris .isi .k {
  display: block; font-size: .8rem; color: var(--abu-500);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
:root[data-tema="cerah"] .pj-riwayat-baris .kanan { flex: 0 0 auto; display: flex; align-items: center; gap: .5rem; }
:root[data-tema="cerah"] .pj-riwayat-baris .panah {
  width: 30px; height: 30px; border-radius: 50%; display: grid; place-items: center;
  background: var(--lembut-biru); color: var(--aksen-pekat);
}

@media (max-width: 560px) {
  :root[data-tema="cerah"] .pj-hero-kutipan { flex: 1 1 100%; }
  :root[data-tema="cerah"] .pj-lampiran .isi { flex: 1 1 100%; }
  /* Lencana status turun ke bawah panah agar teks alasan tidak terhimpit jadi satu-dua kata. */
  :root[data-tema="cerah"] .pj-riwayat-baris { flex-wrap: wrap; }
  :root[data-tema="cerah"] .pj-riwayat-baris .kanan { margin-left: auto; }
}

/* ==========================================================================
   Daftar Pengumuman — susunan khusus tema CERAH
   ========================================================================== */

:root[data-tema="cerah"] .pg-hero {
  position: relative; overflow: hidden;
  display: flex; align-items: center; gap: 1rem; flex-wrap: wrap;
  padding: 1.3rem; border-radius: var(--radius-lg);
  background: linear-gradient(135deg, #dbeafe 0%, #eaf3ff 55%, #e3edfd 100%);
  border: 1px solid #cfe0fb;
}
:root[data-tema="cerah"] .pg-hero-isi { flex: 1 1 240px; min-width: 0; }
:root[data-tema="cerah"] .pg-hero-isi .mata {
  display: block; font-size: .74rem; font-weight: 800; letter-spacing: .18em;
  text-transform: uppercase; color: var(--aksen-pekat); margin-bottom: .3rem;
}
:root[data-tema="cerah"] .pg-hero-isi h2 { font-size: 1.45rem; line-height: 1.2; letter-spacing: -.02em; }
:root[data-tema="cerah"] .pg-hero-isi p { margin: .4rem 0 0; font-size: .9rem; line-height: 1.4; color: var(--abu-600); }
:root[data-tema="cerah"] .pg-hero-lambang {
  flex: 0 0 auto; width: 86px; height: 86px; border-radius: 50%; display: grid; place-items: center;
  background: rgba(255, 255, 255, .7); color: #1d6fe0;
}
:root[data-tema="cerah"] .pg-hero-kutipan {
  flex: 0 1 150px; min-width: 130px; font-style: italic; font-weight: 700;
  font-size: .9rem; line-height: 1.3; color: var(--aksen-pekat);
}

/* ---- Keping kategori ---- */
:root[data-tema="cerah"] .pg-keping-baris { display: flex; gap: .5rem; flex-wrap: wrap; }
:root[data-tema="cerah"] .pg-keping {
  display: inline-flex; align-items: center; gap: .45rem; cursor: pointer; font: inherit;
  padding: .55rem 1rem; border-radius: 999px;
  border: 1px solid var(--abu-200); background: var(--putih); color: var(--abu-700);
  font-size: .86rem; font-weight: 700;
  transition: background var(--transisi), border-color var(--transisi);
}
:root[data-tema="cerah"] .pg-keping:hover { border-color: var(--abu-400); }
:root[data-tema="cerah"] .pg-keping .n {
  min-width: 22px; padding: 0 .35rem; border-radius: 999px; text-align: center;
  background: var(--abu-100); color: var(--abu-600); font-size: .78rem; font-variant-numeric: tabular-nums;
}
/* Digelapkan 15% dari --ubin-kuat: label keping berukuran .86rem (teks normal, ambang 4,5:1),
   dan putih di atas oranye --ubin-kuat apa adanya hanya 3,56:1. */
:root[data-tema="cerah"] .pg-keping.aktif {
  background: color-mix(in srgb, var(--ubin-kuat) 85%, #000);
  border-color: color-mix(in srgb, var(--ubin-kuat) 85%, #000);
  color: #fff;
}
:root[data-tema="cerah"] .pg-keping.aktif .n { background: rgba(255, 255, 255, .25); color: #fff; }

/* ---- Bilah cari & urutkan ---- */
:root[data-tema="cerah"] .pg-alat { display: flex; gap: .6rem; flex-wrap: wrap; align-items: center; }
:root[data-tema="cerah"] .pg-alat .kotak-cari { flex: 1 1 220px; min-width: 0; }
:root[data-tema="cerah"] .pg-alat .kotak-cari .kendali { border-radius: 999px; }
:root[data-tema="cerah"] .pg-urut {
  position: relative; display: flex; align-items: center; flex: 0 0 auto;
}
:root[data-tema="cerah"] .pg-urut .ikon {
  position: absolute; left: .8rem; color: var(--abu-500); pointer-events: none;
}
:root[data-tema="cerah"] .pg-urut .kendali {
  width: auto; min-width: 150px; padding-left: 2.2rem; border-radius: 999px; font-weight: 600;
}

/* ---- Kartu pengumuman ---- */
:root[data-tema="cerah"] .pg-daftar { display: grid; gap: .7rem; }
:root[data-tema="cerah"] .pg-kartu {
  position: relative; display: flex; align-items: flex-start; gap: .85rem;
  padding: 1rem; border-radius: var(--radius-lg);
  background: var(--putih); border: 1px solid var(--abu-200); box-shadow: var(--bayang-sm);
  transition: transform var(--transisi), box-shadow var(--transisi);
}
:root[data-tema="cerah"] .pg-kartu:hover { transform: translateY(-2px); box-shadow: var(--bayang); text-decoration: none; }
/* Kategori "penting" diberi latar bernada merah muda — satu-satunya yang menyimpang dari kartu
   putih, supaya benar-benar menonjol di antara sisanya alih-alih sekadar berbeda ikon. */
:root[data-tema="cerah"] .pg-kartu.sorot { background: #fdf0f1; border-color: #f8d4d8; }
:root[data-tema="cerah"] .pg-kartu .lambang {
  flex: 0 0 52px; width: 52px; height: 52px; border-radius: var(--radius);
  display: grid; place-items: center; background: var(--ubin-kuat); color: #fff;
}
:root[data-tema="cerah"] .pg-kartu .isi { flex: 1; min-width: 0; }
:root[data-tema="cerah"] .pg-kartu .baris-atas { display: flex; gap: .4rem; align-items: center; flex-wrap: wrap; margin-bottom: .25rem; }
:root[data-tema="cerah"] .pg-kartu .kategori {
  display: inline-block; padding: .15rem .6rem; border-radius: 999px;
  background: color-mix(in srgb, var(--ubin-warna) 16%, var(--putih));
  /* Digelapkan 25%: pada .74rem ambangnya 4,5:1, dan --ubin-kuat di atas tint-nya sendiri
     tinggal 3,0-4,5:1 untuk oranye/merah/biru/ungu. */
  color: color-mix(in srgb, var(--ubin-kuat) 75%, #000);
  font-size: .74rem; font-weight: 700; text-transform: capitalize;
}
:root[data-tema="cerah"] .pg-draf {
  display: inline-block; padding: .15rem .6rem; border-radius: 999px;
  background: var(--abu-100); color: var(--abu-600); font-size: .74rem; font-weight: 700;
}
:root[data-tema="cerah"] .pg-kartu .judul { display: block; font-size: 1.02rem; font-weight: 700; color: var(--judul); line-height: 1.3; }
:root[data-tema="cerah"] .pg-kartu .ringkas {
  display: -webkit-box; -webkit-line-clamp: 2; line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
  font-size: .86rem; line-height: 1.4; color: var(--abu-600); margin-top: .2rem;
}
:root[data-tema="cerah"] .pg-kartu .kaki {
  display: inline-flex; align-items: center; gap: .3rem; margin-top: .45rem;
  font-size: .78rem; color: var(--abu-500);
}
:root[data-tema="cerah"] .pg-kartu .panah {
  flex: 0 0 auto; align-self: center; width: 32px; height: 32px; border-radius: 50%;
  display: grid; place-items: center; background: var(--lembut-biru); color: var(--aksen-pekat);
}
/* Penanda "Baru" menempel di sudut kanan-atas kartu, di luar alur isi supaya tidak mendorong
   judul ke bawah pada kartu yang sudah dibaca. */
:root[data-tema="cerah"] .pg-baru {
  position: absolute; top: 0; right: 0;
  padding: .2rem .7rem; border-radius: 0 var(--radius-lg) 0 var(--radius);
  background: #be123c; color: #fff; font-size: .74rem; font-weight: 800;
}

@media (max-width: 560px) {
  :root[data-tema="cerah"] .pg-hero-lambang { width: 60px; height: 60px; }
  :root[data-tema="cerah"] .pg-hero-kutipan { flex: 1 1 100%; }
  :root[data-tema="cerah"] .pg-hero-isi h2 { font-size: 1.2rem; }
  :root[data-tema="cerah"] .pg-urut { flex: 1 1 100%; }
  :root[data-tema="cerah"] .pg-urut .kendali { width: 100%; }
  :root[data-tema="cerah"] .pg-kartu .lambang { flex-basis: 44px; width: 44px; height: 44px; }
  :root[data-tema="cerah"] .pg-kartu .panah { display: none; }
}

/* ==========================================================================
   Lapor Patroli — susunan khusus tema CERAH
   ========================================================================== */

:root[data-tema="cerah"] .pt-hero {
  display: flex; align-items: center; gap: 1.1rem; flex-wrap: wrap;
  padding: 1.2rem; border-radius: var(--radius-lg);
  background: linear-gradient(135deg, #dbeafe 0%, #eaf3ff 55%, #e3edfd 100%);
  border: 1px solid #cfe0fb;
}
:root[data-tema="cerah"] .pt-hero-lambang {
  width: 68px; height: 68px; flex: 0 0 68px; border-radius: 20px; display: grid; place-items: center;
  background: rgba(255, 255, 255, .75); color: #1d6fe0;
}
:root[data-tema="cerah"] .pt-hero-isi { flex: 1 1 220px; min-width: 0; }
:root[data-tema="cerah"] .pt-hero-isi h2 { font-size: 1.3rem; line-height: 1.25; letter-spacing: -.02em; }
:root[data-tema="cerah"] .pt-hero-isi p { margin: .3rem 0 0; font-size: .88rem; line-height: 1.4; color: var(--abu-600); }
:root[data-tema="cerah"] .pt-hero-langkah {
  list-style: none; margin: 0; padding: .6rem .8rem; flex: 0 0 auto;
  border-radius: var(--radius); background: rgba(255, 255, 255, .7);
  font-size: .84rem; font-weight: 700; color: var(--aksen-pekat); line-height: 1.5;
}
:root[data-tema="cerah"] .pt-hero-langkah li { display: flex; align-items: center; gap: .3rem; }

/* ---- Tab ---- */
:root[data-tema="cerah"] .pt-tab {
  background: var(--putih); border: 1px solid var(--abu-200); border-radius: var(--radius-lg);
  padding: .3rem; gap: .2rem; box-shadow: var(--bayang-sm);
}
:root[data-tema="cerah"] .pt-tab button {
  flex: 1; display: inline-flex; align-items: center; justify-content: center; gap: .4rem;
  padding: .7rem .5rem; border-radius: var(--radius); border-bottom: none; font-size: .86rem;
}
:root[data-tema="cerah"] .pt-tab button.aktif { background: var(--biru-600); color: #fff; }

/* ---- Panel pemicu pemindaian ---- */
:root[data-tema="cerah"] .pt-pindai {
  position: relative; display: flex; flex-direction: column; align-items: center; gap: .3rem;
  width: 100%; padding: 1.5rem 1.2rem; border: none; border-radius: var(--radius-lg); cursor: pointer;
  font: inherit; color: #fff;
  background: linear-gradient(160deg, #1e293b, #0f172a);
  box-shadow: var(--bayang);
  transition: transform var(--transisi);
}
:root[data-tema="cerah"] .pt-pindai:hover { transform: translateY(-2px); }
:root[data-tema="cerah"] .pt-pindai .j { font-size: 1.12rem; font-weight: 800; }
:root[data-tema="cerah"] .pt-pindai .k { font-size: .85rem; color: rgba(255, 255, 255, .82); }
:root[data-tema="cerah"] .pt-pindai .bidik {
  position: relative; display: grid; place-items: center;
  width: 168px; height: 168px; margin: 1rem 0; border-radius: var(--radius);
  background: rgba(255, 255, 255, .06); color: rgba(255, 255, 255, .5);
}
:root[data-tema="cerah"] .pt-pindai .sudut { position: absolute; width: 30px; height: 30px; border: 3px solid #3b82f6; }
:root[data-tema="cerah"] .pt-pindai .sudut.ka { top: 0; left: 0; border-right: none; border-bottom: none; border-radius: 10px 0 0 0; }
:root[data-tema="cerah"] .pt-pindai .sudut.kb { top: 0; right: 0; border-left: none; border-bottom: none; border-radius: 0 10px 0 0; }
:root[data-tema="cerah"] .pt-pindai .sudut.kc { bottom: 0; left: 0; border-right: none; border-top: none; border-radius: 0 0 0 10px; }
:root[data-tema="cerah"] .pt-pindai .sudut.kd { bottom: 0; right: 0; border-left: none; border-top: none; border-radius: 0 0 10px 0; }
:root[data-tema="cerah"] .pt-pindai .petunjuk-pil {
  display: inline-flex; align-items: center; gap: .4rem;
  padding: .5rem 1rem; border-radius: 999px;
  background: rgba(255, 255, 255, .14); font-size: .82rem; font-weight: 600;
}

/* ---- Kode manual ---- */
:root[data-tema="cerah"] .pt-manual { display: flex; align-items: center; gap: .75rem; flex-wrap: wrap; padding: 1rem; }
:root[data-tema="cerah"] .pt-manual > .lambang {
  width: 40px; height: 40px; flex: 0 0 40px; border-radius: 11px; display: grid; place-items: center;
  background: var(--lembut-biru); color: var(--aksen-pekat);
}
:root[data-tema="cerah"] .pt-manual .isi { flex: 0 1 auto; min-width: 150px; }
:root[data-tema="cerah"] .pt-manual .isi label { display: block; font-weight: 700; font-size: .95rem; color: var(--judul); }
:root[data-tema="cerah"] .pt-manual .isi .sub { display: block; font-size: .8rem; color: var(--abu-500); line-height: 1.35; }
:root[data-tema="cerah"] .pt-manual .kendali { flex: 1; min-width: 0; text-transform: uppercase; font-weight: 700; }

/* ---- Kartu umum ---- */
:root[data-tema="cerah"] .pt-kartu { padding: 1.1rem; }
:root[data-tema="cerah"] .pt-kartu-kepala { display: flex; align-items: flex-start; gap: .7rem; flex-wrap: wrap; margin-bottom: 1rem; }
:root[data-tema="cerah"] .pt-kartu-kepala .isi { flex: 1; min-width: 150px; }
:root[data-tema="cerah"] .pt-kartu-kepala h3 { font-size: 1.02rem; }
:root[data-tema="cerah"] .pt-kartu-kepala .sub { font-size: .82rem; color: var(--abu-500); margin: .1rem 0 0; line-height: 1.35; }
:root[data-tema="cerah"] .pt-kartu-kepala .lambang {
  flex: 0 0 36px; width: 36px; height: 36px; border-radius: 11px; display: grid; place-items: center;
  background: var(--biru-600); color: #fff;
}
:root[data-tema="cerah"] .pt-aksi {
  flex: 0 0 auto; display: inline-flex; align-items: center; gap: .25rem;
  font-size: .84rem; font-weight: 700; color: var(--aksen-pekat);
}

/* ---- Linimasa titik ---- */
:root[data-tema="cerah"] .pt-linimasa { list-style: none; margin: 0; padding: 0; }
:root[data-tema="cerah"] .pt-linimasa li {
  position: relative; display: flex; align-items: center; gap: .7rem; padding: .55rem 0 1rem;
}
:root[data-tema="cerah"] .pt-linimasa li:last-child { padding-bottom: 0; }
:root[data-tema="cerah"] .pt-linimasa li::before {
  content: ''; position: absolute; left: 11px; top: 30px; bottom: 0; width: 2px; background: var(--abu-200);
}
:root[data-tema="cerah"] .pt-linimasa li:last-child::before { display: none; }
:root[data-tema="cerah"] .pt-linimasa .titik {
  position: relative; z-index: 1; flex: 0 0 24px; width: 24px; height: 24px; border-radius: 50%;
  display: grid; place-items: center; background: var(--abu-200); color: #fff;
}
:root[data-tema="cerah"] .pt-linimasa li.selesai .titik { background: var(--hijau-700); }
:root[data-tema="cerah"] .pt-linimasa .jam {
  flex: 0 0 auto; min-width: 3.2rem; font-weight: 700; font-size: .88rem;
  color: var(--abu-900); font-variant-numeric: tabular-nums;
}
:root[data-tema="cerah"] .pt-linimasa li.menunggu .jam { color: var(--abu-500); font-weight: 600; }
:root[data-tema="cerah"] .pt-linimasa .isi { flex: 1; min-width: 0; }
:root[data-tema="cerah"] .pt-linimasa .isi .j { display: block; font-weight: 700; font-size: .9rem; color: var(--abu-900); }
:root[data-tema="cerah"] .pt-linimasa .isi .k {
  display: block; font-size: .78rem; color: var(--abu-500);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
:root[data-tema="cerah"] .pt-linimasa .status { flex: 0 0 auto; }
:root[data-tema="cerah"] .pt-chip {
  display: inline-block; padding: .25rem .7rem; border-radius: 999px;
  font-size: .78rem; font-weight: 700; white-space: nowrap;
}
:root[data-tema="cerah"] .pt-chip.hijau { background: #d1fae5; color: #065f46; }
:root[data-tema="cerah"] .pt-chip.abu { background: var(--abu-100); color: var(--abu-600); }

/* ---- Peta titik ---- */
:root[data-tema="cerah"] .pt-peta {
  height: 340px; border-radius: var(--radius); overflow: hidden;
  background: var(--abu-100); border: 1px solid var(--abu-200);
}

@media (max-width: 560px) {
  :root[data-tema="cerah"] .pt-hero-langkah { flex: 1 1 100%; display: flex; gap: 1rem; justify-content: center; }
  :root[data-tema="cerah"] .pt-tab button span:not(.ikon-svg) { display: none; }
  :root[data-tema="cerah"] .pt-manual .isi { flex: 1 1 100%; }
  :root[data-tema="cerah"] .pt-linimasa li { flex-wrap: wrap; }
  :root[data-tema="cerah"] .pt-linimasa .status { margin-left: auto; }
  :root[data-tema="cerah"] .pt-peta { height: 260px; }
}

/* ==========================================================================
   Kunjungan Sales — susunan khusus tema CERAH
   ========================================================================== */

:root[data-tema="cerah"] .kj-hero {
  display: flex; align-items: center; gap: 1.1rem; flex-wrap: wrap;
  padding: 1.2rem; border-radius: var(--radius-lg);
  background: linear-gradient(135deg, #dbeafe 0%, #eaf3ff 55%, #e3edfd 100%);
  border: 1px solid #cfe0fb;
}
:root[data-tema="cerah"] .kj-hero-lambang {
  width: 68px; height: 68px; flex: 0 0 68px; border-radius: 20px; display: grid; place-items: center;
  background: rgba(255, 255, 255, .75); color: #1d6fe0;
}
:root[data-tema="cerah"] .kj-hero-isi { flex: 1 1 220px; min-width: 0; }
:root[data-tema="cerah"] .kj-hero-isi h2 { font-size: 1.35rem; line-height: 1.22; letter-spacing: -.02em; }
:root[data-tema="cerah"] .kj-hero-isi p { margin: .3rem 0 0; font-size: .88rem; line-height: 1.4; color: var(--abu-600); }
:root[data-tema="cerah"] .kj-hero-kutipan {
  flex: 0 1 180px; min-width: 145px; padding: .7rem .9rem; border-radius: var(--radius);
  background: rgba(255, 255, 255, .55); border: 1px solid rgba(255, 255, 255, .9);
  font-style: italic; font-weight: 600; font-size: .86rem; line-height: 1.35; color: var(--aksen-pekat);
}

/* ---- Ubin ringkasan ---- */
:root[data-tema="cerah"] .kj-ubin-baris {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(148px, 1fr)); gap: .6rem;
}
:root[data-tema="cerah"] .kj-ubin {
  padding: .85rem .9rem; border-radius: var(--radius-lg);
  background: color-mix(in srgb, var(--ubin-warna) 11%, var(--putih));
}
:root[data-tema="cerah"] .kj-ubin .atas { display: flex; align-items: center; gap: .45rem; }
:root[data-tema="cerah"] .kj-ubin .bulat {
  width: 26px; height: 26px; flex: 0 0 26px; border-radius: 8px; display: grid; place-items: center;
  background: var(--ubin-kuat); color: #fff;
}
:root[data-tema="cerah"] .kj-ubin .l {
  font-size: .8rem; color: var(--abu-600); min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
:root[data-tema="cerah"] .kj-ubin .n {
  font-size: 1.6rem; font-weight: 800; line-height: 1.15; margin-top: .3rem;
  color: var(--ubin-kuat); font-variant-numeric: tabular-nums;
}
:root[data-tema="cerah"] .kj-ubin .k { font-size: .8rem; font-weight: 700; color: var(--abu-600); }

/* ---- Kartu sesi berjalan ---- */
:root[data-tema="cerah"] .kj-sesi {
  display: flex; align-items: center; gap: 1rem; flex-wrap: wrap;
  padding: 1.1rem; border-radius: var(--radius-lg);
  background: var(--lembut-biru); border: 1px solid var(--lembut-biru-kuat);
}
:root[data-tema="cerah"] .kj-sesi-lambang {
  width: 64px; height: 64px; flex: 0 0 64px; border-radius: 50%; display: grid; place-items: center;
  background: var(--putih); color: var(--aksen-pekat);
}
:root[data-tema="cerah"] .kj-sesi-isi { flex: 1 1 200px; min-width: 0; }
:root[data-tema="cerah"] .kj-sesi-isi .chip {
  display: inline-block; padding: .2rem .7rem; border-radius: 999px; margin-bottom: .25rem;
  background: var(--putih); color: var(--aksen-pekat); font-size: .76rem; font-weight: 700;
}
:root[data-tema="cerah"] .kj-sesi-isi h3 { font-size: 1.15rem; }
:root[data-tema="cerah"] .kj-sesi-isi .alamat,
:root[data-tema="cerah"] .kj-sesi-isi .jarak {
  display: flex; align-items: center; gap: .3rem; margin: .2rem 0 0;
  font-size: .82rem; color: var(--abu-600); line-height: 1.35;
}
/* #065f46, bukan --hijau-700: latarnya --lembut-biru (bukan kartu putih), dan hijau-700 di sana
   tinggal 4,40:1 — meleset tipis dari ambang AA untuk teks sekecil ini. */
:root[data-tema="cerah"] .kj-sesi-isi .jarak { color: #065f46; font-weight: 600; }
:root[data-tema="cerah"] .kj-sesi-kanan {
  flex: 0 0 auto; display: flex; flex-direction: column; align-items: stretch; gap: .45rem;
}
:root[data-tema="cerah"] .kj-timer {
  display: block; text-align: center; padding: .4rem .9rem; border-radius: 999px;
  background: var(--putih); color: var(--judul);
  font-size: 1.15rem; font-weight: 800; font-variant-numeric: tabular-nums;
}
:root[data-tema="cerah"] .kj-akhiri {
  display: inline-flex; align-items: center; justify-content: center; gap: .4rem;
  padding: .65rem 1.1rem; border: none; border-radius: 999px; cursor: pointer; font: inherit;
  font-size: .92rem; font-weight: 700;
  background: linear-gradient(135deg, #1a5fc4, #0f4494); color: #fff;
}
:root[data-tema="cerah"] .kj-akhiri:hover:not(:disabled) { filter: brightness(1.08); }
:root[data-tema="cerah"] .kj-batal {
  border: none; background: none; cursor: pointer; font: inherit;
  font-size: .8rem; font-weight: 600; color: var(--abu-600); text-decoration: underline;
}

/* ---- Tombol mulai kunjungan (disisipkan ke formulir) ---- */
:root[data-tema="cerah"] .kj-mulai {
  display: flex; align-items: center; justify-content: center; gap: .5rem; width: 100%;
  margin-bottom: 1rem; padding: .8rem 1rem; border-radius: 999px; cursor: pointer; font: inherit;
  font-size: .95rem; font-weight: 700;
  border: 1px solid var(--biru-500); background: var(--lembut-biru); color: var(--aksen-pekat);
}
:root[data-tema="cerah"] .kj-mulai:hover:not(:disabled) { background: var(--lembut-biru-kuat); }

/* ---- Kartu & tautan ---- */
:root[data-tema="cerah"] .kj-kartu { padding: 1.1rem; }
:root[data-tema="cerah"] .kj-kartu-kepala { display: flex; align-items: flex-start; gap: .7rem; flex-wrap: wrap; margin-bottom: 1rem; }
:root[data-tema="cerah"] .kj-kartu-kepala .isi { flex: 1; min-width: 150px; }
:root[data-tema="cerah"] .kj-kartu-kepala h3 { font-size: 1.02rem; }
:root[data-tema="cerah"] .kj-kartu-kepala .sub { font-size: .82rem; color: var(--abu-500); margin: .1rem 0 0; line-height: 1.35; }
:root[data-tema="cerah"] .kj-kartu-kepala .lambang {
  flex: 0 0 36px; width: 36px; height: 36px; border-radius: 11px; display: grid; place-items: center; color: #fff;
}
:root[data-tema="cerah"] .kj-kartu-kepala .lambang.biru { background: var(--biru-600); }
:root[data-tema="cerah"] .kj-kartu-kepala .lambang.ungu { background: #7c3aed; }

:root[data-tema="cerah"] .kj-tautan { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: .6rem; }
:root[data-tema="cerah"] .kj-tautan-kartu {
  display: flex; align-items: center; gap: .7rem; padding: .9rem 1rem; border-radius: var(--radius-lg);
  background: var(--putih); border: 1px solid var(--abu-200); box-shadow: var(--bayang-sm);
}
:root[data-tema="cerah"] .kj-tautan-kartu:hover { box-shadow: var(--bayang); text-decoration: none; }
:root[data-tema="cerah"] .kj-tautan-kartu .lambang {
  width: 38px; height: 38px; flex: 0 0 38px; border-radius: 11px; display: grid; place-items: center;
  background: var(--lembut-biru); color: var(--aksen-pekat);
}
:root[data-tema="cerah"] .kj-tautan-kartu .isi { flex: 1; min-width: 0; }
:root[data-tema="cerah"] .kj-tautan-kartu .isi .j { display: block; font-weight: 700; color: var(--judul); }
:root[data-tema="cerah"] .kj-tautan-kartu .isi .k { display: block; font-size: .8rem; color: var(--abu-500); }
:root[data-tema="cerah"] .kj-tautan-kartu .panah { flex: 0 0 auto; color: var(--abu-400); }

@media (max-width: 560px) {
  :root[data-tema="cerah"] .kj-hero-kutipan { flex: 1 1 100%; }
  :root[data-tema="cerah"] .kj-ubin-baris { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  :root[data-tema="cerah"] .kj-sesi-kanan { flex: 1 1 100%; }
}

/* ==========================================================================
   Kartu puncak dashboard tema CERAH — tiga slide bergeser
   (jam absen · kalender shift · pratinjau slip gaji)
   ========================================================================== */

/* Tiap slide dipatok setinggi slide tertinggi supaya titik indikator tidak melompat naik-turun
   saat digeser. `align-items: stretch` pada trek sudah bawaan flex; yang perlu dijamin adalah
   slide-nya benar-benar memenuhi tinggi slotnya. */
:root[data-tema="cerah"] .cerah-dasbor .geser-slot > .cerah-hero,
:root[data-tema="cerah"] .cerah-slide { height: 100%; }

:root[data-tema="cerah"] .cerah-slide {
  display: flex; flex-direction: column;
  padding: 1.2rem; border-radius: 24px;
  background: linear-gradient(145deg, #1a5fc4 0%, #1657bb 45%, #0f4494 100%);
  color: #fff; box-shadow: 0 16px 34px -14px rgba(15, 68, 148, .65);
}
:root[data-tema="cerah"] .cerah-slide .kosong {
  margin: auto; padding: 2rem 0; text-align: center; color: rgba(255, 255, 255, .9); font-size: .9rem;
}
:root[data-tema="cerah"] .cerah-slide .kop {
  display: flex; align-items: flex-start; justify-content: space-between; gap: .8rem; margin-bottom: .9rem;
}
:root[data-tema="cerah"] .cerah-slide .kop .l { display: block; font-size: .88rem; color: rgba(255, 255, 255, .9); }
:root[data-tema="cerah"] .cerah-slide .kop .j { display: block; font-size: 1.2rem; font-weight: 800; letter-spacing: -.01em; }
:root[data-tema="cerah"] .cerah-slide .tautan {
  flex: 0 0 auto; display: inline-flex; align-items: center; gap: .25rem;
  padding: .3rem .7rem; border-radius: 999px;
  /* .10, bukan .16 — makin putih latarnya makin turun kontras teks putih di atasnya; pada .16
     tinggal 4,35:1. */
  background: rgba(255, 255, 255, .10); color: #fff; font-size: .8rem; font-weight: 700;
}
:root[data-tema="cerah"] .cerah-slide .tautan:hover { background: rgba(255, 255, 255, .2); text-decoration: none; }

/* ---- Slide kalender shift ---- */
:root[data-tema="cerah"] .cerah-slide-kalender .hari,
:root[data-tema="cerah"] .cerah-slide-kalender .kisi {
  display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 2px;
}
:root[data-tema="cerah"] .cerah-slide-kalender .hari {
  font-size: .72rem; font-weight: 700; text-align: center; color: rgba(255, 255, 255, .82); margin-bottom: .25rem;
}
:root[data-tema="cerah"] .cerah-slide-kalender .sel {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 1px;
  min-height: 34px; border-radius: 7px; background: rgba(255, 255, 255, .10);
}
:root[data-tema="cerah"] .cerah-slide-kalender .sel.kosong { background: none; }
:root[data-tema="cerah"] .cerah-slide-kalender .sel .t { font-size: .76rem; font-weight: 700; line-height: 1; }
/* Kode shift ditulis di atas warna shiftnya sendiri, dan warna itu datang dari basis data —
   bisa terang maupun gelap. Warna teksnya karena itu TIDAK dipatok di sini melainkan dihitung
   per shift oleh kontrasTeks() (lihat slideKalenderCerah): teks gelap yang dipatok akan hilang
   di atas shift berwarna ungu/biru tua. */
:root[data-tema="cerah"] .cerah-slide-kalender .sel .k {
  padding: 0 3px; border-radius: 3px; font-size: .56rem; font-weight: 800;
  max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
:root[data-tema="cerah"] .cerah-slide-kalender .sel.libur { background: rgba(248, 113, 113, .26); }
/* Putih penuh, bukan merah muda: di atas sel libur yang sudah kemerahan, #ffe1e1 tinggal 4,49:1. */
:root[data-tema="cerah"] .cerah-slide-kalender .sel.libur .t { color: #fff; }
:root[data-tema="cerah"] .cerah-slide-kalender .sel.hari-ini { outline: 2px solid #fff; outline-offset: -2px; }
:root[data-tema="cerah"] .cerah-slide-kalender .kaki {
  margin-top: auto; padding-top: .7rem; font-size: .78rem; color: rgba(255, 255, 255, .9); line-height: 1.35;
}

/* ---- Slide slip gaji ---- */
:root[data-tema="cerah"] .cerah-slide-gaji .g-mata {
  flex: 0 0 auto; width: 34px; height: 34px; border-radius: 50%; border: none; cursor: pointer;
  display: grid; place-items: center; background: rgba(255, 255, 255, .18); color: #fff;
}
:root[data-tema="cerah"] .cerah-slide-gaji .g-mata:hover { background: rgba(255, 255, 255, .3); }
:root[data-tema="cerah"] .cerah-slide-gaji .nominal {
  min-height: 2.4rem; display: flex; align-items: center;
  font-size: 1.85rem; font-weight: 800; letter-spacing: -.02em; font-variant-numeric: tabular-nums;
}
:root[data-tema="cerah"] .cerah-slide-gaji .g-titik { font-size: 1.5rem; letter-spacing: .18em; }
:root[data-tema="cerah"] .cerah-slide-gaji .rinci { list-style: none; margin: .5rem 0 0; padding: 0; }
:root[data-tema="cerah"] .cerah-slide-gaji .rinci li {
  display: flex; justify-content: space-between; gap: .6rem;
  padding: .35rem 0; font-size: .88rem; border-bottom: 1px solid rgba(255, 255, 255, .18);
}
:root[data-tema="cerah"] .cerah-slide-gaji .rinci li:last-child { border-bottom: none; }
:root[data-tema="cerah"] .cerah-slide-gaji .rinci .k { color: rgba(255, 255, 255, .9); }
:root[data-tema="cerah"] .cerah-slide-gaji .rinci .v { font-weight: 700; font-variant-numeric: tabular-nums; }
:root[data-tema="cerah"] .cerah-slide-gaji .tautan-kaki {
  display: inline-flex; align-items: center; gap: .3rem; margin-top: auto; padding-top: .7rem;
  color: #fff; font-size: .85rem; font-weight: 700;
}
:root[data-tema="cerah"] .cerah-slide-gaji .catatan { margin: .3rem 0 0; font-size: .76rem; color: rgba(255, 255, 255, .82); }

/* Titik indikator geser: warnanya disesuaikan agar terlihat di atas latar halaman yang terang. */
:root[data-tema="cerah"] .cerah-dasbor .geser-titik button { background: var(--abu-300); }
:root[data-tema="cerah"] .cerah-dasbor .geser-titik button.aktif { background: var(--biru-600); }

/* ==========================================================================
   Dashboard admin & moderator — hanya bagian yang KHAS admin
   --------------------------------------------------------------------------
   Sisanya sengaja memakai kelas dashboard karyawan apa adanya (.cerah-sapa, .cerah-hero,
   .cerah-slide, .cerah-kartu, .cerah-rekap, .cerah-ubin). Menyalinnya menjadi .ad-* hanya akan
   membuat perbaikan kontras atau jarak di satu sisi diam-diam tidak sampai ke sisi lain.
   ========================================================================== */

/* Angka kehadiran ditulis sebagai pecahan: "12" tidak berarti apa-apa, "12/20" langsung terbaca.
   Penyebutnya dikecilkan & diredupkan supaya pembilangnya tetap yang pertama tertangkap mata. */
:root[data-tema="cerah"] .ad-pembagi {
  font-size: .5em; font-weight: 700; color: rgba(255, 255, 255, .82); margin-left: .1em;
}

/* Baris chip rincian status. Hanya digambar untuk status yang jumlahnya > 0 — chip "0 Sakit"
   memakan ruang untuk mengabarkan ketiadaan. */
:root[data-tema="cerah"] .ad-chip {
  display: flex; flex-wrap: wrap; gap: .4rem; margin-top: 1.1rem;
}
:root[data-tema="cerah"] .ad-chip .k {
  padding: .25rem .7rem; border-radius: 999px;
  /* Menggelapkan, tidak memutihkan — alasan yang sama seperti chip jam pada .cerah-hero-shift:
     latar putih tembus pandang justru menaikkan luminansi biru di baliknya dan menjatuhkan
     kontras teks putihnya di ujung tercerah gradasi. */
  background: rgba(0, 0, 0, .18); border: 1px solid rgba(255, 255, 255, .22);
  font-size: .78rem; font-weight: 600; white-space: nowrap;
}
:root[data-tema="cerah"] .ad-chip .k b { font-weight: 800; }

/* Pratinjau antrean pengajuan pada kartu geser ketiga. */
:root[data-tema="cerah"] .ad-antrian { list-style: none; margin: 0; padding: 0; }
:root[data-tema="cerah"] .ad-antrian li {
  display: flex; align-items: center; gap: .5rem;
  padding: .45rem 0; border-bottom: 1px solid rgba(255, 255, 255, .18); font-size: .86rem;
}
:root[data-tema="cerah"] .ad-antrian li:last-child { border-bottom: none; }
:root[data-tema="cerah"] .ad-antrian .n { flex: 1; min-width: 0; font-weight: 700; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
:root[data-tema="cerah"] .ad-antrian .j { flex: 0 0 auto; color: rgba(255, 255, 255, .88); }
:root[data-tema="cerah"] .ad-antrian .t { flex: 0 0 auto; font-size: .78rem; color: rgba(255, 255, 255, .82); font-variant-numeric: tabular-nums; }
:root[data-tema="cerah"] .cerah-slide-antrian .catatan { margin: .5rem 0 0; font-size: .78rem; color: rgba(255, 255, 255, .82); }

/* Ubin Identitas Perusahaan bagi admin non-moderator: tetap digambar, tetapi tidak bisa ditekan.
   Dihilangkan sama sekali, admin akan mengira datanya tidak ada — bukan bahwa ia tidak berwenang. */
:root[data-tema="cerah"] .ad-ubin-mati { opacity: .65; cursor: not-allowed; }
:root[data-tema="cerah"] .cerah-ubin small { display: block; font-weight: 600; opacity: .78; font-size: .72rem; }

/* ==========================================================================
   Widget chat — layar depan bergaya kartu (kepala hero, kartu Admin/HR,
   pencarian, daftar rekan & departemen). Tidak dikurung tema: seluruhnya
   memakai token, jadi benar di tema terang, gelap, maupun cerah.
   ========================================================================== */

.chat-hero {
  position: relative; flex: 0 0 auto; overflow: hidden;
  padding: 1.1rem 1rem 1.2rem;
  /* Stop tercerahnya #1a5fc4, bukan #2f86f2: seluruh teks di kepala ini putih (sebagian
     semi-transparan), dan di atas biru yang lebih cerah teks kecilnya tinggal ~3,2:1. */
  background: linear-gradient(135deg, #1a5fc4, #0f4494); color: #fff;
}
.chat-hero-teks { position: relative; z-index: 1; max-width: 62%; }
.chat-hero-teks .j { font-size: 1.5rem; font-weight: 800; letter-spacing: -.02em; line-height: 1.1; }
.chat-hero-teks .k { font-size: .84rem; line-height: 1.35; color: rgba(255, 255, 255, .9); margin-top: .2rem; }
.chat-hero-lambang {
  position: absolute; right: 3.2rem; top: 50%; transform: translateY(-50%);
  color: rgba(255, 255, 255, .3); pointer-events: none;
}
.chat-hero-kutipan {
  position: absolute; right: .9rem; bottom: .8rem; text-align: right;
  font-style: italic; font-weight: 700; font-size: .78rem; line-height: 1.25;
  color: rgba(255, 255, 255, .92); pointer-events: none;
}
.chat-hero #chat-minimize {
  position: absolute; right: .7rem; top: .7rem; z-index: 2;
  width: 30px; height: 30px; border-radius: 9px; border: none; cursor: pointer;
  display: grid; place-items: center;
  /* .12, bukan .2 — makin putih latarnya makin turun kontras ikon putih di atasnya. */
  background: rgba(255, 255, 255, .12); color: #fff;
}
.chat-hero #chat-minimize:hover { background: rgba(255, 255, 255, .26); }

/* ---- Kartu Admin/HR ---- */
.chat-kartu-admin {
  display: flex; align-items: center; gap: .7rem;
  margin: .7rem .75rem 0; width: calc(100% - 1.5rem);
  padding: .8rem .85rem; border: none; border-radius: var(--radius); cursor: pointer;
  background: var(--lembut-biru); font: inherit; text-align: left;
}
.chat-kartu-admin:hover { background: var(--lembut-biru-kuat); }
.chat-kartu-admin .lambang {
  width: 44px; height: 44px; flex: 0 0 44px; border-radius: 12px; display: grid; place-items: center;
  background: var(--biru-700); color: #fff;
}
.chat-kartu-admin .isi { flex: 1; min-width: 0; }
.chat-kartu-admin .isi .j {
  display: flex; align-items: center; gap: .4rem;
  font-weight: 700; font-size: .95rem; color: var(--judul);
}
.chat-kartu-admin .isi .k { display: block; font-size: .8rem; color: var(--abu-600); line-height: 1.3; }
.chat-kartu-admin .panah { flex: 0 0 auto; color: var(--aksen-teks); }

/* ---- Pencarian layar depan ---- */
.chat-cari { position: relative; margin: .7rem .75rem .2rem; }
.chat-cari .ikon { position: absolute; left: .7rem; top: 50%; transform: translateY(-50%); color: var(--abu-400); pointer-events: none; }
.chat-cari .kendali { padding-left: 2.2rem; border-radius: 999px; }

/* ---- Judul bagian ---- */
.chat-bagian {
  display: flex; align-items: baseline; justify-content: space-between; gap: .6rem;
  padding: .9rem .85rem .35rem;
}
.chat-bagian .j { font-weight: 800; font-size: 1rem; color: var(--judul); }
.chat-lihat {
  border: none; background: none; cursor: pointer; font: inherit;
  display: inline-flex; align-items: center; gap: .2rem;
  font-size: .82rem; font-weight: 700; color: var(--aksen-teks);
}
.chat-kosong { margin: 0; padding: .8rem .85rem; font-size: .84rem; color: var(--abu-500); }
.chat-kosong-rapat { padding-top: 0; padding-bottom: .3rem; font-size: .78rem; }

/* ---- Avatar dengan titik online ---- */
.chat-ava { position: relative; flex: 0 0 auto; display: block; }
.chat-ava .titik {
  position: absolute; right: -1px; bottom: -1px; width: 10px; height: 10px; border-radius: 50%;
  background: var(--hijau-600); border: 2px solid var(--putih);
}
/* --abu-500, bukan --abu-400: panah ini menandai baris yang bisa dibuka, jadi ia membawa makna;
   abu-400 di atas kartu hanya 2,4-2,6:1, di bawah ambang 3:1 untuk elemen non-teks. */
.chat-daftar-item .panah { flex: 0 0 auto; color: var(--abu-500); }

/* ---- Baris departemen ---- */
.chat-dept-lambang {
  width: 36px; height: 36px; flex: 0 0 36px; border-radius: 11px; display: grid; place-items: center;
  /* Bidang pekat berlambang putih, bukan tint berlambang berwarna: tint dicampur dari --putih
     sehingga kontrasnya ikut berubah per tema, sedangkan putih di atas --ubin-kuat bernilai sama
     di mana pun. */
  background: var(--ubin-kuat); color: #fff;
}

/* ---- Tombol mulai chat baru ---- */
.chat-mulai {
  display: flex; align-items: center; justify-content: center; gap: .45rem;
  margin: .9rem .75rem 1rem; width: calc(100% - 1.5rem);
  padding: .75rem 1rem; border-radius: var(--radius); cursor: pointer; font: inherit;
  font-size: .92rem; font-weight: 700;
  border: 1px dashed var(--biru-500); background: var(--putih); color: var(--aksen-teks);
}
.chat-mulai:hover { background: var(--lembut-biru); }

/* ==========================================================================
   Layar kamera absensi — tata letak layar penuh
   --------------------------------------------------------------------------
   Dipakai HANYA saat bukaKamera() diberi opsi `absen`. Modal kamera biasa (pendaftaran wajah di
   Profil, foto bukti patroli) tetap memakai .kamera-wadah dan tidak tersentuh satu aturan pun di
   bawah ini.
   ========================================================================== */

/* Kepala & kaki modal disembunyikan: seluruh kontrol layar ini hidup di dalam isinya. Modalnya
   sendiri tetap dipakai supaya Esc, klik-latar, dan kunci gulir badan ikut apa adanya. */
.modal-latar.kamera-absen .modal-kepala,
.modal-latar.kamera-absen .modal-kaki { display: none; }
.modal-latar.kamera-absen { padding: 0; background: #000; }
.modal-latar.kamera-absen .modal {
  width: 100%; max-width: none; height: 100dvh; margin: 0;
  border-radius: 0; background: #000; box-shadow: none; border: none;
  -webkit-backdrop-filter: none; backdrop-filter: none;
}
.modal-latar.kamera-absen .modal-isi { padding: 0; max-height: none; height: 100%; overflow: hidden; }

/*
 * Layar dibagi dua yang tidak saling menumpuk: kamera di atas (meregang mengisi sisa ruang), panel
 * kendali di bawah dengan tingginya sendiri. Sebelumnya panel melayang di atas gambar dan keempat
 * kartu statusnya justru menutupi wajah yang sedang dinilai.
 */
.ka-layar {
  display: flex; flex-direction: column;
  width: 100%; height: 100%; overflow: hidden; background: #0f172a;
}
.ka-kamera { position: relative; flex: 1 1 auto; min-height: 0; overflow: hidden; }

/*
 * `cover` — kamera MENGISI PENUH areanya, tanpa menyisakan bidang kosong di atas & bawah.
 *
 * Ini mungkin justru karena area kameranya bukan lagi seluruh layar: dengan panel kendali punya
 * ruangnya sendiri, sisa area untuk kamera jauh lebih dekat ke rasio kameranya, sehingga yang
 * terpotong tinggal sedikit. Dengan `contain` sebelumnya, bidang kosong itu muncul justru karena
 * layar ponsel jauh lebih jangkung daripada bidang kamera mana pun.
 */
.ka-kamera video, .ka-kamera #kamera-hasil {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
  /* Cermin: kamera depan terasa alami dipakai seperti bercermin. */
  transform: scaleX(-1);
}
.ka-kamera video[hidden], .ka-kamera #kamera-hasil[hidden] { display: none; }
.ka-kamera .kamera-bingkai {
  /* Ikut `cover` supaya kotak penanda wajah mendarat tepat di atas wajah yang dilihat — kanvas
     dan video yang berbeda object-fit akan menggeser seluruh koordinatnya. */
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; transform: scaleX(-1);
  pointer-events: none;
}

/* ---- Bagian atas ---- */
.ka-atas {
  position: absolute; left: 0; right: 0; top: 0; z-index: 3;
  padding: calc(.6rem + env(safe-area-inset-top)) 1rem .9rem;
  text-align: center; color: var(--judul);
  /* Gradasi, bukan bidang rata: teks gelap di atasnya butuh latar terang, tetapi memotong kamera
     dengan garis lurus membuat layar terbaca seperti dua panel yang tidak berhubungan. */
  background: linear-gradient(180deg, rgba(255, 255, 255, .96) 0%, rgba(255, 255, 255, .88) 62%, rgba(255, 255, 255, 0) 100%);
}
.ka-baris-atas { display: flex; align-items: center; justify-content: space-between; gap: .6rem; }
.ka-merek { display: flex; align-items: center; justify-content: center; min-width: 0; }
.ka-merek img, .ka-merek svg { max-height: 34px; width: auto; }
.ka-bulat {
  flex: 0 0 auto; width: 42px; height: 42px; border-radius: 50%; border: none; cursor: pointer;
  display: grid; place-items: center; background: rgba(255, 255, 255, .92); color: var(--aksen-pekat);
  box-shadow: var(--bayang-sm);
}
/* Ikon panah dipakai ulang, diputar — tidak perlu satu ikon baru hanya untuk arah yang berlawanan. */
.ka-bulat .ikon-svg { transform: rotate(180deg); }
/* Penyeimbang tak terlihat seukuran tombol kembali. Tanpa ini, logo perusahaan bergeser ke kanan
   begitu tombol Flash dicabut — flex space-between hanya punya dua anak untuk dibagi. */
.ka-bulat-kosong { flex: 0 0 42px; height: 42px; }

.ka-judul { margin: .7rem 0 0; font-size: 1.6rem; font-weight: 800; letter-spacing: -.02em; }
.ka-sub { margin: .15rem 0 0; font-size: .95rem; color: var(--abu-600); }
.ka-jam {
  display: inline-flex; align-items: center; gap: .45rem; margin-top: .7rem;
  padding: .45rem 1rem; border-radius: 999px; background: rgba(255, 255, 255, .92);
  box-shadow: var(--bayang-sm); font-size: .92rem; color: var(--abu-700);
}
.ka-jam .ikon-svg { color: var(--aksen-teks); }
.ka-jam b { color: var(--aksen-teks); font-variant-numeric: tabular-nums; font-weight: 800; }

/* ---- Bingkai bidik ---- */
/* Empat sudut, bukan kotak penuh: bingkai tertutup menghalangi wajah yang justru sedang dinilai. */
.ka-bidik {
  position: absolute; z-index: 2; pointer-events: none;
  left: 50%; top: 52%; transform: translate(-50%, -50%);
  width: min(58vw, 240px); aspect-ratio: 3 / 4;
}
.ka-bidik i {
  position: absolute; width: 42px; height: 42px;
  border: 4px solid rgba(255, 255, 255, .95); border-radius: 6px;
}
.ka-bidik i:nth-child(1) { top: 0; left: 0; border-right: none; border-bottom: none; border-top-left-radius: 18px; }
.ka-bidik i:nth-child(2) { top: 0; right: 0; border-left: none; border-bottom: none; border-top-right-radius: 18px; }
.ka-bidik i:nth-child(3) { bottom: 0; right: 0; border-left: none; border-top: none; border-bottom-right-radius: 18px; }
.ka-bidik i:nth-child(4) { bottom: 0; left: 0; border-right: none; border-top: none; border-bottom-left-radius: 18px; }

/* ---- Tombol samping ---- */
.ka-sisi {
  position: absolute; right: .8rem; top: 50%; z-index: 3;
  display: flex; flex-direction: column; gap: 1rem; align-items: center;
}
.ka-sisi-tbl {
  display: flex; flex-direction: column; align-items: center; gap: .3rem;
  border: none; background: none; cursor: pointer; font: inherit; color: #fff;
  font-size: .74rem; font-weight: 600; line-height: 1.15; text-align: center;
  /* Halo: label putih ini melayang di atas gambar kamera yang isinya tak bisa diduga. */
  text-shadow: 0 1px 3px rgba(0, 0, 0, .75);
}
.ka-sisi-tbl .b {
  width: 46px; height: 46px; border-radius: 50%; display: grid; place-items: center;
  background: rgba(15, 23, 42, .55); border: 1px solid rgba(255, 255, 255, .35);
  -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
}

/* ---- Pil petunjuk ---- */
.ka-petunjuk {
  position: absolute; left: 50%; bottom: 1rem; transform: translateX(-50%); z-index: 3;
  display: inline-flex; align-items: center; gap: .5rem; max-width: 80vw;
  padding: .5rem .9rem; border-radius: 999px;
  background: rgba(15, 23, 42, .62); color: #fff; font-size: .86rem; font-weight: 500;
  -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
}
.ka-petunjuk .ikon-svg { flex: 0 0 auto; }

/* ---- Panel bawah ---- */
/* Latar PUTIH SOLID, bukan gradasi di atas gambar: panel ini kini punya ruangnya sendiri, dan
   teksnya tidak perlu lagi bersaing dengan isi kamera yang tak bisa diduga. */
.ka-bawah {
  flex: 0 0 auto;
  padding: .9rem .9rem calc(.9rem + env(safe-area-inset-bottom));
  display: flex; flex-direction: column; gap: .7rem;
  background: var(--putih);
  border-radius: var(--radius-lg) var(--radius-lg) 0 0;
  /* Mengangkat panel dari gambar kamera di atasnya, menegaskan keduanya lapisan berbeda. */
  box-shadow: 0 -8px 24px -12px rgba(15, 37, 87, .3);
}

.ka-status-baris { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: .5rem; }
.ka-status {
  position: relative; display: flex; flex-direction: column; align-items: center; gap: .15rem;
  padding: .6rem .3rem; border-radius: var(--radius); background: var(--abu-50);
  font-size: .72rem; text-align: center;
}
.ka-status .i { color: var(--abu-500); }
.ka-status .l { font-weight: 600; color: var(--abu-700); }
.ka-status .v { font-weight: 700; color: var(--abu-500); }
/* Tanda centang/silang di sudut — penanda kedua di samping warna, supaya keadaannya tetap terbaca
   oleh mata yang sulit membedakan hijau dan merah. */
.ka-status .tanda {
  position: absolute; right: .35rem; top: .35rem; width: 14px; height: 14px; border-radius: 50%;
  display: none; place-items: center; font-size: .6rem; font-weight: 800; color: #fff;
}
.ka-status[data-keadaan="ok"] { background: #eafaf0; }
.ka-status[data-keadaan="ok"] .i { color: var(--hijau-700); }
.ka-status[data-keadaan="ok"] .v { color: var(--hijau-700); }
.ka-status[data-keadaan="ok"] .tanda { display: grid; background: var(--hijau-700); }
.ka-status[data-keadaan="ok"] .tanda::after { content: '✓'; }
.ka-status[data-keadaan="gagal"] { background: #fdecec; }
.ka-status[data-keadaan="gagal"] .i,
.ka-status[data-keadaan="gagal"] .v { color: var(--merah-600); }
.ka-status[data-keadaan="gagal"] .tanda { display: grid; background: var(--merah-600); }
.ka-status[data-keadaan="gagal"] .tanda::after { content: '!'; }

.ka-lokasi {
  display: flex; align-items: center; gap: .6rem;
  padding: .65rem .8rem; border-radius: var(--radius); background: var(--abu-50);
}
.ka-lokasi .i { flex: 0 0 auto; color: var(--aksen-teks); }
.ka-lokasi .t { flex: 1; min-width: 0; display: flex; flex-direction: column; line-height: 1.25; }
.ka-lokasi .t b { font-size: .92rem; color: var(--judul); }
.ka-lokasi .t i { font-size: .78rem; font-style: normal; color: var(--abu-600); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ka-detail {
  flex: 0 0 auto; display: inline-flex; align-items: center; gap: .2rem; cursor: pointer;
  padding: .4rem .7rem; border: none; border-radius: 999px;
  background: var(--lembut-biru); color: var(--aksen-pekat); font: inherit; font-size: .8rem; font-weight: 700;
}

/* ---- Rana ---- */
.ka-rana-baris { display: flex; align-items: center; justify-content: center; gap: .8rem; }
.ka-rana {
  width: 74px; height: 74px; flex: 0 0 74px; border-radius: 50%; cursor: pointer;
  display: grid; place-items: center; color: #fff;
  background: var(--biru-700); border: 5px solid #fff;
  box-shadow: 0 6px 18px -4px rgba(15, 37, 87, .45);
  transition: transform .15s ease, background var(--transisi);
}
.ka-rana:active:not(:disabled) { transform: scale(.94); }
.ka-rana:disabled { background: var(--abu-400); cursor: not-allowed; box-shadow: none; }
.ka-rana.pratinjau { background: var(--hijau-700); }
.ka-ulang {
  padding: .6rem 1rem; border-radius: 999px; border: 1px solid var(--abu-300);
  background: var(--putih); color: var(--abu-700); font: inherit; font-weight: 700; cursor: pointer;
}


/* ---- Keterangan pada peta Detail Lokasi ---- */
/*
 * Baris keterangan di bawah peta: jarak Anda ke titik kantor, atau sebab posisinya tidak bisa
 * diambil. Warnanya mengikuti keadaan supaya terbaca sekilas — tetapi angkanya SELALU disebut,
 * termasuk saat di luar jangkauan: "di luar area" tanpa angka tidak memberi tahu apakah orangnya
 * kurang sepuluh meter atau salah kota.
 */
.ka-peta-ket {
  display: flex; align-items: center; gap: .55rem;
  margin-top: .8rem; padding: .7rem .9rem; border-radius: var(--radius);
  background: var(--abu-50); color: var(--abu-700); font-size: .88rem; line-height: 1.35;
}
.ka-peta-ket .lambang { flex: 0 0 auto; color: var(--abu-500); }
.ka-peta-ket.hijau { background: #eafaf0; color: var(--hijau-700); }
.ka-peta-ket.hijau .lambang { color: var(--hijau-700); }
/* --merah-700, bukan --merah-600: di atas latar merah muda ini --merah-600 hanya 4,23:1. */
.ka-peta-ket.merah { background: #fdecec; color: #b91c1c; }
.ka-peta-ket.merah .lambang { color: #b91c1c; }
.ka-peta-ket.netral { background: var(--lembut-biru); color: var(--aksen-pekat); }
.ka-peta-ket.netral .lambang { color: var(--aksen-pekat); }

/* Layar pendek (ponsel mendatar): panel bawah dipadatkan agar rana tetap terjangkau. */
@media (max-height: 680px) {
  .ka-judul { font-size: 1.25rem; }
  .ka-sub { display: none; }
  .ka-rana { width: 62px; height: 62px; flex-basis: 62px; }
  .ka-status { padding: .45rem .25rem; font-size: .68rem; }
  .ka-jam { display: none; }
}

/* ==========================================================================
   Halaman Masuk — penyempurnaan tampilan
   --------------------------------------------------------------------------
   Menumpang pada kerangka switcher yang sudah ada (.auth-tukar), bukan menggantikannya: animasi
   berpindah Masuk <-> Daftar beserta ketiga lapisannya tetap seperti semula. Yang ditambahkan di
   sini hanya hiasan latar, penanda bidang, dan pemisah.
   ========================================================================== */

/*
 * Hiasan latar: lingkaran lembut di kiri atas dan kisi titik di kanan atas.
 *
 * Digambar sebagai pseudo-elemen pada .auth-putih, bukan sebagai <div> tambahan — keduanya murni
 * hiasan dan tidak boleh pernah muncul di pohon aksesibilitas maupun ikut tersalin saat teks
 * halaman diseleksi. pointer-events dimatikan supaya tidak pernah menghalangi bidang isian.
 */
.auth-putih::before {
  content: ''; position: absolute; left: -120px; top: -140px; z-index: 0;
  width: 320px; height: 320px; border-radius: 50%;
  background: radial-gradient(circle at 60% 60%, rgba(37, 99, 235, .13), rgba(37, 99, 235, .04) 70%);
  pointer-events: none;
}
.auth-putih::after {
  content: ''; position: absolute; right: 18px; top: 120px; z-index: 0;
  width: 132px; height: 108px;
  background-image: radial-gradient(rgba(37, 99, 235, .28) 1.6px, transparent 1.6px);
  background-size: 18px 18px;
  pointer-events: none;
}
/* Isi formulir harus berada DI ATAS kedua hiasan itu — keduanya digambar pada induk yang sama. */
.auth-putih > .auth-kotak { position: relative; z-index: 1; }

/* ---- Bidang berpenanda ikon ---- */
/*
 * Ikon duduk di LUAR kotak isian, bukan di dalamnya. Ikon di dalam kotak memakan lebar yang
 * dipakai teks — dan pada bidang email, alamat panjang jadi terpotong lebih awal.
 */
.auth-bidang { display: flex; align-items: flex-start; gap: .75rem; }
.auth-bidang > .isi { flex: 1; min-width: 0; }
.auth-lambang {
  flex: 0 0 52px; height: 52px; border-radius: 16px; display: grid; place-items: center;
  background: var(--biru-50); color: var(--biru-700);
  /* Sejajar dengan kotak isian, bukan dengan labelnya: label ada di atas kotak, dan ikon yang
     sejajar label akan terbaca sebagai bagian dari tulisan labelnya. */
  margin-top: 1.65rem;
}

/* ---- Baris "Ingat saya" & "Lupa kata sandi?" ---- */
.auth-baris-bantu {
  display: flex; align-items: center; justify-content: space-between; gap: .75rem;
  flex-wrap: wrap; margin-bottom: 1.1rem;
}
.auth-ingat {
  display: flex; align-items: center; gap: .5rem; cursor: pointer;
  font-size: .92rem; font-weight: 500; color: var(--abu-700);
}
.auth-ingat input { width: 20px; height: 20px; accent-color: var(--biru-700); cursor: pointer; }
.auth-lupa {
  background: none; border: none; padding: 0; cursor: pointer; font: inherit; font-size: .92rem;
  color: var(--biru-700); font-weight: 600; text-decoration: underline; text-underline-offset: 3px;
}

/* ---- Tombol Masuk ---- */
.auth-kirim {
  display: inline-flex; align-items: center; justify-content: center; gap: .6rem;
  border-radius: 999px; font-size: 1.05rem;
}
/* Panah tidak ikut menyusut saat labelnya berganti jadi pemuat (lihat saatProses di ui.js). */
.auth-kirim .ikon-svg { flex: 0 0 auto; }

/* ---- Tombol langkah pada formulir Daftar ---- */
/* Disamakan dengan .auth-kirim di halaman Masuk: pil, berpanah, dan sejajar tingginya. */
.auth-langkah-tbl {
  display: inline-flex; align-items: center; justify-content: center; gap: .45rem;
  border-radius: 999px;
}
.auth-langkah-tbl .ikon-svg { flex: 0 0 auto; }

/* ---- Bidang bertekstarea ---- */
/*
 * Ikon disejajarkan dengan BARIS PERTAMA textarea, bukan dengan tengahnya: textarea tiga baris
 * membuat ikon yang terpusat melayang jauh di bawah labelnya dan terbaca lepas dari bidangnya.
 */
.auth-bidang:has(textarea) .auth-lambang { align-self: flex-start; }

/* ---- Pemisah "atau" ---- */
.auth-pemisah {
  display: flex; align-items: center; gap: .9rem;
  margin: 1.4rem 0 .2rem; color: var(--abu-500); font-size: .92rem;
}
.auth-pemisah::before, .auth-pemisah::after {
  content: ''; flex: 1; height: 1px; background: var(--abu-200);
}
