/* Dosen Tracker — gaya "liquid glass" ala iOS, CSS mandiri tanpa build tool */
* { box-sizing: border-box; }

:root {
  /* Palet dasar */
  --navy: #111844;
  --navy-2: #1B2456;
  --slate: #7288AE;
  --krem: #EAE0CF;
  --putih: #FFFFFF;

  /* Teks di atas area terang (konten) */
  --teks-gelap: #1A1A2E;
  --teks-gelap-redup: rgba(26, 26, 46, .64);
  --teks-gelap-samar: rgba(26, 26, 46, .42);

  /* Teks di atas sidebar navy */
  --teks-terang: rgba(255, 255, 255, .92);
  --teks-terang-redup: rgba(255, 255, 255, .64);
  --teks-terang-samar: rgba(255, 255, 255, .42);

  /* Kaca & garis */
  --kaca-sidebar: rgba(17, 24, 68, .82);
  --kaca-topbar: rgba(255, 255, 255, .58);
  --kaca-kartu: rgba(255, 255, 255, .58);
  --kaca-kartu-krem: rgba(234, 224, 207, .42);
  --kaca-terang-hover: rgba(255, 255, 255, .09);

  --garis-navy: rgba(255, 255, 255, .14);
  --garis-navy-kuat: rgba(255, 255, 255, .28);
  --garis: rgba(114, 136, 174, .28);
  --garis-kuat: rgba(114, 136, 174, .5);

  /* Status — fungsional, dipertahankan hijau/merah */
  --ok: #2F9E63;      --ok-bg: rgba(47, 158, 99, .12);    --ok-garis: rgba(47, 158, 99, .35);
  --bad: #C43C46;     --bad-bg: rgba(196, 60, 70, .12);   --bad-garis: rgba(196, 60, 70, .35);
  --warn: #B4791E;    --warn-bg: rgba(180, 121, 30, .12); --warn-garis: rgba(180, 121, 30, .35);
  --info: #3E6FB0;    --info-bg: rgba(62, 111, 176, .12); --info-garis: rgba(62, 111, 176, .32);
  --gold: #C89B3C;    --gold-bg: rgba(200, 155, 60, .12); --gold-garis: rgba(200, 155, 60, .35);

  --radius: 18px;
  --radius-kecil: 10px;
}

html, body { height: 100%; }
body {
  margin: 0; color: var(--teks-gelap);
  font-family: "Segoe UI", system-ui, -apple-system, sans-serif;
  font-size: 15px; line-height: 1.55;
  background:
    radial-gradient(1200px 800px at 15% -10%, rgba(255, 255, 255, .95), transparent 55%),
    radial-gradient(900px 700px at 100% 110%, rgba(234, 224, 207, .9), transparent 60%),
    linear-gradient(160deg, #FFFFFF 0%, #F5EFE1 55%, var(--krem) 100%);
  background-attachment: fixed;
}
a { color: var(--navy); }
a:hover { color: var(--slate); }

/* ===== Kerangka aplikasi: sidebar + area utama ===== */
.app-shell { display: flex; min-height: 100vh; }

.sidebar {
  position: fixed; top: 0; left: 0; bottom: 0; width: 244px;
  background: var(--kaca-sidebar);
  backdrop-filter: blur(26px) saturate(160%);
  -webkit-backdrop-filter: blur(26px) saturate(160%);
  border-right: 1px solid var(--garis-navy);
  padding: 20px 14px;
  display: flex; flex-direction: column; gap: 4px;
  z-index: 10;
}
.merek {
  display: flex; flex-direction: column; align-items: flex-start; gap: 8px;
  padding: 6px 10px 24px;
}
.merek-logo-sidebar { height: 52px; width: auto; display: block; }
.merek-logo { height: 100px; width: auto; max-width: 100%; display: block; }
.merek-tagline { font-size: .7rem; color: var(--teks-terang-samar); letter-spacing: .02em; }
.kunci-merek { align-items: center; text-align: center; }

.sidebar-nav {
  display: flex; flex-direction: column; gap: 3px; flex: 1;
  min-height: 0; overflow-y: auto; overflow-x: hidden;
}
.sidebar-nav::-webkit-scrollbar { width: 6px; }
.sidebar-nav::-webkit-scrollbar-thumb { background: var(--garis-navy-kuat); border-radius: 999px; }
.sidebar-nav::-webkit-scrollbar-track { background: transparent; }

.menu-label {
  font-size: .68rem; font-weight: 700; text-transform: uppercase; letter-spacing: .08em;
  color: var(--teks-terang-redup);
  padding: 14px 12px 4px;
}
.sidebar-nav .menu-label:first-child { padding-top: 4px; }
.menu-label-toggle {
  display: flex; align-items: center; justify-content: space-between;
  width: 100%; background: transparent; border: none; cursor: pointer;
  font: inherit; font-weight: 500; text-align: left;
}
.menu-label-toggle:hover { color: var(--teks-terang); }
.menu-label-chevron { width: 14px; height: 14px; flex-shrink: 0; transition: transform .15s ease; }
.menu-label-chevron-terbuka { transform: rotate(180deg); }
.menu-label-isi { display: flex; flex-direction: column; gap: 3px; }
.sidebar-nav a.menu {
  display: flex; align-items: center; gap: 12px;
  text-decoration: none; color: var(--teks-terang-redup);
  padding: 10px 12px; border-radius: 12px;
  font-weight: 500; font-size: .94rem;
  border: 1px solid transparent;
  transition: background .15s ease, color .15s ease, border-color .15s ease;
}
.sidebar-nav a.menu:hover { background: var(--kaca-terang-hover); color: var(--teks-terang); }
.sidebar-nav a.menu.aktif {
  background: rgba(114, 136, 174, .38);
  border-color: var(--garis-navy-kuat);
  color: #fff;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .12);
}
.menu-ikon { width: 20px; height: 20px; flex-shrink: 0; display: flex; align-items: center; justify-content: center; color: inherit; }
.menu-ikon svg { width: 20px; height: 20px; display: block; }

.sidebar-pemilih {
  border-top: 1px solid var(--garis-navy); padding-top: 12px; margin-top: 8px;
}
.sidebar-pemilih label { font-size: .74rem; color: var(--teks-terang-samar); text-transform: uppercase; letter-spacing: .04em; margin-bottom: 4px; }
.sidebar-pemilih select {
  font-size: .85rem;
  background: rgba(255, 255, 255, .1); color: var(--teks-terang);
  border: 1px solid var(--garis-navy-kuat);
}
.sidebar-pemilih select option { background: var(--navy); color: var(--teks-terang); }

.tombol-tutup-sidebar {
  display: none;
  position: absolute; top: 16px; right: 14px;
  width: 32px; height: 32px; padding: 0;
  align-items: center; justify-content: center;
  background: transparent; color: var(--teks-terang-redup);
  border: 1px solid var(--garis-navy); border-radius: 999px;
  box-shadow: none; cursor: pointer;
}
.tombol-tutup-sidebar:hover { color: var(--teks-terang); border-color: var(--garis-navy-kuat); filter: none; }
.tombol-tutup-sidebar svg { width: 16px; height: 16px; display: block; }

.sidebar-overlay {
  display: none;
  position: fixed; inset: 0;
  background: rgba(17, 24, 68, .45);
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
  z-index: 9;
}

/* min-width:0 di .area-utama & main (di bawah) WAJIB ada begitu ada konten
   nowrap lebar di dalamnya (mis. <x-tabel-data>) — keduanya flex item
   (.area-utama anak .app-shell, main anak .area-utama), dan default
   min-width:auto flex item bikin browser menghitung lebar minimum dari
   konten TERLEBAR di dalamnya (termasuk tabel nowrap yang jauh di dalam),
   memaksa seluruh .app-shell/body ikut melebar & discroll — bukan cuma
   .tabel-gulir yang seharusnya jadi satu-satunya area scroll. */
.area-utama { flex: 1; min-width: 0; margin-left: 244px; display: flex; flex-direction: column; min-height: 100vh; }

.topbar {
  position: sticky; top: 0; z-index: 5;
  display: flex; align-items: center; gap: 14px;
  padding: 14px 28px;
  background: var(--kaca-topbar);
  backdrop-filter: blur(22px) saturate(150%);
  -webkit-backdrop-filter: blur(22px) saturate(150%);
  border-bottom: 1px solid var(--garis);
}
.tombol-hamburger {
  display: none;
  width: 38px; height: 38px; padding: 0; flex-shrink: 0;
  align-items: center; justify-content: center;
  background: var(--kaca-sidebar); color: var(--teks-terang);
  border: 1px solid var(--garis-navy-kuat); border-radius: var(--radius-kecil);
  backdrop-filter: blur(16px) saturate(150%);
  -webkit-backdrop-filter: blur(16px) saturate(150%);
  box-shadow: none; cursor: pointer;
}
.tombol-hamburger svg { width: 20px; height: 20px; display: block; }
.avatar {
  width: 40px; height: 40px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-weight: 700; font-size: .95rem; color: #fff;
  background: linear-gradient(135deg, var(--navy), var(--navy-2) 60%, var(--slate) 140%);
  border: 1px solid var(--garis-kuat);
  flex-shrink: 0;
}
.avatar-kosong { color: var(--teks-gelap-samar); background: rgba(114, 136, 174, .1); }
.avatar-foto { object-fit: cover; background: none; }
.profil-nama { font-weight: 700; font-size: 1.05rem; color: var(--teks-gelap); }
.profil-jenjang { font-size: .82rem; color: var(--teks-gelap-redup); }

.berbagi-profil-publik { position: relative; display: flex; align-items: center; gap: 14px; }
.berbagi-profil-publik form { display: inline; }

.tombol-bagikan { position: relative; }
.titik-aktif {
  position: absolute; top: -3px; right: -3px; width: 9px; height: 9px;
  border-radius: 50%; background: var(--ok); border: 2px solid var(--putih);
}

.popover-bagikan {
  position: absolute; top: calc(100% + 8px); right: 0; z-index: 30;
  width: 300px; max-width: calc(100vw - 24px);
  background: var(--putih); border: 1px solid var(--garis);
  border-radius: var(--radius-kecil);
  box-shadow: 0 10px 34px rgba(17, 24, 68, .22);
  padding: 14px; display: flex; flex-direction: column; gap: 10px;
}
.popover-bagikan[hidden] { display: none; }
.popover-bagikan label { margin-bottom: 0; font-size: .78rem; color: var(--teks-gelap-redup); }
.popover-bagikan .input-link-publik {
  width: 100%; padding: 6px 9px; font-size: .8rem;
  border: 1px solid var(--garis); border-radius: var(--radius-kecil);
  background: rgba(255, 255, 255, .9); color: var(--teks-gelap-redup);
}
.popover-bagikan-aksi { display: flex; gap: 8px; }
.popover-bagikan-aksi button, .popover-bagikan-aksi form { flex: 1; }
.popover-bagikan-aksi form button { width: 100%; }
.popover-bagikan-pemisah { border-top: 1px solid var(--garis); margin: 0; }
.tombol-unduh-cv { display: block; width: 100%; text-align: center; }
.tombol-buat-ulang {
  background: transparent; color: var(--teks-gelap-redup);
  border: 1px solid var(--garis); box-shadow: none;
  padding: 5px 12px; font-size: .82rem;
}
.tombol-buat-ulang:hover { filter: none; background: rgba(17, 24, 68, .04); }

.modal-overlay {
  position: fixed; inset: 0; z-index: 100;
  background: rgba(17, 24, 68, .45);
  display: flex; align-items: center; justify-content: center;
  padding: 16px;
}
.modal-overlay[hidden] { display: none; }
.modal-kotak {
  background: var(--putih); border-radius: var(--radius);
  padding: 22px 24px; max-width: 380px; width: 100%;
  box-shadow: 0 20px 50px rgba(17, 24, 68, .35);
}
.modal-kotak h3 { margin: 0 0 8px; color: var(--navy); font-size: 1.05rem; }
.modal-kotak p { margin: 0 0 18px; color: var(--teks-gelap-redup); font-size: .9rem; }
.modal-aksi { display: flex; justify-content: flex-end; gap: 10px; }

/* ===== Foto profil (halaman Profil) ===== */
.foto-profil-baris { display: flex; align-items: center; gap: 18px; }
.foto-profil-pratinjau, .foto-profil-kosong {
  width: 110px; height: 110px; border-radius: 50%; flex-shrink: 0;
  border: 1px solid var(--garis-kuat);
}
.foto-profil-pratinjau { object-fit: cover; }
.foto-profil-kosong {
  display: flex; align-items: center; justify-content: center;
  font-weight: 700; font-size: 1.9rem; color: #fff;
  background: linear-gradient(135deg, var(--navy), var(--navy-2) 60%, var(--slate) 140%);
}
.input-file-tersembunyi {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}
#nama-file-foto { margin-top: 6px; }

/* ===== Sampul artikel (Admin CMS) ===== */
.sampul-artikel-pratinjau, .sampul-artikel-kosong {
  width: 160px; height: 90px; border-radius: var(--radius-kecil); flex-shrink: 0;
  border: 1px solid var(--garis-kuat);
}
.sampul-artikel-pratinjau { object-fit: cover; }
.sampul-artikel-kosong {
  display: flex; align-items: center; justify-content: center;
  font-size: .78rem; color: var(--teks-gelap-samar); text-align: center; padding: 4px;
  background: rgba(114, 136, 174, .1);
}

main { max-width: 1100px; margin: 0 auto; padding: 22px 24px 60px; width: 100%; min-width: 0; flex: 1 0 auto; }

.app-footer {
  text-align: center;
  font-size: .78rem;
  color: var(--teks-gelap-samar);
  padding: 10px 24px 20px;
  flex-shrink: 0;
}
.app-footer a { color: var(--teks-gelap-redup); text-decoration: underline; }
.app-footer a:hover { color: var(--slate); }

/* Breakpoint navigasi sidebar<->hamburger: DI BAWAH 1024px (HP semua orientasi,
   tablet portrait, termasuk iPad Pro 12.9" portrait=1024px persis dianggap
   "desktop" karena max-width di sini 1023px, bukan 1024px) sidebar
   disembunyikan (slide-in dari kiri + overlay gelap, tombol hamburger jadi
   toggle-nya) — >=1024px (tablet landscape ke atas) sidebar tampil penuh dari
   rule dasar .sidebar/.tombol-hamburger/.area-utama di atas, TIDAK butuh
   override apa pun. Angka ini SENGAJA beda dari breakpoint 767px di bawah:
   767px itu utk elemen KONTEN (topbar wrap, ukuran icon header, dst.) yang
   independen dari lebar sidebar; breakpoint NAVIGASI (kapan sidebar jadi
   hamburger) sekarang 1024px sesuai kebutuhan produk, dua hal ini boleh beda
   angka karena mengatur aspek yang berbeda. */
@media (max-width: 1023px) {
  .sidebar {
    width: min(280px, 82vw);
    transform: translateX(-100%);
    transition: transform .28s ease;
    box-shadow: 10px 0 34px rgba(17, 24, 68, .35);
  }
  .sidebar.terbuka { transform: translateX(0); }
  .tombol-tutup-sidebar { display: flex; }
  .tombol-hamburger { display: inline-flex; }
  .sidebar-overlay.terbuka { display: block; }
  .area-utama { margin-left: 0; }
}

@media (max-width: 767px) {
  .topbar { flex-wrap: wrap; row-gap: 8px; }
  .popover-bagikan { width: calc(100vw - 24px); max-width: calc(100vw - 24px); }
  .modal-kotak { max-width: none; }

  /* Proporsi header dashboard dosen: icon tombol Bagikan/Undang/Keluar terasa
     lebih besar dari nama di mobile. Icon (bukan area tap 44x44 — itu WAJIB
     tetap, standar touch target) dikecilkan ~20% (20px -> 16px), nama
     diperbesar supaya tetap jadi elemen dominan. Posisi rata kiri/kanan
     tidak disentuh, murni ukuran. */
  .tombol-ikon svg { width: 16px; height: 16px; }
  .profil-nama { font-size: 1.15rem; }
}

/* ===== Tipografi =====
   h1 pakai Fraunces (font brand) — HANYA h1, judul halaman level
   tertinggi (satu per halaman, lihat mis. publikasi/index.blade.php,
   bkd.blade.php, admin/dashboard.blade.php). h2 (judul section/card di
   dalamnya, mis. "Tambah Publikasi/Karya") SENGAJA tetap Segoe UI/system
   supaya tidak terlalu ramai — body/label/tabel/tombol semuanya tidak
   disentuh. Berlaku ke dashboard dosen (layouts/app.blade.php) DAN panel
   admin (layouts/admin.blade.php) — keduanya load app.css & sudah
   masing-masing load font Fraunces sendiri. */
h1 { font-family: 'Fraunces', serif; font-size: 1.5rem; margin: 0 0 4px; color: var(--navy); }
h2 { font-size: 1.12rem; margin: 26px 0 10px; color: var(--teks-gelap); }
.sub { color: var(--teks-gelap-redup); margin: 0 0 18px; }
.keterangan-kecil { font-size: .82rem; color: var(--teks-gelap-redup); }
code { background: rgba(17, 24, 68, .07); color: var(--navy); padding: 1px 6px; border-radius: 5px; font-size: .88em; }

/* ===== Panel kaca (kartu, statistik) ===== */
.kartu {
  background: var(--kaca-kartu);
  backdrop-filter: blur(18px) saturate(140%);
  -webkit-backdrop-filter: blur(18px) saturate(140%);
  border: 1px solid var(--garis);
  border-radius: var(--radius);
  padding: 18px 20px; margin-bottom: 16px;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .7), 0 10px 34px rgba(17, 24, 68, .1);
}
.kartu h2:first-child { margin-top: 0; }
.kartu.kartu-penting { border-left: 3px solid var(--gold); }

.baris-kartu { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: 12px; margin-bottom: 16px; }
.stat {
  background: var(--kaca-kartu-krem);
  backdrop-filter: blur(16px) saturate(140%);
  -webkit-backdrop-filter: blur(16px) saturate(140%);
  border: 1px solid var(--garis);
  border-radius: var(--radius);
  padding: 14px 16px;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .7);
}
.stat .angka { font-size: 1.6rem; font-weight: 700; color: var(--navy); }
.stat .label { color: var(--teks-gelap-redup); font-size: .85rem; }
.stat.hijau { border-left: 3px solid var(--ok); }
.stat.merah { border-left: 3px solid var(--bad); }
.stat.biru { border-left: 3px solid var(--slate); }

/* ===== Tabel ===== */
table { width: 100%; border-collapse: collapse; background: transparent; color: var(--teks-gelap); }
th, td { text-align: left; padding: 9px 10px; border-bottom: 1px solid var(--garis); vertical-align: top; }
th { background: rgba(17, 24, 68, .04); font-size: .78rem; text-transform: uppercase; letter-spacing: .04em; color: var(--teks-gelap-redup); font-weight: 600; }
tr:hover td { background: rgba(17, 24, 68, .03); }
.tabel-gulir { overflow-x: auto; -webkit-overflow-scrolling: touch; }

/* Wrapper LUAR, TIDAK ikut scroll (beda dari .tabel-gulir di dalamnya yang
   overflow-x:auto) — gradient indikator "masih ada konten di kanan" dipasang
   di sini, bukan di .tabel-gulir sendiri, supaya posisinya diam menempel tepi
   kanan area tabel dan tidak ikut ter-translate saat tabel digeser. */
.tabel-gulir-luar { position: relative; }
.tabel-gulir-luar::after {
  content: '';
  position: absolute; top: 0; right: 0; bottom: 0; width: 28px;
  background: linear-gradient(to right, transparent, rgba(17, 24, 68, .12));
  pointer-events: none;
  opacity: 1; transition: opacity .15s ease;
}
.tabel-gulir-luar.tabel-gulir-habis::after { opacity: 0; }

/* ===== <x-tabel-data>: search, sort, pagination, sticky column ===== */
[x-cloak] { display: none !important; }

/* Tabel di dalam komponen ini TIDAK BOLEH kena "table { width: 100% }" global
   (baris di atas) — itu yang bikin kolom menyempit dan teks wrap ke bawah alih-alih
   tabel melebar+discroll. min-width:100% + width:auto = tetap penuh selebar wrapper
   kalau konten muat, tapi boleh melebar lebih kalau tidak (lalu discroll .tabel-gulir). */
.tabel-data-wrapper table { width: auto; min-width: 100%; }
.tabel-data-wrapper th, .tabel-data-wrapper td { white-space: nowrap; }

/* Kolom non-sticky BOLEH diberi batas lebar + wrap lewat prop 'lebar' di definisi
   kolom (mis. ['key'=>'judul','lebar'=>'20rem']) — dipakai kolom kedua dst. yang
   kontennya berpotensi panjang (lihat komponen tabel-data.blade.php). SENGAJA
   opt-in per kolom (bukan default semua kolom) — kolom TANPA 'lebar' tetap
   nowrap penuh seperti sebelumnya, supaya tabel tetap py lebar minimum yang
   memicu scroll horizontal (kalau SEMUA kolom wrap, tabel bakal menyempit
   mengikuti container dan scroll-nya hilang). Kolom pendek (Tahun/SKS/dst.)
   sengaja TIDAK diberi 'lebar'.

   PENTING: max-width DITARUH DI DIV PEMBUNGKUS DI DALAM <td> (.tabel-data-sel-lebar),
   BUKAN langsung di <td>/<th> itu sendiri. Percobaan pertama menaruh max-width
   langsung di <td> ternyata diabaikan browser — pada table-layout:auto (default,
   dipakai tabel ini), lebar kolom dihitung oleh algoritma otomatis dari lebar
   "preferred" konten SEBELUM max-width sel diterapkan, jadi teks tidak pernah
   wrap dan meluber ke sel sebelah. <div> biasa (bukan kotak tabel) menghormati
   max-width secara normal di layout block biasa — begitu div itu wrap jadi
   sempit, barulah <td> mewarisi lebar "preferred" yang sudah sempit itu dari
   div-nya, bukan dari teks mentah yang tidak pernah dibatasi. overflow-wrap:
   anywhere (bukan break-word) supaya kata tunggal yang sangat panjang tanpa
   spasi pun tetap wrap, bukan cuma di celah kata.

   Kolom dengan 'lebar' TAPI 'wrap' => false (lihat komponen): sengaja TIDAK
   pakai div+max-width di atas — ini kolom yang justru harus tetap SATU baris
   (nowrap default tidak diubah), 'lebar'-nya cuma jadi hint `width` langsung di
   <th>/<td> supaya browser mengalokasikan ruang kolom itu secara sadar/proporsional,
   bukan dibiarkan mengikuti kebetulan. `width` (beda dari `max-width`) memang
   DIHORMATI algoritma auto-layout sebagai target ukuran kolom — kalau kontennya
   ternyata butuh lebih (nowrap tidak bisa dipotong), kolom akan melebar
   melebihi hint ini, bukan error, cuma berarti nilainya perlu dinaikkan. */
.tabel-data-sel-lebar { white-space: normal; overflow-wrap: anywhere; }

.tabel-data-wrapper { margin-bottom: 16px; }

/* Sticky wajib background SOLID (bukan transparan seperti td biasa) — kalau
   tidak, teks kolom lain menembus di baliknya saat tabel digeser. #F5EFE1
   dipilih (bukan var(--putih)/#fff) karena itu warna cream yang SUDAH dipakai
   di gradient latar halaman (baris 53, stop 55%) — satu keluarga dengan
   --krem/#EAE0CF, tapi lebih terang/halus, jadi beda tipis dari tampilan
   putih-kaca .kartu di sekitarnya, bukan blok warna asing. th & hover sticky
   melapisi tint navy yang sama persis dengan th/tr:hover biasa DI ATAS cream
   ini (bukan di atas putih) supaya tetap konsisten look-nya, cuma opaque.
   Tidak ada zebra striping di tabel ini (td polos tidak py background
   per-baris), jadi cukup satu warna solid untuk semua baris. */
.tabel-data-sticky { position: sticky; left: 0; z-index: 1; }
td.tabel-data-sticky { background: #F5EFE1; }
th.tabel-data-sticky { background: linear-gradient(rgba(17, 24, 68, .04), rgba(17, 24, 68, .04)), #F5EFE1; }
tr:hover td.tabel-data-sticky { background: linear-gradient(rgba(17, 24, 68, .03), rgba(17, 24, 68, .03)), #F5EFE1; }

/* Batasan lebar kolom sticky di DESKTOP (default, di luar media query mobile
   di bawah): cuma max-width (BUKAN width tetap seperti mobile) supaya kolom
   tetap menyempit mengikuti konten kalau pendek, dan hanya dibatasi kalau
   kontennya panjang (mis. nama organisasi panjang) — sisa lebar tabel jadi
   lebih adil buat kolom lain. 28vw dipilih (bukan 40-50vw ala mobile, apalagi
   50%) dengan acuan menu berkolom TERBANYAK (Publikasi & Penelitian, 6 kolom):
   kalau kolom pertama mengambil ~28% lebar tabel, sisa ~72% masih cukup lega
   dibagi 5 kolom lain (+kolom aksi). min(28vw, 24rem) menambahkan plafon rem
   supaya di layar desktop sangat lebar (mis. monitor ultrawide) kolom pertama
   tidak ikut melebar proporsional tanpa batas — 24rem (384px) sudah lebih dari
   cukup untuk judul/nama terpanjang yang pernah dipakai di menu manapun.
   white-space:normal supaya teks panjang wrap ke bawah, bukan memaksa kolom
   melebar sampai max-width-nya (browser tetap izinkan menyempit di bawah
   max-width itu kalau konten pendek). Kolom lain (th/td biasa) tidak disentuh,
   tetap nowrap dari aturan umum .tabel-data-wrapper th/td di atas. */
th.tabel-data-sticky, td.tabel-data-sticky {
  max-width: min(28vw, 24rem);
  white-space: normal; overflow-wrap: break-word;
}

/* Batasan lebar kolom sticky di mobile/tablet (breakpoint 767px — SAMA dengan
   breakpoint collapse sidebar di atas, bukan angka baru): beda dari desktop,
   di sini width DIPAKSA (bukan cuma max-width) supaya kolom pertama konsisten
   lebarnya di semua baris (perilaku ini TIDAK berubah dari sebelumnya). vw
   dipakai (BUKAN px, BUKAN %): tabel ini width:auto+min-width:100% (lihat
   rule di atas) jadi % akan dihitung relatif ke lebar TABEL yang melar sesuai
   konten (tidak terprediksi) — vw dihitung relatif ke lebar VIEWPORT, konsisten
   di HP kecil/besar/tablet. 45vw = titik tengah target 40-50vw. Aturan ini
   ditulis SETELAH rule desktop di atas supaya menang di breakpoint ini
   (specificity sama, urutan sumber yang menentukan).
   Background solid tetap menutupi penuh tinggi sel berapapun tingginya
   karena wrap (background selalu mengisi penuh box elemen, di kedua mode). */
@media (max-width: 767px) {
  th.tabel-data-sticky, td.tabel-data-sticky {
    width: 45vw; max-width: 45vw;
    white-space: normal; overflow-wrap: break-word;
  }
}

.tabel-data-kontrol { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; justify-content: space-between; margin-bottom: 12px; }
.tabel-data-cari { flex: 1 1 220px; max-width: 320px; margin: 0; }
.tabel-data-per-halaman-label { display: flex; align-items: center; gap: 6px; font-size: .85rem; color: var(--teks-gelap-redup); white-space: nowrap; }
.tabel-data-per-halaman-label select { width: auto; margin: 0; }

.tabel-data-th-sortable { cursor: pointer; user-select: none; white-space: nowrap; }
.tabel-data-sort-panah { display: inline-block; margin-left: 4px; opacity: .4; font-size: .78em; }
.tabel-data-sort-panah.tabel-data-sort-aktif { opacity: 1; color: var(--navy); }

.tabel-data-paginasi { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 10px; margin-top: 12px; font-size: .85rem; color: var(--teks-gelap-redup); }
.tabel-data-paginasi-tombol { display: flex; align-items: center; gap: 10px; }
.tabel-data-paginasi-tombol button:disabled { opacity: .45; cursor: not-allowed; filter: none; }

/* ===== .tabel-responsif: perilaku scroll horizontal tabel manual (BUKAN <x-tabel-data>) =====
   Dipakai di tabel yang arsitektur datanya tidak cocok jadi komponen Alpine (paginate()
   server-side di Kelola Artikel/Halaman Statis, atau inline-form per sel di Pengaturan AK)
   tapi tetap butuh perilaku scroll yang sama: nowrap, kolom pertama sticky+dibatasi lebar,
   indikator gradient diam di wrapper. TIDAK bergantung Alpine.js sama sekali — murni CSS
   pada wrapper existing (`.tabel-gulir`), ditambah SATU wrapper luar (`.tabel-gulir-luar`,
   class yang SAMA dipakai <x-tabel-data> untuk gradient — di-reuse langsung, bukan dibuat
   ulang) untuk memisahkan gradient dari area yang ikut ter-scroll.

   Beda dari <x-tabel-data>: gradient di sini SELALU tampil (tidak fade otomatis saat sudah
   di-scroll habis) karena fade itu butuh JS (@scroll listener) untuk toggle class
   .tabel-gulir-habis — sengaja tidak ditambahkan di sini sesuai batasan "tanpa JS/Alpine",
   cuma CSS pada wrapper. Kolom pertama dipilih via :first-child (bukan class per-sel)
   supaya TIDAK perlu ubah markup baris @forelse/@foreach satu-satu; :not([colspan])
   mengecualikan baris "belum ada data" (kolom kosong span semua kolom) dari sticky+lebar
   supaya tidak salah tampil sempit. */
.tabel-responsif table { width: auto; min-width: 100%; }
.tabel-responsif th, .tabel-responsif td { white-space: nowrap; }

/* PENTING: max-width langsung di <td>/<th> DIABAIKAN browser waktu table-layout:auto
   (default, dipakai tabel ini) — pelajaran yang sama persis dengan <x-tabel-data>/
   Publikasi. Makanya kolom pertama di sini HANYA dapat position:sticky+background
   langsung di sel (itu properti yang memang bekerja normal di td) — max-width+wrap
   TIDAK ditaruh di sini, tapi di div anak lewat .tabel-responsif-sel-lebar di bawah. */
.tabel-responsif th:first-child:not([colspan]),
.tabel-responsif td:first-child:not([colspan]) {
  position: sticky; left: 0; z-index: 1;
}
.tabel-responsif td:first-child:not([colspan]) { background: #F5EFE1; }
.tabel-responsif th:first-child:not([colspan]) { background: linear-gradient(rgba(17, 24, 68, .04), rgba(17, 24, 68, .04)), #F5EFE1; }
.tabel-responsif tr:hover td:first-child:not([colspan]) { background: linear-gradient(rgba(17, 24, 68, .03), rgba(17, 24, 68, .03)), #F5EFE1; }

@media (max-width: 767px) {
  /* Di mobile, width (BUKAN cuma max-width) ditaruh langsung di sel — beda dari
     desktop, "width" eksplisit memang DIHORMATI table-layout:auto sebagai target
     ukuran kolom (sudah dibuktikan di <x-tabel-data>), jadi tidak butuh div anak
     di sini. Blok ini TIDAK diubah oleh perbaikan lebar kolom Kelola User (yang
     khusus desktop) — perilaku mobile tetap sama persis seperti sebelumnya.

     Default 45vw dipertahankan utk semua tabel .tabel-responsif lain (Judul di
     Artikel/Halaman Statis, Kunci di Pengaturan AK) — supaya tetap TIDAK berubah,
     lebar kolom pertama bisa di-override PER TABEL lewat custom property
     --tabel-responsif-lebar-mobile di inline style pada <td>/<th> itu sendiri
     (lihat kolom Nama Kelola User), tanpa perlu class/selector baru. */
  .tabel-responsif th:first-child:not([colspan]),
  .tabel-responsif td:first-child:not([colspan]) {
    width: var(--tabel-responsif-lebar-mobile, 45vw);
    max-width: var(--tabel-responsif-lebar-mobile, 45vw);
    white-space: normal; overflow-wrap: break-word;
  }
}

/* Div pembungkus utk kolom .tabel-responsif yang butuh lebar+wrap KHUSUS DESKTOP
   (mis. Nama/Jabatan Fungsional/Asal Kampus/Email di Kelola User, Judul di
   Artikel/Halaman Statis) — mobile SENGAJA tidak disentuh.

   BUG YANG SUDAH DIPERBAIKI: sebelumnya white-space:normal + overflow-wrap:anywhere
   ditulis di rule DASAR (di luar media query) — cuma max-width yang dibungkus
   @media(min-width:768px). Akibatnya di mobile, div INI TETAP membawa
   overflow-wrap:anywhere sendiri (meng-override overflow-wrap:break-word yang
   di-set TD sticky-nya lewat rule mobile terpisah, karena properti eksplisit di
   elemen sendiri menang atas inheritance dari ancestor) — mengubah cara teks
   Judul patah baris di HP dibanding sebelum div ini ada, padahal seharusnya
   mobile tidak disentuh sama sekali. Sekarang SEMUA properti (bukan cuma
   max-width) dibungkus media query yang sama — di mobile div ini benar-benar
   tanpa CSS sendiri, jadi white-space/overflow-wrap-nya otomatis WARISAN murni
   dari TD leluhurnya (persis seperti sebelum div ini pernah ditambahkan):
   kolom sticky (Judul dkk.) mewarisi white-space:normal;overflow-wrap:break-word
   dari rule mobile TD, kolom non-sticky (Jabatan dkk.) mewarisi
   white-space:nowrap dari rule dasar .tabel-responsif th,td — sama persis
   kondisi SEBELUM class ini pernah dipakai. Lebar per kolom diatur lewat
   custom property --tabel-responsif-lebar di inline style masing-masing
   pemakaian (nilainya beda-beda per kolom). */
@media (min-width: 768px) {
  .tabel-responsif-sel-lebar {
    max-width: var(--tabel-responsif-lebar, 14rem);
    white-space: normal; overflow-wrap: anywhere;
  }
}

/* Form "Nilai" per baris di Pengaturan AK (input+tombol Simpan) — flex eksplisit
   supaya tombol Simpan (flex-shrink:0, tidak pernah mengecil/ketimpa) selalu py
   ruang sendiri terpisah dari input, alih-alih mengandalkan default inline-block
   form control yang gampang tertimpa/collapse waktu kolom lain (Keterangan)
   melebar akibat wrap. */
.tabel-responsif .form-nilai-pengaturan { display: flex; align-items: flex-start; gap: 8px; }
.tabel-responsif .form-nilai-pengaturan input { flex: 1; min-width: 0; margin-bottom: 0 !important; }
.tabel-responsif .form-nilai-pengaturan button { flex-shrink: 0; white-space: nowrap; }

/* ===== Lencana status ===== */
.lencana { display: inline-block; padding: 3px 11px; border-radius: 999px; font-size: .78rem; font-weight: 600; white-space: nowrap; }
.lencana.lolos { background: var(--ok-bg); color: var(--ok); border: 1px solid var(--ok-garis); }
.lencana.gagal { background: var(--bad-bg); color: var(--bad); border: 1px solid var(--bad-garis); }
.lencana.manual { background: var(--warn-bg); color: var(--warn); border: 1px solid var(--warn-garis); }
.lencana.info { background: var(--info-bg); color: var(--info); border: 1px solid var(--info-garis); }
.lencana.penting { background: var(--gold-bg); color: var(--gold); border: 1px solid var(--gold-garis); margin-left: 8px; vertical-align: middle; }

/* ===== Alert/notifikasi ===== */
.peringatan { background: var(--warn-bg); border: 1px solid var(--warn-garis); border-radius: var(--radius-kecil); padding: 10px 14px; margin: 8px 0; font-size: .9rem; color: var(--teks-gelap); }
.blok-gagal { background: var(--bad-bg); border: 1px solid var(--bad-garis); border-radius: var(--radius-kecil); padding: 12px 16px; color: var(--teks-gelap); }
.blok-sukses { background: var(--ok-bg); border: 1px solid var(--ok-garis); border-radius: var(--radius-kecil); padding: 12px 16px; color: var(--teks-gelap); }
.notif { background: var(--ok-bg); border: 1px solid var(--ok-garis); border-radius: var(--radius-kecil); padding: 10px 14px; margin-bottom: 14px; color: var(--teks-gelap); }
.galat { background: var(--bad-bg); border: 1px solid var(--bad-garis); border-radius: var(--radius-kecil); padding: 10px 14px; margin-bottom: 14px; color: var(--teks-gelap); }

/* ===== Formulir ===== */
.formulir { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 12px; }
.formulir .lebar-penuh { grid-column: 1 / -1; }
.formulir.formulir-kompak { grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); }

/* Item grid CSS defaultnya min-width:auto (bukan 0) — kalau konten di dalamnya
   (placeholder panjang tanpa spasi mis. "https://drive.google.com/...", atau
   value/text lain yang tidak bisa wrap) lebih lebar dari minmax minimum
   trek-nya, item itu MEMAKSA lebar track lebih besar dari minmax yang
   diminta, dan grid auto-fit jadi meleset dari perhitungan kolom — di layar
   sempit ini bisa bikin form melebar keluar .kartu/viewport. Sama persis
   akar masalah min-width:auto yang sudah pernah diperbaiki untuk flex
   (.area-utama/main di atas), cuma versi grid-nya belum ada rule-nya. */
.formulir > * { min-width: 0; }

/* Kontrol proporsi lebar kolom per field di dalam .formulir, dipakai opsional:
   .lebar-ganda untuk field yang butuh ruang lebih (judul/nama/URL panjang),
   .lebar-sempit untuk field pendek (tahun/angka) supaya tidak ikut melebar
   penuh saat jadi satu-satunya field tersisa di baris terakhir. */
.formulir .lebar-ganda { grid-column: span 2; }
.formulir .lebar-sempit { max-width: 160px; }

/* Bug: .lebar-ganda (grid-column:span 2) memaksa auto-fit grid punya
   MINIMAL 2 kolom eksplisit walaupun kontainer sempit — begitu dipaksa
   2 kolom, tiap kolom tetap punya lantai minmax(190px atau 230px, 1fr)
   yang TIDAK bisa menyusut, jadi total lebar grid > lebar kontainer
   (.kartu bersarang di HP bisa cuma ~260-300px). Grid jadi meluber ke
   luar .kartu/viewport, dan kolom kedua (mis. "Nomor/Issue" di
   publikasi/_form.blade.php) berakhir cuma sekelumit tipis kepotong di
   tepi kanan. auto-fit sendiri TIDAK bisa mendeteksi/mencegah ini
   (span eksplisit selalu menang atas hitungan auto-fit). Breakpoint
   767px dipilih supaya konsisten dengan breakpoint collapse grid lain
   yang sudah ada di file ini (.grup-nama, .tabel-responsif) — bukan
   angka baru. */
@media (max-width: 767px) {
  .formulir, .formulir.formulir-kompak { grid-template-columns: 1fr; }
  .formulir .lebar-ganda { grid-column: auto; }
  .formulir .lebar-sempit { max-width: none; }
}

/* Grup "Data Penilaian AK" — pembeda visual saja, mengikuti pola kartu
   kaca ".stat" (blur, radius besar, border tipis) + border-left aksen
   seperti ".stat.biru" supaya senada dengan stat tile Dashboard.
   Field/name/logic di dalamnya tidak berubah. */
.grup-penilaian-ak {
  background: var(--kaca-kartu-krem);
  backdrop-filter: blur(16px) saturate(140%);
  -webkit-backdrop-filter: blur(16px) saturate(140%);
  border: 1px solid var(--garis);
  border-left: 3px solid var(--slate);
  border-radius: var(--radius);
  padding: 16px 20px;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .7);
}
.grup-penilaian-ak-judul {
  font-size: .72rem; font-weight: 700; text-transform: uppercase; letter-spacing: .06em;
  color: var(--teks-gelap-redup); margin: 0 0 12px;
}

/* Baris DOI + tombol "Tarik dari Crossref" di dalam grup Detail Sitasi. */
.baris-doi { display: flex; align-items: flex-end; gap: 12px; flex-wrap: wrap; margin-bottom: 10px; }
.baris-doi .lebar-ganda { flex: 1; min-width: 220px; }

/* Grup gelar depan/nama/gelar belakang dalam satu baris (halaman Profil). */
.grup-nama { display: grid; grid-template-columns: 1fr 2.6fr 1.5fr; gap: 12px; }
@media (max-width: 767px) {
  .grup-nama { grid-template-columns: 1fr; }
}
label { display: block; font-weight: 600; font-size: .85rem; margin-bottom: 4px; color: var(--teks-gelap); }
label .opsional { color: var(--teks-gelap-samar); font-weight: 400; }

input[type=text], input[type=number], input[type=date], input[type=url], input[type=password], select, textarea {
  width: 100%; padding: 8px 10px;
  border: 1px solid var(--garis); border-radius: var(--radius-kecil);
  font: inherit; color: var(--teks-gelap);
  background: rgba(255, 255, 255, .7);
  backdrop-filter: blur(6px);
}
input::placeholder, textarea::placeholder { color: var(--teks-gelap-samar); }
input:focus, select:focus, textarea:focus {
  outline: none; border-color: var(--garis-kuat);
  box-shadow: 0 0 0 3px rgba(114, 136, 174, .2);
}
select option { background: var(--putih); color: var(--teks-gelap); }
textarea { min-height: 60px; resize: vertical; }

/* flex-wrap:wrap WAJIB — tanpa ini (default nowrap), teks bantuan
   panjang (mis. span.keterangan-kecil di publikasi/_form.blade.php)
   TIDAK pindah ke baris baru waktu tidak muat; browser malah
   menyusutkan box teks itu sampai jadi kolom sempit lalu wrap kata
   per kata di dalamnya (kelihatan kepepet vertikal di samping
   checkbox). Unconditional (bukan cuma di media query) karena ini
   perbaikan wrapping yang aman di lebar berapa pun — baru aktif
   kalau memang tidak muat satu baris. */
.centang { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; font-weight: 400; }
.centang input { width: auto; }

/* ===== Tombol ===== */
button, .tombol {
  background: linear-gradient(160deg, var(--navy), var(--navy-2));
  color: #fff;
  border: 1px solid rgba(255, 255, 255, .22);
  border-radius: var(--radius-kecil);
  padding: 9px 18px; font: inherit; font-weight: 700; cursor: pointer;
  text-decoration: none; display: inline-block;
  box-shadow: 0 4px 14px rgba(17, 24, 68, .28), inset 0 1px 0 rgba(255, 255, 255, .12);
  transition: filter .15s ease, transform .1s ease;
}
button:hover, .tombol:hover { filter: brightness(1.12); }
button:active, .tombol:active { transform: translateY(1px); }

button.bahaya, .tombol.bahaya {
  background: var(--bad-bg); color: var(--bad); border: 1px solid var(--bad-garis);
  padding: 5px 12px; font-size: .82rem; box-shadow: none;
}
button.bahaya:hover, .tombol.bahaya:hover { filter: brightness(.92); }
button.waspada, .tombol.waspada {
  background: var(--warn-bg); color: var(--warn); border: 1px solid var(--warn-garis);
  padding: 5px 12px; font-size: .82rem; box-shadow: none;
}
button.waspada:hover, .tombol.waspada:hover { filter: brightness(.92); }
.kecil { padding: 5px 12px; font-size: .82rem; }
.netral {
  background: rgba(17, 24, 68, .06); color: var(--teks-gelap);
  border: 1px solid var(--garis-kuat); box-shadow: none;
}

/* Tombol icon-only (tanpa label teks) — lebar/tinggi dijaga 44px supaya
   area tap tetap memenuhi standar aksesibilitas touch target minimum,
   meski icon di dalamnya kecil (20px). Dipasang setelah .bahaya/.netral
   supaya padding di sini menang (spesifisitas sama, urutan menentukan). */
.tombol-ikon {
  width: 44px; height: 44px; padding: 0; flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center;
  box-shadow: none;
}
.tombol-ikon svg { width: 20px; height: 20px; display: block; }

.aksi-sel { white-space: nowrap; }
.aksi-sel form { display: inline; }

/* Kontras icon toolbar EasyMDE. Root cause (dicek langsung dari easymde.min.css
   via CDN): tombol toolbar dirender sebagai <button> polos, dan
   ".editor-toolbar button" bawaan EasyMDE SAMA SEKALI tidak set "color" di
   state manapun (normal/:hover/.active/disabled-for-preview) — cuma atur
   background & border. Jadi color-nya jatuh ke rule global project
   "button, .tombol { color: #fff; ... }" (app.css), bikin semua icon toolbar
   putih di atas background toolbar yang terang — nyaris tak kelihatan kecuali
   pas hover/active kebetulan kontras cukup dari border abu-abu (bukan dari
   warna icon-nya). Fix: satu rule override warna icon ke --navy, spesifisitas
   sama dengan selector bawaan EasyMDE (".editor-toolbar button", class+tag)
   jadi otomatis menang atas "button" global (tag saja) TANPA !important.
   Karena EasyMDE tidak override color di :hover/.active sama sekali, rule
   ini otomatis ikut berlaku di kedua state itu juga (navy di atas
   background terang tetap kontras baik) — tidak perlu rule terpisah.
   State disabled-for-preview cuma pakai opacity:.6 (bukan ganti warna), jadi
   otomatis jadi navy pudar — beda kentara dari tombol aktif, tapi tidak
   sampai putih-di-atas-putih. */
.editor-toolbar button { color: var(--navy); }

/* Icon tombol custom "Sisipkan Video" di toolbar EasyMDE (lihat
   public/js/markdown-editor.js) — EasyMDE tidak punya icon bawaan untuk ini.
   Selector diperbaiki dari "a.mde-video-embed" ke "button.mde-video-embed"
   (ditemukan saat investigasi kontras di atas): toolbar EasyMDE dirender
   sebagai <button>, bukan <a>, jadi selector lama tidak pernah cocok sama
   sekali — icon ▶ ini kemungkinan tidak pernah tampil sebelumnya. */
.editor-toolbar button.mde-video-embed:before { content: "\25B6"; font-family: inherit; }

/* ===== Progress bar ===== */
.progress { background: rgba(17, 24, 68, .1); border-radius: 999px; height: 14px; overflow: hidden; margin: 4px 0; }
.progress > div { height: 100%; background: linear-gradient(90deg, var(--ok), #7FCBA0); }
.progress > div.kurang { background: linear-gradient(90deg, var(--bad), #E38A91); }

.kartu-kolaps {
  background: var(--info-bg);
  border: 1px solid var(--info-garis);
}

details { margin: 6px 0; }
details:first-child { margin-top: 0; }
details:last-child { margin-bottom: 0; }
summary {
  cursor: pointer; font-weight: 600; color: var(--teks-gelap);
  list-style: none;
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
}
summary::-webkit-details-marker { display: none; }
summary::after {
  content: '';
  width: 9px; height: 9px; flex-shrink: 0;
  border-right: 2px solid var(--info);
  border-bottom: 2px solid var(--info);
  transform: rotate(-45deg);
  transition: transform .2s ease;
}
details[open] > summary::after { transform: rotate(45deg); }

/* ===== Layar Auth (register / login / forgot & reset password / verify email / menunggu approval) ===== */
.auth-shell {
  min-height: 100vh; display: flex; align-items: center; justify-content: center;
  padding: 24px;
}
.auth-kartu { width: 100%; max-width: 440px; padding: 28px 26px; }
.auth-kartu h1 { text-align: center; font-size: 1.3rem; }
.auth-kartu .sub { text-align: center; font-size: .88rem; }
.auth-kartu form.formulir { grid-template-columns: 1fr; gap: 14px; }
.auth-kartu button[type=submit] { width: 100%; }
.auth-kartu form.formulir + form.formulir { margin-top: 10px; }
.auth-kartu .centang { justify-content: flex-start; font-size: .88rem; margin: -2px 0 2px; }

/* Widget Cloudflare Turnstile: dijaga selalu utuh & center, boleh scroll
   sendiri kalau kartu lebih sempit dari lebar widget (layar sangat sempit). */
.auth-kartu .cf-turnstile {
  display: flex; justify-content: center; align-items: center;
  max-width: 100%; overflow-x: auto; margin: 2px 0;
}

/* Tombol sekunder (mis. "Keluar") tidak ikut melebar penuh seperti tombol utama. */
.auth-kartu button.kecil[type=submit] { width: auto; display: block; margin: 4px auto 0; }

.auth-tautan { text-align: center; font-size: .85rem; margin-top: 16px; color: var(--teks-gelap-redup); }
.auth-tautan + .auth-tautan { margin-top: 8px; }
.auth-tautan a { font-weight: 600; }

/* Pesan galat per-field (dipasang lewat @error di masing-masing view). */
.pesan-galat { display: block; color: var(--bad); font-size: .8rem; margin-top: 5px; }
.pesan-galat-tengah { text-align: center; margin-top: -6px; }
input.input-galat, textarea.input-galat, select.input-galat {
  border-color: var(--bad); background: var(--bad-bg);
}
input.input-galat:focus, textarea.input-galat:focus, select.input-galat:focus {
  box-shadow: 0 0 0 3px rgba(196, 60, 70, .18);
}

@media (max-width: 480px) {
  .auth-shell { padding: 12px; }
  .auth-kartu { padding: 22px 16px; }
}
