/* ==========================================================================
   SIAP IPDN — KOMPONEN
   ==========================================================================

   Gaya untuk komponen bernama: kerangka (sidebar, topbar), dan pola halaman
   (page-header, stat card, filter bar, tabel, badge, empty state).

   PENTING — markup sidebar dibekukan.
   Nama kelas di bawah (`nav-submenu`, `has-active-child`, `nav-soon`, dst.)
   dikunci oleh tests/Feature/SidebarRenderTest.php sampai ke tingkat atribut
   `aria-expanded` dan `id="sb-*"`. Perombakan tampilan dilakukan LEWAT CSS ini;
   struktur partials/_sidebar_menu.blade.php tidak disentuh.
   ========================================================================== */

/* ==========================================================================
   SIDEBAR — gaya "accent ladder", cangkang "open plane"
   ==========================================================================
   Arahan dari skill design-taste-frontend (kind smb-admin, style
   accent-ladder): sidebar duduk di atas LATAR HALAMAN, dipisah satu garis
   rambut, bukan balok dongker pekat. Di 23 aplikasi kerja yang diteliti skill
   itu, tidak satu pun memasang sidebar gelap di samping kanvas terang (0 dari
   17); balok gelap setinggi layar adalah ciri dashboard buatan template.

   Dongker IPDN tidak hilang — ia pindah ke tempat yang bermakna: menu aktif
   (latar dongker muda, tulisan dongker tua, ikon dongker penuh), tombol
   utama, dan data. Emas tinggal di cincin lambang. */

#sidebar {
    width: var(--sidebar-width);
    height: 100vh;
    max-height: 100vh;
    background: var(--surface-app);
    border-right: 1px solid var(--border);
    position: fixed;
    left: 0; top: 0;
    z-index: 1000;
    transition: transform .3s ease;
    display: flex;
    flex-direction: column;
}

#sidebar .sidebar-brand,
#sidebar .sidebar-footer { flex-shrink: 0; }

#sidebar .sidebar-brand {
    padding: var(--s-4) var(--s-5);
    display: flex;
    align-items: center;
    gap: var(--s-3);
    text-decoration: none;
}

/* Lambang IPDN adalah segel BULAT. Alas putih dan cincin emas dipertahankan:
   itu aset merek, bukan hiasan, dan satu-satunya tempat emas tampil. */
#sidebar .sidebar-brand .brand-logo {
    width: 40px; height: 40px;
    background: var(--n-0);
    border-radius: 50%;
    display: flex; align-items: center; justify-content: center;
    font-size: 1.2rem; color: var(--a-700); font-weight: var(--fw-bold);
    flex-shrink: 0; overflow: hidden;
    box-shadow: 0 0 0 2px var(--a-emas);
}
#sidebar .sidebar-brand .brand-logo img {
    width: 100%; height: 100%; object-fit: contain; padding: 2px;
}

#sidebar .sidebar-brand .brand-text .title {
    font-size: var(--t-lg); font-weight: var(--fw-bold);
    color: var(--text); line-height: 1.2;
}

#sidebar .sidebar-brand .brand-text .subtitle {
    font-size: var(--t-2xs); color: var(--text-muted);
}

#sidebar .sidebar-nav {
    flex: 1;
    padding: 0 var(--s-3) var(--s-3);
    overflow-y: auto;
    /* Menggulir melewati ujung menu tidak ikut menggulir halaman. */
    overscroll-behavior: contain;
}

/* Judul kelompok: huruf biasa, abu-abu, tanpa jarak huruf. Sumbernya sudah
   ditulis "Akademik"; KAPITAL berjarak lebar hanya datang dari CSS lama, dan
   menurut penelitian skill itu terbaca lebih keras daripada menunya sendiri. */
#sidebar .nav-section-title {
    font-size: var(--t-2xs);
    font-weight: var(--fw-medium);
    color: var(--text-muted);
    padding: var(--s-5) var(--s-3) var(--s-1);
}

/* Satu aturan untuk tiga elemen: <a> (tautan), <button> (induk submenu), dan
   <span> (item "Segera") — supaya ketiganya tampil identik. */
#sidebar .nav-item .nav-link {
    display: flex;
    align-items: center;
    gap: var(--s-3);
    padding: 7px var(--s-3);
    margin: 1px 0;
    color: var(--n-700);
    text-decoration: none;
    font-size: var(--t-base);
    font-weight: var(--fw-normal);
    border-radius: var(--r-md);
    transition: background var(--gerak), color var(--gerak);
    width: 100%;
    background: none;
    border: 0;
    text-align: left;
    cursor: pointer;
}

#sidebar .nav-item .nav-link:hover {
    background: var(--n-100);
    color: var(--text);
}

/* Baris aktif: TINT dongker dengan tulisan dongker tua — inti gaya accent
   ladder: hue penuh hanya pada tanda kecil (ikonnya), tint-nya pada bidang.
   Kontras: --a-700 di atas --a-50 sekitar 11:1. Tanpa garis kiri: skill
   menandai garis kiri di atas tint sebagai penanda ganda. */
#sidebar .nav-item .nav-link.active {
    background: var(--a-50);
    color: var(--a-700);
    font-weight: var(--fw-medium);
}
#sidebar .nav-item .nav-link.active .nav-icon { color: var(--a-500); }

#sidebar .nav-item .nav-link .nav-icon {
    width: 18px; text-align: center;
    font-size: .9rem;
    color: var(--text-muted);
    flex-shrink: 0;
}

/* Label mengambil sisa ruang agar caret & badge terdorong ke kanan. */
#sidebar .nav-item .nav-link .nav-label { flex: 1; min-width: 0; }

#sidebar .nav-item .nav-link:focus-visible {
    outline: 2px solid var(--a-500);
    outline-offset: 0;
}

/* ── Submenu ───────────────────────────────────────────────────────────────
   Indentasi memakai child combinator (>) supaya aturan tingkat 2 tidak ikut
   mengenai tingkat 3. Garis pemandu berada di bawah pusat ikon induk:
   12px padding tautan + 9px setengah lebar ikon. */
#sidebar .nav-submenu { position: relative; }

#sidebar .nav-submenu::before {
    content: '';
    position: absolute; left: 21px; top: 4px; bottom: 4px;
    width: 1px; background: var(--border);
}

#sidebar .nav-submenu > .nav-item > .nav-link {
    padding-left: 42px;
    font-size: var(--t-sm);
}

/* Anak tidak memakai ikon — indentasi & garis pemandu sudah cukup. */
#sidebar .nav-submenu > .nav-item > .nav-link .nav-icon { display: none; }

#sidebar .nav-submenu .nav-submenu > .nav-item > .nav-link {
    padding-left: 58px;
    font-size: var(--t-sm);
}

/* Caret berputar mengikuti aria-expanded, jadi hanya satu atribut yang harus
   benar (Bootstrap yang memeliharanya setelah render pertama). */
#sidebar .nav-caret {
    font-size: .65rem;
    color: var(--text-muted);
    flex-shrink: 0;
    transition: transform .2s ease;
}

#sidebar .nav-toggle[aria-expanded="true"] .nav-caret { transform: rotate(90deg); }

/* Induk yang memuat halaman aktif: tulisannya tinta penuh dan ikonnya
   dongker — penanda yang tetap terlihat walau cabangnya ditutup, tanpa
   menyaingi baris aktif yang sesungguhnya. */
#sidebar .nav-toggle.has-active-child { color: var(--text); }
#sidebar .nav-toggle.has-active-child .nav-icon { color: var(--a-500); }

/* ── Item "Segera" (fitur belum ada) ──────────────────────────────────────*/
#sidebar .nav-item .nav-soon {
    color: var(--text-muted);
    cursor: not-allowed;
    user-select: none;
}
#sidebar .nav-item .nav-soon:hover {
    background: none;
    color: var(--text-muted);
}

#sidebar .nav-badge {
    font-size: var(--t-2xs); font-weight: var(--fw-medium);
    padding: 1px var(--s-2); border-radius: var(--r-sm);
    background: var(--n-100);
    color: var(--text-muted);
    flex-shrink: 0;
}

#sidebar .sidebar-footer {
    padding: var(--s-3) var(--s-5);
    border-top: 1px solid var(--border);
}

#sidebar .sidebar-footer .user-info { display: flex; align-items: center; gap: var(--s-3); }

#sidebar .sidebar-footer .avatar {
    width: 32px; height: 32px;
    background: var(--a-100);
    border-radius: 50%;
    display: flex; align-items: center; justify-content: center;
    font-size: var(--t-sm); font-weight: var(--fw-semi); color: var(--a-700);
    flex-shrink: 0;
}

/* min-width:0 WAJIB. Bawaan flex item adalah min-width:auto, yang menolak
   menyusut lebih kecil daripada isinya — sehingga .user-name tidak pernah
   membungkus ke baris berikut dan nama panjang menembus tepi sidebar. */
#sidebar .sidebar-footer .user-meta { min-width: 0; flex: 1 1 auto; }

/* Nama boleh dua baris, bukan dipotong dengan "…". Nama orang adalah
   identitas: "AHMAD IZZA KAIZARO D…" memaksa pemiliknya mengarahkan tetikus
   hanya untuk membaca namanya sendiri. Baru di baris ketiga ia dipotong —
   nama sepanjang itu langka, dan title="" tetap menyimpan versi utuhnya. */
#sidebar .sidebar-footer .user-name {
    font-size: var(--t-sm); color: var(--text); font-weight: var(--fw-medium);
    line-height: 1.3;
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    overflow: hidden;
    overflow-wrap: anywhere;
}

#sidebar .sidebar-footer .user-role {
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    font-size: var(--t-2xs); color: var(--text-muted);
}

#sidebar .sidebar-nav::-webkit-scrollbar { width: 4px; }
#sidebar .sidebar-nav::-webkit-scrollbar-thumb { background: var(--border); border-radius: 2px; }

/* ==========================================================================
   KERANGKA HALAMAN
   ========================================================================== */

/* Tautan "Lewati ke isi": di luar layar sampai difokus papan ketik. */
.lewati-ke-isi {
    position: absolute;
    left: var(--s-3); top: -100px;
    z-index: 2000;
    padding: var(--s-2) var(--s-4);
    border-radius: var(--r-md);
    background: var(--a-500);
    color: var(--n-0);
    font-weight: var(--fw-semi);
    text-decoration: none;
}
.lewati-ke-isi:focus { top: var(--s-3); color: var(--n-0); }

/* Fokus yang dipindah ke <main> lewat tautan di atas tidak perlu cincin. */
#isi-utama:focus { outline: none; }

#main-content {
    margin-left: var(--sidebar-width);
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    transition: margin-left .3s ease;
}

#topbar {
    height: var(--topbar-height);
    /* Warna latar halaman, buram, tanpa kaca: skill melarang backdrop blur.
       Garis bawahnya baru muncul setelah halaman digulir (.tergulir, dipasang
       skrip di layouts/app) — sebelum itu bilah ini menyatu dengan halaman. */
    background: var(--surface-app);
    border-bottom: 1px solid transparent;
    transition: border-color var(--gerak);
    display: flex;
    align-items: center;
    padding: 0 var(--s-6);
    position: sticky;
    top: 0; z-index: 999;
    gap: var(--s-3);
}

#topbar .topbar-title {
    font-size: var(--t-lg);
    font-weight: var(--fw-semi);
    color: var(--text);
    flex: 1;
}

#topbar .topbar-actions { display: flex; align-items: center; gap: var(--s-2); }

#topbar.tergulir { border-bottom-color: var(--border); }

.page-content { padding: var(--s-6); flex: 1; }

/* ── Kepala halaman ───────────────────────────────────────────────────────*/
.page-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    margin-bottom: var(--s-5);
    flex-wrap: wrap;
    gap: var(--s-3);
}

.page-header .page-title {
    font-size: var(--t-xl);
    font-weight: var(--fw-bold);
    color: var(--text);
    margin: 0;
    letter-spacing: -.015em;
}

/* Ikon judul kartu: polos dan abu-abu. Ikon dongker di tiap judul menaruh
   warna merek di bingkai, bukan di data — gaya accent ladder menyimpan hue
   penuh untuk tanda kecil yang bermakna saja. text-primary Bootstrap memakai
   !important, jadi penggantinya juga. */
.card-header .card-title > i:first-child { color: var(--text-muted) !important; }

.page-header .page-subtitle {
    font-size: var(--t-sm);
    color: var(--text-muted);
    margin: var(--s-1) 0 0;
    max-width: 78ch;   /* baris terlalu panjang sulit dibaca */
}

.page-header__actions { display: flex; align-items: center; gap: var(--s-2); flex-wrap: wrap; }

/* ==========================================================================
   KARTU STATISTIK
   ==========================================================================
   Dua bentuk yang sebelumnya hidup terpisah:
   - `.stat-card` di 4 dashboard
   - pola `$kartu = [...]` di 4 halaman daftar, identik byte-per-byte
   Keduanya kini memakai satu bentuk lewat <x-stat-cards>. */

.stat-card {
    background: var(--surface-card);
    border: 0;
    border-radius: var(--r-lg);
    box-shadow: var(--sh-kartu);
    padding: var(--s-5);
}

/* KPI adalah tulisan, bukan ubin: label dan angka. Ikon dalam kotak berwarna
   di tiap kartu — tidak satu pun dari 23 aplikasi kerja yang diteliti skill
   design-taste-frontend memakainya, dan alat pemeriksanya menandainya sebagai
   ciri dashboard template paling umum. Elemennya dibiarkan di markup (dipakai
   beberapa view lewat <x-stat-cards>), hanya tidak ditampilkan. */
.stat-card .stat-icon { display: none !important; }

.stat-card .stat-icon {
    width: 44px; height: 44px;
    border-radius: var(--r-md);
    display: flex; align-items: center; justify-content: center;
    font-size: 1.2rem;
    flex-shrink: 0;
}

.stat-card .stat-value {
    font-size: var(--t-2xl); font-weight: var(--fw-semi);
    color: var(--text); line-height: 1.1;
    letter-spacing: -.02em;
    font-variant-numeric: tabular-nums;
}

.stat-card .stat-label {
    font-size: var(--t-sm); color: var(--text-muted);
    font-weight: var(--fw-medium);
}

/* Kartu statistik ringkas untuk halaman daftar — ikon di samping, bukan di
   atas, supaya empat kartu tetap muat satu baris di layar sedang. */
.stat-card--ringkas { padding: var(--s-4); }
.stat-card--ringkas .stat-value { font-size: var(--t-xl); }
.stat-card--ringkas .stat-icon { width: 38px; height: 38px; font-size: 1.05rem; }

/* ── Wadah angka utama (dashboard) ─────────────────────────────────────────
   Satu kartu dibagi garis 1px menjadi sel-sel sama lebar — pola bawaan KPI
   pada lembar arahan accent-ladder. Label di atas angka, keterangan kecil di
   bawahnya menyebut pembanding atau artinya. Di ponsel menjadi dua kolom,
   tidak pernah empat kolom yang terjepit. */
.kpi-strip {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
}
.kpi-strip__sel {
    padding: var(--s-4) var(--s-5);
    min-width: 0;
}
.kpi-strip__sel + .kpi-strip__sel { border-left: 1px solid var(--border); }
.kpi-strip__label {
    font-size: var(--t-sm);
    color: var(--text-muted);
}
.kpi-strip__nilai {
    margin-top: var(--s-1);
    font-size: var(--t-xl);
    font-weight: var(--fw-semi);
    color: var(--text);
    line-height: 1.2;
    font-variant-numeric: tabular-nums;
}
.kpi-strip__ket {
    margin-top: 2px;
    font-size: var(--t-2xs);
    color: var(--text-faint);
}
@media (max-width: 768px) {
    .kpi-strip { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .kpi-strip__sel + .kpi-strip__sel { border-left: 0; }
    .kpi-strip__sel:nth-child(even) { border-left: 1px solid var(--border); }
    .kpi-strip__sel:nth-child(n+3) { border-top: 1px solid var(--border); }
}

/* ==========================================================================
   TABEL & PEMBUNGKUSNYA
   ========================================================================== */

/* overflow-x: auto, BUKAN hidden.
   Dulu `overflow: hidden` MEMOTONG tabel yang lebih lebar dari wadahnya — kolom
   paling kanan (yang justru berisi tombol aksi) hilang tanpa scrollbar, tanpa
   tanda apa pun. */
.table-wrapper {
    border-radius: 0 0 calc(var(--r-lg) - 1px) calc(var(--r-lg) - 1px);
    overflow-x: auto;
    overflow-y: hidden;
}

/* Untuk tabel yang belum punya .table-wrapper. */
.tabel-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }

/* ── Keadaan kosong ───────────────────────────────────────────────────────
   Sebelumnya ada dua bentuk berbeda di 54 view: satu hanya ikon + satu baris,
   satu lagi ikon + judul + petunjuk. Yang kedua lebih berguna — keadaan kosong
   adalah tempat paling tepat memberi tahu apa langkah berikutnya. */
.empty-state {
    text-align: center;
    padding: var(--s-10) var(--s-5);
    color: var(--text-muted);
}

.empty-state__icon {
    font-size: 1.6rem;
    color: var(--text-faint);
    opacity: .55;
    margin-bottom: var(--s-3);
}

.empty-state__title {
    font-size: var(--t-base);
    font-weight: var(--fw-medium);
    color: var(--n-600);
}

.empty-state__hint {
    font-size: var(--t-sm);
    color: var(--text-muted);
    margin-top: var(--s-1);
}

/* ── Paginasi ─────────────────────────────────────────────────────────────
   Satu pembungkus, menggantikan 8 varian berbeda di 27 view. */
.pager {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: var(--s-3);
    padding: var(--s-3) var(--s-5);
    border-top: 1px solid var(--border);
}

.pager__info { font-size: var(--t-sm); color: var(--text-muted); }

/* ==========================================================================
   SARINGAN
   ========================================================================== */

.filter-bar { margin-bottom: var(--s-5); }
.filter-bar .card-body { padding: var(--s-3) var(--s-4); }

.search-box { position: relative; }

.search-box .fa-magnifying-glass {
    position: absolute;
    left: var(--s-3); top: 50%;
    transform: translateY(-50%);
    color: var(--text-faint);
    font-size: .8rem;
    pointer-events: none;
}

.search-box input { padding-left: var(--s-8); }

/* ==========================================================================
   BADGE SEMANTIK
   ==========================================================================
   Menggantikan triplet warna yang ditulis tangan di 72 view, mis.
   `background:#fffbeb;color:#92400e;border:1px solid #fcd34d;` — palet yang
   sama diulang di khs/index, akm/index, kelulusan/index, kegiatan/index. */

/* Kapsul tanpa garis. Lencana bergaris terbaca seperti kolom isian; warna
   latarnya sendiri sudah cukup membedakan status. border-width 0 (bukan
   menghapus border-color di tiap varian) supaya varian lama tetap sah. */
.badge-siap {
    display: inline-flex; align-items: center; gap: var(--s-1);
    font-size: var(--t-2xs);
    font-weight: var(--fw-semi);
    border-radius: var(--r-pill);
    padding: var(--s-1) 10px;
    border: 0 solid transparent;
    white-space: nowrap;
}

.badge-siap--netral  { background: var(--n-100);   border-color: var(--border);     color: var(--n-600); }
.badge-siap--aksen   { background: var(--a-50);    border-color: var(--a-100);      color: var(--a-500); }
.badge-siap--ok      { background: var(--ok-50);   border-color: var(--ok-200);     color: var(--ok-800); }
.badge-siap--warn    { background: var(--warn-50); border-color: var(--warn-200);   color: var(--warn-800); }
.badge-siap--bad     { background: var(--bad-50);  border-color: var(--bad-200);    color: var(--bad-800); }
.badge-siap--info    { background: var(--info-50); border-color: var(--info-200);   color: var(--info-800); }
/* Ungu bukan status — hanya pembeda identitas (peran superadmin, avatar). */
.badge-siap--ungu    { background: var(--ungu-50); border-color: var(--ungu-50);   color: var(--ungu-600); }

/* Tingkat praja — makna khas IPDN, bukan status umum. */
.badge-tingkat-nindya { background: var(--a-50);    color: var(--a-500); }
.badge-tingkat-madya  { background: var(--warn-50); color: var(--warn-600); }
.badge-tingkat-wasana { background: var(--ok-50);   color: var(--ok-600); }

/* ==========================================================================
   TOMBOL AKSI IKON
   ==========================================================================
   Tombol ikon-saja WAJIB punya aria-label atau title — ikonnya sendiri tidak
   terbaca pembaca layar. */

.btn-action {
    width: 32px; height: 32px;
    display: inline-flex; align-items: center; justify-content: center;
    border-radius: var(--r-sm);
    font-size: var(--t-xs);
    border: 1px solid transparent;
    cursor: pointer;
    text-decoration: none;
    transition: background var(--gerak), color var(--gerak);
}

/* Polos sampai disorot. Dulu tiap baris membawa tiga kotak berwarna (biru,
   kuning, merah) — di tabel 15 baris itu 45 kotak berwarna, lebih keras
   daripada datanya; pemeriksa skill design-taste-frontend menandainya
   sebagai ikon-dalam-kotak. Warnanya kini muncul saat disorot atau difokus,
   tepat ketika maknanya dibutuhkan. Hapus tetap merah agar tidak tertukar. */
.btn-action.btn-view,
.btn-action.btn-edit,
.btn-action.btn-approve { background: transparent; color: var(--text-muted); }
.btn-action.btn-delete  { background: transparent; color: var(--bad-600); }

.btn-action.btn-view:hover,    .btn-action.btn-view:focus-visible    { background: var(--a-50);    color: var(--a-700); }
.btn-action.btn-edit:hover,    .btn-action.btn-edit:focus-visible    { background: var(--warn-50); color: var(--warn-800); }
.btn-action.btn-delete:hover,  .btn-action.btn-delete:focus-visible  { background: var(--bad-50);  color: var(--bad-800); }
.btn-action.btn-approve:hover, .btn-action.btn-approve:focus-visible { background: var(--ok-50);   color: var(--ok-800); }

.avatar-circle {
    width: 36px; height: 36px;
    border-radius: 50%;
    display: inline-flex; align-items: center; justify-content: center;
    font-size: var(--t-sm); font-weight: var(--fw-semi);
    flex-shrink: 0;
}

/* ==========================================================================
   UTILITAS KECIL
   ==========================================================================
   Sengaja SEDIKIT. Ini pengganti gaya inline yang paling sering muncul, bukan
   awal dari kerangka utility sendiri — untuk itu Bootstrap sudah cukup. */

/* Skala lengkap. `.t-base` sempat dipakai di view tanpa pernah didefinisikan di
   sini, jadi elemennya diam-diam mewarisi ukuran induknya — tidak terlihat
   rusak, hanya salah ukuran. Skalanya dilengkapi seluruhnya supaya lubang
   seperti itu tidak bisa terulang. */
.t-2xs  { font-size: var(--t-2xs); }
.t-xs   { font-size: var(--t-xs); }
.t-sm   { font-size: var(--t-sm); }
.t-base { font-size: var(--t-base); }
.t-md   { font-size: var(--t-md); }
.t-lg   { font-size: var(--t-lg); }
.t-xl   { font-size: var(--t-xl); }
.t-2xl  { font-size: var(--t-2xl); }

.c-muted { color: var(--text-muted); }
.c-faint { color: var(--text-faint); }
.c-text  { color: var(--text); }
.c-aksen { color: var(--a-500); }

.fw-semi { font-weight: var(--fw-semi); }
.fw-bold { font-weight: var(--fw-bold); }

/* Radius. Menutupi 342+ gaya inline `border-radius:` — pola inline tunggal
   terbanyak di aplikasi. Nilai 4/7/9/12/14px yang sebelumnya tersebar tanpa
   aturan dibulatkan ke langkah terdekat; bedanya tidak terlihat mata, dan
   mempertahankan tujuh nilai berbeda hanya melestarikan ketidaksengajaan. */
.r-sm    { border-radius: var(--r-sm); }
.r-md    { border-radius: var(--r-md); }
.r-lg    { border-radius: var(--r-lg); }
.r-pill  { border-radius: var(--r-pill); }
.r-bulat { border-radius: 50%; }

/* Warna teks lanjutan — pasangan gelap/terang tiap status, dipakai badge dan
   angka yang menyatakan keadaan. */
.c-body       { color: var(--text-body); }
.c-putih      { color: var(--n-0); }
.c-ok-gelap   { color: var(--ok-800); }
.c-warn-gelap { color: var(--warn-800); }
.c-bad-gelap  { color: var(--bad-800); }
.c-info       { color: var(--info-600); }
.c-info-gelap { color: var(--info-800); }
.c-ungu       { color: var(--ungu-600); }

/* Latar datar. Awalan `l-` (latar), bukan `bg-`, supaya tidak bertabrakan
   dengan utilitas Bootstrap yang namanya sama tapi paletnya berbeda. */
.l-kartu  { background: var(--surface-card); }
.l-cekung { background: var(--surface-sunken); }
.l-app    { background: var(--surface-app); }
.l-aksen  { background: var(--a-50); }
.l-ok     { background: var(--ok-50); }
.l-warn   { background: var(--warn-50); }
.l-bad    { background: var(--bad-50); }
.l-info   { background: var(--info-50); }
.l-ungu   { background: var(--ungu-50); }

/* Garis batas. Menggantikan `border:1px solid #e2e8f0` dan kawan-kawan yang
   ditulis tangan ratusan kali dengan lima nilai hex berbeda. */
.garis        { border: 1px solid var(--border); }
/* Dulu 1,5px — dipakai 27 kartu kecil di dalam kartu, dan garis setebal itu
   yang paling membuat halaman terbaca sebagai susunan balok. Namanya
   dipertahankan supaya 27 view itu tidak perlu disentuh. */
.garis-tebal  { border: 1px solid var(--border); }
.garis-samar  { border: 1px solid var(--n-100); }
.garis-tegas  { border: 1px solid var(--border-strong); }
.garis-ok     { border: 1px solid var(--ok-200); }
.garis-warn   { border: 1px solid var(--warn-200); }
.garis-bad    { border: 1px solid var(--bad-200); }
.garis-info   { border: 1px solid var(--info-200); }
.garis-aksen  { border: 1px solid var(--a-100); }
.garis-tanpa  { border: 0; }

/* Label kecil huruf besar — kepala kolom & penanda bagian. Dua properti ini
   praktis selalu datang bersama, tapi tetap dipisah karena sebagian tempat
   hanya butuh salah satunya. */
.huruf-besar { text-transform: uppercase; }
.renggang    { letter-spacing: .04em; }

/* Abu paling redup — keadaan mati, ikon pengganti, teks contoh. */
.c-samar   { color: var(--border-strong); }

/* Nuansa menengah tiap status. Ada karena aplikasi memang memakainya — bukan
   demi kelengkapan skala: #f59e0b, #22c55e, dan #ef4444 masing-masing ditulis
   tangan 30, 14, dan 10 kali. */
.c-ok-terang   { color: var(--ok-500); }
.c-warn-terang { color: var(--warn-600); }  /* ikon & angka besar (≥3:1); teks kecil pakai .c-warn-gelap */
.c-bad-terang  { color: var(--bad-500); }
.c-aksen-redup { color: var(--a-300); }

/* Latar status satu tingkat lebih pekat dari -50, untuk pita yang perlu lebih
   terbaca di atas kartu putih. */
.l-ok-kuat   { background: var(--ok-100); }
.l-warn-kuat { background: var(--warn-100); }
.l-bad-kuat  { background: var(--bad-100); }
.l-aksen-kuat { background: var(--a-100); }

/* `box-shadow:none` ditulis tangan 15 kali untuk mematikan bayangan bawaan
   Bootstrap pada kartu dan kendali. Tampilan bersih memisahkan bidang dengan
   GARIS, bukan bayangan — jadi ini pola yang memang sering dibutuhkan. */
.tanpa-bayang { box-shadow: none; }

.bisa-klik { cursor: pointer; }

/* ── Kartu di dalam kisi ──────────────────────────────────────────────────
   Kartu yang seluruhnya merupakan pintu masuk (kartu mata kuliah, kartu
   kelas praja). Terangkat sedikit saat disorot supaya terasa bisa dipilih;
   kartu biasa (formulir, panel isian) sengaja TIDAK diberi efek ini, karena
   efek sorot pada sesuatu yang tidak bisa diklik itu menyesatkan. */
.kartu-kisi { transition: border-color var(--gerak); }
/* Sorot = garis yang menegas ke dongker, bukan kartu terangkat berbayang:
   di layar kerja bayangan hanya untuk yang melayang (menu, dialog). */
.kartu-kisi:hover { border-color: var(--a-300); }

/* ── Tombol lembut ────────────────────────────────────────────────────────
   Untuk tindakan yang BERULANG di setiap kartu sebuah kisi ("Kelola Kelas",
   "Lihat Absensi & Jadwal"). Dua belas balok dongker penuh dalam satu layar
   saling bersaing dan membuat halaman terasa berat; tindakan utama halaman
   tetap .btn-primary, dan hanya ia yang menarik mata. */
.btn-lembut {
    background: var(--a-50);
    border: 1px solid transparent;
    color: var(--a-500);
    font-weight: var(--fw-semi);
}
.btn-lembut:hover,
.btn-lembut:focus-visible {
    background: var(--a-500);
    color: var(--n-0);
}

/* Gambar yang mengisi wadahnya penuh tanpa gepeng — foto praja & dosen. */
.isi-penuh { width: 100%; height: 100%; object-fit: cover; }

/* ==========================================================================
   PORTAL DOSEN — POLA BERSAMA
   ==========================================================================
   Kelas-kelas di bawah tadinya didefinisikan ULANG di tiap view lewat
   @push('styles'): `.btn-nilai` di tiga view, `.keterangan-bagian` di empat.
   Definisinya sudah mulai menyimpang tanpa sengaja — padding 18px di satu
   tempat, 20px di tempat lain, satu punya `cursor:pointer` dan yang lain tidak.
   Disatukan di sini dengan satu nilai; itulah gunanya lapis bersama.

   Ukurannya sengaja lebih besar dari bawaan aplikasi (min-height 44px, huruf
   .9rem): penggunanya dosen senior dan ini halaman yang paling sering dibuka.
   Angka 44px bukan karangan — itu ambang sasaran sentuh yang nyaman di layar
   sentuh. */

/* Paragraf keterangan di bawah judul bagian. max-width menahan panjang baris
   di ±62 karakter supaya tetap nyaman dibaca, sekaligus mencegah paragraf
   melebar mengikuti kartu di layar lebar. */
.keterangan-bagian {
    font-size: var(--t-base);
    color: var(--text-muted);
    line-height: 1.6;
    margin: var(--s-1) 0 0;
    max-width: 62ch;
    overflow-wrap: break-word;
}

.judul-bagian {
    font-size: var(--t-lg);
    font-weight: var(--fw-bold);
    color: var(--text);
    margin: 0;
}

.btn-nilai {
    min-height: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--s-2);
    padding: 10px var(--s-5);
    border-radius: var(--r-lg);
    font-size: var(--t-base);
    font-weight: var(--fw-semi);
    border: 0;
    text-decoration: none;
    cursor: pointer;
}

.btn-nilai-utama       { background: var(--a-500); color: var(--n-0); }
.btn-nilai-utama:hover { background: var(--a-700); color: var(--n-0); }
.btn-nilai-kedua       { background: var(--surface-app); color: var(--n-600); }
.btn-nilai-kedua:hover { background: var(--border); color: var(--text); }

/* Chip status kehadiran. Sasaran sentuh 40px — chip lama (padding 4px 12px)
   terlalu kecil untuk diklik tanpa membidik. */
.status-chip {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 40px; min-width: 78px;
    padding: var(--s-2) var(--s-4);
    border-radius: var(--r-lg);
    font-size: var(--t-base);
    font-weight: var(--fw-semi);
    transition: background .15s, color .15s, border-color .15s;
    cursor: pointer;
}

.btn-absen-massal,
.btn-absen-simpan {
    min-height: 44px;
    display: inline-flex;
    align-items: center;
    gap: var(--s-2);
    padding: 10px 18px;
    border-radius: var(--r-lg);
    font-size: var(--t-base);
    font-weight: var(--fw-semi);
    border: 0;
    cursor: pointer;
    text-decoration: none;
}

.btn-absen-simpan       { background: var(--a-500); color: var(--n-0); padding: 10px 26px; }
.btn-absen-simpan:hover { background: var(--a-700); color: var(--n-0); }

.tabel-absensi td        { padding: var(--s-3) var(--s-4); font-size: var(--t-base); }
.tabel-absensi thead th  { padding: var(--s-3) var(--s-4); font-size: var(--t-sm); }

.judul-kelas-blok { font-size: var(--t-lg); font-weight: var(--fw-bold); color: var(--text); }

/* Tab pemilih kelas — dipakai Absensi Gabungan dan Nilai Paket. min-width 130px,
   nilai terbesar dari dua definisi yang tadinya berbeda (120 vs 130): yang lebih
   sempit membuat nama kelas panjang terpotong. */
.tab-kelas {
    display: flex;
    gap: var(--s-2);
    flex-wrap: wrap;
    background: var(--surface-app);
    border-radius: var(--r-lg);
    padding: var(--s-1) var(--s-1);
    margin-bottom: var(--s-4);
}

.tab-kelas-btn {
    flex: 1 1 auto;
    min-width: 130px; min-height: 62px;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 1px;
    padding: var(--s-2) var(--s-4);
    border: 2px solid transparent;
    border-radius: var(--r-md);
    background: transparent;
    color: var(--n-600);
    cursor: pointer;
    transition: background .15s, border-color .15s, color .15s;
}

.tab-kelas-btn:hover { background: var(--border); }

.tab-kelas-btn.aktif {
    background: var(--surface-card);
    border-color: var(--a-500);
    color: var(--a-700);
    box-shadow: var(--sh-1);
}

.tab-nama   { font-size: var(--t-lg); font-weight: var(--fw-bold); line-height: 1.2; }
.tab-jumlah { font-size: var(--t-xs); opacity: .8; }

.tab-lencana {
    font-size: var(--t-2xs);
    font-weight: var(--fw-bold);
    padding: 1px 9px;
    border-radius: var(--r-pill);
    margin-top: 3px;
    white-space: nowrap;
}

.tab-lencana.lengkap  { background: var(--ok-100);   color: var(--ok-800); }
.tab-lencana.sebagian { background: var(--warn-100); color: var(--warn-800); }
.tab-lencana.kosong   { background: var(--surface-app); color: var(--text-muted); }

/* Teks utama satu baris pada sel tabel + keterangan kecil di bawahnya —
   pola yang muncul di hampir setiap halaman daftar. */
.sel-utama { font-weight: var(--fw-medium); color: var(--text); }
.sel-sub   { font-size: var(--t-xs); color: var(--text-faint); }

/* ==========================================================================
   RESPONSIVE
   ==========================================================================
   Sebelumnya seluruh aplikasi hanya punya SATU media query. */

@media (max-width: 992px) {
    .page-content { padding: var(--s-4); }
    #topbar { padding: 0 var(--s-4); }
}

@media (max-width: 768px) {
    #sidebar { transform: translateX(-100%); }
    #sidebar.show { transform: translateX(0); }
    #main-content { margin-left: 0; }

    .page-header { flex-direction: column; align-items: stretch; }
    .page-header__actions { width: 100%; }

    /* Tombol di kepala halaman melebar penuh di layar sempit — sasaran sentuh
       yang terlalu kecil lebih menyusahkan daripada tombol yang lebar. */
    .page-header__actions > .btn { flex: 1; justify-content: center; }

    .pager { justify-content: center; }
    .pager__info { width: 100%; text-align: center; }
}

@media (max-width: 576px) {
    .page-header .page-title { font-size: var(--t-lg); }
    .stat-card { padding: var(--s-4); }
}

/* Sidebar & topbar tidak ikut tercetak. Sebelumnya keduanya masuk ke kertas
   pada halaman cetak KHS/transkrip yang memakai layout aplikasi. */
@media print {
    #sidebar, #topbar { display: none !important; }
    #main-content { margin-left: 0; }
    .page-content { padding: 0; }
    .card, .stat-card { border: none; box-shadow: none; }
}

/* ── Kepingan kerangka ────────────────────────────────────────────────────
   Dipakai layouts/app.blade.php; ditaruh di sini alih-alih inline supaya tidak
   ada lagi gaya yang hidup di dalam berkas Blade. */
.avatar-circle--kecil {
    width: 28px; height: 28px;
    font-size: var(--t-2xs);
    background: var(--a-50);
    color: var(--a-500);
}

.menu-akun { font-size: var(--t-sm); min-width: 170px; }

.dropdown-menu {
    border: 1px solid var(--border-soft);
    border-radius: var(--r-md);
    box-shadow: var(--sh-3);
    padding: var(--s-1);
}

.dropdown-item {
    border-radius: var(--r-sm);
    padding: 7px var(--s-3);
}

.fw-medium { font-weight: var(--fw-medium); }

/* ==========================================================================
   VARIAN KOMPONEN
   ==========================================================================
   Warna kartu statistik & badge menyatakan MAKNA lewat nama varian, bukan hex
   yang disalin per halaman. Menggeser palet nanti cukup di tokens.css. */

.stat-icon--netral { background: var(--n-100);   color: var(--n-600); }
.stat-icon--aksen  { background: var(--a-50);    color: var(--a-500); }
.stat-icon--ok     { background: var(--ok-50);   color: var(--ok-600); }
.stat-icon--warn   { background: var(--warn-50); color: var(--warn-800); }
.stat-icon--bad    { background: var(--bad-50);  color: var(--bad-600); }
.stat-icon--info   { background: var(--info-50); color: var(--info-600); }

/* Angka mengikuti maknanya, tapi netral & aksen tetap gelap: angka utama harus
   terbaca sebagai angka, bukan sebagai penanda status. */
.stat-value--netral,
.stat-value--aksen { color: var(--text); }
.stat-value--ok    { color: var(--ok-600); }
.stat-value--warn  { color: var(--warn-800); }
.stat-value--bad   { color: var(--bad-600); }
.stat-value--info  { color: var(--info-600); }

/* Kartu yang bisa diklik — isyaratnya halus, bukan seperti tombol. */
.stat-card--tautan { text-decoration: none; color: inherit; display: flex; }
.stat-card--tautan:hover { border-color: var(--a-100); }

.badge-siap__ikon { font-size: .6rem; }

/* Panel di dalam kartu: latar sedikit tenggelam, untuk mengelompokkan tanpa
   menambah kartu di dalam kartu. */
.panel-dalam {
    background: var(--surface-sunken);
    border: 1px solid var(--border);
    border-radius: var(--r-md);
    padding: var(--s-3) var(--s-4);
}

.c-aksen-gelap { color: var(--a-700); }

/* Dipakai kartu statistik agar teks panjang terpotong, bukan mendorong ikon. */
.min-w-0 { min-width: 0; }

/* ── Bilah kemajuan ───────────────────────────────────────────────────────
   Lebarnya satu-satunya gaya inline yang sah di view: nilainya dinamis dan
   tidak bisa dinyatakan sebagai kelas. */
.bilah {
    background: var(--n-100);
    border-radius: var(--r-pill);
    height: 6px;
    overflow: hidden;
}

.bilah__isi {
    height: 100%;
    background: var(--a-500);
    border-radius: var(--r-pill);
    transition: width .3s ease;
}

.bilah--tebal { height: 8px; }

/* Kolom yang perlu lebar tetap agar bilahnya tidak menyusut habis. */
.kol-kemajuan { width: 150px; min-width: 150px; }

.c-warn { color: var(--warn-800); }
.c-ok   { color: var(--ok-700); }   /* 4,8:1 di atas --ok-50; --ok-600 hanya 3,1:1 */
.c-bad  { color: var(--bad-600); }

/* Tautan yang tidak perlu tampak seperti tautan — judul di sel tabel yang bisa
   diklik. Garis bawah muncul saat disorot supaya kemampuan kliknya tetap
   terungkap, bukan disembunyikan sama sekali. */
.tautan-diam { color: var(--text); text-decoration: none; }
.tautan-diam:hover { color: var(--a-500); text-decoration: underline; }

/* ── Nilai huruf ──────────────────────────────────────────────────────────
   Sembilan huruf (A … E) dipetakan ke EMPAT pita makna, bukan sembilan warna
   sendiri. Empat biru yang nyaris sama untuk B+/B/B- tidak menyampaikan apa pun
   selain kebisingan; yang perlu terbaca sekilas adalah baik / cukup / kurang /
   gagal. */
.huruf {
    font-size: var(--t-lg);
    font-weight: var(--fw-bold);
}

.huruf--baik       { color: var(--ok-600); }
.huruf--cukup-baik { color: var(--a-500); }
.huruf--cukup      { color: var(--warn-600); }
.huruf--kurang     { color: var(--bad-600); }
.huruf--gagal      { color: var(--bad-800); }
.huruf--netral     { color: var(--text-muted); }

/* ── Varian avatar ────────────────────────────────────────────────────────
   Lima rona, dipilih dari nama lewat crc32 sehingga orang yang sama selalu
   mendapat warna yang sama di halaman mana pun. */
.avatar-circle--v1 { background: var(--a-50);    color: var(--a-500); }
.avatar-circle--v2 { background: var(--warn-50); color: var(--warn-600); }
.avatar-circle--v3 { background: var(--ok-50);   color: var(--ok-600); }
.avatar-circle--v4 { background: var(--ungu-50); color: var(--ungu-600); }
.avatar-circle--v5 { background: var(--bad-50);  color: var(--bad-600); }

.avatar-circle--kecil { width: 28px; height: 28px; font-size: var(--t-2xs); }
.avatar-circle--besar { width: 48px; height: 48px; font-size: var(--t-lg); }

/* ── Varian warna bilah ───────────────────────────────────────────────────*/
.bilah__isi--netral     { background: var(--n-400); }
.bilah__isi--aksen      { background: var(--a-500); }
.bilah__isi--ok         { background: var(--ok-600); }
.bilah__isi--warn       { background: var(--warn-600); }
.bilah__isi--bad        { background: var(--bad-600); }
.bilah__isi--info       { background: var(--info-600); }
.bilah__isi--ungu       { background: var(--ungu-600); }

.bilah__isi--huruf-baik       { background: var(--ok-600); }
.bilah__isi--huruf-cukup-baik { background: var(--a-500); }
.bilah__isi--huruf-cukup      { background: var(--warn-600); }
.bilah__isi--huruf-kurang     { background: var(--bad-600); }
.bilah__isi--huruf-gagal      { background: var(--bad-800); }
.bilah__isi--huruf-netral     { background: var(--n-400); }

/* ── Peringkat ────────────────────────────────────────────────────────────*/
.baris-peringkat {
    display: flex;
    align-items: center;
    gap: var(--s-2);
    padding: var(--s-2) var(--s-5);
    font-size: var(--t-sm);
}

.baris-peringkat--bergaris { border-top: 1px solid var(--n-100); }

.peringkat {
    width: 22px; height: 22px;
    border-radius: 50%;
    display: flex; align-items: center; justify-content: center;
    font-size: var(--t-2xs); font-weight: var(--fw-bold);
    background: var(--n-100); color: var(--n-600);
    flex-shrink: 0;
}

/* Tiga teratas ditandai — sisanya netral, supaya penandanya berarti. */
.peringkat--podium { background: var(--warn-50); color: var(--warn-600); }

/* ── Lebar kolom ──────────────────────────────────────────────────────────*/
.kol-progres      { width: 200px; min-width: 180px; }
.kol-huruf        { width: 28px; flex-shrink: 0; font-size: var(--t-sm); }
.kol-angka-kecil  { width: 40px; flex-shrink: 0; }

/* Teks satu baris yang dipotong bila kepanjangan — nama praja di kartu sempit. */
.teks-potong {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* ==========================================================================
   KALENDER PERTEMUAN — portal dosen
   ==========================================================================
   Dipindah dari @push('styles') di dosen/_kalender_pertemuan. Di sana 99
   baris CSS dengan 34 hex ditulis tangan, jadi kalender ini tidak akan ikut
   berubah kalau warna aplikasi digeser. Sekarang seluruhnya lewat token. */
.kalender-kepala {
        display: flex; align-items: flex-start; justify-content: space-between;
        gap: 16px; flex-wrap: wrap; padding: 18px 22px;
    }
    .kalender-bulan  { font-size: var(--t-xl); font-weight: var(--fw-bold); color: var(--text); }
    .kalender-jumlah { font-size: var(--t-base); color: var(--text-muted); margin-top: 2px; }

    .kalender-nav {
        min-height: 44px; display: inline-flex; align-items: center; gap: 8px;
        padding: 10px 16px; border-radius: 10px; font-size: var(--t-base); font-weight: var(--fw-semi);
        background: var(--surface-app); color: var(--n-600); text-decoration: none;
    }
    .kalender-nav:hover { background: var(--border); color: var(--text); }
    .kalender-nav-kini { background: var(--a-50); color: var(--a-700); }
    .kalender-nav-kini:hover { background: var(--a-100); color: var(--a-700); }

    .kalender-petunjuk {
        margin: 0 22px 16px; padding: 12px 16px; border-radius: 10px;
        background: var(--a-50); color: var(--a-700); font-size: var(--t-base);
    }

    .kalender-grid {
        display: grid; grid-template-columns: repeat(7, 1fr);
        gap: 1px; background: var(--border); border-top: 1px solid var(--border);
    }
    .kalender-nama-hari {
        background: var(--surface-sunken); border-top: none;
    }
    .kalender-nama-hari > div {
        background: var(--surface-sunken); padding: 10px 8px; text-align: center;
        font-size: var(--t-sm); font-weight: var(--fw-bold); color: var(--text-muted);
        text-transform: uppercase; letter-spacing: .03em;
    }

    .kalender-sel {
        background: var(--n-0); min-height: 112px; padding: 8px;
        display: flex; flex-direction: column; gap: 6px;
    }
    /* Diredupkan, bukan dikosongkan: baris minggu tetap terlihat utuh. */
    .kalender-sel.luar-bulan { background: var(--surface-sunken); }
    .kalender-sel.luar-bulan .kalender-tanggal { color: var(--border-strong); }

    .kalender-tanggal {
        font-size: var(--t-lg); font-weight: var(--fw-bold); color: var(--n-600);
        width: 30px; height: 30px; display: flex;
        align-items: center; justify-content: center; flex-shrink: 0;
    }
    .kalender-tanggal.hari-ini {
        background: var(--a-500); color: var(--n-0); border-radius: 50%;
    }

    .kalender-chip {
        display: flex; flex-direction: column; gap: 2px;
        padding: 7px 9px; border-radius: 9px; text-decoration: none;
        border: 1.5px solid transparent; transition: transform .12s, box-shadow .12s;
    }
    .kalender-chip:hover { transform: translateY(-1px); box-shadow: 0 3px 10px rgba(0,0,0,.12); }
    .chip-baris  { display: flex; align-items: center; gap: 5px; font-size: var(--t-sm); line-height: 1.3; }
    .chip-kecil  { font-size: var(--t-2xs); opacity: .85; }

    .chip-sudah { background: var(--ok-100); color: var(--ok-800); border-color: var(--ok-200); }
    .chip-belum { background: var(--warn-100); color: var(--warn-800); border-color: var(--warn-200); }

    .kalender-legenda {
        display: flex; gap: 20px; flex-wrap: wrap; align-items: center;
        padding: 16px 22px; font-size: var(--t-base); color: var(--n-600);
    }
    .kalender-legenda .kotak {
        display: inline-block; width: 14px; height: 14px;
        border-radius: 4px; border: 1.5px solid; vertical-align: -2px;
    }

    /* Nama hari lengkap hanya untuk tampilan ponsel. */
    .kalender-tanggal-ponsel { display: none; }

    /* Ponsel: petak 7 kolom membuat chip terlalu kecil untuk disentuh, jadi
       beralih ke daftar per hari. Hari tanpa pertemuan disembunyikan supaya
       tidak menghasilkan 42 baris kosong. */
    @media (max-width: 768px) {
        .kalender-nama-hari { display: none; }
        .kalender-grid { grid-template-columns: 1fr; gap: 0; background: transparent; }

        /* Hari hampa & tanggal dari bulan sebelah tidak berguna dalam bentuk
           daftar — yang dicari dosen adalah hari yang ADA pertemuannya. */
        .kalender-sel.kosong { display: none; }

        .kalender-sel {
            min-height: 0; padding: 14px 22px;
            border-bottom: 1px solid var(--surface-app); background: var(--n-0);
        }
        /* Angka bulat diganti tanggal lengkap: "Jumat, 21 Agu". */
        .kalender-sel .kalender-tanggal { display: none; }
        .kalender-tanggal-ponsel {
            display: block; font-size: var(--t-base); font-weight: var(--fw-bold);
            color: var(--text); margin-bottom: 8px;
        }
        .kalender-sel.luar-bulan .kalender-tanggal-ponsel { color: var(--text-faint); }
    }

/* ── dosen/matkul_detail ───────────────────────────────────────────────
   Dipindah dari @push('styles') di view ini. Hex diganti token supaya
   halaman ini ikut berubah saat warna aplikasi digeser. */
/* Ukuran di halaman ini sengaja lebih besar dari bawaan aplikasi:
       penggunanya dosen senior, dan ini halaman yang paling sering dibuka. */
    /* max-width membatasi panjang baris agar tetap nyaman dibaca (±75 karakter)
       sekaligus mencegah paragraf ini melebar mengikuti kartu di layar lebar. */
    .keterangan-bagian {
        font-size: var(--t-base); color: var(--text-muted); line-height: 1.6; margin: 4px 0 0;
        max-width: 62ch; overflow-wrap: break-word;
    }

    /* Kartu pertemuan — bukan baris tabel, supaya tidak ada kolom yang bisa
       terpotong dan setiap keterangan punya ruang untuk kalimat penuh. */
    .pertemuan-item {
        display: flex; gap: 18px; align-items: flex-start;
        padding: 18px 22px; border-bottom: 1px solid var(--surface-app);
    }
    .pertemuan-item:last-child { border-bottom: none; }
    .pertemuan-item:hover { background: var(--surface-sunken); }

    /* Lebar 84px + nowrap: pada 62px dengan letter-spacing, kata "PERTEMUAN"
       terpecah jadi "PERTEM / UAN". */
    .pertemuan-nomor {
        flex-shrink: 0; width: 84px; text-align: center;
        border-radius: 12px; padding: 8px 4px;
    }
    .pertemuan-nomor .angka { font-size: var(--t-2xl); font-weight: var(--fw-bold); line-height: 1; }
    .pertemuan-nomor .kata  {
        font-size: var(--t-2xs); font-weight: var(--fw-bold); text-transform: uppercase;
        letter-spacing: 0; white-space: nowrap;
    }

    /* Pemilih Daftar / Kalender */
    .pemilih-tampilan { display: inline-flex; background: var(--surface-app); border-radius: 11px; padding: 4px; gap: 4px; }
    .pemilih-tampilan a {
        min-height: 40px; display: inline-flex; align-items: center; gap: 7px;
        padding: 8px 16px; border-radius: 8px; font-size: var(--t-base); font-weight: var(--fw-semi);
        color: var(--n-600); text-decoration: none; white-space: nowrap;
    }
    .pemilih-tampilan a:hover { color: var(--text); }
    .pemilih-tampilan a.aktif { background: var(--n-0); color: var(--a-700); box-shadow: 0 1px 3px rgba(0,0,0,.1); }

    .pertemuan-tanggal { font-size: var(--t-lg); font-weight: var(--fw-bold); color: var(--text); }
    .pertemuan-baris   { font-size: var(--t-base); color: var(--n-600); margin-top: 3px; }

    /* Tombol aksi: minimal 44px tinggi — sasaran sentuh yang layak untuk
       tangan yang kurang stabil, sesuai anjuran aksesibilitas. */
    .btn-aksi {
        min-height: 44px; display: inline-flex; align-items: center; gap: 8px;
        padding: 10px 18px; border-radius: 10px; font-size: var(--t-base); font-weight: var(--fw-semi);
        border: none; cursor: pointer; text-decoration: none; white-space: nowrap;
    }
    .btn-aksi-utama   { background: var(--a-500); color: var(--n-0); }
    .btn-aksi-utama:hover { background: var(--a-700); color: var(--n-0); }
    .btn-aksi-kedua   { background: var(--a-50); color: var(--a-700); }
    .btn-aksi-kedua:hover { background: var(--a-100); color: var(--a-700); }
    .btn-aksi-hapus   { background: var(--bad-50); color: var(--bad-600); }
    .btn-aksi-hapus:hover { background: var(--bad-100); color: var(--bad-800); }

    .chip-kelas {
        display: inline-block; background: var(--ungu-50); color: var(--ungu-600);
        border: 1px solid var(--ungu-50); border-radius: 8px;
        padding: 2px 10px; font-size: var(--t-sm); font-weight: var(--fw-semi);
    }
    .label-pilih-kelas {
        cursor: pointer; background: var(--surface-sunken); border: 2px solid var(--border);
        border-radius: 12px; padding: 12px 18px; font-size: var(--t-lg);
        display: flex; align-items: center; gap: 10px; min-height: 52px;
        transition: border-color .15s, background .15s;
    }
    .label-pilih-kelas:has(input:checked) { border-color: var(--a-500); background: var(--a-50); }
    .label-pilih-kelas input { width: 20px; height: 20px; margin: 0; flex-shrink: 0; }

/* ── dosen/rekap_nilai ───────────────────────────────────────────────
   Dipindah dari @push('styles') di view ini. Hex diganti token supaya
   halaman ini ikut berubah saat warna aplikasi digeser. */
.batang-sebaran { display: flex; height: 22px; border-radius: 6px; overflow: hidden; background: var(--surface-app); }
    .batang-sebaran > span {
        display: flex; align-items: center; justify-content: center;
        font-size: var(--t-2xs); font-weight: var(--fw-bold); color: var(--n-0); min-width: 0;
    }
    .legenda-huruf { display: flex; gap: 14px; flex-wrap: wrap; font-size: var(--t-sm); color: var(--n-600); }
    .legenda-huruf .kotak { display: inline-block; width: 12px; height: 12px; border-radius: 3px; vertical-align: -1px; }
    .tabel-rekap td { padding: 14px; font-size: var(--t-base); vertical-align: middle; }
    .tabel-rekap thead th { font-size: var(--t-sm); padding: 12px 14px; }

/* ── dosen/nilai_index ───────────────────────────────────────────────
   Dipindah dari @push('styles') di view ini. Hex diganti token supaya
   halaman ini ikut berubah saat warna aplikasi digeser. */
.kartu-paket { border: 1.5px solid var(--border); box-shadow: none; height: 100%; }
    .kartu-paket:hover { border-color: var(--a-500); }

/* ── dosen/nilai_paket ───────────────────────────────────────────────
   Dipindah dari @push('styles') di view ini. Hex diganti token supaya
   halaman ini ikut berubah saat warna aplikasi digeser. */
/* Tab kelas — pola sama dengan halaman Absensi Gabungan. */
    .tab-kelas {
        display: flex; gap: 8px; flex-wrap: wrap;
        background: var(--surface-app); border-radius: 14px; padding: 6px; margin-bottom: 16px;
    }

    .tabel-nilai td { padding: 10px 14px; font-size: var(--t-base); vertical-align: middle; }
    .tabel-nilai thead th { font-size: var(--t-sm); padding: 10px 14px; }
    .input-komponen {
        width: 84px; min-height: 40px; text-align: center;
        border-radius: 8px; font-size: var(--t-lg); font-weight: var(--fw-semi);
    }
    .sel-akhir { font-weight: var(--fw-bold); color: var(--text); font-size: var(--t-lg); }
    .sel-huruf {
        display: inline-block; min-width: 42px; padding: 4px 10px;
        border-radius: 8px; font-weight: var(--fw-bold); font-size: var(--t-base);
    }
    .huruf-ada   { background: var(--a-100); color: var(--a-700); }
    .huruf-kosong{ background: var(--surface-app); color: var(--text-faint); }

/* ── khs/create ───────────────────────────────────────────────
   Dipindah dari @push('styles') di view ini. Hex diganti token supaya
   halaman ini ikut berubah saat warna aplikasi digeser. */
.hasil-cari {
        border: 1.5px solid var(--border); border-top: none;
        border-radius: 0 0 10px 10px; max-height: 300px; overflow-y: auto;
    }
    .hasil-cari button {
        display: block; width: 100%; text-align: left; border: 0;
        background: var(--n-0); padding: 10px 14px; cursor: pointer;
        border-bottom: 1px solid var(--surface-app); font-size: var(--t-base);
    }
    .hasil-cari button:hover { background: var(--a-50); }
    .hasil-cari button:last-child { border-bottom: none; }
    .praja-terpilih {
        background: var(--a-50); border: 1.5px solid var(--a-200);
        border-radius: 10px; padding: 12px 16px;
    }

/* ── partials/_pilih_praja ───────────────────────────────────────────────
   Dipindah dari @push('styles') di view ini. Hex diganti token supaya
   halaman ini ikut berubah saat warna aplikasi digeser. */
.hasil-praja {
        border: 1.5px solid var(--border); border-top: none; border-radius: 0 0 10px 10px;
        max-height: 260px; overflow-y: auto;
    }
    .hasil-praja button {
        display: block; width: 100%; text-align: left; border: 0; background: var(--n-0);
        padding: 9px 13px; cursor: pointer; border-bottom: 1px solid var(--surface-app); font-size: var(--t-base);
    }
    .hasil-praja button:hover { background: var(--a-50); }
    .hasil-praja button:last-child { border-bottom: none; }

/* ── partials/pengumuman_popup ───────────────────────────────────────────────
   Dipindah dari @push('styles') di view ini. Hex diganti token supaya
   halaman ini ikut berubah saat warna aplikasi digeser. */
@keyframes slideUp {
    from { opacity:0; transform:translateY(30px) scale(0.96); }
    to   { opacity:1; transform:translateY(0) scale(1); }
}

/* ── dosen/qr_absensi ───────────────────────────────────────────────
   Dipindah dari @push('styles') di view ini. Hex diganti token supaya
   halaman ini ikut berubah saat warna aplikasi digeser. */
@keyframes pulse-dot {
    0%,100% { box-shadow:0 0 0 3px rgba(34,197,94,0.25); }
    50%      { box-shadow:0 0 0 6px rgba(34,197,94,0.1); }
}

/* ── Pintasan Akses Cepat (dashboard) ─────────────────────────────────────
   Baris tautan: satu ikon polos 16px abu-abu lalu labelnya. Dulu petak
   dengan ikon di dalam kotak bertint — alat pemeriksa skill
   design-taste-frontend menandai ikon-dalam-kotak yang diulang sebagai ciri
   dashboard template. Sorot menegaskan garis dan mewarnai ikon dongker. */
.pintasan {
    display: flex;
    align-items: center;
    gap: var(--s-3);
    min-height: 44px;              /* sasaran sentuh */
    padding: var(--s-2) var(--s-3);
    /* Kotak di DALAM kartu: dipisah satu tingkat warna latar, bukan garis. */
    border: 0;
    border-radius: var(--r-md);
    background: var(--surface-app);
    text-decoration: none;
    transition: background-color var(--gerak), color var(--gerak);
}

.pintasan:hover { background: var(--a-50); }

.pintasan:focus-visible { outline: 2px solid var(--a-500); outline-offset: 2px; }

.pintasan__ikon {
    width: 16px;
    display: inline-flex; justify-content: center;
    color: var(--text-muted);
    flex-shrink: 0;
    transition: color var(--gerak);
}

.pintasan:hover .pintasan__ikon { color: var(--a-500); }

.pintasan__label {
    font-size: var(--t-sm);
    font-weight: var(--fw-medium);
    color: var(--text);
    line-height: 1.3;
    min-width: 0;
}

/* Kolom pemilih peran di Manajemen Pengguna. Lebar tetap supaya tabelnya tidak
   bergeser tiap kali label perannya beda panjang. */
.kol-peran { width: 140px; }

/* ── Chip huruf mutu ──────────────────────────────────────────────────────
   Huruf nilai sebagai petak berlatar. Lima pita, bukan sembilan warna: bedanya
   A dengan A- tidak perlu diberitahukan lewat warna karena hurufnya sendiri
   sudah tertulis, dan sembilan rona di satu tabel membuatnya terlihat seperti
   palet. Pemetaan huruf→pita ada di App\Support\Pita. */
.huruf-chip {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 42px;
    padding: var(--s-1) var(--s-3);
    border-radius: var(--r-md);
    border: 1px solid transparent;
    font-weight: var(--fw-bold);
    line-height: 1.2;
}

.huruf-chip--baik       { background: var(--ok-50);   border-color: var(--ok-200);   color: var(--ok-800); }
.huruf-chip--cukup-baik { background: var(--a-50);    border-color: var(--a-200);    color: var(--a-500); }
.huruf-chip--cukup      { background: var(--warn-50); border-color: var(--warn-200); color: var(--warn-800); }
.huruf-chip--kurang     { background: var(--bad-50);  border-color: var(--bad-200);  color: var(--bad-600); }
.huruf-chip--gagal      { background: var(--bad-100); border-color: var(--bad-200);  color: var(--bad-800); }
.huruf-chip--netral     { background: var(--surface-app); border-color: var(--border); color: var(--text-muted); }

/* ── Visualisasi rentang nilai (rentang-nilai/index) ──────────────────────
   Satu petak per huruf, lebarnya mengikuti lebar rentang skornya. Warnanya
   memakai pita huruf yang sama dengan chip dan tabel nilai. */
.rentang-pita {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    min-width: 28px;
    border-right: 1px solid var(--n-0);
}

.rentang-pita:last-child { border-right: 0; }

.rentang-pita__skor { font-size: var(--t-2xs); opacity: .75; }

.rentang-pita--baik       { background: var(--ok-50);   color: var(--ok-800); }
.rentang-pita--cukup-baik { background: var(--a-50);    color: var(--a-500); }
.rentang-pita--cukup      { background: var(--warn-50); color: var(--warn-800); }
.rentang-pita--kurang     { background: var(--bad-50);  color: var(--bad-600); }
.rentang-pita--gagal      { background: var(--bad-100); color: var(--bad-800); }
.rentang-pita--netral     { background: var(--surface-app); color: var(--text-muted); }

/* Kartu "tambah baru" bergaris putus — dibedakan dari kartu data biasa supaya
   jelas ia formulir, bukan isi. */
.kartu-tambah  { border: 2px dashed var(--a-200); background: var(--a-50); }

/* Baris tabel dalam mode sunting. */
.baris-sunting { background: var(--a-50); }

/* ── Panel profil praja (praja/dashboard) ─────────────────────────────────
   Satu-satunya bidang dongker di halaman isi. Dipakai hemat dan sengaja: ini
   identitas pemilik halaman, bukan hiasan. */
.panel-profil {
    /* Tint dongker dengan tinta dongker tua — bidang "kartu paket" dalam gaya
       accent ladder. Dulu gradasi dongker penuh: hue penuh pada bidang besar
       dan gradasi, keduanya di luar gaya. */
    background: var(--a-50);
    border: 1px solid var(--a-100);
    border-radius: var(--r-lg);
    padding: var(--s-5) var(--s-6);
}

.panel-profil__isi {
    display: flex;
    align-items: center;
    gap: var(--s-5);
    flex-wrap: wrap;
}

.panel-profil__inisial {
    width: 64px; height: 64px;
    flex-shrink: 0;
    border-radius: 50%;
    background: var(--a-100);
    display: flex; align-items: center; justify-content: center;
    font-size: var(--t-2xl);
    font-weight: var(--fw-bold);
    color: var(--a-700);
}

.panel-profil__identitas { flex: 1; min-width: 200px; }

.panel-profil__nama {
    margin: 0;
    font-size: var(--t-lg);
    font-weight: var(--fw-bold);
    color: var(--a-700);
}

.panel-profil__meta {
    margin-top: var(--s-1);
    font-size: var(--t-sm);
    color: var(--n-600);
    display: flex;
    flex-wrap: wrap;
    gap: var(--s-2);
}

.panel-profil__angka { display: flex; gap: var(--s-3); }

.panel-profil__petak {
    text-align: center;
    padding: var(--s-2) var(--s-4);
    border-radius: var(--r-md);
    background: var(--surface-card);
    border: 1px solid var(--a-100);
}

.panel-profil__label {
    font-size: var(--t-2xs);
    color: var(--text-muted);
}

/* Satu warna untuk semua tingkat: tingkat bukan status baik/buruk yang
   perlu warna. */
.panel-profil__nilai {
    font-size: var(--t-lg);
    font-weight: var(--fw-bold);
    color: var(--a-700);
    font-variant-numeric: tabular-nums;
}

@media (max-width: 575.98px) {
    .panel-profil        { padding: var(--s-4); }
    .panel-profil__angka { width: 100%; }
    .panel-profil__petak { flex: 1; }
}

/* ── Kartu aksi (portal praja) ────────────────────────────────────────────
   Kartu tautan netral. Ikonnya yang membedakan, bukan warnanya — keempat
   aksinya sejenis, jadi empat rona berbeda tidak menambah informasi. */
.kartu-aksi {
    display: block;
    background: var(--surface-card);
    border: 0;
    border-radius: var(--r-lg);
    box-shadow: var(--sh-kartu);
    text-decoration: none;
    transition: box-shadow var(--gerak);
}

/* Bisa diklik: sorot menebalkan bayangannya sedikit. */
.kartu-aksi:hover { box-shadow: var(--sh-2); }

/* Ikon polos, bukan di dalam kotak bertint (lihat .pintasan). */
.kartu-aksi__ikon {
    width: 20px;
    flex-shrink: 0;
    color: var(--text-muted);
    display: flex; justify-content: center;
    font-size: var(--t-lg);
    transition: color var(--gerak);
}

.kartu-aksi:hover .kartu-aksi__ikon { color: var(--a-500); }

/* Ikon pada petak keterangan (kartu info kelas, detail praja). Netral beraksen
   — petak-petak ini keterangan, bukan status, jadi tidak diberi rona per item. */
.petak-info__ikon {
    width: 40px; height: 40px;
    margin: 0 auto var(--s-2);
    border-radius: var(--r-lg);
    background: var(--a-50);
    color: var(--a-500);
    display: flex; align-items: center; justify-content: center;
    font-size: var(--t-lg);
}

/* ==========================================================================
   HALAMAN QR ABSENSI
   ==========================================================================
   Dulu seluruh halaman ini memakai gaya inline, termasuk palet di dalam
   JavaScript-nya. Yang paling berbahaya: penghitung "X / Y hadir" menghitung
   dengan mencari string hex di atribut style, jadi angka kehadiran bergantung
   pada warna. Sekarang JS menempelkan kelas dan menghitung dari data-status. */

/* Titik hidup penanda sesi aktif. */
.titik-hidup {
    width: 10px; height: 10px;
    border-radius: 50%;
    background: var(--ok-500);
    display: inline-block;
    box-shadow: 0 0 0 3px rgba(34, 197, 94, .25);
    animation: pulse-dot 1.5s infinite;
}

/* Pil kecil — penanda ringkas di kepala kartu. */
.pil {
    font-size: var(--t-2xs);
    font-weight: var(--fw-bold);
    padding: 3px var(--s-3);
    border-radius: var(--r-pill);
    white-space: nowrap;
}

.pil--ok    { background: var(--ok-50);   color: var(--ok-800); }
.pil--warn  { background: var(--warn-50); color: var(--warn-800); }
.pil--bad   { background: var(--bad-50);  color: var(--bad-800); }
.pil--aksen { background: var(--a-100);   color: var(--a-700); }

/* Wadah QR. Ukuran minimum dipertahankan supaya kotaknya tidak mengecil
   sebelum gambar QR-nya masuk — pergeseran tata letak tiap 5 detik membuat
   halaman terasa berkedip. */
.wadah-qr {
    display: flex;
    align-items: center;
    justify-content: center;
    min-width: 272px; min-height: 272px;
    padding: var(--s-4);
    margin: 0 auto;
    background: var(--n-0);
    border: 2px solid var(--border);
    border-radius: var(--r-lg);
}

.url-qr {
    font-size: var(--t-2xs);
    color: var(--text-faint);
    max-width: 200px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Daftar keterangan pertemuan — ikon selebar tetap supaya teksnya lurus. */
.daftar-info { line-height: 2; }
.daftar-info i { width: 14px; text-align: center; color: var(--text-faint); flex-shrink: 0; }

/* Tombol ubah cepat status kehadiran.
   Keadaan aktif ditandai KELAS `aktif`, bukan warna yang ditulis JS. */
.cepat-btn {
    padding: 3px var(--s-2);
    border: 0;
    border-radius: var(--r-sm);
    font-size: var(--t-2xs);
    background: var(--surface-app);
    color: var(--text-faint);
    cursor: pointer;
    transition: background .15s, color .15s;
}

.cepat-btn:hover { background: var(--border); color: var(--text-body); }

.cepat-btn--ok.aktif   { background: var(--ok-100);   color: var(--ok-800); }
.cepat-btn--warn.aktif { background: var(--warn-100); color: var(--warn-800); }
.cepat-btn--info.aktif { background: var(--a-100);    color: var(--a-700); }
.cepat-btn--bad.aktif  { background: var(--bad-100);  color: var(--bad-800); }

@keyframes pulse-dot {
    0%, 100% { box-shadow: 0 0 0 3px rgba(34, 197, 94, .25); }
    50%      { box-shadow: 0 0 0 6px rgba(34, 197, 94, .10); }
}

/* Baris pemisah kelompok kelas pada tabel absensi sesi gabungan. */
.baris-kelompok { padding: var(--s-2) var(--s-5); }

/* Kolom centang pada tabel pilihan (wizard kirim Feeder). */
.kol-centang { width: 44px; }

/* ── Penanda tahap (tugas_akhir/show) ─────────────────────────────────────
   Sebelas tahap workflow tugas akhir. Dua keadaan saja — sudah dilewati atau
   belum — bukan sebelas warna. */
.tahap {
    padding: 2px var(--s-2);
    border-radius: var(--r-sm);
    border: 1px solid transparent;
    font-size: var(--t-2xs);
    font-weight: var(--fw-normal);
    line-height: 1.4;
}

.tahap--lewat { background: var(--a-50);          border-color: var(--a-200); color: var(--a-500); }
.tahap--belum { background: var(--surface-sunken); border-color: var(--border); color: var(--border-strong); }

/* Garis pemisah dalam kartu. Menggantikan `border-top:1px solid #f1f5f9` dan
   sejenisnya yang ditulis tangan puluhan kali. */
.batas-atas  { border-top: 1px solid var(--n-100); }
.batas-bawah { border-bottom: 1px solid var(--n-100); }

/* Angka besar pada kartu ringkasan. */
.angka-besar { font-size: var(--t-2xl); font-weight: var(--fw-bold); line-height: 1.1; }

/* Bilah sempit — dipakai di dalam sel tabel, di samping angka persen. */
.bilah--sempit { width: 70px; flex-shrink: 0; }

/* ── Tab dalam halaman (dosen/kelas_detail) ───────────────────────────────
   Tombol, bukan tautan: keduanya tidak menuju ke mana-mana, hanya menukar
   panel. Keadaan terpilih ditandai kelas `aktif` dan aria-selected. */
.tab-bar {
    display: flex;
    gap: var(--s-1);
    border-bottom: 2px solid var(--border);
    margin-bottom: 0;
}

.tab-link {
    padding: 10px var(--s-5);
    border: 0;
    border-bottom: 2px solid transparent;
    border-radius: var(--r-md) var(--r-md) 0 0;
    margin-bottom: -2px;
    background: none;
    font-size: var(--t-sm);
    font-weight: var(--fw-semi);
    color: var(--text-muted);
    cursor: pointer;
}

.tab-link:hover { color: var(--text-body); background: var(--surface-sunken); }

.tab-link.aktif {
    color: var(--a-500);
    border-bottom-color: var(--a-500);
}

/* Varian chip status kehadiran. Keadaan terpilih ditandai kelas `aktif`;
   sebelumnya warnanya ditulis dua kali — di markup Blade dan di JavaScript. */
.status-chip                  { background: var(--surface-app); color: var(--text-faint);
                                border: 2px solid transparent; }
.status-chip--ok.aktif        { background: var(--ok-100);   color: var(--ok-800);   border-color: var(--ok-800); }
.status-chip--warn.aktif      { background: var(--warn-100); color: var(--warn-800); border-color: var(--warn-800); }
.status-chip--info.aktif      { background: var(--a-100);    color: var(--a-700);    border-color: var(--a-700); }
.status-chip--bad.aktif       { background: var(--bad-100);  color: var(--bad-800);  border-color: var(--bad-800); }

/* Ikon pada petak angka verifikasi (halaman tarik & kirim Feeder).
   Penambahan aturan ini pernah GAGAL SENYAP karena disk penuh: CSS-nya tetap
   sah, kelasnya saja tidak pernah ada — jadi petak ikonnya tampil tanpa kotak
   tanpa satu pun galat. Uji kelas-mati kini menutupi seluruh awalan lapis ini. */
.petak-angka__ikon {
    width: 36px; height: 36px;
    margin: 0 auto var(--s-2);
    border-radius: var(--r-lg);
    display: flex; align-items: center; justify-content: center;
}

/* Petak hitungan kehadiran (portal praja) — empat angka bersebelahan. */
.petak-hitung {
    border-radius: var(--r-lg);
    padding: 10px var(--s-1);
}

.petak-hitung__label { font-size: var(--t-2xs); opacity: .8; }

/* Latar status satu tingkat lebih pekat, varian info — melengkapi
   l-ok-kuat / l-warn-kuat / l-bad-kuat yang sudah ada. */
.l-info-kuat { background: var(--a-100); }

/* Foto praja pada halaman detail. Petak kosongnya memakai ukuran yang sama
   supaya tata letak tidak bergeser antara praja yang berfoto dan yang belum. */
.foto-praja {
    width: 120px; height: 150px;
    object-fit: cover;
    border: 3px solid var(--border);
    border-radius: var(--r-lg);
    display: block;
    margin-left: auto;
    margin-right: auto;
}

.foto-praja--kosong {
    background: var(--surface-app);
    border-style: solid;
    display: flex;
    align-items: center;
    justify-content: center;
}

/* Ikon dekoratif pada kartu ringkasan — diredupkan supaya angkanya yang
   menonjol, bukan ikonnya. */
.ikon-redup { opacity: .5; }

/* Garis bawah tegas — pemisah kepala tabel dari isinya. */
.batas-bawah-tegas { border-bottom: 2px solid var(--border); }

/* Panel sambutan portal dosen — satu-satunya bidang dongker di halaman itu. */
.panel-sambut { background: linear-gradient(135deg, var(--a-700) 0%, var(--a-500) 100%); }

/* Ikon pada petak ringkasan mendatar (laporan akademik). */
.petak-ringkas__ikon {
    width: 44px; height: 44px;
    flex-shrink: 0;
    border-radius: var(--r-lg);
    display: flex; align-items: center; justify-content: center;
    font-size: var(--t-xl);
}

/* Garis batas varian ungu — melengkapi garis-* status yang sudah ada. */
.garis-ungu { border: 1px solid var(--ungu-50); }

/* Kolom angka persen di samping bilah, lebar tetap supaya bilahnya tidak
   bergeser tiap kali jumlah digitnya berubah. */
.kol-persen { min-width: 34px; }

/* Tombol ikon mungil di dalam baris tabel. */
.tombol-mini { padding: 3px 10px; }

/* ── Popup pengumuman ─────────────────────────────────────────────────────*/
.popup-kepala {
    background: linear-gradient(135deg, var(--a-700), var(--a-500));
    padding: var(--s-5) var(--s-6);
    flex-shrink: 0;
}

.popup-kaki { padding: var(--s-4) var(--s-6); flex-shrink: 0; }

.isi-pengumuman { line-height: 1.75; white-space: pre-wrap; }

/* Titik navigasi antar pengumuman. Keadaan terpilih ditandai kelas `aktif`;
   sebelumnya JavaScript menulis warnanya langsung ke elemen. */
.dot-indicator {
    width: 8px; height: 8px;
    border-radius: 50%;
    cursor: pointer;
    background: rgba(255, 255, 255, .35);
    transition: background .2s;
}

.dot-indicator.aktif { background: var(--n-0); }

/* Petak keterangan huruf mutu (legenda rentang nilai di KHS). */
.petak-huruf { padding: var(--s-2) var(--s-3); min-width: 70px; }

/* Kolom alasan pada tabel semester — dibatasi lebarnya supaya kalimat panjang
   tidak mendorong kolom aksi keluar layar. */
.kol-alasan { max-width: 30ch; }

/* ── Pemilih wilayah PDDIKTI ──────────────────────────────────────────────
   Menggantikan medan teks bebas untuk id_wilayah: 8.069 kode Dapodik tidak
   bisa dihafal, dan 59 praja sudah memakai kode yang tidak dikenal PDDIKTI
   sebagai akibatnya. Lihat resources/views/components/pilih-wilayah.blade.php */
.pilih-wilayah {
    position: relative;
}

.pilih-wilayah__hasil {
    position: absolute;
    z-index: 20;
    inset-inline: 0;
    top: calc(100% + 4px);
    margin: 0;
    padding: 4px;
    list-style: none;
    max-height: 17rem;
    overflow-y: auto;
    background: var(--surface-card);
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    box-shadow: var(--sh-2);
}

.pilih-wilayah__baris,
.pilih-wilayah__kosong {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--s-3);
    padding: var(--s-2) var(--s-3);
    border-radius: var(--r-md);
    font-size: var(--t-sm);
    line-height: 1.4;
}

.pilih-wilayah__baris {
    cursor: pointer;
    color: var(--text);
}

.pilih-wilayah__baris:hover,
.pilih-wilayah__baris:focus-visible {
    background: var(--surface-sunken);
}

.pilih-wilayah__kode {
    flex: none;
    font-variant-numeric: tabular-nums;
    font-size: var(--t-2xs);
    color: var(--text-faint);
}

.pilih-wilayah__kosong {
    color: var(--text-faint);
    cursor: default;
}

/* ── Lebar kolom tabel wizard Kirim ke NeoFeeder ──────────────────────────
   Menggantikan style="width:NNpx" yang tersebar di lima view wizard. Diberi
   nama menurut ISI kolomnya, bukan menurut angkanya: ".kol-90" akan menyesatkan
   begitu lebarnya diubah. */
.kol-status-feeder { width: 160px; }
.kol-status        { width: 110px; }
.kol-aksi-kirim    { width: 120px; }
.kol-durasi        { width: 90px;  }
.kol-rincian       { width: 90px;  }

/* ── Pilihan bercari (x-pilih-cari) ───────────────────────────────────────
   Menggantikan <select> untuk daftar panjang — 453 dosen tidak bisa ditemukan
   dengan menggulir. Lihat resources/views/components/pilih-cari.blade.php */
.pilih-cari {
    position: relative;
}

.pilih-cari .search-box {
    position: relative;
}

/* Ruang untuk tombol bersihkan di ujung kanan medan. */
.pilih-cari .search-box .form-control {
    padding-right: 2.25rem;
}

.pilih-cari__hapus {
    position: absolute;
    right: var(--s-2);
    top: 50%;
    transform: translateY(-50%);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.5rem;
    height: 1.5rem;
    padding: 0;
    border: 0;
    border-radius: var(--r-pill);
    background: transparent;
    color: var(--text-faint);
    cursor: pointer;
    line-height: 1;
}

.pilih-cari__hapus:hover,
.pilih-cari__hapus:focus-visible {
    background: var(--surface-sunken);
    color: var(--text);
}

.pilih-cari__hasil {
    position: absolute;
    z-index: 20;
    inset-inline: 0;
    top: calc(100% + 4px);
    margin: 0;
    padding: 4px;
    list-style: none;
    max-height: 17rem;
    overflow-y: auto;
    background: var(--surface-card);
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    box-shadow: var(--sh-2);
}

.pilih-cari__baris,
.pilih-cari__kosong {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: var(--s-2) var(--s-3);
    border-radius: var(--r-md);
    font-size: var(--t-sm);
    line-height: 1.35;
}

.pilih-cari__baris {
    cursor: pointer;
    color: var(--text);
}

.pilih-cari__baris:hover,
.pilih-cari__baris:focus-visible {
    background: var(--surface-sunken);
}

.pilih-cari__sub {
    font-size: var(--t-2xs);
    color: var(--text-faint);
}

.pilih-cari__kosong {
    color: var(--text-faint);
    cursor: default;
}

/* ── Tombol sibuk (form yang lama) ────────────────────────────────────────
   Impor NeoFeeder berjalan SINKRON dan bisa memakan menit — 1.189 kelas, atau
   19.813 mahasiswa. Tanpa penanda, satu-satunya tanda bahwa sesuatu sedang
   terjadi adalah lingkaran kecil di tab peramban, dan operator menekan tombolnya
   berulang kali atau menutup halaman di tengah jalan.
   Lihat resources/views/feeder/index.blade.php */
.btn-sibuk {
    position: relative;
    pointer-events: none;
    opacity: .75;
}

.btn-sibuk__putar {
    display: inline-block;
    width: .75rem;
    height: .75rem;
    margin-right: .35rem;
    vertical-align: -1px;
    border: 2px solid currentColor;
    border-right-color: transparent;
    border-radius: 50%;
    animation: btn-sibuk-putar .7s linear infinite;
}

@keyframes btn-sibuk-putar {
    to { transform: rotate(360deg); }
}

/* Pemberitahuan "sedang berjalan" di bawah kartu. */
.proses-lama {
    display: flex;
    align-items: flex-start;
    gap: var(--s-2);
    margin-top: var(--s-3);
    padding: var(--s-3);
    border-radius: var(--r-lg);
    background: var(--warn-50);
    color: var(--warn-800);
    font-size: var(--t-sm);
}

/* Hormati pengguna yang meminta gerakan dikurangi. */
@media (prefers-reduced-motion: reduce) {
    .btn-sibuk__putar { animation: none; }
}

/* ── Pemilih banyak nilai (x-pilih-banyak) ────────────────────────────────
   Dipakai memilih kelas yang mengikuti satu sesi jadwal — satu sesi bisa
   diikuti dua sampai lima kelas, dan daftarnya 3.076 baris.
   Lihat resources/views/components/pilih-banyak.blade.php */
.pilih-banyak { position: relative; }

.pilih-banyak__keping {
    display: flex;
    flex-wrap: wrap;
    gap: var(--s-2);
    min-height: 2rem;
}

.keping {
    display: inline-flex;
    align-items: center;
    gap: var(--s-2);
    padding: 4px var(--s-2) 4px var(--s-3);
    border-radius: var(--r-pill);
    background: var(--a-50);
    color: var(--a-800);
    font-size: var(--t-sm);
    font-weight: var(--fw-semi);
    line-height: 1.3;
}

.keping__hapus {
    border: 0;
    background: transparent;
    color: inherit;
    opacity: .6;
    cursor: pointer;
    font-size: var(--t-md);
    line-height: 1;
    padding: 0 2px;
}

.keping__hapus:hover,
.keping__hapus:focus-visible { opacity: 1; }

.pilih-banyak__hasil {
    position: absolute;
    z-index: 20;
    inset-inline: 0;
    top: 100%;
    margin: 4px 0 0;
    padding: 4px;
    list-style: none;
    max-height: 17rem;
    overflow-y: auto;
    background: var(--surface-card);
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    box-shadow: var(--sh-2);
}

.pilih-banyak__baris,
.pilih-banyak__kosong {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: var(--s-2) var(--s-3);
    border-radius: var(--r-md);
    font-size: var(--t-sm);
    line-height: 1.35;
}

.pilih-banyak__baris { cursor: pointer; color: var(--text); }

.pilih-banyak__baris:hover { background: var(--surface-sunken); }

/* Yang sudah dipilih tetap DITAMPILKAN, bukan disembunyikan: hilang dari hasil
   pencarian membuat operator mengira kelasnya tidak ada. */
.pilih-banyak__baris--dipakai { opacity: .55; cursor: default; }

.pilih-banyak__sub { font-size: var(--t-2xs); color: var(--text-faint); }

.pilih-banyak__kosong { color: var(--text-faint); cursor: default; }

/* Baris jadwal yang bentrok. */
.jadwal-bentrok {
    border-left: 3px solid var(--bad-500);
}

/* Keping usulan kelas serumpun.
   Dibedakan dari keping terpilih: bergaris putus-putus dan berlatar netral,
   supaya sekali lihat jelas ia BELUM masuk sesi — hanya tawaran. */
.keping--usul {
    border: 1px dashed var(--border-strong);
    background: transparent;
    color: var(--n-700);
    cursor: pointer;
    text-align: left;
    flex-wrap: wrap;
}

.keping--usul:hover,
.keping--usul:focus-visible {
    border-style: solid;
    border-color: var(--a-300);
    background: var(--a-50);
    color: var(--a-800);
}

/* ==========================================================================
   PELAPORAN PDDIKTI — grafik & kartu (partials/_pelaporan_pddikti)
   ==========================================================================
   Grafik bilah berskala 0–100%: jenis data yang jumlahnya ratusan (dosen)
   dan yang jutaan (nilai) tidak bisa dibandingkan dengan angka mentah, tapi
   persentasenya bisa. Satu warna untuk semua bilah — dongker IPDN pada data,
   bukan pelangi per jenis. */

.judul-grafik {
    font-size: var(--t-base);
    font-weight: var(--fw-semi);
    color: var(--text);
    margin: 0;
}
.ket-grafik {
    font-size: var(--t-xs);
    color: var(--text-muted);
    margin: 2px 0 var(--s-3);
}

.grafik-bilah { list-style: none; margin: 0; padding: 0; }

/* Label | bilah | nilai — label dan nilai lebar tetap, supaya semua bilah
   mulai dan berakhir di garis yang sama (bisa dibandingkan sekilas). */
.grafik-bilah__baris {
    display: grid;
    grid-template-columns: minmax(0, 11rem) minmax(0, 1fr) 5.5rem;
    align-items: center;
    gap: var(--s-3);
    min-height: 32px;
}
.grafik-bilah__label {
    font-size: var(--t-sm);
    color: var(--text-body);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.grafik-bilah__jalur { margin: 0; height: 8px; }
/* Jalur & isinya berupa <span> (anak <li>): tanpa display:block lebarnya diabaikan. */
.grafik-bilah__jalur,
.grafik-bilah__jalur > .bilah__isi { display: block; }
.grafik-bilah__nilai {
    font-size: var(--t-sm);
    text-align: right;
    font-variant-numeric: tabular-nums;
    color: var(--text);
}

/* Kartu per jenis data. Lima kolom di layar lebar: sepuluh jenis data = dua
   baris penuh, tanpa sel yatim di baris terakhir. */
.kisi-pelaporan {
    display: grid;
    grid-template-columns: repeat(5, minmax(0, 1fr));
    gap: var(--s-4);
}
@media (max-width: 1399.98px) { .kisi-pelaporan { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 575.98px)  { .kisi-pelaporan { grid-template-columns: minmax(0, 1fr); } }

.kartu-pelaporan {
    display: flex;
    flex-direction: column;
    padding: var(--s-4) var(--s-5);
    margin: 0;
}
.kartu-pelaporan__judul {
    font-size: var(--t-sm);
    font-weight: var(--fw-semi);
    color: var(--text-muted);
    margin: 0 0 var(--s-2);
}
.kartu-pelaporan__angka {
    font-size: var(--t-xl);
    font-weight: var(--fw-semi);
    color: var(--text);
    line-height: 1.15;
    font-variant-numeric: tabular-nums;
}
.kartu-pelaporan__ket {
    font-size: var(--t-xs);
    color: var(--text-muted);
    margin-top: 2px;
}
.kartu-pelaporan__bilah { margin-top: var(--s-3); }
.kartu-pelaporan__catatan {
    font-size: var(--t-xs);
    color: var(--text-muted);
    margin: var(--s-3) 0 0;
}
/* Kaki selalu di dasar kartu, supaya tautan "belum terlapor" sebaris di
   seluruh kisi walau isi kartunya berbeda tinggi. */
.kartu-pelaporan__kaki {
    margin-top: auto;
    padding-top: var(--s-3);
    font-size: var(--t-sm);
}

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

/* ══ RPL ═════════════════════════════════════════════════════════════════════
   Rekognisi Pembelajaran Lampau: penanda empat tahapan, halaman informasi
   publik, dan berkas cetak. */

/* Penanda tahapan pemohon (Perdir Pasal 5). Satu warna aksen; hanya "gagal"
   yang memakai warna masalah. */
.alur-rpl {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    list-style: none;
    margin: 0;
    padding: var(--s-4) var(--s-5);
    gap: var(--s-3);
}
.alur-rpl__langkah { display: flex; align-items: center; gap: var(--s-2); min-width: 0; }
.alur-rpl__nomor {
    flex-shrink: 0;
    width: 28px; height: 28px;
    display: inline-flex; align-items: center; justify-content: center;
    border-radius: var(--r-pill);
    font-size: var(--t-xs);
    font-weight: var(--fw-semi);
    border: 1px solid var(--border);
    background: var(--surface-sunken);
    color: var(--text-faint);
}
.alur-rpl__nama { font-size: var(--t-sm); color: var(--text-muted); }
.alur-rpl__langkah--lewat .alur-rpl__nomor { background: var(--a-50); border-color: var(--a-200); color: var(--a-500); }
.alur-rpl__langkah--kini .alur-rpl__nomor  { background: var(--a-500); border-color: var(--a-500); color: var(--n-0); }
.alur-rpl__langkah--kini .alur-rpl__nama   { color: var(--text); font-weight: var(--fw-semi); }
.alur-rpl__langkah--gagal .alur-rpl__nomor { background: var(--bad-50); border-color: var(--bad-200); color: var(--bad-600); }
@media (max-width: 767.98px) {
    .alur-rpl { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* ── Halaman publik ── */
.publik { background: var(--surface-app); }
.publik__wadah { max-width: 1120px; margin: 0 auto; padding-left: var(--s-4); padding-right: var(--s-4); }
.publik__kepala { background: var(--surface-card); border-top: 3px solid var(--gold); border-bottom: 1px solid var(--border); }
.publik__kepala-isi { display: flex; align-items: center; justify-content: space-between; gap: var(--s-3); padding-top: var(--s-3); padding-bottom: var(--s-3); }
.publik__merek { display: flex; align-items: center; gap: var(--s-3); text-decoration: none; min-width: 0; }
.publik__merek > span { display: flex; flex-direction: column; min-width: 0; }
.publik__merek-nama { font-size: var(--t-sm); font-weight: var(--fw-semi); color: var(--text); }
.publik__merek-sub { font-size: var(--t-xs); color: var(--text-muted); }

/* Sampul: foto kampus yang sama dengan halaman login di bawah lapisan
   dongker. Heading di sini WAJIB menyetel warnanya sendiri, karena base.css
   mewarnai h1–h6 dengan warna teks gelap. */
.publik__sampul { position: relative; overflow: hidden; color: var(--n-0); padding: var(--s-10) 0 var(--s-8); background: var(--a-900); isolation: isolate; }
.publik__sampul::before {
    content: ''; position: absolute; inset: 0; z-index: -2;
    background: url('../../img/bg.jpeg') center 40% / cover no-repeat;
    filter: blur(2px) saturate(.85); transform: scale(1.05);
}
.publik__sampul::after {
    content: ''; position: absolute; inset: 0; z-index: -1;
    background:
        radial-gradient(60rem 30rem at 90% -10%, rgba(201, 146, 43, .22), transparent 60%),
        linear-gradient(105deg, rgba(10, 28, 58, .97) 0%, rgba(13, 36, 73, .9) 45%, rgba(18, 48, 94, .72) 100%);
}
.publik__sampul-isi { position: relative; }
.publik__sampul-label { display: flex; align-items: center; gap: var(--s-3); font-size: var(--t-xs); font-weight: var(--fw-semi); letter-spacing: .08em; text-transform: uppercase; color: var(--gold); margin-bottom: var(--s-3); }
.publik__garis-emas { display: inline-block; width: 32px; height: 2px; background: var(--gold); border-radius: var(--r-pill); }
.publik__sampul-judul { font-size: var(--t-2xl); font-weight: var(--fw-bold); line-height: 1.2; color: var(--n-0); margin-bottom: var(--s-3); max-width: 40rem; text-wrap: balance; }
.publik__sampul-teks { font-size: var(--t-md); line-height: 1.65; color: var(--a-100); max-width: 46rem; margin-bottom: var(--s-6); }
.publik__sampul-kembali { display: inline-block; font-size: var(--t-sm); color: var(--a-200); margin-bottom: var(--s-4); text-decoration: none; }
.publik__sampul-kembali:hover { color: var(--n-0); }
.publik__sampul-aksi { display: flex; flex-wrap: wrap; gap: var(--s-3); }
.publik__btn-emas { background: var(--gold); border: 1px solid var(--gold); color: var(--a-900); font-weight: var(--fw-semi); padding: var(--s-2) var(--s-5); border-radius: var(--r-md); transition: transform var(--gerak), box-shadow var(--gerak), filter var(--gerak); }
.publik__btn-emas:hover, .publik__btn-emas:focus-visible { background: var(--gold); color: var(--a-900); filter: brightness(1.08); box-shadow: 0 8px 24px -8px rgba(201, 146, 43, .7); transform: translateY(-1px); }
.publik__btn-garis { border: 1px solid rgba(255, 255, 255, .35); color: var(--n-0); padding: var(--s-2) var(--s-5); border-radius: var(--r-md); transition: background var(--gerak), border-color var(--gerak); }
.publik__btn-garis:hover, .publik__btn-garis:focus-visible { background: rgba(255, 255, 255, .1); border-color: var(--n-0); color: var(--n-0); }

.publik__angka { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: var(--s-3); margin: var(--s-8) 0 0; }
.publik__angka > div {
    padding: var(--s-4) var(--s-5); border-radius: var(--r-lg);
    background: rgba(255, 255, 255, .07); border: 1px solid rgba(255, 255, 255, .12);
    backdrop-filter: blur(6px);
}
.publik__angka dt { font-size: var(--t-xs); font-weight: var(--fw-normal); color: var(--a-200); margin-bottom: var(--s-1); }
.publik__angka dd { font-size: var(--t-xl); font-weight: var(--fw-bold); color: var(--n-0); margin: 0; font-variant-numeric: tabular-nums; }
.publik__angka small { font-size: var(--t-sm); font-weight: var(--fw-normal); color: var(--a-200); }

/* ── Bilah tab: menempel di atas saat digulir ── */
.publik__tab-bar { position: sticky; top: 0; z-index: 20; background: rgba(255, 255, 255, .92); backdrop-filter: blur(10px); border-bottom: 1px solid var(--border); }
.publik__tab { position: relative; display: flex; gap: var(--s-1); overflow-x: auto; scrollbar-width: none; }
.publik__tab::-webkit-scrollbar { display: none; }
.publik__tab-item {
    display: inline-flex; align-items: center; gap: var(--s-2); flex-shrink: 0;
    padding: var(--s-4) var(--s-4); font-size: var(--t-sm); font-weight: var(--fw-medium);
    color: var(--text-muted); text-decoration: none; transition: color var(--gerak);
}
.publik__tab-item > i { color: var(--n-400); transition: color var(--gerak); }
.publik__tab-item:hover, .publik__tab-item:hover > i { color: var(--a-500); }
.publik__tab-item[aria-selected="true"] { color: var(--a-700); font-weight: var(--fw-semi); }
.publik__tab-item[aria-selected="true"] > i { color: var(--gold); }
.publik__tab-item:focus-visible { outline: 2px solid var(--a-500); outline-offset: -4px; border-radius: var(--r-sm); }
.publik__tab-penanda { display: none; position: absolute; left: 0; bottom: 0; height: 3px; border-radius: 3px 3px 0 0; background: var(--gold); }
.publik--js .publik__tab-penanda { display: block; }

.publik__isi { padding-top: var(--s-8); padding-bottom: var(--s-10); min-height: 26rem; }
.publik__panel { scroll-margin-top: 72px; outline: none; }
.publik__panel + .publik__panel { margin-top: var(--s-10); }
.publik--js .publik__panel + .publik__panel { margin-top: 0; }
.publik__panel[hidden] { display: none; }
.publik__panel-kepala { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: var(--s-3); margin-bottom: var(--s-5); }
.publik__judul { display: flex; align-items: center; gap: var(--s-2); font-size: var(--t-xl); font-weight: var(--fw-bold); color: var(--text); margin-bottom: var(--s-4); }
.publik__judul > i { color: var(--gold); }
.publik__label-kecil { font-size: var(--t-xs); font-weight: var(--fw-semi); letter-spacing: .06em; text-transform: uppercase; color: var(--text-faint); margin: 0 0 var(--s-1); }

.publik__kartu { background: var(--surface-card); border-radius: var(--r-lg); box-shadow: var(--sh-kartu); padding: var(--s-6); }
.publik__ikon-centang { list-style: none; padding: 0; margin: 0; display: grid; gap: var(--s-3); }
.publik__ikon-centang li { display: flex; gap: var(--s-3); align-items: flex-start; color: var(--text-body); }
.publik__ikon-centang li > i {
    flex-shrink: 0; width: 22px; height: 22px; margin-top: 1px; display: inline-flex; align-items: center; justify-content: center;
    border-radius: var(--r-pill); background: var(--ok-100); color: var(--ok-700); font-size: var(--t-2xs);
}
.publik__sorot { display: flex; gap: var(--s-3); align-items: flex-start; margin-top: var(--s-4); padding: var(--s-4) var(--s-5); border-radius: var(--r-lg); background: var(--a-50); border: 1px solid var(--a-100); }
.publik__sorot > i { color: var(--a-500); margin-top: 3px; }
.publik__sorot strong { color: var(--a-700); }
.publik__sorot p { margin: var(--s-1) 0 0; font-size: var(--t-sm); color: var(--text-body); }

.publik__sumber { display: grid; gap: var(--s-3); }
.publik__sumber-item {
    display: flex; gap: var(--s-3); align-items: flex-start; padding: var(--s-4); border-radius: var(--r-lg);
    background: var(--surface-card); border: 1px solid var(--border-soft); transition: transform var(--gerak), box-shadow var(--gerak), border-color var(--gerak);
}
.publik__sumber-item:hover { transform: translateY(-2px); box-shadow: var(--sh-2); border-color: var(--a-100); }
.publik__sumber-item > i {
    flex-shrink: 0; width: 40px; height: 40px; display: inline-flex; align-items: center; justify-content: center;
    border-radius: var(--r-md); background: var(--a-50); color: var(--a-500);
}
.publik__sumber-item strong { color: var(--text); }
.publik__sumber-item p { margin: var(--s-1) 0 0; font-size: var(--t-sm); color: var(--text-muted); }

/* ── Mata kuliah: akordeon <details>, jalan tanpa JS ── */
.publik__lencana-sks { font-size: var(--t-sm); color: var(--a-700); background: var(--a-50); border-radius: var(--r-pill); padding: var(--s-1) var(--s-4); }
.publik__mk-daftar { display: grid; gap: var(--s-3); margin-bottom: var(--s-5); }
.publik__mk { background: var(--surface-card); border-radius: var(--r-lg); box-shadow: var(--sh-kartu); border: 1px solid transparent; transition: border-color var(--gerak), box-shadow var(--gerak); }
.publik__mk[open] { border-color: var(--a-100); box-shadow: var(--sh-2); }
.publik__mk > summary { display: flex; align-items: center; gap: var(--s-4); padding: var(--s-4) var(--s-5); cursor: pointer; list-style: none; }
.publik__mk > summary::-webkit-details-marker { display: none; }
.publik__mk > summary:focus-visible { outline: 2px solid var(--a-500); outline-offset: 2px; border-radius: var(--r-lg); }
.publik__mk-nomor { flex-shrink: 0; width: 40px; height: 40px; display: inline-flex; align-items: center; justify-content: center; border-radius: var(--r-md); background: var(--a-700); color: var(--gold); font-size: var(--t-sm); font-weight: var(--fw-semi); font-variant-numeric: tabular-nums; }
.publik__mk-nama { flex: 1; min-width: 0; font-size: var(--t-base); font-weight: var(--fw-semi); color: var(--text); }
.publik__mk-caret { color: var(--n-400); transition: transform var(--gerak); }
.publik__mk[open] .publik__mk-caret { transform: rotate(180deg); color: var(--a-500); }
.publik__mk-isi { padding: 0 var(--s-5) var(--s-5) calc(var(--s-5) + 40px + var(--s-4)); }
.publik__mk-bukti { list-style: none; padding: 0; margin: 0; display: grid; gap: var(--s-2); font-size: var(--t-sm); color: var(--text-body); }
.publik__mk-bukti li { display: flex; gap: var(--s-2); align-items: baseline; }
.publik__mk-bukti li > i { color: var(--a-300); }
.publik__mk-catatan { margin: var(--s-3) 0 0; font-size: var(--t-xs); color: var(--warn-800); background: var(--warn-50); border-radius: var(--r-sm); padding: var(--s-2) var(--s-3); }
.publik__catatan { display: flex; gap: var(--s-3); font-size: var(--t-sm); color: var(--text-body); background: var(--surface-card); border-left: 3px solid var(--gold); border-radius: var(--r-md); padding: var(--s-4) var(--s-5); }
.publik__catatan > i { color: var(--gold); margin-top: 3px; }
@media (max-width: 575.98px) { .publik__mk-isi { padding-left: var(--s-5); } }

/* ── Alur tahapan ── */
.publik__alur { background: var(--surface-card); border-radius: var(--r-xl); box-shadow: var(--sh-kartu); padding: var(--s-6); }
.publik__alur-langkah { position: relative; list-style: none; margin: 0 0 var(--s-6); padding: 0; display: grid; grid-template-columns: repeat(var(--jumlah), minmax(0, 1fr)); gap: var(--s-2); }
.publik__alur-rel { position: absolute; z-index: 0; top: 23px; left: calc(100% / var(--jumlah) / 2); right: calc(100% / var(--jumlah) / 2); height: 3px; border-radius: var(--r-pill); background: var(--n-200); }
.publik__alur-isi { display: block; height: 100%; width: calc(var(--progres, 0) * 100%); border-radius: inherit; background: linear-gradient(90deg, var(--a-500), var(--gold)); transition: width .45s cubic-bezier(.2, .7, .3, 1); }
.publik__alur-langkah > li { position: relative; z-index: 1; }
.publik__alur-tombol { width: 100%; display: flex; flex-direction: column; align-items: center; gap: var(--s-2); background: none; border: 0; padding: 0; text-align: center; cursor: pointer; color: var(--text-muted); }
.publik__alur-bulat {
    width: 48px; height: 48px; display: inline-flex; align-items: center; justify-content: center; border-radius: var(--r-pill);
    background: var(--surface-card); border: 2px solid var(--n-200); color: var(--n-400);
    transition: background var(--gerak), border-color var(--gerak), color var(--gerak), transform var(--gerak), box-shadow var(--gerak);
}
.publik__alur-label { font-size: var(--t-sm); font-weight: var(--fw-medium); line-height: 1.3; }
.publik__alur-label small { display: block; font-size: var(--t-2xs); color: var(--text-faint); text-transform: uppercase; letter-spacing: .06em; }
.publik__alur-tombol:hover .publik__alur-bulat { border-color: var(--a-300); color: var(--a-500); }
.publik__alur-tombol[data-lewat="true"] .publik__alur-bulat { background: var(--a-500); border-color: var(--a-500); color: var(--n-0); }
.publik__alur-tombol[aria-pressed="true"] { color: var(--a-700); }
.publik__alur-tombol[aria-pressed="true"] .publik__alur-bulat { background: var(--a-700); border-color: var(--gold); color: var(--gold); transform: scale(1.1); box-shadow: 0 0 0 6px rgba(201, 146, 43, .16); }
.publik__alur-tombol:focus-visible { outline: none; }
.publik__alur-tombol:focus-visible .publik__alur-bulat { box-shadow: var(--sh-focus); border-color: var(--a-500); }
.publik__alur-detail { border-top: 1px solid var(--border-soft); padding-top: var(--s-5); }
.publik__alur-kartu { display: flex; gap: var(--s-5); align-items: flex-start; min-height: 6.5rem; }
.publik__alur-kartu + .publik__alur-kartu { margin-top: var(--s-5); }
.publik--js .publik__alur-kartu + .publik__alur-kartu { margin-top: 0; }
.publik__alur-kartu[hidden] { display: none; }
.publik__alur-ikon-besar { flex-shrink: 0; width: 64px; height: 64px; display: inline-flex; align-items: center; justify-content: center; border-radius: var(--r-lg); background: var(--a-50); color: var(--a-500); font-size: var(--t-xl); }
.publik__alur-kartu h3 { font-size: var(--t-lg); font-weight: var(--fw-semi); color: var(--text); margin: 0 0 var(--s-2); }
.publik__alur-kartu p:last-child { margin: 0; color: var(--text-body); max-width: 44rem; }
.publik__alur-navigasi { display: none; justify-content: flex-end; gap: var(--s-2); margin-top: var(--s-4); }
.publik--js .publik__alur-navigasi { display: flex; }
@media (max-width: 767.98px) {
    .publik__alur { padding: var(--s-4); }
    .publik__alur-langkah { grid-template-columns: repeat(var(--jumlah), 56px); justify-content: space-between; }
    .publik__alur-label { display: none; }
    .publik__alur-rel { left: 28px; right: 28px; }
    .publik__alur-kartu { gap: var(--s-3); }
    .publik__alur-ikon-besar { width: 48px; height: 48px; font-size: var(--t-md); }
}

/* ── Cara mendaftar ── */
.publik__garis-waktu { list-style: none; padding: 0; margin: 0; position: relative; }
.publik__garis-waktu::before { content: ''; position: absolute; left: 17px; top: 8px; bottom: 8px; width: 2px; background: var(--a-100); }
.publik__garis-waktu li { position: relative; display: flex; gap: var(--s-4); align-items: flex-start; padding-bottom: var(--s-5); }
.publik__garis-waktu li:last-child { padding-bottom: 0; }
.publik__garis-waktu-nomor { position: relative; flex-shrink: 0; width: 36px; height: 36px; display: inline-flex; align-items: center; justify-content: center; border-radius: var(--r-pill); background: var(--a-500); color: var(--n-0); font-size: var(--t-sm); font-weight: var(--fw-semi); box-shadow: 0 0 0 4px var(--surface-app); }
.publik__garis-waktu p { margin: 6px 0 0; color: var(--text-body); }
.publik__kartu-gelap { background: linear-gradient(160deg, var(--a-700), var(--a-900)); color: var(--a-100); border-radius: var(--r-xl); padding: var(--s-6); box-shadow: var(--sh-3); }
.publik__judul-terang { font-size: var(--t-lg); font-weight: var(--fw-semi); color: var(--n-0); margin-bottom: var(--s-2); }
.publik__kartu-gelap > p { font-size: var(--t-sm); margin-bottom: var(--s-4); }
.publik__tautan { display: grid; gap: var(--s-2); }
.publik__tautan a {
    display: flex; align-items: center; gap: var(--s-3); padding: var(--s-3) var(--s-4); border-radius: var(--r-md);
    background: rgba(255, 255, 255, .06); border: 1px solid rgba(255, 255, 255, .1); color: var(--n-0); text-decoration: none;
    transition: background var(--gerak), border-color var(--gerak), transform var(--gerak);
}
.publik__tautan a > i:first-child { color: var(--gold); width: 18px; text-align: center; }
.publik__tautan a > span { flex: 1; }
.publik__tautan-ikon-keluar { font-size: var(--t-2xs); opacity: .6; }
.publik__tautan a:hover, .publik__tautan a:focus-visible { background: rgba(255, 255, 255, .12); border-color: rgba(201, 146, 43, .6); transform: translateX(3px); color: var(--n-0); }

/* ── Biaya ── */
.publik__biaya { background: var(--surface-card); border-radius: var(--r-lg); box-shadow: var(--sh-kartu); overflow: hidden; }
.publik__biaya-baris { display: flex; justify-content: space-between; align-items: center; gap: var(--s-4); padding: var(--s-4) var(--s-5); }
.publik__biaya-baris + .publik__biaya-baris { border-top: 1px solid var(--border-soft); }
.publik__biaya-baris strong { display: block; color: var(--text); font-weight: var(--fw-medium); }
.publik__biaya-baris div > span { font-size: var(--t-xs); color: var(--text-faint); }
.publik__biaya-baris > span { font-weight: var(--fw-semi); color: var(--text); white-space: nowrap; }
.publik__total { position: sticky; top: 80px; background: linear-gradient(160deg, var(--a-700), var(--a-900)); border-radius: var(--r-xl); padding: var(--s-6); color: var(--a-100); box-shadow: var(--sh-3); border-top: 3px solid var(--gold); }
.publik__total .publik__label-kecil { color: var(--gold); }
.publik__total-angka { font-size: var(--t-2xl); font-weight: var(--fw-bold); color: var(--n-0); margin: 0 0 var(--s-3); }
.publik__total-catatan { font-size: var(--t-xs); line-height: 1.6; margin: 0; color: var(--a-200); }

/* ── Dasar hukum & kontak ── */
.publik__hukum { counter-reset: hukum; list-style: none; padding: 0; margin: 0; display: grid; gap: var(--s-2); }
.publik__hukum li { counter-increment: hukum; display: flex; gap: var(--s-3); padding: var(--s-3) var(--s-4); background: var(--surface-card); border-radius: var(--r-md); border: 1px solid var(--border-soft); font-size: var(--t-sm); color: var(--text-body); }
.publik__hukum li::before { content: counter(hukum); flex-shrink: 0; width: 24px; height: 24px; display: inline-flex; align-items: center; justify-content: center; border-radius: var(--r-sm); background: var(--a-50); color: var(--a-500); font-size: var(--t-2xs); font-weight: var(--fw-semi); }
.publik__kontak { font-size: var(--t-sm); white-space: pre-line; }

/* ── Ajakan penutup ── */
.publik__ajakan { background: linear-gradient(105deg, var(--a-900), var(--a-700)); color: var(--a-100); border-top: 3px solid var(--gold); }
.publik__ajakan-isi { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--s-4); padding-top: var(--s-8); padding-bottom: var(--s-8); }
.publik__ajakan-judul { font-size: var(--t-xl); font-weight: var(--fw-bold); color: var(--n-0); margin-bottom: var(--s-1); }
.publik__ajakan p { margin: 0; }

.publik__pilihan { display: flex; align-items: center; justify-content: space-between; gap: var(--s-3); padding: var(--s-4) var(--s-5); text-decoration: none; }
.publik__pilihan:hover { box-shadow: var(--sh-2); }
.publik__kaki { padding: var(--s-5) 0; font-size: var(--t-xs); color: var(--text-muted); background: var(--surface-card); border-top: 1px solid var(--border); }
.publik__kaki-isi { display: flex; flex-wrap: wrap; justify-content: space-between; gap: var(--s-2); }

/* ── Gerak masuk. Hanya bila pengguna tidak meminta gerak dikurangi. ── */
@media (prefers-reduced-motion: no-preference) {
    @keyframes publik-naik { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }
    @keyframes publik-pudar { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
    @keyframes publik-geser { from { opacity: 0; transform: translateX(16px); } to { opacity: 1; transform: none; } }
    .publik__muncul { animation: publik-naik .6s cubic-bezier(.2, .7, .3, 1) both; animation-delay: calc(var(--i, 0) * 80ms); }
    .publik__sampul::before { animation: publik-zoom 14s ease-out both; }
    @keyframes publik-zoom { from { transform: scale(1.14); } to { transform: scale(1.05); } }
    .publik--js .publik__panel:not([hidden]) { animation: publik-pudar .35s cubic-bezier(.2, .7, .3, 1) both; }
    .publik--js .publik__panel:not([hidden]) .publik__anak { animation: publik-naik .5s cubic-bezier(.2, .7, .3, 1) both; animation-delay: calc(var(--i, 0) * 60ms + 80ms); }
    .publik--js .publik__alur-kartu:not([hidden]) { animation: publik-geser .35s cubic-bezier(.2, .7, .3, 1) both; }
    .publik__tab-penanda { transition: transform .3s cubic-bezier(.2, .7, .3, 1), width .3s cubic-bezier(.2, .7, .3, 1); }
}
@media (max-width: 575.98px) { .publik__sampul { padding: var(--s-8) 0 var(--s-6); } .publik__total { position: static; } }

/* ── Berkas cetak RPL ── */
.cetak-rpl { background: var(--n-100); font-size: var(--t-sm); color: var(--text); }
.cetak-rpl__alat { max-width: 210mm; margin: var(--s-4) auto; display: flex; align-items: center; gap: var(--s-3); }
.cetak-rpl__halaman { background: var(--n-0); max-width: 210mm; margin: 0 auto var(--s-4); padding: 16mm 18mm; box-shadow: var(--sh-1); }
.cetak-rpl h3 { font-size: var(--t-sm); font-weight: var(--fw-bold); margin: var(--s-4) 0 var(--s-2); color: var(--text); }
.cetak-rpl__kop, .cetak-rpl__tabel { width: 100%; border-collapse: collapse; margin-bottom: var(--s-3); }
.cetak-rpl__kop td, .cetak-rpl__tabel th, .cetak-rpl__tabel td { border: 1px solid var(--n-800); padding: var(--s-1) var(--s-2); vertical-align: top; }
.cetak-rpl__kop td { text-align: center; vertical-align: middle; font-size: var(--t-xs); }
.cetak-rpl__kop-logo { width: 70px; }
.cetak-rpl__kop-logo img { width: 52px; height: auto; }
.cetak-rpl__kop-inst, .cetak-rpl__kop-judul { font-weight: var(--fw-bold); }
.cetak-rpl__kop-label { width: 90px; font-weight: var(--fw-bold); }
.cetak-rpl__kop-nilai { width: 60px; font-weight: var(--fw-bold); }
.cetak-rpl__tabel th { background: var(--n-75); font-weight: var(--fw-semi); text-align: center; font-size: var(--t-xs); }
.cetak-rpl__tabel td { font-size: var(--t-xs); }
.cetak-rpl__isian { width: 100%; margin-bottom: var(--s-3); }
.cetak-rpl__isian th { width: 34%; font-weight: var(--fw-normal); padding: var(--s-1) 0; vertical-align: top; }
.cetak-rpl__isian td { border-bottom: 1px dotted var(--n-400); padding: var(--s-1) 0; }
.cetak-rpl .tengah { text-align: center; }
.cetak-rpl .kanan { text-align: right; }
.cetak-rpl__kecil { font-size: var(--t-2xs); color: var(--text-muted); }
.cetak-rpl__ttd { display: flex; justify-content: flex-end; gap: var(--s-8); flex-wrap: wrap; margin-top: var(--s-6); text-align: center; }
.cetak-rpl__ruang-ttd { height: 60px; }
@media print {
    .cetak-rpl { background: none; }
    .cetak-rpl__alat { display: none; }
    .cetak-rpl__halaman { box-shadow: none; margin: 0; padding: 0; max-width: none; page-break-after: always; }
    .cetak-rpl__halaman:last-child { page-break-after: auto; }
}
