/* ============================================================
   Font — Inter, self-hosted (bukan Google Fonts CDN, konsisten dgn pola
   Bootstrap/vendor JS di app ini yg semua self-host, tak ada dependensi
   eksternal saat runtime). Satu file variable-font (woff2, subset latin,
   axis wght 100-900) mencakup SEMUA weight yg dipakai (400/500/600/700/800)
   -- sebelum ini tak ada font-family kustom sama sekali, jadi tiap OS jatuh
   ke font sistemnya sendiri (San Francisco di Mac, Segoe UI di Windows,
   Roboto di Android) via default stack Bootstrap -- itu sebabnya tampilan
   beda2 antar client. Skrng SEMUA client render file font yg sama persis.
   ============================================================ */
@font-face {
  font-family: Inter;
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url('../fonts/inter/Inter-Variable.woff2') format('woff2');
}

/* Override variabel CSS Bootstrap-nya sendiri (bukan cuma `body`) — sebagian
   komponen (.tooltip/.popover) baca `--bs-font-sans-serif` langsung, bukan
   inherit dari body, jadi kalau cuma override body font-family komponen itu
   tetap jatuh ke stack sistem lama. */
:root {
  --bs-body-font-family: 'Inter', -apple-system, blinkmacsystemfont, "Segoe UI", roboto,
    "Helvetica Neue", arial, sans-serif;
  --bs-font-sans-serif: 'Inter', -apple-system, blinkmacsystemfont, "Segoe UI", roboto,
    "Helvetica Neue", arial, sans-serif;
}

/* ============================================================
   Base
   ============================================================ */
*, *::before, *::after { box-sizing: border-box; }
body {
  margin: 0;
  padding: 0;
  font-family: var(--bs-body-font-family);
}
table, th, td { text-align: center; }

/* ============================================================
   Action buttons (table rows)
   ============================================================ */
div.action-btn a {
    text-decoration: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 30px;
    border-radius: 15px;
    background-color: #6c757d;
    line-height: 30px;
}
div.action-btn a:hover { background-color: #343a40; }

/* ============================================================
   Bootstrap SVG icons
   ============================================================ */
.bi {
    display: inline-block;
    width: 1rem;
    height: 1rem;
    vertical-align: -.125em;
    fill: currentcolor;
}

/* Ikon dgn atribut title= (mis. #info-circle di header tabel) dipakai sbg
   penjelasan hover -- cursor:help memberi sinyal visual "ada keterangan kalau
   di-hover", drpd cuma ikon diam yg tak kelihatan interaktif. */
.bi[title] {
    cursor: help;
}

/* ============================================================
   Sidebar  (YouTube-style rounded pill)
   ============================================================ */
@media (width >= 768px) {
    .sidebar .offcanvas-md,
    .sidebar .offcanvas-lg {
        position: static;
    }
}

/* Padding wrapper agar pill tidak mepet pinggir sidebar */
.sidebar .offcanvas-body > .nav,
.sidebar .offcanvas-body > ul.nav {
    padding: 8px 8px 4px;
}

/* ── Nav link utama ── */
.sidebar .nav-link {
    border-radius: 10px;
    padding: 8px 14px;
    min-height: 40px;
    font-size: .875rem;
    font-weight: 500;
    color: #111827;
    transition: background .12s ease;
}
.sidebar .nav-link:hover {
    background: rgb(0 0 0 / 6%);
    color: #111827;
}
.sidebar .nav-link.active {
    background: #e2e5e9;
    font-weight: 600;
    color: #111827;
}
/* Hapus garis biru kiri */
.sidebar .nav-link.active::before { display: none; }

.sidebar-heading { font-size: .75rem; }

/* ── Section toggle (Absensi, Jadwal, dst.) ── */
.sidebar-toggle {
    background: none;
    border: none;
    border-radius: 10px;
    padding: 8px 14px;
    min-height: 40px;
    color: #111827;
    font-size: .875rem;
    font-weight: 500;
    width: 100%;
    text-align: left;
    cursor: pointer;
    display: flex;
    align-items: center;
    transition: background .12s ease;
}
.sidebar-toggle:hover { background: rgb(0 0 0 / 6%); color: #111827; }
.sidebar-toggle.active-section {
    background: rgb(0 0 0 / 6%);
    font-weight: 600;
    color: #111827;
}
.sidebar-toggle .chevron {
    margin-left: auto;
    flex-shrink: 0;
    transition: transform .2s ease;
}
.sidebar-toggle[aria-expanded="true"] .chevron { transform: rotate(90deg); }

/* ── Sub-nav item ── */
.sidebar .sub-nav .nav-link {
    font-size: .8125rem;
    font-weight: 400;
    min-height: 36px;
    padding: 6px 14px;
    border-radius: 8px;
}
.sidebar .sub-nav .nav-link.active {
    background: #e2e5e9;
    font-weight: 600;
    color: #111827;
}

/* Sub-nav items tidak perlu border kiri juga */
.sidebar .sub-nav .nav-link.active::before { display: none; }

/* Label grup (class name di Kelas Wali — tidak interaktif) */
.sidebar .sub-nav .nav-link[style*="cursor:default"] {
    background: none !important;
    cursor: default !important;
    min-height: unset;
    padding-top: 10px;
    padding-bottom: 2px;
    font-size: .72rem;
    font-weight: 600;
    color: #6b7280;
    text-transform: uppercase;
    letter-spacing: .04em;
}

/* ============================================================
   Navbar
   ============================================================ */
.app-topbar {
    min-height: 72px;
    background: #212529;
    box-shadow: 0 3px 12px rgb(15 23 42 / 14%);
    z-index: 1030;
}
.navbar-brand {
    min-width: 0;
    padding: .5rem 1rem;
}
.brand-logo-frame {
    display: inline-flex;
    align-items: center;
    min-width: 0;
    height: 40px;
}
.brand-logo {
    display: block;
    width: auto;
    height: auto;
    max-width: 160px;
    max-height: 40px;
    object-fit: contain;
}
.brand-name {
    color: #fff;
    font-size: 1.25rem;
    font-weight: 700;
    line-height: 1.2;
}
/* Nama Yayasan di samping logo (bukan pengganti logo) -- lebih kecil drpd
   varian tanpa-logo, tapi TAK dipotong/ellipsis -- teks lengkap sengaja tampil
   utuh spy jadi penanda jelas VPS/deployment mana yg sedang diakses admin. */
.brand-name-with-logo {
    font-size: .95rem;
    font-weight: 600;
    white-space: nowrap;
}

/* ============================================================
   Login page
   ============================================================ */
.form-signin { max-width: 380px; padding: 1.5rem; }
.form-signin .form-floating:focus-within { z-index: 2; }
.form-signin .form-floating + .form-floating { margin-top: -1px; }
.form-signin .form-floating:first-of-type input {
    border-bottom-right-radius: 0;
    border-bottom-left-radius: 0;
}
.form-signin .form-floating:last-of-type input {
    border-top-right-radius: 0;
    border-top-left-radius: 0;
    margin-bottom: 10px;
}

/* ============================================================
   Forms — invalid feedback always visible when is-invalid set
   ============================================================ */
.was-validated .form-control:invalid ~ .invalid-feedback,
.form-control.is-invalid ~ .invalid-feedback,
.was-validated .form-select:invalid ~ .invalid-feedback,
.form-select.is-invalid ~ .invalid-feedback,
.was-validated .form-check-input:invalid ~ .invalid-feedback,
.form-check-input.is-invalid ~ .invalid-feedback { display: block; }

/* ============================================================
   Attendance checklist
   ============================================================ */
.checklist-table td { vertical-align: middle; }
.status-badge { font-size: .75rem; }

/* ============================================================
   NFC scanner
   ============================================================ */
.nfc-scanner-box {
    border: 3px dashed #2470dc;
    border-radius: 12px;
    padding: 2rem;
    text-align: center;
    min-height: 200px;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 1rem;
}
.nfc-scanner-box.scanning {
    border-color: #198754;
    animation: pulse-border 1.5s infinite;
}
.nfc-scanner-box.error { border-color: #dc3545; }

@keyframes pulse-border {
    0%   { border-color: #198754; }
    50%  { border-color: #20c997; }
    100% { border-color: #198754; }
}

/* ============================================================
   Gate record status badges
   ============================================================ */
.arrival-on-time  { color: #198754; }
.arrival-late     { color: #dc3545; }
.departure-normal { color: #6c757d; }
.departure-early  { color: #fd7e14; }

/* ============================================================
   Pagination
   ============================================================ */
.pagination a { margin: 0 .5rem; }

/* ── Collapsible sidebar ─────────────────────────────── */
@media (width >= 768px) {
  .sidebar {
    overflow: hidden;
    transition: width .24s ease, flex-basis .24s ease, max-width .24s ease,
                padding .24s ease, border-color .24s ease;
  }
  body.sb-hidden .sidebar {
    width: 72px !important;
    flex: 0 0 72px !important;
    max-width: 72px !important;
    padding: 0 !important;
  }
  body.sb-hidden .sidebar .offcanvas-md { display: none !important; }
  body.sb-hidden main {
    max-width: calc(100% - 72px) !important;
    flex: 0 0 calc(100% - 72px) !important;
    margin-left: 0 !important;
  }
}
.sb-toggle-btn {
  width: 52px;
  height: 52px;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: none;
  border-radius: 8px;
  color: rgb(255 255 255 / 75%);
  padding: 0;
  cursor: pointer;
  transition: color .15s ease, background-color .15s ease;
}
.sb-toggle-btn:hover {
  color: #fff;
  background: rgb(255 255 255 / 10%);
}

/* ============================================================
   Utility classes — text size
   ============================================================ */
.text-xs   { font-size: .75rem !important; }
.text-xxs  { font-size: .68rem !important; }
.text-micro { font-size: .65rem !important; }

/* ============================================================
   Utility classes — sticky table columns
   ============================================================ */
.table-sticky-col {
  position: sticky;
  left: 0;
  z-index: 1;
  background-color: var(--bs-body-bg);
}
.table-sticky-col-2 {
  position: sticky;
  left: 0;
  z-index: 1;
  background-color: var(--bs-table-bg, var(--bs-body-bg));
}

/* ============================================================
   Utility classes — report table
   ============================================================ */
.report-table th,
.report-table td { font-size: .78rem; vertical-align: middle; }

/* ============================================================
   Utility classes — KPI / stat card
   ============================================================ */
.kpi-val {
  font-size: 1.5rem;
  font-weight: 700;
  line-height: 1.15;
}
.kpi-label {
  font-size: .7rem;
  color: var(--bs-secondary-color);
  text-transform: uppercase;
  letter-spacing: .04em;
}

/* ============================================================
   Utility classes — scroll panel
   ============================================================ */
.scroll-panel { overflow-y: auto; }
.scroll-panel-sm  { max-height: 240px; overflow-y: auto; }
.scroll-panel-md  { max-height: 360px; overflow-y: auto; }
.scroll-panel-lg  { max-height: 480px; overflow-y: auto; }

/* ============================================================
   Utility classes — soft badges (alternative to Bootstrap subtle)
   ============================================================ */
.badge-soft-primary   { background: #dbeafe; color: #1d4ed8; }
.badge-soft-success   { background: #dcfce7; color: #15803d; }
.badge-soft-warning   { background: #fef9c3; color: #92400e; }
.badge-soft-danger    { background: #fee2e2; color: #b91c1c; }
.badge-soft-secondary { background: #f1f5f9; color: #475569; }
.badge-soft-purple    { background: #ede9fe; color: #6d28d9; }
.text-purple          { color: #6d28d9 !important; }
.bg-purple            { background: #6d28d9 !important; }

/* ============================================================
   Utility classes — truncate with ellipsis
   ============================================================ */
.text-truncate-col {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 0;
}

/* Sortable table headers (sortable-table.js) */
.th-sortable {
  cursor: pointer;
  user-select: none;
  white-space: nowrap;
}

.th-sortable:hover {
  background-color: rgb(0 0 0 / 4%);
}

.th-sortable .sort-ind {
  color: #2563eb;
  font-size: 0.8em;
}

/* Indikator diam "bisa diurutkan" (⇅) utk header yg BELUM aktif diurutkan —
   tanpa ini, header sortable identik dgn header biasa sampai user kebetulan
   coba klik (cuma beda cursor:pointer, tak kelihatan di screenshot/first
   glance). Sembunyi otomatis begitu kolom itu aktif diurutkan (.sort-ind
   sudah terisi ▲/▼ dari sortable-table.js, atau lewat sort_th.html server-side)
   -- dicek via :has() drpd toggle class manual, jalan utk KEDUA pola markup
   (span.sort-ind selalu ada tp kosong di sortable-table.js, ATAU tak ada sama
   sekali di kolom non-aktif utk macro sort_th). */
.th-sortable:not(:has(.sort-ind:not(:empty)))::after {
  content: ' \21C5';
  color: #adb5bd;
  font-size: 0.75em;
  opacity: 0.85;
}

/* ============================================================
   Dropdown Status/Persentase di Input Absensi Manual (checklist.html) —
   warna mencolok per kondisi supaya bisa dipindai cepat scr visual tanpa
   buka tiap dropdown satu-satu (mis. scan 80+ baris siswa). Dipasang via
   atribut data-status/data-pct-level yg disetel checklist.js (initial load
   dari nilai <select> yg sudah ter-render server, DAN tiap kali user ganti
   pilihan) -- CSS attribute selector otomatis ikut begitu atribut berubah,
   tak perlu toggle class manual.
   ============================================================ */
select.status-select[data-status='Hadir'] {
  background-color: #d1e7dd;
  border-color: #a3cfbb;
  color: #0f5132;
  font-weight: 600;
}
select.status-select[data-status='Terlambat'] {
  background-color: #fff3cd;
  border-color: #ffe69c;
  color: #664d03;
  font-weight: 600;
}
select.status-select[data-status='Sakit'] {
  background-color: #cff4fc;
  border-color: #9eeaf9;
  color: #055160;
  font-weight: 600;
}
select.status-select[data-status='Izin'] {
  background-color: #cfe2ff;
  border-color: #9ec5fe;
  color: #084298;
  font-weight: 600;
}
select.status-select[data-status='Dispensasi'] {
  background-color: #e0cffc;
  border-color: #c8a9fa;
  color: #4a1a8d;
  font-weight: 600;
}
select.status-select[data-status='AFK'] {
  background-color: #ede9fe;
  border-color: #ddd6fe;
  color: #5b21b6;
  font-weight: 600;
}
select.status-select[data-status='Alpha'] {
  background-color: #f8d7da;
  border-color: #f1aeb5;
  color: #842029;
  font-weight: 600;
}
select.status-select[data-status='Pulang'] {
  background-color: #e2e3e5;
  border-color: #c4c8cb;
  color: #41464b;
  font-weight: 600;
}

select.pct-select[data-pct-level='full'] {
  background-color: #d1e7dd;
  border-color: #a3cfbb;
  color: #0f5132;
  font-weight: 600;
}
select.pct-select[data-pct-level='partial'] {
  background-color: #fff3cd;
  border-color: #ffe69c;
  color: #664d03;
  font-weight: 600;
}
select.pct-select[data-pct-level='low'] {
  background-color: #f8d7da;
  border-color: #f1aeb5;
  color: #842029;
  font-weight: 600;
}

/* ============================================================
   Papan Jadwal — mode Grid (Hari x JP, kalender mingguan)

   Pola "frozen header" spreadsheet — BUKAN position:sticky (2x percobaan
   sebelumnya masih kelihatan header "menutupi" baris JP yg lg discroll, krn
   sticky di dalam CSS Grid + scroll halaman penuh punya batasan yg rapuh).
   Header (.sched-grid-header-scroll) & body (.sched-grid-body-scroll) kini 2
   KONTAINER SCROLL TERPISAH — header betul2 di luar area yg discroll vertikal
   (elemen biasa, posisi statis, tak pernah ketutup apa pun), body py
   max-height + overflow-y:auto SENDIRI (scroll lokal, bukan scroll halaman).
   Scroll horizontal keduanya disinkronkan via schedules-grid.js (scrollLeft).
   ============================================================ */
.sched-grid,
.sched-grid-header {
  display: grid;
  gap: 2px;
  min-width: max-content;
}

.sched-grid-header-scroll {
  overflow-x: hidden;
  /* scrollLeft di-drive JS (schedules-grid.js), bukan interaksi user langsung
     di sini — scrollbar-nya sendiri disembunyikan, body-lah yg py scrollbar. */
  border-bottom: 2px solid #e2e8f0;
}

.sched-grid-body-scroll {
  overflow: auto;
  max-height: 65vh;
}

.sched-grid-cell {
  padding: 4px 6px;
  font-size: 0.72rem;
  color: #64748b;
}

.sched-grid-corner {
  position: sticky;
  left: 0;
  z-index: 3;
  background: var(--bs-body-bg, #fff);
}

.sched-grid-day-header {
  background: #f8fafc;
  border-radius: 4px 4px 0 0;
  text-align: center;
  font-weight: 600;
  padding: 6px 4px;
  color: #334155;
  /* Kunci teks (span sticky di dalam) tetap DI DALAM batas sel Hari ini —
     spy tak "kabur" nampilkan diri di atas sel Selasa dkk saat scroll. */
  overflow: hidden;
}

/* Tint selang-seling (hari genap/ganjil) — dipakai BERSAMA di header (di sini)
   MAUPUN pita latar badan grid (.sched-grid-day-band-alt di bawah), spy
   header & badan tampak sbg SATU kolom menyatu drpd teks header yg "mengambang"
   tanpa kaitan visual ke isinya begitu discroll turun lewat baris header. */
.sched-grid-day-header.sched-grid-day-alt {
  background: #eef1f5;
}

/* Sel Hari bisa sangat lebar (span byk lane sekaligus) — teks label ini sticky
   thd kontainer scroll horizontal header (#sched-grid-header-scroll), jadi
   tetap kelihatan selagi scroll menyusuri lebar sel itu, bukan cuma sekilas
   di ujung kiri lalu hilang. left:90px = lebar kolom label JP (kolom 1) yg
   jg sticky di sisi kiri, spy teks Hari tak ketutup di baliknya. */
.sched-grid-day-header-label {
  position: sticky;
  left: 90px;
  display: inline-block;
}

.sched-grid-day-header.sched-grid-today {
  background: #dbeafe;
  color: #1d4ed8;
}

.sched-grid-jp-label {
  position: sticky;
  left: 0;
  z-index: 1;
  background: var(--bs-body-bg, #fff);
  font-weight: 600;
  white-space: nowrap;
}

/* Pita latar per-hari (baru) — membentang PENUH tinggi grid (grid-row:1/-1) di
   BADAN grid, memisahkan kolom antar hari scr visual jelas sampai ke bawah,
   bukan cuma di baris header. Sebelum ini, batas antar hari cuma "gap: 2px"
   SERAGAM yg jg dipakai antar-lane DALAM hari yg sama — begitu discroll turun
   dari header, kolom hari jadi tak bisa dibedakan lagi ("tercampur"). Dirender
   PALING AWAL dlm markup .sched-grid (sebelum label JP & chip) spy otomatis
   di lapisan paling belakang tanpa perlu z-index eksplisit. */
.sched-grid-day-band {
  grid-row: 1 / -1;
  border-left: 2px solid #e2e8f0;
}

.sched-grid-day-band:first-child {
  border-left: none;
}

.sched-grid-day-band-alt {
  background: rgb(100 116 139 / 5%);
}

.sched-grid-day-band.sched-grid-today {
  background: rgb(219 234 254 / 40%);
}

/* Baris istirahat/ISHOMA — pita abu-abu netral per hari (sejajar label baris di
   kolom JP kiri, lih. sched-grid-jp-label), spy scr visual jelas beda dari baris JP
   biasa dan Event yg ditempatkan di situ (lih. docs/plan/event-istirahat-ishoma.md)
   tetap kelihatan MENUMPANG di atasnya (z-index bawaan urutan markup: band dirender
   sebelum chip, jadi chip otomatis di lapisan atas). */
.sched-grid-break-band {
  background: rgb(128 128 128 / 12%);
}

.sched-grid-chip {
  display: block;
  border-radius: 6px;
  padding: 3px 5px;
  margin: 1px;
  font-size: 0.68rem;
  line-height: 1.15;
  text-decoration: none;
  overflow: hidden;
  border: 1px solid rgb(0 0 0 / 8%);
  transition: transform 0.08s ease, box-shadow 0.08s ease;
}

.sched-grid-chip:hover {
  transform: scale(1.03);
  box-shadow: 0 2px 8px rgb(0 0 0 / 15%);
  z-index: 4;
  position: relative;
}

.sched-grid-chip.sched-grid-status-live {
  outline: 2px solid #22c55e;
  outline-offset: -1px;
}

.sched-grid-chip.sched-grid-status-missed {
  outline: 2px solid #dc2626;
  outline-offset: -1px;
}

.sched-grid-chip.sched-grid-status-done {
  opacity: 0.6;
}

/* Dipakai papan /attendance/sessions mode Grid (sesi is_cancelled=True) — mirror
   styling baris dibatalkan di sessions_list.html (table-danger text-muted). */
.sched-grid-chip.sched-grid-status-cancelled {
  opacity: 0.55;
  text-decoration: line-through;
  border-color: #dc2626;
}
