/* =============================================================================
   AplikasiGURU — app.css
   Satu berkas CSS untuk seluruh aplikasi, berbasis CSS Custom Properties
   (design token) + utility ringan. Tanpa framework CSS.
   Referensi: docs/prd/00-arsitektur-teknis.md §1 & §9.

   Struktur:
     1. Design token
     2. Reset & dasar
     3. Layout (sidebar desktop / bottom nav mobile)
     4. Komponen (kartu, tombol, form, tabel, badge, dll.)
     5. Utility
     6. Cetak (@media print)
   ============================================================================= */

/* ------------------------------------------------------------------ 1. TOKEN */
:root {
  /* ------------------------------------------------------------------ WARNA

     Palet dasar mengikuti Portal Dapodik (dapo.kemendikdasmen.go.id) — rujukan
     visual yang sudah dikenal guru karena dipakai untuk pendataan wajib mereka.
     Nilainya diambil dari token situs itu sendiri, bukan dikira-kira dari
     tangkapan layar.

     Wataknya: biru navy pekat sebagai warna utama, latar halaman biru-sian yang
     sangat pucat, garis bernada sian, dan warna status yang cerah — bukan palet
     teredam.

     TOKEN `-teks` DI BAWAH BUKAN DUPLIKAT. Warna status yang cerah tidak dapat
     dipakai sebagai teks di atas tint-nya sendiri: #1FAD7E di atas #E6F7F1 hanya
     2,6:1. Karena itu tiap warna punya sepasang — satu untuk bidang/garis, satu
     lagi yang digelapkan untuk teks. Seluruh pasangan diukur, bukan ditaksir. */

  /* Brand */
  --c-brand:            #1C4F8D;
  --c-brand-dark:       #16406F;
  --c-brand-light:      #DCF1F9;
  --c-brand-contrast:   #FFFFFF;

  /* Accent */
  --c-accent:           #4987C5;

  /* Neutral */
  --c-bg:               #F2F9FD;
  --c-surface:          #FFFFFF;
  --c-surface-alt:      #F7FBFE;
  --c-border:           #C2E3F0;

  /* Garis untuk KENDALI ISIAN, bukan pemisah dekoratif.

     --c-border hanya 1,35:1 terhadap permukaan putih — cukup untuk memisahkan
     kartu, tetapi WCAG 1.4.11 menuntut 3:1 bagi batas komponen yang menyampaikan
     keberadaannya, dan kotak isian termasuk. Dengan garis sepucat itu, guru harus
     menebak di mana bidang isian berakhir. Situs rujukannya sendiri memakai garis
     pucat untuk keduanya; kelemahan itu tidak ikut disalin. */
  --c-border-kuat:      #6795B4;

  /* Text */
  --c-text:             #0B2041;
  --c-text-muted:       #3E5374;
  --c-text-inverse:     #FFFFFF;

  /* Text on backgrounds */
  --c-brand-teks:       #1C4F8D;
  --c-danger-teks:      #C02626;
  --c-success-teks:     #0F7A57;
  --c-info-teks:        #1C4F8D;
  --c-warning-teks:     #8A5A06;

  /* Status */
  --c-success:          #1FAD7E;
  --c-success-bg:       #E6F7F1;

  --c-info:             #4987C5;
  --c-info-bg:          #DCF1F9;

  --c-warning:          #F59F0A;
  --c-warning-bg:       #FEF3DC;

  --c-danger:           #EF4444;
  --c-danger-bg:        #FDECEC;

  /* Tipografi */
  --font-sans: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --fs-xs:   0.75rem;
  --fs-sm:   0.875rem;
  --fs-base: 1rem;
  --fs-lg:   1.125rem;
  --fs-xl:   1.375rem;
  --fs-2xl:  1.75rem;
  --fs-3xl:  2.25rem;
  --lh-tight: 1.25;
  --lh-base:  1.55;

  /* Spasi (skala 4px) */
  --sp-1: 0.25rem;  --sp-2: 0.5rem;   --sp-3: 0.75rem;  --sp-4: 1rem;
  --sp-5: 1.25rem;  --sp-6: 1.5rem;   --sp-8: 2rem;     --sp-10: 2.5rem;

  /* Radius & bayangan */
  --r-sm: 6px;  --r-md: 10px;  --r-lg: 14px;  --r-xl: 20px;  --r-full: 999px;
  --shadow-sm: 0 1px 2px rgba(16, 24, 40, .05);
  --shadow-md: 0 4px 12px rgba(16, 24, 40, .08);
  --shadow-lg: 0 12px 28px rgba(16, 24, 40, .12);

  /* Layout */
  --sidebar-w:  264px;
  --bottomnav-h: 64px;
  --topbar-h:   60px;

  --container-max: 1360px;

  /* Cangkang boxed halaman guru (docs/prd/modul/01-dashboard.md §4c).

     Token TERPISAH dari --container-max meski nilainya kebetulan sama:
     --container-max membatasi `.main` pada layout cetak dan panel admin, yang
     tidak memakai cangkang ini. Menyatukannya berarti menyetel lebar dashboard
     ikut menggeser lebar pratinjau cetak — kaitan yang membuat `.main` dan
     cangkang saling menimpa. Biarkan terpisah walau nilainya kembar. */
  --cangkang-max: 1360px;

  /* Target sentuh minimum di mobile (docs/prd/00-ringkasan-produk.md §7) */
  --tap-min: 44px;
}

/* ------------------------------------------------------------- MODE GELAP
   TERANG ADALAH DEFAULT. Mode gelap TIDAK pernah aktif dengan sendirinya —
   hanya bila guru memilihnya, sesuai kolom account_settings.tema:

     terang    -> default, dipakai bila atribut data-theme tidak ada
     gelap     -> dipaksa gelap
     otomatis  -> baru mengikuti preferensi sistem operasi

   Selektornya WAJIB `[data-theme="otomatis"]`, bukan `:not([data-theme="terang"])`:
   yang terakhir membuat aplikasi ikut gelap begitu OS pengguna gelap, padahal
   skema database menetapkan 'terang' sebagai bawaan. */
/* PERINGATAN: blok ini dan :root[data-theme="gelap"] di bawah WAJIB berisi token
   yang sama persis. CSS tidak dapat memakai satu blok untuk dua kondisi ini —
   yang satu bergantung media query, yang lain pada atribut — sehingga satu-
   satunya penjaganya adalah menyalin utuh, termasuk kelima token `-teks`.

   Menyalin latar gelapnya saja tanpa token `-teks` membuat pengguna bertema
   otomatis dengan OS gelap mendapat latar gelap namun warna teks tema terang di
   atasnya — persis kegagalan kontras yang token itu diciptakan untuk mencegah. */
@media (prefers-color-scheme: dark) {
  :root[data-theme="otomatis"] {
    --c-bg:          #0B1220;
    --c-surface:     #111A2B;
    --c-surface-alt: #16223A;
    --c-border:      #24334D;
    --c-text:        #E6EDF7;
    --c-text-muted:  #94A6C0;
    --c-brand-light: #14263F;
    --c-success-bg:  #10281F;
    --c-info-bg:     #14263F;
    --c-warning-bg:  #2A2113;
    --c-danger-bg:   #2D1717;
    --c-border-kuat: #4A6285;

    --c-brand-teks:   #7FB3E8;
    --c-danger-teks:  #F87171;
    --c-success-teks: #4ADE80;
    --c-info-teks:    #7FB3E8;
    --c-warning-teks: #FBBF24;
  }
}

/* Kembaran blok di atas — lihat peringatan di sana sebelum menyunting salah satu.

   Netralnya bernada NAVY, mengikuti rona warna utama: nada netral gelap mewarisi
   rona brand-nya, dan latar kehijauan di bawah antarmuka biru membuat kartu
   tampak kotor. --c-brand-teks pun biru muda dengan alasan yang sama — token
   berona lain membuat tautan di tema gelap berwarna berbeda dari tombolnya.

   Latar bernada di sini gelap, jadi warna TEKS di atasnya harus diterangkan:
   memakai --c-brand / --c-danger apa adanya jatuh di bawah ambang WCAG AA. */
:root[data-theme="gelap"] {
  --c-bg:          #0B1220;
  --c-surface:     #111A2B;
  --c-surface-alt: #16223A;
  --c-border:      #24334D;
  --c-text:        #E6EDF7;
  --c-text-muted:  #94A6C0;
  --c-brand-light: #14263F;
  --c-success-bg:  #10281F;
  --c-info-bg:     #14263F;
  --c-warning-bg:  #2A2113;
  --c-danger-bg:   #2D1717;
  --c-border-kuat: #4A6285;

  --c-brand-teks:   #7FB3E8;
  --c-danger-teks:  #F87171;
  --c-success-teks: #4ADE80;
  --c-info-teks:    #7FB3E8;
  --c-warning-teks: #FBBF24;
}

/* ------------------------------------------------------- 2. RESET & DASAR */
*, *::before, *::after { box-sizing: border-box; }

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

body {
  margin: 0;
  font-family: var(--font-sans);
  font-size: var(--fs-base);
  line-height: var(--lh-base);
  color: var(--c-text);
  background: var(--c-bg);
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 { margin: 0 0 var(--sp-2); line-height: var(--lh-tight); font-weight: 700; }
h1 { font-size: var(--fs-2xl); }
h2 { font-size: var(--fs-xl); }
h3 { font-size: var(--fs-lg); }
p  { margin: 0 0 var(--sp-3); }

a { color: var(--c-brand); text-decoration: none; }
a:hover { text-decoration: underline; }

img { max-width: 100%; height: auto; display: block; }

/* Fokus terlihat jelas demi aksesibilitas keyboard */
:focus-visible {
  outline: 2px solid var(--c-brand);
  outline-offset: 2px;
  border-radius: var(--r-sm);
}

/* Hanya terbaca screen reader */
.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}

/* -------------------------------------------------------------- 3. LAYOUT */
.app-shell { min-height: 100vh; }

/* Sidebar — tersembunyi di mobile, kartu dalam alur normal di desktop.
   BUKAN `position: fixed`: ia satu kolom grid di dalam cangkang boxed dan
   menggulir bersama halaman, sehingga tidak ada dua batang gulir berdampingan
   dan `.main` tidak perlu dikompensasi `margin-left`
   (docs/prd/modul/01-dashboard.md §4c). */
.sidebar {
  background: var(--c-surface);
  border: 1px solid var(--c-border);
  border-radius: var(--r-lg);
  display: none;
  flex-direction: column;
  align-self: start;
}

/* Mini profil */
.sidebar__profil {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  margin: var(--sp-3) var(--sp-3) 0;
  border: 1px solid var(--c-border);
  border-radius: var(--r-lg);
  background: var(--c-surface-alt);
  color: inherit;
  text-decoration: none;
}

.sidebar__profil:hover { border-color: var(--c-brand); text-decoration: none; }

.sidebar__avatar {
  display: grid;
  place-items: center;
  flex: none;
  width: 40px;
  height: 40px;
  border-radius: var(--r-full);
  background: var(--c-brand-light);
  color: var(--c-brand);
  font-size: var(--fs-sm);
  font-weight: 700;
  overflow: hidden;
}

.sidebar__avatar img { width: 100%; height: 100%; object-fit: cover; }

/* `min-width: 0` wajib pada anak flex yang isinya dipotong ellipsis — tanpa itu
   ia menolak menyusut di bawah lebar teksnya dan mendorong chevron keluar. */
.sidebar__profil-teks { flex: 1; min-width: 0; }

.sidebar__profil-nama,
.sidebar__profil-kelas {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.sidebar__profil-nama  { font-size: var(--fs-sm); font-weight: 600; }
.sidebar__profil-kelas { font-size: var(--fs-xs); color: var(--c-text-muted); }

.sidebar__profil-chevron { flex: none; color: var(--c-text-muted); }

/* Navigasi berkelompok */
.sidebar__nav { padding: var(--sp-4) var(--sp-2) var(--sp-2); flex: 1; }

.sidebar__bagian {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  margin: 0 0 var(--sp-2);
  padding: 0 var(--sp-3);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--c-text-muted);
}

/* Titik penanda bagian: pembeda visual yang tidak menambah elemen ke markup,
   sehingga judul bagian tetap satu simpul teks bagi pembaca layar. */
.sidebar__bagian::before {
  content: '';
  flex: none;
  width: 6px;
  height: 6px;
  border-radius: var(--r-full);
  background: var(--c-brand);
}

.sidebar__bagian:not(:first-child) { margin-top: var(--sp-5); }

/* Judul bagian pertama disembunyikan secara visual (PRD Modul 1 §4b). Ditulis
   ulang di sini karena `.sidebar__bagian` datang belakangan di berkas ini dan
   akan menimpa padding & margin milik `.sr-only`. */
.sidebar__bagian.sr-only { padding: 0; margin: -1px; }

/* Padding vertikalnya 10px, bukan 12px. Empat belas tautan plus mini profil dan
   tombol keluar tidak muat di layar setinggi 900px dengan ukuran penuh — dan
   sidebar ini hanya tampil di desktop, tempat sasaran sentuh 40px sudah lebih
   dari cukup. */
.sidebar__link {
  display: flex; align-items: center; gap: var(--sp-3);
  padding: 10px var(--sp-3);
  border-radius: var(--r-md);
  color: var(--c-text);
  font-size: var(--fs-sm);
  margin-bottom: 2px;
}

.sidebar__link:hover { background: var(--c-surface-alt); text-decoration: none; }

/* Pil brand SOLID, bukan latar bernada: satu-satunya butir aktif di antara empat
   belas baris seragam perlu terbaca dari sudut mata, dan `--c-brand-light` tidak
   cukup jauh dari permukaan sidebar untuk itu. Teksnya `--c-brand-contrast`
   sehingga pasangannya tetap lolos WCAG AA di kedua tema. */
.sidebar__link--active,
.sidebar__link--active:hover {
  background: var(--c-brand);
  color: var(--c-brand-contrast);
  font-weight: 600;
}

/* Keluar — merah, dipisah garis, baris terakhir kartu sidebar.
   TIDAK `sticky`: sidebar bukan lagi scrollport-nya sendiri, sehingga
   `sticky; bottom: 0` justru membuat tombol menggantung di tepi bawah viewport
   selama kolom konten yang panjang digulir (PRD Modul 1 §4b). */
.sidebar__keluar {
  margin-top: auto;
  padding: var(--sp-3) var(--sp-3) var(--sp-4);
  border-top: 1px solid var(--c-border);
}

.sidebar__keluar-btn {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  width: 100%;
  padding: var(--sp-3);
  border: 0;
  border-radius: var(--r-md);
  background: none;
  color: var(--c-danger-teks);
  font-family: inherit;
  font-size: var(--fs-sm);
  font-weight: 600;
  cursor: pointer;
  text-align: left;
}

.sidebar__keluar-btn:hover { background: var(--c-danger-bg); }
.sidebar__keluar-btn:focus-visible { outline: 2px solid var(--c-danger); outline-offset: -2px; }

/* Konten utama */
.main {
  padding: var(--sp-4);
  padding-bottom: calc(var(--bottomnav-h) + var(--sp-8)); /* ruang untuk bottom nav */
  max-width: var(--container-max);
  margin: 0 auto;
}

.topbar {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--sp-3);
  margin-bottom: var(--sp-4);
}

/* Bottom navigation — hanya mobile, sesuai referensi desain */
.bottomnav {
  position: fixed; inset: auto 0 0 0;
  height: var(--bottomnav-h);
  background: var(--c-surface);
  border-top: 1px solid var(--c-border);
  display: flex; align-items: center; justify-content: space-around;
  padding-bottom: env(safe-area-inset-bottom);
  z-index: 50;
}

.bottomnav__item {
  flex: 1;
  min-height: var(--tap-min);
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 2px;
  font-size: var(--fs-xs);
  color: var(--c-text-muted);
}

.bottomnav__item:hover { text-decoration: none; }
.bottomnav__item--active { color: var(--c-brand); font-weight: 600; }

/* Pembungkus ikon: jangkar bagi lencana angka. Lencananya menempel pada IKON,
   bukan pada butir — butir juga memuat label, dan lencana di sudut butir akan
   menindih label tetangganya pada layar sempit. */
.bottomnav__ikon { position: relative; display: inline-flex; }
.bottomnav__lencana { top: -5px; right: -9px; border-color: var(--c-surface); }

/* Tombol aksi mengambang di tengah bottom nav */
.bottomnav__fab {
  width: 52px; height: 52px;
  margin-top: -22px;
  border-radius: var(--r-full);
  background: var(--c-brand);
  color: var(--c-brand-contrast);
  display: flex; align-items: center; justify-content: center;
  font-size: var(--fs-xl);
  box-shadow: var(--shadow-md);
  border: none;
}

@media (min-width: 1024px) {
  /* Cangkang boxed dua kolom (docs/prd/modul/01-dashboard.md §4c).
     `:not(.adm-panel)` WAJIB: panel admin memakai kelas .app-shell yang sama
     tetapi masih mengandalkan `.adm-panel__isi { margin-left: … }`, dan tanpa
     pengecualian ini tata letaknya ikut runtuh. */
  .app-shell:not(.adm-panel) {
    display: grid;
    grid-template-columns: var(--sidebar-w) minmax(0, 1fr);
    gap: var(--sp-4);
    max-width: var(--cangkang-max);
    margin: 0 auto;
    padding: var(--sp-6) var(--sp-6) var(--sp-8);
    align-items: start;
  }

  .sidebar   { display: flex; }
  .bottomnav { display: none; }

  .main { padding: var(--sp-6); padding-bottom: var(--sp-8); }

  /* Reset ini HANYA untuk `.main` di dalam cangkang guru — di sanalah lebar,
     pemusatan, dan jarak tepi sudah disediakan cangkangnya. Menerapkannya ke
     `.main` secara umum ikut mengosongkan jarak tepi layouts/print.php, yang
     memakai `.main` tanpa cangkang sama sekali.

     `margin-left` ikut dinolkan: sebagai kompensasi untuk sidebar `fixed` ia
     membuat kolom konten menyempit dua kali di dalam cangkang. */
  .app-shell:not(.adm-panel) > .main {
    padding: 0;
    max-width: none;
    margin: 0;
    min-width: 0;
  }
}

/* ---------------------------------------------------------- 4. KOMPONEN */

/* Kartu */
.card {
  background: var(--c-surface);
  border: 1px solid var(--c-border);
  border-radius: var(--r-lg);
  padding: var(--sp-4);
  box-shadow: var(--shadow-sm);
}

.card__title  { font-size: var(--fs-base); font-weight: 700; margin-bottom: var(--sp-3); }

/* Baris kepala kartu: judul di kiri, satu aksi di kanan.
   Membungkus di layar sempit supaya tombolnya turun utuh alih-alih menekan
   judul menjadi kolom setipis satu kata. */
.kartu__kepala {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  flex-wrap: wrap;
  margin-bottom: var(--sp-3);
}

.kartu__kepala > .card__title { flex: 1 1 auto; min-width: 0; }

.card--brand {
  background: linear-gradient(135deg, var(--c-brand), var(--c-brand-dark));
  color: var(--c-brand-contrast);
  border: none;
}

/* Kartu metrik (angka ringkasan di dashboard) */
.stat {
  background: var(--c-surface);
  border: 1px solid var(--c-border);
  border-radius: var(--r-lg);
  padding: var(--sp-4);
  text-align: center;
}

.stat__value { font-size: var(--fs-2xl); font-weight: 700; line-height: 1.1; }
.stat__label { font-size: var(--fs-xs); color: var(--c-text-muted); margin-top: var(--sp-1); }

/* Tombol */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--sp-2);
  min-height: var(--tap-min);
  padding: var(--sp-3) var(--sp-5);
  border: 1px solid transparent;
  border-radius: var(--r-md);
  font-family: inherit;
  font-size: var(--fs-sm);
  font-weight: 600;
  cursor: pointer;
  background: var(--c-surface);
  color: var(--c-text);
  border-color: var(--c-border);
}

.btn:hover { text-decoration: none; filter: brightness(.98); }
.btn:disabled { opacity: .55; cursor: not-allowed; }

.btn--primary { background: var(--c-brand); color: var(--c-brand-contrast); border-color: var(--c-brand); }
.btn--danger  { background: var(--c-danger); color: #fff; border-color: var(--c-danger); }
.btn--ghost   { background: transparent; border-color: transparent; color: var(--c-brand); }
.btn--block   { width: 100%; }
.btn--sm      { min-height: 36px; padding: var(--sp-2) var(--sp-3); font-size: var(--fs-xs); }

/* Tombol simpan yang menempel di bawah layar mobile (pola dari referensi desain) */
.btn-sticky {
  position: sticky;
  bottom: calc(var(--bottomnav-h) + var(--sp-3));
  z-index: 30;
  box-shadow: var(--shadow-lg);
}

/* Form */
.field { margin-bottom: var(--sp-4); }

/* Fieldset dipakai untuk mengelompokkan checkbox/radio (Asesmen di Jurnal,
   Tema & Format Nilai di Preferensi). Border "groove 2px" bawaan browser
   menabrak bahasa visual kartu, jadi dinolkan — legend tetap tampil sebagai
   label biasa lewat class .label. */
fieldset.field { border: 0; padding: 0; margin-inline: 0; min-width: 0; }
fieldset.field > legend { padding: 0; }

.label {
  display: block;
  font-size: var(--fs-sm);
  font-weight: 600;
  margin-bottom: var(--sp-2);
}

.label__hint { font-weight: 400; color: var(--c-text-muted); }

.input, .select, .textarea {
  width: 100%;
  min-height: var(--tap-min);
  padding: var(--sp-3);
  font-family: inherit;
  font-size: var(--fs-base);
  color: var(--c-text);
  background: var(--c-surface);
  border: 1px solid var(--c-border-kuat);
  border-radius: var(--r-md);
}

.input:focus, .select:focus, .textarea:focus {
  border-color: var(--c-brand);
  outline: none;
  box-shadow: 0 0 0 3px var(--c-brand-light);
}

.textarea { min-height: 96px; resize: vertical; line-height: var(--lh-base); }

.input--error, .select--error, .textarea--error { border-color: var(--c-danger); }

.field__error { display: block; margin-top: var(--sp-2); font-size: var(--fs-xs); color: var(--c-danger); }
.field__help  { display: block; margin-top: var(--sp-2); font-size: var(--fs-xs); color: var(--c-text-muted); }

/* Badge status */
.badge {
  display: inline-flex; align-items: center; gap: var(--sp-1);
  padding: 2px var(--sp-2);
  border-radius: var(--r-full);
  font-size: var(--fs-xs);
  font-weight: 600;
  line-height: 1.6;
}

/* Token `-teks`, bukan warna solid: badge adalah kasus yang persis dimaksud
   CHECKLIST.md §F — teks berwarna di atas latar bernada. Dengan warna solid,
   pasangan success hanya mencapai 2,86:1 di tema gelap. */
.badge--success { background: var(--c-success-bg); color: var(--c-success-teks); }
.badge--info    { background: var(--c-info-bg);    color: var(--c-info-teks); }
.badge--warning { background: var(--c-warning-bg); color: var(--c-warning-teks); }
.badge--danger  { background: var(--c-danger-bg);  color: var(--c-danger); }
.badge--muted   { background: var(--c-surface-alt); color: var(--c-text-muted); }

/* Daftar (list item siswa/jadwal/dll.) */
.list { display: flex; flex-direction: column; gap: var(--sp-2); }

.list__item {
  display: flex; align-items: center; gap: var(--sp-3);
  padding: var(--sp-3);
  background: var(--c-surface);
  border: 1px solid var(--c-border);
  border-radius: var(--r-md);
}

/* Butir notifikasi yang BERPINDAH KELAS sekaligus membuka modulnya berupa tombol
   di dalam form POST — berpindah kelas mengubah keadaan sesi, dan GET yang
   mengubah keadaan dapat terpicu pramuat peramban. Tombolnya dilucuti agar
   terbaca sama persis dengan butir tautan di sebelahnya; yang membedakan
   keduanya adalah metode HTTP-nya, bukan penampilannya. */
.notif__form { display: contents; }

button.notif__tombol {
  width: 100%;
  font: inherit;
  color: inherit;
  text-align: left;
  cursor: pointer;
}

button.notif__tombol:hover { border-color: var(--c-brand); }
button.notif__tombol:focus-visible { outline: 2px solid var(--c-brand); outline-offset: 2px; }

.list__body  { flex: 1; min-width: 0; }
.list__title { font-weight: 600; font-size: var(--fs-sm); }
.list__meta  { font-size: var(--fs-xs); color: var(--c-text-muted); }

/* Avatar inisial (fallback saat siswa belum punya foto) */
.avatar {
  width: 40px; height: 40px;
  flex: 0 0 40px;
  border-radius: var(--r-full);
  background: var(--c-brand-light);
  color: var(--c-brand);
  display: flex; align-items: center; justify-content: center;
  font-weight: 700; font-size: var(--fs-sm);
  overflow: hidden;
}

/* Tabel — dibungkus .table-wrap agar bisa digeser horizontal di layar kecil */
/* max-width mengunci pembungkus pada lebar induknya. Tanpa itu, tabel yang lebar
   minimumnya melebihi layar dapat melebarkan viewport tata letak di peramban
   ponsel — halaman ikut bergeser dan navigasi bawah yang position:fixed
   memanjang keluar layar, alih-alih hanya tabelnya yang digeser. */
.table-wrap { overflow-x: auto; max-width: 100%; -webkit-overflow-scrolling: touch; }

.table { width: 100%; border-collapse: collapse; font-size: var(--fs-sm); }

/* Grid Daftar Nilai (Modul 6 FR-2).
   Sel input dibuat sempit dan rata tengah supaya puluhan kolom tetap muat;
   kolom Nilai Akhir diberi latar berbeda karena ia terhitung, bukan diketik. */
.tabel-nilai th { text-align: center; vertical-align: middle; }
.tabel-nilai th:nth-child(-n+2) { text-align: left; }
.tabel-nilai td { padding: var(--sp-1) var(--sp-2); }

.tabel-nilai .sel-nilai {
  width: 4.5rem;
  min-height: 38px;
  padding: var(--sp-1);
  text-align: center;
}

.tabel-nilai .kolom-akhir {
  background: var(--c-warning-bg);
  border-left: 2px solid var(--c-warning);
  min-width: 5.5rem;
}

/* Kolom nomor & nama pada tampilan tabel (desktop). Nomor yang diulang di dalam
   sel nama hanya untuk tampilan kartu, jadi di sini disembunyikan. */
.njl__nama { white-space: normal; }
.njl__nama-no { display: none; }

/* --- Daftar Nilai di layar sempit: KARTU PER SISWA, bukan tabel digeser ---

   Tabel ini satu-satunya yang lebar minimumnya tidak dapat menyusut: sel angkanya
   berlebar tetap, sehingga dua belas kolom menuntut ~900px berapa pun lebar
   layarnya. Menggesernya menyamping bukan jalan keluar — nama siswa hilang dari
   pandangan begitu guru menggeser ke kolom keempat, dan mengisi nilai berarti
   menebak baris. Yang lebih buruk, lebar sebesar itu MELEBARKAN viewport tata
   letak ponsel: seluruh halaman ikut bergeser dan navigasi bawah memanjang
   keluar layar.

   Karena itu barisnya dijadikan kartu: satu siswa satu kartu, tiap sel menjadi
   baris berlabel (label diambil dari data-label). Markupnya TETAP SATU —
   merender dua set input akan mengirim nilai dua kali, dan set yang tersembunyi
   akan menimpa yang barusan diketik guru. */
@media (max-width: 767px) {
  .tabel-nilai,
  .tabel-nilai tbody,
  .tabel-nilai tr,
  .tabel-nilai td { display: block; width: auto; }

  /* Kepala tabel tidak dapat mengikuti bentuk kartu; namanya pindah ke tiap sel
     lewat data-label. */
  .tabel-nilai thead { display: none; }

  .tabel-nilai tr {
    border: 1px solid var(--c-border);
    border-radius: var(--r-md);
    padding: var(--sp-3);
    margin-bottom: var(--sp-3);
    background: var(--c-surface);
  }

  .tabel-nilai tr:last-child { margin-bottom: 0; }

  /* Kolom No berdiri sendiri tidak berguna di kartu — nomornya menyatu dengan nama. */
  .tabel-nilai .njl__no { display: none; }

  /* Kepala kartu: block, BUKAN flex seperti sel angka di bawahnya. Sebagai flex
     ber-space-between, nomor akan terlempar ke kiri dan nama ke tepi kanan —
     keduanya satu kesatuan yang harus terbaca berurutan. */
  .tabel-nilai .njl__nama {
    display: block;
    padding: 0 0 var(--sp-3);
    margin-bottom: var(--sp-2);
    border-bottom: 1px solid var(--c-border);
    font-size: var(--fs-base);
    font-weight: 600;
  }

  .tabel-nilai .njl__nama-no {
    display: inline;
    color: var(--c-text-muted);
    margin-right: var(--sp-1);
  }

  /* Sel angka: label di kiri, isian di kanan — bentuk daftar yang sudah dikenal
     dari layar Absensi, sehingga tidak ada pola baru yang harus dipelajari. */
  .tabel-nilai tbody td {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--sp-3);
    padding: var(--sp-1) 0;
    border-bottom: 0;
    text-align: left;
    white-space: normal;
  }

  .tabel-nilai tbody td[data-label]::before {
    content: attr(data-label);
    font-size: var(--fs-xs);
    font-weight: 600;
    color: var(--c-text-muted);
    text-transform: uppercase;
    letter-spacing: .03em;
  }

  /* Isian dilebarkan justru karena ruangnya kini ada — sasaran sentuh penuh,
     kebalikan dari tabel rapat yang harus dicubit-zoom. */
  .tabel-nilai .sel-nilai { width: 6rem; min-height: var(--tap-min); }

  .tabel-nilai .kolom-akhir {
    min-width: 0;
    margin-top: var(--sp-2);
    padding-top: var(--sp-2);
    border-left: 0;
    border-top: 2px solid var(--c-warning);
    background: transparent;
    font-size: var(--fs-lg);
  }
}

/* Sembunyikan anak panah spinner: di grid rapat ia mencuri lebar sel. */
.tabel-nilai .sel-nilai::-webkit-outer-spin-button,
.tabel-nilai .sel-nilai::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.tabel-nilai .sel-nilai { -moz-appearance: textfield; }

.table th, .table td {
  padding: var(--sp-3);
  text-align: left;
  border-bottom: 1px solid var(--c-border);
  white-space: nowrap;
}

.table th { font-weight: 600; color: var(--c-text-muted); font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: .03em; }
.table tbody tr:hover { background: var(--c-surface-alt); }

/* Tab */
.tabs { display: flex; gap: var(--sp-2); overflow-x: auto; padding-bottom: var(--sp-2); }

.tab {
  flex: 0 0 auto;
  padding: var(--sp-2) var(--sp-4);
  border-radius: var(--r-full);
  background: var(--c-surface);
  border: 1px solid var(--c-border);
  font-size: var(--fs-sm);
  color: var(--c-text-muted);
  min-height: 38px;
  display: inline-flex; align-items: center;
}

.tab--active { background: var(--c-brand); color: var(--c-brand-contrast); border-color: var(--c-brand); font-weight: 600; }
.tab:hover { text-decoration: none; }

/* Pesan flash & peringatan */
.alert {
  padding: var(--sp-3) var(--sp-4);
  border-radius: var(--r-md);
  font-size: var(--fs-sm);
  margin-bottom: var(--sp-4);
  border: 1px solid transparent;
}

.alert--success { background: var(--c-success-bg); color: var(--c-success); border-color: var(--c-success); }
.alert--error   { background: var(--c-danger-bg);  color: var(--c-danger);  border-color: var(--c-danger); }
.alert--warning { background: var(--c-warning-bg); color: var(--c-warning); border-color: var(--c-warning); }
.alert--info    { background: var(--c-info-bg);    color: var(--c-info);    border-color: var(--c-info); }

/* Toast (notifikasi ringan dari JS) */
.toast-area {
  position: fixed;
  left: 50%; transform: translateX(-50%);
  bottom: calc(var(--bottomnav-h) + var(--sp-4));
  z-index: 100;
  display: flex; flex-direction: column; gap: var(--sp-2);
  width: min(92vw, 420px);
}

.toast {
  padding: var(--sp-3) var(--sp-4);
  border-radius: var(--r-md);
  background: var(--c-text);
  color: var(--c-text-inverse);
  font-size: var(--fs-sm);
  box-shadow: var(--shadow-lg);
}

.toast--success { background: var(--c-success); }
.toast--error   { background: var(--c-danger); }

/* ---- Ikon SVG inline (app/Helpers/icons.php) ----
   Mewarisi warna teks lewat fill="currentColor", sehingga otomatis mengikuti
   status aktif/hover tanpa aturan warna tambahan. */
.icon {
  display: inline-block;
  vertical-align: -0.15em;
  flex: none;
}

/* Ikon di dalam tombol & item daftar diberi jarak dari teksnya. */
.btn .icon { margin-right: var(--sp-2); }
.btn .icon:only-child { margin-right: 0; }

/* ---- Toggle absensi H/I/S/A (Modul 5) ----
   Radio asli disembunyikan, <label> yang tampil sebagai tombol. Dengan begitu
   pemilihan status bekerja penuh tanpa JavaScript, sekaligus tetap dapat
   dioperasikan lewat keyboard dan terbaca screen reader. */
.abs-toggle {
  display: flex;
  gap: var(--sp-1);
  border: 0;
  margin: 0;
  padding: 0;
}

.abs-toggle input {
  position: absolute;
  width: 1px; height: 1px;
  opacity: 0;
  pointer-events: none;
}

.abs-pill {
  width: 40px;
  min-height: var(--tap-min);
  display: flex; align-items: center; justify-content: center;
  border: 1px solid var(--c-border);
  border-radius: var(--r-full);
  background: var(--c-surface);
  color: var(--c-text-muted);
  font-size: var(--fs-sm);
  font-weight: 700;
  cursor: pointer;
  user-select: none;
}

.abs-pill:hover { border-color: var(--c-text-muted); }

/* Fokus keyboard harus terlihat walau input-nya tersembunyi. */
.abs-toggle input:focus-visible + .abs-pill {
  outline: 2px solid var(--c-brand);
  outline-offset: 2px;
}

.abs-toggle input:checked + .abs-pill--belum       { background: var(--c-text-muted); border-color: var(--c-text-muted); color: #fff; }
.abs-toggle input:checked + .abs-pill--dikumpulkan { background: var(--c-success);    border-color: var(--c-success);    color: #fff; }

.abs-toggle input:checked + .abs-pill--hadir { background: var(--c-success); border-color: var(--c-success); color: #fff; }
.abs-toggle input:checked + .abs-pill--izin  { background: var(--c-info);    border-color: var(--c-info);    color: #fff; }
.abs-toggle input:checked + .abs-pill--sakit { background: var(--c-warning); border-color: var(--c-warning); color: #fff; }
.abs-toggle input:checked + .abs-pill--alpa  { background: var(--c-danger);  border-color: var(--c-danger);  color: #fff; }

/* Keterangan hanya relevan untuk siswa yang tidak hadir. Disembunyikan lewat CSS
   agar tetap bekerja tanpa JavaScript; browser lama yang belum mendukung :has()
   sekadar menampilkannya terus — tidak merusak apa pun. */
.abs-ket { margin-top: var(--sp-2); }
.abs-row:has(input[value="hadir"]:checked) .abs-ket { display: none; }

/* ---- Grafik batang distribusi nilai (Modul 6) ----
   Digambar dengan HTML/CSS, bukan canvas: ikut tercetak pada modul Rekap dan Cetak,
   tetap terbaca tanpa JavaScript, dan tidak menambah beban unduh. */
.chart-bars {
  display: flex;
  align-items: flex-end;
  gap: var(--sp-2);
  height: 180px;
  padding-top: var(--sp-4);
}

.chart-bars__col {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  height: 100%;
}

.chart-bars__value {
  font-size: var(--fs-sm);
  font-weight: 700;
  color: var(--c-text);
  margin-bottom: var(--sp-1);
}

.chart-bars__track {
  flex: 1;
  width: 100%;
  display: flex;
  align-items: flex-end;
  border-bottom: 1px solid var(--c-border);
}

.chart-bars__bar {
  width: 100%;
  min-height: 0;
  background: var(--c-brand);
  border-radius: var(--r-sm) var(--r-sm) 0 0;
}

.chart-bars__bar--rendah { background: var(--c-danger); }

.chart-bars__label {
  margin-top: var(--sp-2);
  font-size: var(--fs-xs);
  color: var(--c-text-muted);
  white-space: nowrap;
}

/* ---- Donut absensi (Modul 1) ----
   Memakai conic-gradient, bukan canvas: ikut tercetak, tidak butuh pustaka,
   dan tetap tampil bila JavaScript gagal dimuat. */
.donut {
  width: 140px;
  height: 140px;
  flex: 0 0 140px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
}

.donut__hole {
  width: 92px;
  height: 92px;
  border-radius: 50%;
  background: var(--c-surface);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

.donut__total { font-size: var(--fs-xl); font-weight: 700; line-height: 1; }
.donut__label { font-size: var(--fs-xs); color: var(--c-text-muted); }

/* ---- Bar progres (Modul 8: progres pengumpulan tugas) ----
   Murni CSS, tanpa JS maupun pustaka chart — ikut tercetak dengan benar. */
.progres {
  display: block;
  height: 6px;
  border-radius: var(--r-full);
  background: var(--c-surface-alt);
  border: 1px solid var(--c-border);
  overflow: hidden;
}

.progres__isi {
  display: block;
  height: 100%;
  background: var(--c-brand);
  border-radius: var(--r-full);
}

/* Keadaan kosong */
.empty {
  text-align: center;
  padding: var(--sp-8) var(--sp-4);
  color: var(--c-text-muted);
}

.empty__title { font-weight: 600; color: var(--c-text); margin-bottom: var(--sp-2); }

/* Grid menu (pola layar "Menu" pada referensi desain mobile) */
.menu-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--sp-3);
}

.menu-grid__item {
  background: var(--c-surface);
  border: 1px solid var(--c-border);
  border-radius: var(--r-lg);
  padding: var(--sp-4);
  min-height: 104px;
  display: flex; flex-direction: column; gap: var(--sp-2);
  color: var(--c-text);
}

.menu-grid__item:hover { text-decoration: none; box-shadow: var(--shadow-md); }
.menu-grid__icon { display: block; line-height: 0; }
.menu-grid__title { font-weight: 600; font-size: var(--fs-sm); color: var(--c-brand); }
.menu-grid__desc  { font-size: var(--fs-xs); color: var(--c-text-muted); }

@media (min-width: 768px) {
  .menu-grid { grid-template-columns: repeat(4, 1fr); }
}

/* --------------------------------------------------------------- 5. UTILITY */
/* `minmax(0, 1fr)`, BUKAN `1fr`. Nilai `1fr` sama dengan `minmax(auto, 1fr)`:
   kolom menolak menyusut di bawah lebar min-content isinya, sehingga satu kartu
   berisi teks panjang melebarkan kolomnya sendiri dan mendorong total grid
   melewati wadahnya — di 375px terukur 200px + 175px pada wadah selebar 343px,
   dan halaman ikut menggulir mendatar. */
.grid    { display: grid; gap: var(--sp-3); }
.grid-2  { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grid-3  { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grid-4  { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grid-5  { grid-template-columns: repeat(2, minmax(0, 1fr)); }

@media (min-width: 768px) {
  .grid-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .grid-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .grid-5 { grid-template-columns: repeat(5, minmax(0, 1fr)); }
}

@media (min-width: 1024px) {
  .grid-4 { grid-template-columns: repeat(5, minmax(0, 1fr)); }
}

.flex     { display: flex; }
.flex-col { flex-direction: column; }
.items-center   { align-items: center; }
.justify-between { justify-content: space-between; }
.gap-1 { gap: var(--sp-1); } .gap-2 { gap: var(--sp-2); }
.gap-3 { gap: var(--sp-3); } .gap-4 { gap: var(--sp-4); }

.mt-1 { margin-top: var(--sp-1); } .mt-2 { margin-top: var(--sp-2); }
.mt-3 { margin-top: var(--sp-3); } .mt-4 { margin-top: var(--sp-4); }
.mt-6 { margin-top: var(--sp-6); }
.mb-0 { margin-bottom: 0; }
.mb-2 { margin-bottom: var(--sp-2); } .mb-3 { margin-bottom: var(--sp-3); }
.mb-4 { margin-bottom: var(--sp-4); } .mb-6 { margin-bottom: var(--sp-6); }

.text-sm    { font-size: var(--fs-sm); }
.text-xs    { font-size: var(--fs-xs); }
.text-lg    { font-size: var(--fs-lg); }
.text-muted { color: var(--c-text-muted); }
.text-brand { color: var(--c-brand); }
.text-danger{ color: var(--c-danger); }
.text-center{ text-align: center; }
.font-bold  { font-weight: 700; }
.font-semi  { font-weight: 600; }

.w-full { width: 100%; }
.hidden { display: none; }

/* `min-width: 0` disertakan karena pemakainya hampir selalu anak flex — tanpa
   itu elemen menolak menyusut di bawah lebar teksnya dan ellipsis tidak pernah
   muncul. */
.truncate {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

@media (min-width: 1024px) {
  .lg-hidden { display: none; }
}

@media (max-width: 1023px) {
  .lg-only { display: none; }
}

/* Penjelajah minggu */
.piket-minggu {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--sp-3);
  margin-bottom: var(--sp-3);
}

.piket-minggu__label   { text-align: center; flex: 1; min-width: 0; }
.piket-minggu__rentang { font-weight: 600; }
.piket-minggu__ke      { font-size: var(--fs-sm); color: var(--c-text-muted); cursor: help; }

/* Tombol khusus ikon — dipakai panah minggu */
.btn--icon { padding: var(--sp-2); min-width: 40px; justify-content: center; }

/* Tab hari dua baris: nama hari di atas, tanggal di bawah */
.piket-tab { flex-direction: column; gap: 0; padding: var(--sp-2) var(--sp-3); min-height: 52px; }
.piket-tab__hari { font-weight: 700; font-size: var(--fs-sm); letter-spacing: .04em; }
.piket-tab__tgl  { font-size: var(--fs-xs); opacity: .85; }

/* Kartu hari */
.piket-pekan { display: flex; flex-direction: column; gap: var(--sp-3); }

.piket-hari__kepala {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--sp-2); flex-wrap: wrap;
  padding-bottom: var(--sp-3);
  margin-bottom: var(--sp-2);
  border-bottom: 1px solid var(--c-border);
  font-size: var(--fs-sm);
}

.piket-hari__aksi {
  display: flex; gap: var(--sp-2); flex-wrap: wrap;
  margin-top: var(--sp-3);
  padding-top: var(--sp-3);
  border-top: 1px solid var(--c-border);
}

/* Daftar kategori tugas — akordeon <details> asli */
.piket-tugas { list-style: none; margin: 0; padding: 0; }
.piket-tugas > li + li { border-top: 1px solid var(--c-border); }

.piket-tugas__ringkas {
  display: flex; align-items: flex-start; gap: var(--sp-3);
  padding: var(--sp-3) 0;
  cursor: pointer;
  list-style: none;
}

.piket-tugas__ringkas::-webkit-details-marker { display: none; }

.piket-tugas__ikon {
  width: 40px; height: 40px; flex: 0 0 40px;
  border-radius: var(--r-full);
  display: flex; align-items: center; justify-content: center;
  background: var(--c-brand-light);
  color: var(--c-brand);
}

/* Warna pembeda antar kategori — dirotasi lewat sisa bagi id kategori */
.piket-tugas__ikon--0 { background: var(--c-brand-light);   color: var(--c-brand); }
.piket-tugas__ikon--1 { background: var(--c-info-bg);       color: var(--c-info); }
.piket-tugas__ikon--2 { background: var(--c-warning-bg);    color: var(--c-warning); }
.piket-tugas__ikon--3 { background: var(--c-surface-alt);   color: var(--c-text-muted); }
.piket-tugas__ikon--4 { background: var(--c-danger-bg);     color: var(--c-danger); }
.piket-tugas__ikon--5 { background: var(--c-success-bg);    color: var(--c-success); }

.piket-tugas__teks   { flex: 1; min-width: 0; }
.piket-tugas__nama   { display: block; font-weight: 600; }
.piket-tugas__siswa  { display: block; font-size: var(--fs-sm); color: var(--c-text-muted); }
.piket-tugas__kosong { display: block; font-size: var(--fs-sm); color: var(--c-warning); }
.piket-tugas__ket    { display: block; font-size: var(--fs-sm); color: var(--c-info); margin-top: var(--sp-1); }
.piket-tugas__isi    { padding: 0 0 var(--sp-3) calc(40px + var(--sp-3)); }

/* Chip nama siswa saat akordeon dibuka */
.chip {
  display: inline-flex; align-items: center; gap: var(--sp-1);
  padding: 2px var(--sp-2);
  background: var(--c-surface-alt);
  border: 1px solid var(--c-border);
  border-radius: var(--r-full);
  font-size: var(--fs-sm);
}

.avatar--xs { width: 24px; height: 24px; flex: 0 0 24px; font-size: 10px; }

/* Catatan harian */
.piket-catatan {
  display: flex; gap: var(--sp-2);
  margin-top: var(--sp-3);
  padding: var(--sp-3);
  background: var(--c-brand-light);
  border-radius: var(--r-md);
  font-size: var(--fs-sm);
  color: var(--c-text);
}

.piket-catatan__judul { font-weight: 600; }

/* Kategori pada layar form */
.piket-form__kategori {
  padding: var(--sp-3);
  border: 1px solid var(--c-border);
  border-radius: var(--r-md);
  margin-bottom: var(--sp-3);
}

/* --- Mobile: hanya hari terpilih yang tampil --- */
@media (max-width: 1023px) {
  .piket-hari:not(.piket-hari--aktif) { display: none; }
}

/* --- Desktop: keenam hari sekaligus, tab tidak diperlukan --- */
@media (min-width: 1024px) {
  .piket-tabs { display: none; }

  .piket-pekan {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    align-items: start;
  }

  .piket-hari { margin: 0; }
}

@media (min-width: 1440px) {
  .piket-pekan { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* ------------------------------------------------ 5d. MODUL 12 — INVENTARIS */
/* docs/prd/modul/12-inventaris.md §9. Mengikuti konsep desain: kartu ringkasan
   kondisi, pencarian, tab kategori, daftar bergambar. */

/* Kartu ringkasan — bergeser horizontal di layar sempit, tidak pernah gepeng */
.inv-ringkasan {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(9.5rem, 1fr);
  gap: var(--sp-2);
  overflow-x: auto;
  padding-bottom: var(--sp-2);
  margin-bottom: var(--sp-2);
  -webkit-overflow-scrolling: touch;
}

@media (min-width: 768px) {
  .inv-ringkasan { grid-auto-flow: row; grid-template-columns: repeat(4, minmax(0, 1fr)); overflow: visible; }
  .inv-ringkasan > :nth-child(5) { grid-column: span 4; }
}

.inv-stat {
  display: flex; align-items: flex-start; gap: var(--sp-2);
  padding: var(--sp-3);
  background: var(--c-surface);
  border: 1px solid var(--c-border);
  border-radius: var(--r-md);
}

.inv-stat__ikon {
  width: 34px; height: 34px; flex: 0 0 34px;
  border-radius: var(--r-md);
  display: flex; align-items: center; justify-content: center;
}

.inv-stat__ikon--brand   { background: var(--c-brand-light);  color: var(--c-brand); }
.inv-stat__ikon--success { background: var(--c-success-bg);   color: var(--c-success); }
.inv-stat__ikon--warning { background: var(--c-warning-bg);   color: var(--c-warning); }
.inv-stat__ikon--danger  { background: var(--c-danger-bg);    color: var(--c-danger); }
.inv-stat__ikon--muted   { background: var(--c-surface-alt);  color: var(--c-text-muted); }

.inv-stat__label  { font-size: var(--fs-xs); color: var(--c-text-muted); }
.inv-stat__angka  { font-size: var(--fs-xl); font-weight: 700; line-height: 1.1; }
.inv-stat__satuan { font-size: var(--fs-xs); color: var(--c-text-muted); }

/* Pencarian + penyaring */
.inv-cari { display: flex; gap: var(--sp-2); align-items: flex-start; flex-wrap: wrap; }

.inv-cari__form {
  position: relative;
  flex: 1; min-width: 12rem;
  display: flex; gap: var(--sp-2);
}

.inv-cari__ikon {
  position: absolute; left: var(--sp-3); top: 50%;
  transform: translateY(-50%);
  color: var(--c-text-muted);
  pointer-events: none;
}

.inv-cari__input { flex: 1; padding-left: calc(var(--sp-3) + 26px); border-radius: var(--r-full); }

/* <details> sebagai penyaring: berfungsi tanpa JavaScript */
.inv-filter { position: relative; }
.inv-filter > summary { list-style: none; cursor: pointer; }
.inv-filter > summary::-webkit-details-marker { display: none; }

@media (min-width: 768px) {
  .inv-filter > .card {
    position: absolute; right: 0; z-index: 20;
    min-width: 16rem;
    box-shadow: 0 8px 24px rgb(0 0 0 / .12);
  }
}

/* Baris barang */
.inv-item { align-items: center; }

.inv-item__foto {
  width: 56px; height: 56px; flex: 0 0 56px;
  border-radius: var(--r-md);
  background: var(--c-surface-alt);
  border: 1px solid var(--c-border);
  color: var(--c-text-muted);
  display: flex; align-items: center; justify-content: center;
  overflow: hidden;
}

.inv-item__foto img { width: 100%; height: 100%; object-fit: cover; }

/* Pilihan kondisi pada form — badge yang dapat diklik, tetap radio asli */
.inv-kondisi { display: flex; gap: var(--sp-2); flex-wrap: wrap; }

.inv-kondisi__pilihan {
  display: inline-flex; align-items: center; gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-3);
  border: 1px solid var(--c-border);
  border-radius: var(--r-md);
  cursor: pointer;
}

.inv-kondisi__pilihan input { width: 18px; height: 18px; }
.inv-kondisi__pilihan:has(input:checked) { border-color: var(--c-brand); background: var(--c-brand-light); }

/* Catatan penutup */
.inv-catatan {
  display: flex; gap: var(--sp-3);
  padding: var(--sp-4);
  background: var(--c-brand-light);
  border-radius: var(--r-lg);
  color: var(--c-text);
}

.inv-catatan__judul { font-weight: 600; color: var(--c-brand); margin-bottom: var(--sp-1); }

/* --------------------------------- 5d-ter. MODUL 15 — PERSIAPAN AWAL */
/* docs/prd/modul/15-persiapan-awal.md §9. */

.persiapan { background: var(--c-bg); }

.persiapan__kepala {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  background: var(--c-surface);
  border-bottom: 1px solid var(--c-border);
}

.persiapan__merek { display: flex; align-items: center; gap: var(--sp-2); font-size: var(--fs-lg); }

.persiapan__logo {
  display: inline-grid;
  place-items: center;
  width: 36px; height: 36px;
  border-radius: var(--r-md);
  background: var(--c-brand);
  color: var(--c-brand-contrast);
}

/* Lebar dijaga sedang: form ini dibaca berurutan dari atas ke bawah, dan baris
   isian selebar layar desktop memaksa mata melompat jauh antara label dan
   kotaknya. */
.persiapan__isi {
  max-width: 720px;
  margin: 0 auto;
  padding: var(--sp-6) var(--sp-4) var(--sp-10);
}

.persiapan__judul { font-size: var(--fs-2xl); margin: 0 0 var(--sp-2); }

/* Penanda langkah. Menumpuk di layar sempit, berjajar sejak 560px — tiga label
   berdampingan di lebar ponsel akan terpotong sampai tidak terbaca. */
.persiapan__langkah {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  list-style: none;
  margin: 0 0 var(--sp-5);
  padding: 0;
}

@media (min-width: 560px) {
  .persiapan__langkah { flex-direction: row; gap: var(--sp-4); }
  .persiapan__langkah-butir { flex: 1; }
}

.persiapan__langkah-butir {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-3);
  border: 1px solid var(--c-border);
  border-radius: var(--r-md);
  background: var(--c-surface);
  font-size: var(--fs-sm);
  color: var(--c-text-muted);
}

.persiapan__langkah-nomor {
  display: inline-grid;
  place-items: center;
  flex: 0 0 auto;
  width: 24px; height: 24px;
  border-radius: var(--r-full);
  background: var(--c-surface-alt);
  border: 1px solid var(--c-border);
  font-size: var(--fs-xs);
  font-weight: 700;
}

.persiapan__langkah-butir--aktif {
  border-color: var(--c-brand);
  color: var(--c-text);
  font-weight: 600;
}

.persiapan__langkah-butir--aktif .persiapan__langkah-nomor {
  background: var(--c-brand);
  border-color: var(--c-brand);
  color: var(--c-brand-contrast);
}

.persiapan__langkah-butir--selesai { color: var(--c-success-teks); border-color: var(--c-success); }

.persiapan__langkah-butir--selesai .persiapan__langkah-nomor {
  background: var(--c-success);
  border-color: var(--c-success);
  color: #fff;
}

/* Baris aksi: keterangan langkah di kiri, tombol lanjut di kanan. Membungkus di
   layar sempit supaya tombolnya turun utuh, bukan menyempit jadi dua baris teks. */
.persiapan__aksi {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  flex-wrap: wrap;
}

.persiapan__ceklis {
  display: inline-grid;
  place-items: center;
  width: 64px; height: 64px;
  margin-bottom: var(--sp-3);
  border-radius: var(--r-full);
  background: var(--c-success-bg);
  color: var(--c-success-teks);
}

/* ------------------------------------ 5d-bis. MODUL 14 — EKSTRAKURIKULER */
/* docs/prd/modul/14-nilai-ekstrakurikuler.md §9. */

/* Daftar centang peserta. Grid, bukan satu kolom: satu kelas berisi 20-30 siswa,
   dan satu nama per baris memaksa guru menggulir jauh untuk pekerjaan yang
   sebenarnya sekali pandang. */
.pilih-siswa {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--sp-1);
}

@media (min-width: 640px)  { .pilih-siswa { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1024px) { .pilih-siswa { grid-template-columns: repeat(3, 1fr); } }

/* Seluruh baris dapat ditekan, bukan hanya kotak centangnya — kotak 18px adalah
   sasaran sentuh yang jauh di bawah ambang 44px pada layar sentuh. */
.pilih-siswa__butir {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  min-height: var(--tap-min);
  padding: var(--sp-2) var(--sp-3);
  border: 1px solid var(--c-border);
  border-radius: var(--r-md);
  font-size: var(--fs-sm);
  cursor: pointer;
}

.pilih-siswa__butir:hover { border-color: var(--c-brand); background: var(--c-surface-alt); }
.pilih-siswa__butir input { width: 20px; height: 20px; flex: 0 0 auto; }
.pilih-siswa__butir:has(input:checked) { border-color: var(--c-brand); background: var(--c-brand-light); }
.pilih-siswa__butir:has(input:focus-visible) { outline: 2px solid var(--c-brand); outline-offset: 2px; }

.pilih-siswa__nama { display: flex; flex-direction: column; min-width: 0; }

/* Baris kegiatan pada layar kelola: <details> asli, sehingga membuka-menutup
   tetap berfungsi tanpa JavaScript — pola yang sama dengan akordeon Piket. */
.ekskul-baris { border-bottom: 1px solid var(--c-border); }
.ekskul-baris:last-child { border-bottom: 0; }

.ekskul-baris__ringkas {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  min-height: var(--tap-min);
  padding: var(--sp-2) 0;
  cursor: pointer;
}

.ekskul-baris__nama { display: flex; align-items: center; gap: var(--sp-2); font-weight: 600; font-size: var(--fs-sm); }
.ekskul-baris__isi  { padding: var(--sp-2) 0 var(--sp-4); }

/* Tabel penilaian: nomor diulang di dalam sel nama hanya untuk tampilan kartu. */
.tabel-ekskul .ekskul__nama { white-space: normal; }
.tabel-ekskul .ekskul__nama-no { display: none; }
.tabel-ekskul td { vertical-align: top; }
.tabel-ekskul .ekskul__deskripsi { min-height: 44px; }

/* Di layar sempit tabelnya menjadi KARTU PER SISWA — alasan yang sama dengan
   grid Daftar Nilai: tabel berisi textarea adalah yang paling cepat rusak di
   layar ponsel, dan menggesernya menyamping menghilangkan nama siswanya dari
   pandangan tepat saat guru mengetik penilaiannya. Markupnya tetap satu. */
@media (max-width: 767px) {
  .tabel-ekskul,
  .tabel-ekskul tbody,
  .tabel-ekskul tr,
  .tabel-ekskul td { display: block; width: auto; }

  .tabel-ekskul thead { display: none; }
  .tabel-ekskul .ekskul__no { display: none; }

  .tabel-ekskul tr {
    border: 1px solid var(--c-border);
    border-radius: var(--r-md);
    padding: var(--sp-3);
    margin-bottom: var(--sp-3);
    background: var(--c-surface);
  }

  .tabel-ekskul tr:last-child { margin-bottom: 0; }

  .tabel-ekskul tbody td {
    padding: var(--sp-1) 0;
    border-bottom: 0;
    white-space: normal;
  }

  .tabel-ekskul tbody td[data-label]:not(.ekskul__nama)::before {
    content: attr(data-label);
    display: block;
    margin-bottom: var(--sp-1);
    font-size: var(--fs-xs);
    font-weight: 600;
    color: var(--c-text-muted);
    text-transform: uppercase;
    letter-spacing: .03em;
  }

  .tabel-ekskul .ekskul__nama {
    padding: 0 0 var(--sp-3);
    margin-bottom: var(--sp-2);
    border-bottom: 1px solid var(--c-border);
    font-size: var(--fs-base);
    font-weight: 600;
  }

  .tabel-ekskul .ekskul__nama-no { display: inline; color: var(--c-text-muted); margin-right: var(--sp-1); }
}

/* Lembar Nilai Ekstrakurikuler seluruh kegiatan.

   Baris lanjutan seorang siswa kehilangan garis pemisah atasnya, sehingga
   kegiatan-kegiatan milik satu anak terbaca sebagai satu blok. Garis penuh hanya
   muncul di baris pertama tiap siswa — itulah yang menggantikan pengulangan nama
   yang sengaja dikosongkan. */
.tabel-ekskul-cetak .ekskul-cetak__lanjutan > td:first-child,
.tabel-ekskul-cetak .ekskul-cetak__lanjutan > td:nth-child(2) {
  border-bottom-color: transparent;
}

.tabel-ekskul-cetak .ekskul-cetak__awal > td { border-top: 1px solid var(--c-border); }
.tabel-ekskul-cetak tbody tr:first-child > td { border-top: 0; }

@media print {
  /* Satu blok siswa tidak boleh terbelah antar halaman: nama di halaman satu
     dan kegiatannya di halaman dua menghasilkan baris yatim tanpa pemilik. */
  .tabel-ekskul-cetak .ekskul-cetak__awal { break-before: auto; }
  .tabel-ekskul-cetak tr { break-inside: avoid; }
}

/* -------------------------------------------- 5e. MODUL 11 — REKAP & CETAK */
/* docs/prd/modul/11-rekap-dan-cetak.md §4 & §9. */

/* Kartu pilihan jenis laporan — pola yang sama dengan grid Menu */
.rekap-kartu {
  display: flex; flex-direction: column; gap: var(--sp-1);
  text-decoration: none;
  color: inherit;
}

.rekap-kartu:hover { border-color: var(--c-brand); text-decoration: none; }

.rekap-kartu__ikon {
  width: 40px; height: 40px;
  border-radius: var(--r-md);
  background: var(--c-brand-light);
  color: var(--c-brand);
  display: flex; align-items: center; justify-content: center;
  margin-bottom: var(--sp-1);
}

.rekap-kartu__judul { font-weight: 600; }
.rekap-kartu__desk  { font-size: var(--fs-xs); color: var(--c-text-muted); }

/* Pemilih kelas di sudut kanan topbar — hanya guru mata pelajaran (FR-15).
   Sengaja ringkas: kelas adalah KONTEKS laporan, bukan penyaringnya, dan kartu
   selebar halaman untuk satu <select> memakan ruang yang seharusnya milik tabel.
   `flex-shrink: 0` menjaga pemilih tetap utuh saat judul laporan memanjang. */
.pemilih-kelas {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  flex-shrink: 0;
}

/* Melawan `width: 100%` bawaan .select, dan memampatkan padding yang dirancang
   untuk field selebar kartu. Tinggi tetap var(--tap-min): sasaran sentuh tidak
   boleh mengecil hanya karena kendalinya pindah ke topbar. */
.pemilih-kelas__pilih {
  width: auto;
  min-width: 9rem;
  max-width: 12rem;
  padding: var(--sp-2) var(--sp-3);
}

/* Di layar sempit topbar membungkus; pemilih turun ke baris sendiri dan
   dirapatkan ke kanan agar tetap terbaca sebagai kendali, bukan sebagai
   bagian dari judul. */
@media (max-width: 560px) {
  .topbar { flex-wrap: wrap; }
  .pemilih-kelas { margin-left: auto; }
}

/* Satu jurnal pada Rekap Jurnal Mengajar — jangan terpotong antar halaman */
.rekap-jurnal {
  padding: var(--sp-3) 0;
  border-bottom: 1px solid var(--c-border);
  break-inside: avoid;
  page-break-inside: avoid;
}

.rekap-jurnal:last-child { border-bottom: none; }
.rekap-jurnal__kepala   { margin-bottom: var(--sp-2); }
.rekap-jurnal__bagian   { margin-bottom: var(--sp-2); font-size: var(--fs-sm); }

.rekap-jurnal__label {
  font-size: var(--fs-xs);
  font-weight: 600;
  color: var(--c-text-muted);
  text-transform: uppercase;
  letter-spacing: .03em;
}

/* -------------------------------------------- 5f. MODUL 14 — PENGATURAN */
/* docs/prd/modul/14-pengaturan.md §9. Mengikuti konsep desain: kartu profil,
   lalu daftar menu berkelompok dengan "Keluar" merah di paling bawah. */

/* Kartu profil */
.set-profil {
  display: flex; align-items: center; gap: var(--sp-3);
  text-decoration: none; color: inherit;
  margin-bottom: var(--sp-4);
}

.set-profil:hover { border-color: var(--c-brand); text-decoration: none; }

.set-profil__foto { flex: 0 0 64px; }

.set-profil__foto img {
  width: 64px; height: 64px;
  border-radius: 50%;
  object-fit: cover;
  border: 2px solid var(--c-brand-light);
}

.set-profil__teks  { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1; }
.set-profil__nama  { font-size: var(--fs-lg); font-weight: 600; }
.set-profil__peran { font-size: var(--fs-sm); color: var(--c-brand); font-weight: 500; }

.set-profil__email {
  font-size: var(--fs-sm); color: var(--c-text-muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* Judul kelompok menu */
.set-judul {
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--c-text-muted);
  margin: var(--sp-4) 0 var(--sp-2);
}

/* Kelompok menu — kartu tunggal berisi beberapa baris bergaris pemisah */
.set-grup {
  background: var(--c-surface);
  border: 1px solid var(--c-border);
  border-radius: var(--r-lg);
  overflow: hidden;
}

.set-baris {
  display: flex; align-items: center; gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  border-bottom: 1px solid var(--c-border);
  text-decoration: none;
  color: inherit;
  background: none;
  border-left: none; border-right: none; border-top: none;
  width: 100%;
  text-align: left;
  font: inherit;
  cursor: pointer;
}

.set-grup > *:last-child .set-baris,
.set-grup > .set-baris:last-child { border-bottom: none; }

.set-baris:hover { background: var(--c-surface-alt); text-decoration: none; }

.set-baris__ikon {
  width: 36px; height: 36px; flex: 0 0 36px;
  border-radius: var(--r-md);
  background: var(--c-brand-light);
  color: var(--c-brand);
  display: flex; align-items: center; justify-content: center;
}

.set-baris__teks  { display: flex; flex-direction: column; gap: 1px; min-width: 0; flex: 1; }
.set-baris__judul { font-weight: 500; }

.set-baris__sub {
  font-size: var(--fs-xs); color: var(--c-text-muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* Baris "Keluar" — satu-satunya aksi merusak di layar ini, jadi dibedakan */
.set-baris--danger .set-baris__ikon { background: var(--c-danger-bg); color: var(--c-danger); }
.set-baris--danger .set-baris__judul { color: var(--c-danger); }

/* Pilihan radio/checkbox bergaya kartu */
.set-pilihan { display: flex; flex-direction: column; gap: var(--sp-2); }

.set-pilihan__item {
  display: flex; align-items: center; gap: var(--sp-3);
  padding: var(--sp-3);
  border: 1px solid var(--c-border);
  border-radius: var(--r-md);
  cursor: pointer;
}

.set-pilihan__item input { width: 18px; height: 18px; flex: 0 0 18px; }
.set-pilihan__item:has(input:checked) { border-color: var(--c-brand); background: var(--c-brand-light); }

/* Logo pada layar Tentang Aplikasi */
.set-logo {
  width: 72px; height: 72px;
  margin: 0 auto var(--sp-3);
  border-radius: var(--r-lg);
  background: var(--c-brand-light);
  color: var(--c-brand);
  display: flex; align-items: center; justify-content: center;
}

/* Layar cetak jurnal — jarak versi layar; versi padatnya ada di @media print */
/* ---- Kop surat sekolah (layouts/print.php) ----
   Identitas lembaga di puncak setiap dokumen cetak. Rata tengah mengikuti
   bentuk kop surat sekolah pada umumnya, sekaligus sebaris dengan judul laporan
   di bawahnya yang juga rata tengah. */
.kop-surat {
  text-align: center;
  padding-bottom: var(--sp-3);
  margin-bottom: var(--sp-5);
  border-bottom: 2px solid var(--c-text);
}

.kop-surat__sekolah {
  margin: 0 0 var(--sp-1);
  font-size: var(--fs-xl);
  line-height: var(--lh-tight);
  text-transform: uppercase;
  letter-spacing: .02em;
}

.kop-surat__baris {
  margin: 0;
  font-size: var(--fs-sm);
  line-height: 1.45;
}

@media print {
  /* Kop mengulang di tiap halaman tidak diinginkan — laporan panjang seperti
     Daftar Hadir memakan beberapa lembar, dan kop kedua di tengah tumpukan
     terbaca sebagai dokumen baru. */
  .kop-surat { break-after: avoid; page-break-after: avoid; }
}

.jurnal-cetak__bagian {
  margin-bottom: var(--sp-5);
  break-inside: avoid;
  page-break-inside: avoid;
}

.jurnal-cetak__judul {
  font-size: var(--fs-base);
  border-bottom: 1px solid var(--c-border);
  padding-bottom: var(--sp-1);
  margin-bottom: var(--sp-2);
}

.jurnal-cetak__ttd {
  margin-top: var(--sp-10);
  display: flex;
  justify-content: flex-end;
  break-inside: avoid;
  page-break-inside: avoid;
}

.jurnal-cetak__ruang-ttd { height: 70px; }

/* ----------------------------------------------------------------- 6. CETAK */
/* Layout cetak A4 untuk modul Rekap dan Cetak (docs/prd/modul/13-rekap-dan-cetak.md) */
@media print {
  :root { --c-bg: #fff; --c-surface: #fff; --c-text: #000; --c-border: #999; }

  .sidebar, .bottomnav, .topbar, .btn, .toast-area, .no-print { display: none !important; }

  body { background: #fff; font-size: 11pt; }

  .main { margin: 0; padding: 0; max-width: none; }

  /* Cangkang kembali satu kolom saat dicetak: kolom sidebar sudah disembunyikan
     di atas, dan grid dua kolom yang menyisakan track kosong selebar 264px
     memotong lebar kertas tanpa alasan. */
  .app-shell:not(.adm-panel) {
    display: block;
    max-width: none;
    padding: 0;
    margin: 0;
  }

  /* Kartu merek: latarnya gradien, dan peramban TIDAK mencetak latar pada
     setelan bawaan. Tanpa aturan ini teksnya yang putih jatuh di atas kertas
     putih dan seluruh isinya hilang. Aturan cetak kartu dashboard selengkapnya
     ada di blok @media print di akhir berkas — harus di sana agar menang
     cascade atas definisi `.dash`. */
  .card--brand { color: #000; border: 1px solid #999; }

  .card {
    border: 1px solid #999;
    box-shadow: none;
    break-inside: avoid;
    page-break-inside: avoid;
  }

  .table th, .table td { border-bottom: 1px solid #999; white-space: normal; }

  /* Cetak jurnal harus muat satu lembar A4. Jarak antarbagian dan ruang tanda
     tangan dipadatkan khusus saat mencetak — di layar tetap lega. */
  .jurnal-cetak__bagian    { margin-bottom: var(--sp-3); }
  .jurnal-cetak__judul     { margin-bottom: var(--sp-1); }
  .jurnal-cetak__ttd       { margin-top: var(--sp-5); }
  .jurnal-cetak__ruang-ttd { height: 48px; }

  a { color: #000; text-decoration: none; }

  @page { size: A4; margin: 1.5cm; }
}

/* Hormati preferensi pengguna yang mengurangi animasi */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    transition-duration: .01ms !important;
  }
}

/* ------------------------------------------------- 14. HALAMAN MASUK (AUTH) */
/* Tata letak dua panel: panel merek berlengkung di kiri, kartu masuk di kanan.
   Panel kiri sepenuhnya dekoratif — pada layar < 900px ia dibuang dan digantikan
   kop ringkas di dalam kolom kartu, sehingga tidak ada konten yang hilang. */

.auth-body {
  min-height: 100vh;
  min-height: 100dvh;
  background: var(--c-bg);
}

.auth {
  position: relative;
  display: grid;

  /* `minmax(0, 1fr)`, bukan `1fr`. Nilai `1fr` sama dengan `minmax(auto, 1fr)`:
     kolom kiri menolak menyusut di bawah lebar min-content isinya, lalu memakan
     jatah kolom kanan — pada lebar 961px kartu tinggal 330px, bukan separuh. */
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  align-items: start;
  min-height: 100vh;
  min-height: 100dvh;

  /* HARUS `overflow-x: clip`, BUKAN `overflow: hidden`. Nilai `hidden` menjadikan
     elemen ini scroll container, dan scroll container adalah scrollport bagi
     anaknya yang `position: sticky` — panel merek pun berhenti menempel karena
     induknya sendiri tidak pernah tergulir. `clip` memangkas tanpa membuat
     scroll container, sehingga sticky tetap mengacu ke viewport. */
  overflow-x: clip;
}

/* Panel promosi MENEMPEL selama halaman digulir. Halaman kebijakan privasi dan
   pemasang jauh lebih tinggi dari satu layar; tanpa sticky + tinggi tetap, panel
   ini meregang mengikuti tinggi dokumen dan isinya terlempar jauh dari kartu. */
.auth__promo {
  grid-column: 1;
  grid-row: 1;
  position: sticky;
  top: 0;
  z-index: 1;
  display: flex;
  align-items: center;
  height: 100vh;
  height: 100dvh;
  padding: var(--sp-8) clamp(var(--sp-5), 3.5vw, var(--sp-10));
}

/* Titik-titik hiasan di sudut kanan atas, mengikuti referensi desain. Digambar
   sebagai pseudo-element karena murni ornamen dan tidak pantas menempati pohon
   dokumen. `radial-gradient` berulang, bukan berkas gambar: nol permintaan. */
.auth__promo::after {
  content: '';
  position: absolute;
  top: clamp(var(--sp-5), 4vh, var(--sp-10));
  right: clamp(-2rem, -1vw, 0rem);
  width: 108px;
  height: 78px;
  background-image: radial-gradient(var(--c-border) 1.7px, transparent 1.8px);
  background-size: 18px 16px;
  pointer-events: none;
}

.promo {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: 34rem;
  margin-left: auto;
}

.promo__pil {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  margin: 0 0 var(--sp-5);
  padding: var(--sp-2) var(--sp-4);
  border-radius: var(--r-full);
  background: var(--c-brand-light);
  color: var(--c-brand);
  font-size: var(--fs-xs);
  font-weight: 600;
}

.promo__judul {
  margin: 0 0 var(--sp-4);
  font-size: clamp(1.6rem, 2.9vw, 2.4rem);
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: -.02em;
}

/* Garis emas di bawah frasa yang ditekankan. Digambar sebagai gradient pada
   background, bukan border-bottom: border akan selebar seluruh baris terakhir,
   sedangkan yang diinginkan hanya selebar teksnya sendiri. */
.promo__tekan {
  color: var(--c-brand);
  background-image: linear-gradient(var(--c-accent), var(--c-accent));
  background-size: 100% 3px;
  background-position: 0 100%;
  background-repeat: no-repeat;
  padding-bottom: 2px;
}

.promo__lead {
  margin: 0 0 var(--sp-6);
  max-width: 30rem;
  font-size: var(--fs-sm);
  line-height: var(--lh-base);
  color: var(--c-text-muted);
}

.promo__fitur {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));

  /* Tanpa ini tiap baris menghitung tingginya sendiri, dan baris kedua tumbuh
     ~18px lebih tinggi begitu keterangannya membungkus — enam kartu sejenis
     yang tingginya berbeda terbaca sebagai kesalahan tata letak. */
  grid-auto-rows: 1fr;
  gap: var(--sp-3);
  margin: 0 0 var(--sp-4);
  padding: 0;
  list-style: none;
}

.promo__kartu {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-3);
  padding: var(--sp-3);
  border: 1px solid var(--c-border);
  border-radius: var(--r-md);
  background: var(--c-surface);
}

.promo__kartu-ikon {
  display: grid;
  place-items: center;
  flex: none;
  width: 34px;
  height: 34px;
  border-radius: var(--r-sm);
  background: var(--c-brand-light);
  color: var(--c-brand);
}

.promo__kartu-judul { display: block; font-size: var(--fs-sm); font-weight: 600; line-height: 1.25; }
.promo__kartu-ket   { display: block; margin-top: 2px; font-size: var(--fs-xs); color: var(--c-text-muted); }

.promo__aman {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-4);
  border: 1px solid var(--c-brand);
  border-radius: var(--r-md);
  background: var(--c-brand-light);
}

.promo__aman-ikon {
  display: grid;
  place-items: center;
  flex: none;
  width: 44px;
  height: 44px;
  border-radius: var(--r-full);
  background: var(--c-brand);
  color: var(--c-brand-contrast);
}

.promo__aman-judul { display: block; font-size: var(--fs-sm); font-weight: 700; color: var(--c-brand-dark); }
.promo__aman-ket   { display: block; margin-top: 2px; font-size: var(--fs-xs); color: var(--c-text-muted); }

/* Slogan bergaya tulisan tangan. TIDAK memakai webfont: arsitektur mengunci
   `font-src 'self'` dan menambah berkas font ratusan KB hanya untuk dua baris
   hiasan bertentangan dengan target muat < 2 detik. Dipakai tumpukan font tulis
   bawaan sistem; bila tak satu pun tersedia, italic tetap membedakannya dari
   teks lain — jadi maknanya tidak pernah bergantung pada font yang gagal muat. */
.promo__slogan {
  position: relative;
  margin: var(--sp-8) 0 0;
  padding-bottom: var(--sp-4);
  font-family: 'Segoe Script', 'Bradley Hand', 'Brush Script MT', cursive;
  font-style: italic;
  font-size: clamp(1.05rem, 1.6vw, 1.35rem);
  font-weight: 600;
  line-height: 1.55;
  color: var(--c-brand-dark);
}

.promo__coret {
  display: block;
  width: min(20rem, 78%);
  height: 14px;
  margin-top: var(--sp-1);
  overflow: visible;
}

.promo__coret path { stroke: var(--c-brand); }

/* Ombak berwarna merek di dasar halaman. `position: fixed` supaya ia tetap di bawah
   layar pada halaman yang panjang (kebijakan privasi, pemasang) alih-alih ikut
   tergulir ke tengah teks. */
.auth__ombak {
  position: fixed;
  right: 0;
  bottom: 0;
  z-index: 0;
  width: 100%;
  height: min(42vh, 380px);
  pointer-events: none;
}

.auth__ombak-1 { fill: var(--c-brand-light); }
.auth__ombak-2 { fill: var(--c-brand); opacity: .13; }

/* Kolomnya ditetapkan eksplisit, bukan mengikuti urutan DOM: kartu masuk
   ditulis lebih dulu di markup agar pengguna papan ketik sampai ke formulir
   tanpa menyeberangi materi pemasaran, tetapi tampil di kolom kanan.
   z-index lebih tinggi menjaga kartu tetap di atas ombak latar. */
.auth__panel {
  grid-column: 2;
  grid-row: 1;
  position: relative;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  min-height: 100dvh;
  padding: var(--sp-8) var(--sp-5);
}

.auth__panel-inner { width: 100%; max-width: 27rem; }

/* ---------------------------------------------------------- Kartu masuk */

/* Kop ringkas — hanya tampil saat panel merek disembunyikan. */
.auth-card__brand { display: none; }

.auth-card {
  padding: clamp(var(--sp-6), 4vw, var(--sp-10)) clamp(var(--sp-5), 4vw, var(--sp-8));
  background: var(--c-surface);
  border: 1px solid var(--c-border);
  border-radius: var(--r-xl);
  box-shadow: var(--shadow-lg);
}

.auth-card__avatar {
  display: grid;
  place-items: center;
  width: 76px;
  height: 76px;
  margin: 0 auto var(--sp-5);
  border-radius: var(--r-full);
  background: var(--c-brand-light);
  color: var(--c-brand);
}

.auth-card__title {
  margin: 0 0 var(--sp-2);
  font-size: var(--fs-2xl);
  font-weight: 700;
  text-align: center;
  color: var(--c-brand);
}

.auth-card__subtitle {
  margin: 0 0 var(--sp-6);
  font-size: var(--fs-sm);
  text-align: center;
  color: var(--c-text-muted);
}

/* Bidang dengan ikon di depan (dan tombol di belakang untuk sandi). */
.input-group { position: relative; }

.input-group__icon,
.input-group__toggle {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  display: grid;
  place-items: center;
  color: var(--c-text-muted);
  pointer-events: none;
}

.input-group__icon { left: var(--sp-3); }

.input-group__toggle {
  right: var(--sp-2);
  width: var(--tap-min);
  height: var(--tap-min);
  padding: 0;
  background: none;
  border: 0;
  border-radius: var(--r-md);
  cursor: pointer;
  pointer-events: auto;
}

.input-group__toggle:hover { color: var(--c-text); }
.input-group__toggle:focus-visible { outline: 2px solid var(--c-brand); outline-offset: -2px; }

.input-group__field { padding-left: 2.75rem; }
.input-group__field--trailing { padding-right: 3rem; }

.auth-card__row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  margin-bottom: var(--sp-5);
  font-size: var(--fs-sm);
}

/* Tanpa centang "Ingat email saya" (JS mati), tautan lupa sandi tetap di kanan. */
.auth-card__row > :only-child { margin-left: auto; }

.auth-card__remember {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  margin: 0;
  color: var(--c-text-muted);
  cursor: pointer;
}

.auth-card__remember input { width: 16px; height: 16px; accent-color: var(--c-brand); }

.auth-card__link { color: var(--c-brand); font-weight: 600; }

.auth-card__divider {
  margin: var(--sp-6) 0 var(--sp-5);
  border: 0;
  border-top: 1px solid var(--c-border);
}

/* ---------------------------------------------------- Halaman prosa (dokumen) */
.auth-card--dokumen { text-align: left; }
.auth-card--dokumen .auth-card__avatar { margin-inline: auto; }

.auth-dok { font-size: var(--fs-sm); color: var(--c-text-muted); }
.auth-dok p  { margin: 0 0 var(--sp-4); }
.auth-dok ul { margin: 0 0 var(--sp-4); padding-left: var(--sp-5); }
.auth-dok li { margin-bottom: var(--sp-2); }

.auth-dok h2 {
  margin: var(--sp-6) 0 var(--sp-2);
  font-size: var(--fs-base);
  font-weight: 700;
  color: var(--c-text);
}

.auth-dok h2:first-child { margin-top: 0; }
.auth-dok strong { color: var(--c-text); }
.auth-card__foot {
  margin: 0;
  font-size: var(--fs-sm);
  text-align: center;
  color: var(--c-text-muted);
}

.auth-foot {
  margin-top: var(--sp-6);
  text-align: center;
  font-size: var(--fs-xs);
  color: var(--c-text-muted);
}

.auth-foot__brand { margin: 0 0 var(--sp-1); }
.auth-foot__links { margin: 0; }
.auth-foot__links a { color: var(--c-brand); font-weight: 600; }

/* ------------------------------------------------------------ Responsif */

/* Lengkung memakan ruang teks jauh sebelum tata letaknya benar-benar sempit,
   jadi panel merek dilepas pada 900px — bukan pada breakpoint mobile biasa. */
/* Lambang + wordmark di kepala kartu masuk. */
.auth-card__logo { text-align: center; margin-bottom: var(--sp-5); }

.auth-card__logo-badge {
  display: inline-grid;
  place-items: center;
  width: 60px;
  height: 60px;
  border-radius: var(--r-lg);
  background: var(--c-brand);
  color: var(--c-brand-contrast);
}

.auth-card__wordmark {
  margin: var(--sp-2) 0 0;
  font-size: var(--fs-xl);
  font-weight: 800;
  letter-spacing: -.01em;
}

.auth-card__wordmark span { color: var(--c-brand); }

/* ---------------------------------------------- Kartu masuk (varian utama) */
/* Kartu masuk diberi napas lebih longgar daripada kartu auth lain: ia satu-
   satunya layar yang dilihat setiap hari, dan mengikuti proporsi rancangan. */
.auth-card--masuk { padding-block: clamp(var(--sp-8), 5vw, var(--sp-10)); }

.auth-card--masuk .auth-card__title {
  font-size: clamp(1.75rem, 3vw, 2.25rem);
  letter-spacing: -.01em;
}

.auth-card--masuk .auth-card__subtitle { margin-bottom: var(--sp-8); }
.auth-card--masuk .field { margin-bottom: var(--sp-5); }
.auth-card--masuk .label { font-weight: 600; }

.auth-card--masuk .input-group__field {
  min-height: 52px;
  border-radius: var(--r-md);
}

.btn--lg { min-height: 52px; font-size: var(--fs-base); }

/* Baris versi: merek, nomor versi, lalu tautan kebijakan. Nomor versinya nyata
   (Pengaturan::VERSI), bukan angka hias — supaya guru dapat menyebutkannya saat
   melapor kendala. */
.auth-card__versi {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: var(--sp-2);
  margin: 0 0 var(--sp-3);
  font-size: var(--fs-xs);
  color: var(--c-text-muted);
}

.auth-card__lencana {
  padding: 2px var(--sp-2);
  border-radius: var(--r-full);
  background: var(--c-brand-light);
  color: var(--c-brand);
  font-weight: 700;
}

.auth-card__pemisah { color: var(--c-border); }
.auth-card__versi a { color: var(--c-brand); font-weight: 600; }

@media (max-width: 900px) {
  .auth { grid-template-columns: 1fr; }
  .auth__promo { display: none; }
  .auth__panel { grid-column: 1; }
  .auth__ombak { height: 30vh; }
  .auth__panel { min-height: 0; padding: var(--sp-6) var(--sp-4); }

  .auth-card__brand {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--sp-3);
    margin-bottom: var(--sp-5);
  }

  .auth-card__brand-badge {
    display: grid;
    place-items: center;
    width: 44px;
    height: 44px;
    border-radius: var(--r-md);
    background: var(--c-brand);
    color: var(--c-accent);
  }

  .auth-card__brand-name {
    font-size: var(--fs-lg);
    font-weight: 700;
    color: var(--c-brand);
  }
}

/* Layar sangat pendek (jendela desktop yang dipendekkan, HP mendatar): panel
   pratinjau dikunci setinggi layar, jadi isinya yang harus menyusut — bukan
   panelnya yang memanjang, karena elemen sticky lebih tinggi dari viewport
   berhenti menempel dan malah ikut tergulir. */
@media (max-height: 700px) {
  .auth { min-height: 0; }
  .auth__panel { min-height: 0; padding-block: var(--sp-6); }
  .promo__slogan { display: none; }
  .promo__lead { margin-bottom: var(--sp-4); }
  .promo__judul { margin-bottom: var(--sp-3); }
}

/* ==========================================================================
   Modul 15 — Struktur Organisasi Kelas
   ========================================================================== */

/* ------------------------------------------------------------ Kartu kepala */
.struktur-kepala {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  flex-wrap: wrap;
}

.struktur-kepala__ikon {
  display: grid;
  place-items: center;
  flex: none;
  width: 56px;
  height: 56px;
  border-radius: var(--r-full);
  color: var(--c-brand-contrast);
  background: var(--c-brand);
}

.struktur-kepala__teks { flex: 1 1 12rem; min-width: 0; }

.struktur-kepala__nama {
  font-size: var(--fs-lg);
  font-weight: 700;
  line-height: var(--lh-tight);
}

/* ------------------------------------------------------------ Banner info */
.callout {
  display: flex;
  gap: var(--sp-3);
  padding: var(--sp-4);
  font-size: var(--fs-sm);
  color: var(--c-text-muted);
  background: var(--c-brand-light);
  border-radius: var(--r-lg);
}

.callout__ikon { flex: none; color: var(--c-brand); }
.callout__judul { margin-bottom: var(--sp-1); font-weight: 700; color: var(--c-text); }

/* ------------------------------------------------------------ Bagan pohon */
.bagan {
  display: flex;
  flex-direction: column;
  align-items: center;
  margin-bottom: var(--sp-8);
}

.bagan__tingkat { display: flex; justify-content: center; }

/* Penghubung antar tingkat. Elemen tersendiri, bukan margin, supaya tingginya
   dapat disamakan persis dengan cabang di bawahnya. */
.bagan__garis {
  width: 2px;
  height: 22px;
  background: var(--c-border);
}

.bagan__cabang {
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
  gap: 0;                 /* WAJIB 0 — lihat catatan pada .bagan__sel */
  width: 100%;
}

/* Jarak antar kotak berupa padding DI DALAM sel, bukan gap pada flex: garis
   horizontal cabang digambar sepanjang sel, sehingga celah gap akan
   memutusnya menjadi potongan-potongan yang menggantung. */
.bagan__sel {
  position: relative;
  flex: 1 1 0;
  min-width: 0;
  padding: 22px var(--sp-2) 0;
}

/* Ruas horizontal — separuh kiri & kanan tiap sel, ujung terluarnya dipangkas. */
.bagan__sel::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 2px;
  background: var(--c-border);
}

.bagan__sel:first-child::before { left: 50%; }
.bagan__sel:last-child::before  { right: 50%; }
.bagan__sel:only-child::before  { display: none; }

/* Ruas vertikal yang turun dari garis horizontal ke tiap kotak. */
.bagan__sel::after {
  content: '';
  position: absolute;
  top: 0;
  left: calc(50% - 1px);
  width: 2px;
  height: 22px;
  background: var(--c-border);
}

.bagan-kotak {
  position: relative;
  padding: var(--sp-6) var(--sp-4) var(--sp-4);
  min-width: 0;
  text-align: center;
  background: var(--c-surface);
  border: 1px solid var(--c-border);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-sm);
}

.bagan__tingkat .bagan-kotak { min-width: min(17rem, 100%); }

/* Badge menumpang di garis atas kotak, separuh di luar separuh di dalam. */
.bagan-kotak__badge {
  position: absolute;
  top: 0;
  left: 50%;
  transform: translate(-50%, -50%);
  display: inline-block;
  max-width: calc(100% - var(--sp-4));
  padding: 3px var(--sp-3);
  font-size: 0.625rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  color: var(--c-brand-contrast);
  background: var(--c-brand);
  border-radius: var(--r-sm);
}

.bagan-kotak__nama {
  font-weight: 700;
  line-height: var(--lh-tight);
  overflow-wrap: anywhere;
}

.bagan-kotak__peran {
  margin-top: var(--sp-1);
  font-size: var(--fs-sm);
  color: var(--c-text-muted);
}

/* ------------------------------------------------------------ Daftar anggota */
.struktur-judul {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  margin-bottom: var(--sp-3);
  font-size: var(--fs-lg);
}

.struktur-judul svg { color: var(--c-brand); }

/* Satu grid, DUA LAJUR, diisi menurun (`grid-auto-flow: column`).
   Jumlah barisnya dikirim view lewat --baris karena hanya PHP yang tahu berapa
   siswanya. Bentuk inilah yang membuat baris ke-n kiri dan kanan berbagi baris
   grid yang sama, sehingga nama yang membungkus dua baris tidak menggeser lajur
   sebelahnya menjadi tidak sejajar. */
.struktur-anggota {
  display: grid;
  grid-auto-flow: column;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  grid-template-rows: repeat(var(--baris, 1), auto);
  gap: 0 var(--sp-5);
  margin: 0;
  padding: 0;
  list-style: none;
  counter-reset: anggota;
}

.struktur-anggota li {
  display: flex;
  gap: var(--sp-3);
  align-items: baseline;
  padding: var(--sp-3) 0;
  border-bottom: 1px solid var(--c-border);
  overflow-wrap: anywhere;
}

.struktur-anggota li:last-child { border-bottom: 0; }

/* Nomor memakai counter, bukan angka di markup: dua kolom harus menyambung
   (1–12 lalu 13–23), dan atribut `start` pada <ol> sudah menanganinya. */
.struktur-anggota li::before {
  content: counter(anggota);
  counter-increment: anggota;
  flex: none;
  min-width: 1.5rem;
  font-size: var(--fs-sm);
  font-variant-numeric: tabular-nums;
  color: var(--c-brand);
}

/* Dua lajur dipertahankan sampai layar HP tersempit — itulah bentuk yang
   dirancang. Nama Indonesia kerap panjang, jadi yang menyusut adalah ukuran
   huruf dan jaraknya, bukan jumlah lajurnya. */
@media (max-width: 560px) {
  .struktur-anggota { gap: 0 var(--sp-3); }
  .struktur-anggota li { font-size: var(--fs-sm); }
  .struktur-anggota li::before { min-width: 1.25rem; }
}

/* Di bawah lebar ini dua lajur sudah tidak terbaca. */
@media (max-width: 340px) {
  .struktur-anggota {
    grid-auto-flow: row;
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: none;
  }
}

/* Empat kotak berjajar tidak muat di layar HP. Menjadi dua lajur, dan garis
   cabangnya dilepas — garis yang terputus karena wrap justru menyesatkan,
   seolah ada hubungan yang tidak ada. */
@media (max-width: 720px) {
  .bagan__cabang {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--sp-3);
  }

  .bagan__sel { padding: 0; }
  .bagan__sel::before,
  .bagan__sel::after { display: none; }
}

/* Empat kotak sejajar mustahil di layar sempit, tetapi 2×2 masih terbaca dan
   itulah susunan yang dirancang — baru di bawah 320px ia menjadi satu lajur. */
@media (max-width: 320px) {
  .bagan__cabang { grid-template-columns: minmax(0, 1fr); }
}

/* ==========================================================================
   Bagan struktur organisasi untuk CETAK (Modul 13 FR-13)
   --------------------------------------------------------------------------
   Setiap garis penghubung di sini adalah ELEMEN NYATA ber-`border`, bukan
   pseudo-element ber-`background`. Alasannya tunggal dan menentukan: hampir
   semua peramban mematikan pencetakan latar belakang secara bawaan, sehingga
   bagan berbasis background tercetak sebagai kotak-kotak melayang tanpa garis.
   Border selalu ikut tercetak.

   Warna pun hanya dipakai pada border dan teks — tidak pernah sebagai isian —
   supaya hasilnya utuh baik di printer hitam-putih maupun berwarna.
   ========================================================================== */

.cbagan {
  --cbagan-garis: 1.5px solid var(--c-brand-dark);

  display: flex;
  flex-direction: column;
  align-items: center;
  margin-bottom: var(--sp-8);
  text-align: center;
}

/* Ruas vertikal: div tanpa lebar, hanya border kiri. */
.cbagan__turun {
  width: 0;
  height: 18px;
  border-left: var(--cbagan-garis);
}

.cbagan__turun--pendek { height: 14px; margin: 0 auto; }

/* Palang mendatar penghubung cabang. Margin kiri/kanan diisi view sebesar
   setengah sel, supaya palang berhenti tepat di pusat kotak terluar dan tidak
   menjulur ke ruang kosong. */
.cbagan__palang {
  width: auto;
  align-self: stretch;
  height: 0;
  border-top: var(--cbagan-garis);
}

.cbagan__cabang {
  display: grid;
  grid-template-columns: repeat(var(--kolom, 4), minmax(0, 1fr));
  width: 100%;
}

.cbagan__sel {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 0 var(--sp-2);
  min-width: 0;
}

.cbagan__kotak {
  display: flex;
  flex-direction: column;
  gap: 2px;
  width: 100%;
  padding: var(--sp-3) var(--sp-2);
  border: 1.5px solid var(--c-brand-dark);
  border-radius: var(--r-md);
  break-inside: avoid;
  page-break-inside: avoid;
}

.cbagan__kotak--puncak { width: auto; min-width: 15rem; max-width: 100%; }

.cbagan__jabatan {
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--c-brand-dark);
}

.cbagan__nama {
  font-weight: 700;
  line-height: var(--lh-tight);
  overflow-wrap: anywhere;
}

.cbagan__kosong { text-align: center; color: var(--c-text-muted); }

.cbagan__judul-anggota {
  margin-bottom: var(--sp-3);
  padding-bottom: var(--sp-2);
  border-bottom: 1.5px solid var(--c-brand-dark);
  text-align: center;
}

.cbagan__anggota {
  columns: 3;
  column-gap: var(--sp-6);
  margin: 0;
  padding-left: var(--sp-6);
}

.cbagan__anggota li {
  break-inside: avoid;
  padding: 3px 0;
  overflow-wrap: anywhere;
}

/* Pratinjau di layar sempit: empat kotak sejajar tidak muat, dan palangnya
   akan menggantung di atas kotak yang sudah pindah baris — jadi cabang menjadi
   satu lajur dan seluruh garisnya dilepas. Hasil CETAK tidak terpengaruh:
   kertas A4 selalu lebih lebar dari ambang ini. */
@media screen and (max-width: 640px) {
  .cbagan__cabang { grid-template-columns: minmax(0, 1fr); gap: var(--sp-3); }
  .cbagan__palang { display: none; }
  .cbagan__turun--pendek { display: none; }
  .cbagan__anggota { columns: 2; }
}

@media print {
  /* Dua kotak puncak dibesarkan karena merekalah yang dibaca dari jauh saat
     dipajang; empat kotak pengurus dibiarkan 10pt supaya nama tiga kata muat
     dalam satu sel selebar ±4 cm tanpa membungkus berlebihan. */
  .cbagan__kotak--puncak .cbagan__nama { font-size: 13pt; }
  .cbagan__nama          { font-size: 10pt; }
  .cbagan__jabatan       { font-size: 7.5pt; }
  .cbagan__judul-anggota { font-size: 12pt; }
  .cbagan__anggota       { font-size: 10.5pt; }

  /* Dipadatkan agar bagan + daftar anggota muat SATU lembar A4 dengan sisa
     ruang memadai. Tanpa pemadatan ini sisanya hanya ~7px, sehingga satu nama
     panjang saja sudah mendorong daftar anggota ke halaman kedua — dan poster
     dinding yang terpotong dua halaman kehilangan gunanya. */
  .cbagan                { margin-bottom: var(--sp-5); }
  .cbagan__turun         { height: 12px; }
  .cbagan__turun--pendek { height: 10px; }
  .cbagan__kotak         { padding: var(--sp-2); }
  .cbagan__judul-anggota { margin-bottom: var(--sp-2); }
  .cbagan__anggota li    { padding: 1px 0; }

  .cbagan { break-inside: avoid; page-break-inside: avoid; }

  /* Kotak berlatar putih tegas: bila pengguna MENGAKTIFKAN pencetakan latar
     belakang, kotak tidak boleh ikut mewarisi latar apa pun dari kartu induk. */
  .cbagan__kotak { background: #fff; }
}

/* ==========================================================================
   Formulir Daftar Hadir Bulanan (Modul 13 FR-14)
   ========================================================================== */

.hadir {
  table-layout: fixed;
  width: 100%;
  font-size: var(--fs-xs);
  border-collapse: collapse;
}

.hadir th,
.hadir td {
  padding: 2px 1px;
  text-align: center;
  border: 1px solid var(--c-border);
  white-space: nowrap;
}

.hadir__no   { width: 2.2rem; }
.hadir__nama { width: 11rem; text-align: left; white-space: normal; padding-left: var(--sp-2); }

/* Kolom tanggal dibiarkan menyusut serata mungkin; `table-layout: fixed`
   membuat lebarnya dibagi rata tanpa dipengaruhi panjang isi tiap sel. */
.hadir__hari { width: auto; font-weight: 700; }
.hadir__ket  { width: 1.6rem; font-weight: 700; }

/* Minggu ditandai lewat WARNA TEKS, bukan latar: latar belakang tidak ikut
   tercetak pada setelan bawaan peramban, sehingga penanda berbasis latar
   hilang justru di kertas — tempat penanda itu paling dibutuhkan.
   Selektornya WAJIB menyertakan `th`: `.table th` sudah menetapkan warna dan
   spesifisitasnya (0,1,1) mengalahkan kelas tunggal (0,1,0). */
.hadir th.hadir__hari--ahad { color: var(--c-danger); }

.hadir__sel { font-weight: 700; }
.hadir__sel--hadir  { color: var(--c-text-muted); font-weight: 400; }
.hadir__sel--sakit  { color: var(--c-info); }
.hadir__sel--izin   { color: var(--c-warning); }
.hadir__sel--alpa   { color: var(--c-danger); }

.hadir__nonaktif { color: var(--c-text-muted); font-size: 0.9em; }

.hadir__legenda {
  display: flex;
  gap: var(--sp-4);
  flex-wrap: wrap;
  margin-top: var(--sp-3);
  font-size: var(--fs-xs);
  color: var(--c-text-muted);
}

@media print {
  /* Kertas lanskap A4 memberi ±27,7 cm lebar cetak. Dengan 31 kolom tanggal,
     tiap kolom tinggal ±5 mm — cukup untuk satu huruf, tidak lebih. Ukuran
     huruf dikecilkan agar angka tanggal tetap muat tanpa membungkus. */
  .hadir { font-size: 7pt; }
  .hadir th, .hadir td { padding: 1px 0; border-color: #000; }
  .hadir__nama { width: 9rem; font-size: 8pt; }
  .hadir__no   { width: 1.8rem; }

  /* Baris tidak boleh terbelah antar halaman; nama siswa di halaman berikutnya
     tanpa kolom tanggalnya tidak berarti apa-apa. */
  .hadir tr { break-inside: avoid; page-break-inside: avoid; }
  .hadir thead { display: table-header-group; }

  .hadir__legenda { font-size: 7pt; margin-top: var(--sp-2); }
}

/* ==========================================================================
   Rekap Absen Siswa per semester (Modul 13 FR-1)
   ========================================================================== */

.rabsen { table-layout: fixed; width: 100%; font-size: var(--fs-xs); }

.rabsen th,
.rabsen td {
  padding: 3px 2px;
  text-align: center;
  border: 1px solid var(--c-border);
  white-space: nowrap;
}

.rabsen__no   { width: 2.4rem; }
.rabsen__nama { width: 12rem; text-align: left; white-space: normal; padding-left: var(--sp-2); }
.rabsen__kode { width: 1.6rem; font-weight: 700; }

.rabsen__bulan { font-weight: 700; }

/* Kelompok Jumlah dipisahkan garis tebal di sisi kirinya, bukan latar berwarna:
   latar tidak ikut tercetak pada setelan bawaan peramban. */
.rabsen__bulan--jumlah,
.rabsen__sel--jumlah { border-left-width: 2px; font-weight: 700; }

.rabsen__nonaktif { color: var(--c-text-muted); font-size: 0.9em; }

@media print {
  .rabsen { font-size: 8pt; }
  .rabsen th, .rabsen td { padding: 2px 1px; border-color: #000; }
  .rabsen__nama { width: 10rem; }
  .rabsen tr { break-inside: avoid; page-break-inside: avoid; }
  .rabsen thead { display: table-header-group; }
}

/* ==========================================================================
   Jadwal Pelajaran siap pajang (Modul 13 FR-15)
   ========================================================================== */

.jdw { table-layout: fixed; width: 100%; }

.jdw th,
.jdw td {
  padding: var(--sp-3) var(--sp-2);
  text-align: center;
  vertical-align: middle;
  border: 1px solid var(--c-border);
}

/* Kolom jam sempit dan tetap; enam kolom hari membagi sisanya rata sehingga
   lebar tiap hari tidak berubah-ubah mengikuti panjang nama mapel. */
.jdw__jam { width: 5.5rem; white-space: nowrap; }

.jdw__jam-mulai,
.jdw__jam-selesai { display: block; line-height: 1.2; }
.jdw__jam-selesai { font-weight: 400; font-size: var(--fs-xs); color: var(--c-text-muted); }

.jdw__hari { font-weight: 700; }

.jdw__mapel {
  display: block;
  font-weight: 600;
  line-height: var(--lh-tight);
  overflow-wrap: anywhere;
}

.jdw__ruang {
  display: block;
  margin-top: 2px;
  font-size: var(--fs-xs);
  color: var(--c-text-muted);
}

/* Sel kosong ditandai garis miring tipis, bukan latar abu: latar tidak ikut
   tercetak pada setelan bawaan peramban, sehingga jam kosong akan tampak sama
   persis dengan jam terisi yang namanya kebetulan pendek. */
.jdw__sel--kosong {
  background-image: linear-gradient(
    to bottom right,
    transparent calc(50% - 0.5px),
    var(--c-border) calc(50% - 0.5px),
    var(--c-border) calc(50% + 0.5px),
    transparent calc(50% + 0.5px)
  );
}

@media print {
  .jdw th, .jdw td { border-color: #000; }
  .jdw tr { break-inside: avoid; page-break-inside: avoid; }
  .jdw thead { display: table-header-group; }

  /* Garis miring penanda sel kosong berbasis background — pada setelan cetak
     bawaan ia tidak muncul. Itu dapat diterima: sel kosong pada kertas memang
     terbaca sebagai kosong. Yang TIDAK boleh hilang adalah garis kisinya, dan
     itu border. */
}

/* Kolom pertama Jadwal Piket memuat nama tugas, bukan jam — perlu lebih lega
   daripada kolom jam pada Jadwal Pelajaran, dan rata kiri agar nama panjang
   seperti "Merapikan Meja & Kursi" terbaca sebagai satu label. */
.jdw__jam--tugas {
  width: 10rem;
  text-align: left;
  white-space: normal;
}

/* Isi sel Jadwal Piket adalah NAMA LENGKAP SISWA, bukan nama mapel yang pendek.
   Tanpa aturan ini selnya mewarisi white-space: nowrap dari .table, sehingga
   satu "Muhammad Rafi Alfarizi" cukup untuk mendorong kisinya melebar keluar
   layar — overflow-wrap pada .jdw__mapel tidak menolong selama nowrap menang. */
.jdw--piket th,
.jdw--piket td { white-space: normal; }

/* Enam kolom hari plus kolom tugas tidak muat di layar ponsel. Dibiarkan
   menciut, tiap kolom hanya selebar dua-tiga huruf dan namanya terpecah per
   suku kata; lebih baik kisinya menjaga lebar minimum lalu digeser mendatar di
   dalam .table-wrap — bentuk kisi itu sendiri yang jadi isi laporannya. */
.jdw--piket { min-width: 44rem; }

/* Nama tugas adalah ISI laporan, bukan label kolom. Sebagai <th> ia mewarisi
   tampilan .table th — kapital kecil, redup, berjarak huruf — yang membuat
   setiap baris terbaca sebagai judul dan keterangannya nyaris tak terbaca.
   Hanya baris di tbody yang dikembalikan; "Tugas" di thead memang label kolom
   dan harus tetap seragam dengan Senin–Sabtu di sebelahnya. */
.jdw--piket tbody th {
  font-size: var(--fs-sm);
  color: var(--c-text);
  text-transform: none;
  letter-spacing: 0;
}

.jdw--piket tbody th .jdw__jam-selesai { margin-top: 2px; }

/* Satu tugas boleh dipegang beberapa siswa pada hari yang sama. Tanpa jarak,
   dua nama beruntun menempel jadi satu blok yang terbaca sebagai satu nama
   panjang. */
.jdw--piket .jdw__mapel { font-weight: 500; }
.jdw--piket .jdw__mapel + .jdw__mapel { margin-top: var(--sp-2); }

/* ==========================================================================
   Denah Tempat Duduk (Modul 16)
   ========================================================================== */

.denah__papan,
.denah__belakang {
  text-align: center;
  font-size: var(--fs-sm);
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--c-text-muted);
  padding: var(--sp-2);
}

/* Papan tulis digambar sebagai balok bernada merek, bukan sekadar teks: ia
   penanda arah, dan penanda arah harus terlihat lebih dulu daripada isi. */
.denah__papan {
  background: var(--c-brand-light);
  color: var(--c-brand-teks);
  border-radius: var(--r-md);
  margin-bottom: var(--sp-3);
}

.denah__belakang { margin-top: var(--sp-2); opacity: .7; }

/* Jumlah kolom datang dari data lewat --denah-kolom; grid-nya sendiri tidak
   pernah tahu berapa. Tanpa itu, tiap ukuran kisi menuntut kelas CSS-nya
   sendiri — sepuluh kelas untuk sesuatu yang cuma satu angka. */
.denah__gulir { overflow-x: auto; }

/* minmax(5.5rem, 1fr): melebar mengikuti tempat yang ada, tetapi tidak pernah
   menciut di bawah 5,5rem. Tanpa batas bawah itu, enam kolom di layar 375 px
   menyisakan 45 px per kursi — namanya pecah huruf demi huruf menjadi kotak
   setinggi 158 px yang tidak terbaca sebagai nama sama sekali. */
.denah__kisi {
  display: grid;
  grid-template-columns: repeat(var(--denah-kolom, 6), minmax(5.5rem, 1fr));
  gap: var(--sp-2);
}

.denah__kursi {
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  min-height: 3.25rem;
  padding: var(--sp-2);
  border: 1px solid var(--c-border-kuat);
  border-radius: var(--r-md);
  background: var(--c-surface);
  font-size: var(--fs-sm);
  line-height: 1.25;
  overflow-wrap: anywhere;
}

/* Garis putus-putus: terbaca sebagai tempat yang memang tidak terisi, bukan
   sebagai nama yang gagal dimuat. */
.denah__kursi--kosong {
  border-style: dashed;
  border-color: var(--c-border);
  background: transparent;
}

.denah__catatan { margin-top: var(--sp-3); font-size: var(--fs-sm); color: var(--c-text-muted); }

/* Kisi form: label posisi kecil di atas select, supaya guru tahu kursi mana
   yang sedang ia isi tanpa menghitung kolom dengan jari. */
.denah__sel { display: flex; flex-direction: column; gap: var(--sp-1); }

.denah__label {
  font-size: var(--fs-xs);
  font-weight: 600;
  color: var(--c-text-muted);
  letter-spacing: .03em;
}

.denah__pilih { width: 100%; min-width: 0; }

/* Di ponsel kisi form menjadi SATU KOLOM. Enam select berdampingan di layar
   375 px menyisakan sekitar 55 px per select — cukup untuk kotaknya, tidak
   cukup untuk satu pun nama yang ada di dalamnya. */
@media (max-width: 767px) {
  .denah__kisi--form { grid-template-columns: 1fr; }
  .denah__kisi--form .denah__label::after { content: ' — pilih siswa'; font-weight: 400; }
}

@media print {
  .denah__kursi { border-color: #000; break-inside: avoid; }
  .denah__kursi--kosong { border-style: dashed; }
  .denah__papan { background: #e5e7eb !important; color: #000; -webkit-print-color-adjust: exact; print-color-adjust: exact; }
  .denah { break-inside: avoid; page-break-inside: avoid; }
}

/* ==========================================================================
   Rekap Jurnal Mengajar berbentuk tabel (Modul 11 FR-3)
   ========================================================================== */

/* Isi jurnal berupa kalimat, bukan label — nowrap bawaan .table akan
   merentangkan satu kolom kegiatan sampai beberapa layar lebarnya. */
.jurnal-tabel th,
.jurnal-tabel td {
  white-space: normal;
  vertical-align: top;
  border: 1px solid var(--c-border);
}

.jurnal-tabel thead th { background: var(--c-brand-light); color: var(--c-brand-dark); text-align: center; }

/* Lebar kolom dalam PERSEN, bukan rem.
   Lembar per mapel dicetak potret dan lembar menerus lanskap, sehingga lebar
   kertasnya berbeda hampir 10 cm. Ukuran tetap yang pas di salah satunya akan
   menyisakan kolom naratif selebar dua kata di yang lain; persen membagi
   apa pun lebar yang tersedia dengan perbandingan yang sama.

   Kepala tabel harian bertingkat dua, sehingga lebarnya harus ditumpangkan
   pada baris PERTAMA: baris kedua hanya berisi empat kolom cacah, dan
   nth-child di situ menunjuk kolom yang sama sekali berbeda. */
/* table-layout: fixed — TANPA ini lebar di bawah hanya usul, dan tabelnya
   melebar mengikuti isi terpanjang sampai harus digeser ke samping. Kedua tabel
   ini hanya muncul di layar cetak, yang tidak punya arah untuk menggeser:
   apa pun yang melebihi lebar kertas hilang terpotong. Tata letak tetap
   menjadikan persen di bawah mengikat, sehingga keduanya selalu pas selebar
   wadahnya — di kertas maupun di layar pratinjaunya. */
.jurnal-tabel--harian,
.jurnal-tabel--menerus { table-layout: fixed; width: 100%; }

.jurnal-tabel--harian thead tr:first-child th:nth-child(1) { width: 14%; }  /* Waktu    */
.jurnal-tabel--harian thead tr:first-child th:nth-child(2) { width: 21%; }  /* Tujuan   */
.jurnal-tabel--harian thead tr:first-child th:nth-child(3) { width: 18%; }  /* Materi   */
.jurnal-tabel--harian thead tr:first-child th:nth-child(4) { width: 20%; }  /* Kegiatan */
.jurnal-tabel--harian thead tr:first-child th:nth-child(5) { width: 13%; }  /* Asesmen  */

.jurnal-tabel--menerus th:nth-child(1) { width: 9%; }   /* Tanggal        */
.jurnal-tabel--menerus th:nth-child(2) { width: 8%; }   /* Waktu          */
.jurnal-tabel--menerus th:nth-child(3) { width: 7%; }   /* Kelas          */
.jurnal-tabel--menerus th:nth-child(4) { width: 10%; }  /* Mata Pelajaran */
.jurnal-tabel--menerus th:nth-child(5) { width: 20%; }  /* Tujuan         */
.jurnal-tabel--menerus th:nth-child(6) { width: 18%; }  /* Materi         */
.jurnal-tabel--menerus th:nth-child(7) { width: 18%; }  /* Kegiatan       */
.jurnal-tabel--menerus th:nth-child(8) { width: 10%; }  /* Asesmen        */

/* Sisa 14% dibagi rata berempat. Kepalanya disingkat satu huruf di markup —
   empat kata utuh menetapkan lebar minimum yang merebut hampir sepertiga
   kertas, dan yang membayar adalah tiga kolom kalimat di sebelahnya. */
.jurnal-tabel__cacah { width: 3.5%; text-align: center; }
.jurnal-tabel__waktu { white-space: nowrap; }

/* Kalimat panjang tanpa spasi — tautan yang tersalin ke kolom materi, misalnya —
   akan menembus kolomnya begitu lebarnya mengikat. */
.jurnal-tabel--harian td,
.jurnal-tabel--menerus td { overflow-wrap: anywhere; }

.jurnal-ket { margin-top: var(--sp-4); font-size: var(--fs-sm); color: var(--c-text-muted); }

/* Tanggal ditulis sekali per hari pada lembar guru mapel; garis bawahnya
   dilesapkan agar satu hari terbaca sebagai satu blok, bukan baris terpisah
   yang kebetulan kosong. */
.jurnal-tabel__lanjutan > td:first-child { border-bottom-color: transparent; border-top-color: transparent; }
.jurnal-tabel__awal > td { border-top: 1px solid var(--c-border-kuat); }

/* Satu mata pelajaran satu kertas; hari-harinya MENGALIR di dalamnya. Di layar
   pemisah antarmapel berupa garis dan jarak; di kertas, halaman baru. */
.jurnal-mapel + .jurnal-mapel { margin-top: var(--sp-6); }
.jurnal-mapel--baru { padding-top: var(--sp-6); border-top: 2px solid var(--c-border-kuat); }

.jurnal-mapel__judul {
  margin: 0 0 var(--sp-3);
  font-size: var(--fs-lg);
  color: var(--c-brand-dark);
}

.jurnal-hari + .jurnal-hari { margin-top: var(--sp-5); }
.jurnal-hari__judul { margin: 0 0 var(--sp-2); font-size: var(--fs-sm); }

/* Daftar ringkas pratinjau: satu jurnal satu baris, setinggi satu baris teks.
   Materi dipotong dengan elipsis — begitu satu sel melipat jadi dua baris,
   seluruh gunanya daftar ini hilang. */
.jurnal-ringkas__materi {
  max-width: 22rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Di ponsel barisnya jadi kartu — pola yang sama dengan Daftar Nilai dan
   Ekstrakurikuler. Enam kolom pada layar 375 px hanya bisa dibaca dengan
   menggeser tabel ke samping, dan menggeser ke samping untuk membaca daftar
   yang gunanya justru "sekali lihat" membatalkan alasan daftar ini dibuat. */
@media (max-width: 767px) {
  .jurnal-ringkas,
  .jurnal-ringkas tbody,
  .jurnal-ringkas tr,
  .jurnal-ringkas td { display: block; width: auto; }

  .jurnal-ringkas thead { display: none; }

  .jurnal-ringkas tr {
    border: 1px solid var(--c-border);
    border-radius: var(--r-md);
    padding: var(--sp-3);
    margin-bottom: var(--sp-3);
    background: var(--c-surface);
  }

  .jurnal-ringkas tr:last-child { margin-bottom: 0; }

  .jurnal-ringkas tbody td {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--sp-3);
    padding: var(--sp-1) 0;
    border-bottom: 0;
    white-space: normal;
  }

  .jurnal-ringkas tbody td[data-label]::before {
    content: attr(data-label);
    flex: none;
    font-size: var(--fs-xs);
    font-weight: 600;
    color: var(--c-text-muted);
    text-transform: uppercase;
    letter-spacing: .03em;
  }

  /* Materi tetap satu baris berelipsis; di kartu ia harus boleh menciut,
     kalau tidak lebarnya yang 22rem mendorong labelnya keluar layar. */
  .jurnal-ringkas__materi { max-width: none; min-width: 0; text-align: right; }
}

@media print {
  .jurnal-tabel th, .jurnal-tabel td { border-color: #000; }
  .jurnal-tabel tr { break-inside: avoid; page-break-inside: avoid; }

  /* Satu kertas baru per mata pelajaran. break-before pada kelompok KEDUA dan
     seterusnya, bukan break-after pada semuanya: break-after akan menyisakan
     satu kertas kosong di ujung berkas. */
  .jurnal-mapel--baru {
    break-before: page;
    page-break-before: always;
    padding-top: 0;
    margin-top: 0;
    border-top: none;
  }

  .jurnal-mapel__judul { font-size: 11pt; margin-bottom: 5pt; }

  /* Kolom cacah dirapatkan supaya keempatnya benar-benar berhenti di 14% yang
     dijatahkan; angka dua digit tetap muat. */
  .jurnal-tabel__cacah { padding-left: 2pt !important; padding-right: 2pt !important; }

  .jurnal-ket { margin-top: 6pt; font-size: 7.5pt; }

  /* Judul hari tidak boleh tertinggal sendirian di kaki halaman sementara
     tabelnya pindah ke kertas berikutnya. Blok harinya sendiri TIDAK dilarang
     terbelah: hari dengan banyak jam pelajaran memang bisa lebih tinggi dari
     satu kertas, dan melarangnya hanya memindahkan luapan itu, bukan
     menghilangkannya. */
  .jurnal-hari__judul { break-after: avoid; page-break-after: avoid; margin-bottom: 3pt; }
  .jurnal-hari + .jurnal-hari { margin-top: 10pt; }
}

/* ==========================================================================
   Pemasangan pertama kali (/install)
   ========================================================================== */

.pasang-langkah {
  display: flex;
  gap: var(--sp-2);
  margin: 0 0 var(--sp-5);
  padding: 0;
  list-style: none;
  counter-reset: none;
}

.pasang-langkah__item {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding-top: var(--sp-2);
  border-top: 3px solid var(--c-border);
  font-size: var(--fs-xs);
  text-align: center;
  color: var(--c-text-muted);
}

.pasang-langkah__item--aktif,
.pasang-langkah__item--selesai { border-top-color: var(--c-brand); color: var(--c-text); }
.pasang-langkah__item--aktif   { font-weight: 700; }

.pasang-langkah__nomor {
  display: grid;
  place-items: center;
  width: 22px;
  height: 22px;
  border: 1.5px solid var(--c-border);
  border-radius: var(--r-full);
  font-size: 0.7rem;
  font-weight: 700;
}

.pasang-langkah__item--aktif .pasang-langkah__nomor,
.pasang-langkah__item--selesai .pasang-langkah__nomor {
  border-color: var(--c-brand);
  color: var(--c-brand);
}

.pasang-judul {
  margin: var(--sp-5) 0 var(--sp-2);
  font-size: var(--fs-base);
  font-weight: 700;
  text-align: left;
}

.pasang-catatan { font-size: var(--fs-sm); color: var(--c-text-muted); text-align: left; }

.pasang-cek { margin: 0; padding: 0; list-style: none; text-align: left; }

.pasang-cek__item {
  display: flex;
  gap: var(--sp-3);
  align-items: flex-start;
  padding: var(--sp-2) 0;
  border-bottom: 1px solid var(--c-border);
  font-size: var(--fs-sm);
}

.pasang-cek__item:last-child { border-bottom: 0; }

/* Status ditandai warna DAN lambang (✓ / ✕ / –), bukan warna saja: pembaca
   yang sulit membedakan warna tetap dapat menemukan butir yang gagal. */
.pasang-cek__tanda {
  flex: none;
  width: 1.2rem;
  font-weight: 700;
  text-align: center;
}

.pasang-cek__item--ok    .pasang-cek__tanda { color: var(--c-success); }
.pasang-cek__item--gagal .pasang-cek__tanda { color: var(--c-danger); }
.pasang-cek__item--lewat .pasang-cek__tanda { color: var(--c-text-muted); }

.pasang-cek__pesan { display: block; color: var(--c-text-muted); font-size: var(--fs-xs); }

@media (max-width: 480px) {
  .pasang-langkah__judul { display: none; }
}

/* ==========================================================================
   Panduan (/panduan)
   ========================================================================== */

/* --- Daftar modul --- */
.panduan-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 244px), 1fr));
  gap: var(--sp-3);
}

.panduan-kartu {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  padding: var(--sp-4);
  background: var(--c-surface);
  border: 1px solid var(--c-border);
  border-radius: var(--r-lg);
  color: inherit;
  text-decoration: none;
  transition: border-color .15s, box-shadow .15s, transform .15s;
}

.panduan-kartu:hover,
.panduan-kartu:focus-visible {
  border-color: var(--c-brand);
  box-shadow: var(--shadow-md);
  transform: translateY(-2px);
}

/* Langkah Awal dibedakan karena ia pintu masuk, bukan salah satu modul. */
.panduan-kartu--utama {
  grid-column: 1 / -1;
  background: var(--c-brand-light);
  border-color: var(--c-brand);
}

.panduan-kartu__ikon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: var(--r-md);
  background: var(--c-brand-light);
  color: var(--c-brand);
}

.panduan-kartu--utama .panduan-kartu__ikon {
  background: var(--c-brand);
  color: var(--c-brand-contrast);
}

.panduan-kartu__judul { font-weight: 600; line-height: var(--lh-tight); }

.panduan-kartu__desc {
  font-size: var(--fs-sm);
  color: var(--c-text-muted);
  line-height: var(--lh-base);
}

.panduan-kartu__kapan {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-1);
  margin-top: auto;
  padding-top: var(--sp-2);
  font-size: var(--fs-xs);
  color: var(--c-text-muted);
}

/* --- Halaman satu modul --- */
.panduan-remah {
  margin: 0 0 var(--sp-1);
  font-size: var(--fs-xs);
  color: var(--c-text-muted);
}

.panduan-remah a { color: inherit; }

.topbar h1 .icon { vertical-align: -4px; margin-right: var(--sp-2); color: var(--c-brand); }

.panduan-ringkas__untuk {
  margin: 0 0 var(--sp-2);
  font-size: var(--fs-lg);
  line-height: var(--lh-base);
}

.panduan-ringkas__kapan {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  margin: 0 0 var(--sp-3);
  font-size: var(--fs-sm);
  color: var(--c-text-muted);
}

.panduan-dua {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: var(--sp-3);
  margin-top: var(--sp-3);
  align-items: start;
}

/* Nomor langkah sengaja dibuat serupa penanda pada sketsa layar, supaya guru
   mengenali penanda 1 di gambar sebagai langkah 1 di daftar ini. */
.panduan-langkah {
  margin: 0;
  padding: 0;
  list-style: none;
  counter-reset: langkah;
}

.panduan-langkah li {
  position: relative;
  counter-increment: langkah;
  padding: 0 0 var(--sp-4) var(--sp-8);
  font-size: var(--fs-sm);
  line-height: var(--lh-base);
}

.panduan-langkah li:last-child { padding-bottom: 0; }

.panduan-langkah li::before {
  content: counter(langkah);
  position: absolute;
  top: -1px;
  left: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  border-radius: var(--r-full);
  background: var(--c-brand);
  color: var(--c-brand-contrast);
  font-size: var(--fs-xs);
  font-weight: 700;
}

/* Garis penyambung antar langkah, berhenti sebelum langkah terakhir. */
.panduan-langkah li:not(:last-child)::after {
  content: "";
  position: absolute;
  top: 24px;
  left: 10px;
  bottom: 6px;
  width: 2px;
  background: var(--c-border);
}

.panduan-tips {
  margin: 0;
  padding-left: var(--sp-5);
  font-size: var(--fs-sm);
  line-height: var(--lh-base);
}

.panduan-tips li { margin-bottom: var(--sp-2); }
.panduan-tips li:last-child { margin-bottom: 0; }

.card__title .icon { vertical-align: -3px; margin-right: var(--sp-2); color: var(--c-brand); }

/* --- Akordeon tanya jawab --- */
.panduan-faq { border-bottom: 1px solid var(--c-border); }
.panduan-faq:last-child { border-bottom: 0; }

.panduan-faq__q {
  position: relative;
  padding: var(--sp-3) var(--sp-6) var(--sp-3) 0;
  font-size: var(--fs-sm);
  font-weight: 600;
  cursor: pointer;
  list-style: none;
}

.panduan-faq__q::-webkit-details-marker { display: none; }

.panduan-faq__q::after {
  content: "+";
  position: absolute;
  top: 50%;
  right: var(--sp-1);
  transform: translateY(-50%);
  color: var(--c-brand);
  font-size: var(--fs-lg);
  font-weight: 400;
}

.panduan-faq[open] .panduan-faq__q::after { content: "\2212"; }

.panduan-faq__a {
  margin: 0 0 var(--sp-3);
  padding-left: var(--sp-5);
  font-size: var(--fs-sm);
  color: var(--c-text-muted);
  line-height: var(--lh-base);
}

ul.panduan-faq__a li { margin-bottom: var(--sp-2); }

/* --- Modul terkait & navigasi --- */
.panduan-terkait { display: flex; flex-wrap: wrap; gap: var(--sp-2); }

.panduan-cip {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-3);
  border: 1px solid var(--c-border);
  border-radius: var(--r-full);
  background: var(--c-surface-alt);
  color: inherit;
  font-size: var(--fs-sm);
  text-decoration: none;
}

.panduan-cip:hover { border-color: var(--c-brand); color: var(--c-brand); }

.panduan-nav {
  display: flex;
  justify-content: space-between;
  gap: var(--sp-3);
  margin: var(--sp-4) 0 var(--sp-8);
}

.panduan-nav__t {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-3) var(--sp-4);
  border: 1px solid var(--c-border);
  border-radius: var(--r-lg);
  background: var(--c-surface);
  color: inherit;
  text-decoration: none;
}

.panduan-nav__t:hover { border-color: var(--c-brand); }
.panduan-nav__t--kanan { margin-left: auto; text-align: right; }
.panduan-nav__label { display: block; font-size: var(--fs-xs); color: var(--c-text-muted); }
.panduan-nav__judul { display: block; font-size: var(--fs-sm); font-weight: 600; }

/* --- Sketsa layar (partials/panduan-gambar.php) --- */
.pgb { margin: 0; }

.pgb__svg {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--r-md);
}

.pgb__cap {
  margin-top: var(--sp-3);
  font-size: var(--fs-xs);
  color: var(--c-text-muted);
  line-height: var(--lh-base);
}

/* Warna sketsa mengikuti variabel tema, sehingga ikut berubah di mode gelap
   tanpa aturan tambahan. */
.pgb-frame   { fill: var(--c-surface);      stroke: var(--c-border); stroke-width: 1; }
.pgb-bar     { fill: var(--c-brand-light); }
.pgb-head    { fill: var(--c-surface-alt);  stroke: var(--c-border); stroke-width: 1; }
.pgb-box     { fill: var(--c-surface-alt);  stroke: var(--c-border); stroke-width: 1; }

/* Kursi kosong pada sketsa Denah — bergaris putus-putus, sama seperti di layar
   sungguhannya, supaya sketsanya mengajarkan lambang yang benar. */
.pgb-dashed  { fill: none; stroke-dasharray: 4 3; }
.pgb-fill    { fill: var(--c-brand-light);  stroke: var(--c-brand);  stroke-width: 1; }
.pgb-primary { fill: var(--c-brand); }
.pgb-line    { stroke: var(--c-border); stroke-width: 1.5; fill: none; }
.pgb-line-s  { stroke: var(--c-border); stroke-width: 4; fill: var(--c-border); stroke-linecap: round; }

.pgb-title   { fill: var(--c-brand);          font-size: 11px; font-weight: 700; font-family: var(--font-sans); }
.pgb-txt     { fill: var(--c-text);           font-size: 9px;  font-family: var(--font-sans); }
.pgb-txt-xs  { fill: var(--c-text-muted);     font-size: 8px;  font-family: var(--font-sans); }
.pgb-txt-inv { fill: var(--c-brand-contrast); font-size: 8px;  font-weight: 600; font-family: var(--font-sans); }

.pgb-mark circle { fill: var(--c-brand); stroke: var(--c-surface); stroke-width: 2; }

.pgb-mark-t {
  fill: var(--c-brand-contrast);
  font-size: 9px;
  font-weight: 700;
  font-family: var(--font-sans);
  text-anchor: middle;
}

@media (max-width: 860px) {
  .panduan-dua { grid-template-columns: minmax(0, 1fr); }
}

@media (max-width: 560px) {
  .panduan-nav { flex-direction: column; }
  .panduan-nav__t--kanan { margin-left: 0; }

  /* Sketsa menyusut mengikuti lebar layar, sehingga ukuran huruf efektifnya
     ikut mengecil — di 375px teks 9 satuan hanya terbaca ~7px. Angka di bawah
     mengembalikannya ke sekitar 9px nyata; batas atasnya ditentukan oleh lebar
     kotak pada sketsa, yang sudah diukur agar teks terlebar tetap muat. */
  .pgb-title   { font-size: 12.5px; }
  .pgb-txt     { font-size: 10.5px; }
  .pgb-txt-xs  { font-size: 9px; }
  .pgb-txt-inv { font-size: 9px; }
  .pgb-mark-t  { font-size: 10px; }
}

/* ==========================================================================
   Layout dokumen (/kebijakan-privasi)
   ========================================================================== */

.dok-body { background: var(--c-bg); }

.dok {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  min-height: 100dvh;
  padding: var(--sp-6) var(--sp-5) var(--sp-8);
}

.dok__kop { display: flex; justify-content: center; margin-bottom: var(--sp-6); }

.dok__merek {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-3);
  color: inherit;
  text-decoration: none;
}

.dok__merek-badge {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border-radius: var(--r-md);
  background: var(--c-brand);
  color: var(--c-brand-contrast);
}

.dok__merek-nama { font-size: var(--fs-lg); font-weight: 700; color: var(--c-brand); }

/* Kolom teks dibatasi ~46rem: di atas itu baris terlalu panjang untuk dibaca
   nyaman, dan margin otomatis yang menengahkannya di layar lebar. */
.dok__isi { width: 100%; max-width: 46rem; margin: 0 auto; flex: 1; }

.dok__kaki {
  margin-top: var(--sp-8);
  text-align: center;
  font-size: var(--fs-xs);
  color: var(--c-text-muted);
}

.dok-kartu {
  padding: clamp(var(--sp-6), 4vw, var(--sp-10));
  background: var(--c-surface);
  border: 1px solid var(--c-border);
  border-radius: var(--r-xl);
  box-shadow: var(--shadow-md);
}

.dok-kartu__lambang {
  display: grid;
  place-items: center;
  width: 64px;
  height: 64px;
  margin: 0 auto var(--sp-4);
  border-radius: var(--r-full);
  background: var(--c-brand-light);
  color: var(--c-brand);
}

.dok-kartu__judul {
  margin: 0 0 var(--sp-2);
  text-align: center;
  font-size: var(--fs-2xl);
  font-weight: 800;
  color: var(--c-brand);
}

.dok-kartu__sub {
  margin: 0 0 var(--sp-8);
  text-align: center;
  font-size: var(--fs-sm);
  color: var(--c-text-muted);
}

/* Prosa dibiarkan rata kiri meski kartunya di tengah halaman: paragraf rata
   tengah memaksa mata mencari awal tiap baris dan melelahkan pada teks panjang. */
.dok-teks { font-size: var(--fs-sm); color: var(--c-text-muted); line-height: var(--lh-base); }
.dok-teks p  { margin: 0 0 var(--sp-4); }
.dok-teks ul { margin: 0 0 var(--sp-4); padding-left: var(--sp-5); }
.dok-teks li { margin-bottom: var(--sp-2); }
.dok-teks strong { color: var(--c-text); }

.dok-teks h2 {
  margin: var(--sp-6) 0 var(--sp-3);
  font-size: var(--fs-base);
  font-weight: 700;
  color: var(--c-text);
}

.dok-teks h2:first-child { margin-top: 0; }
.dok-teks__catatan { margin-bottom: 0; font-size: var(--fs-xs); }

.dok-kartu__garis {
  margin: var(--sp-6) 0 var(--sp-4);
  border: 0;
  border-top: 1px solid var(--c-border);
}

.dok-kartu__balik { margin: 0; text-align: center; font-size: var(--fs-sm); }

.dok-kartu__balik a {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  color: var(--c-brand);
  font-weight: 600;
}

/* ==========================================================================
   Pintu masuk panel admin (/admin/masuk)
   ========================================================================== */

/* Palet gelap sengaja ditulis sebagai nilai tetap, BUKAN variabel tema: layar
   ini harus terlihat sama di tema terang maupun gelap. Perbedaannya dari layar
   guru adalah isyarat keamanan — admin harus selalu sadar sedang membuka area
   lintas akun — dan isyarat itu tidak boleh ikut berganti mengikuti preferensi. */
.adm-body {
  margin: 0;
  background: #0f172a;
  color: #e2e8f0;
  font-family: var(--font-sans);
}

.adm-flash {
  position: fixed;
  top: var(--sp-4);
  left: 50%;
  transform: translateX(-50%);
  z-index: 5;
  max-width: min(92vw, 30rem);
}

.adm-masuk {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  min-height: 100dvh;
  padding: var(--sp-8) var(--sp-5);
  overflow: hidden;
  background:
    radial-gradient(60% 55% at 50% 0%, rgba(22, 121, 74, .28) 0%, transparent 70%),
    linear-gradient(180deg, #111c2e 0%, #0f172a 60%);
}

/* Kisi latar: pattern SVG, bukan berkas gambar — nol permintaan jaringan dan
   ikut menyesuaikan ukuran layar tanpa penskalaan raster. */
.adm-masuk__kisi {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  color: rgba(148, 163, 184, .09);
  pointer-events: none;
}

.adm-masuk__isi {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: 25rem;
}

/* --- Kop merek --- */
.adm-masuk__kop { text-align: center; margin-bottom: var(--sp-6); }

.adm-masuk__lambang {
  display: inline-grid;
  place-items: center;
  width: 60px;
  height: 60px;
  border-radius: var(--r-lg);
  background: rgba(22, 121, 74, .18);
  border: 1px solid rgba(45, 212, 141, .35);
  color: #34d399;
}

.adm-masuk__nama {
  margin: var(--sp-3) 0 0;
  font-size: var(--fs-lg);
  font-weight: 700;
  letter-spacing: .01em;
}

.adm-masuk__produk {
  margin: 2px 0 0;
  font-size: var(--fs-xs);
  letter-spacing: .18em;
  text-transform: uppercase;
  color: #94a3b8;
}

/* --- Kartu --- */
.adm-kartu {
  padding: clamp(var(--sp-6), 4vw, var(--sp-8));
  border: 1px solid rgba(148, 163, 184, .18);
  border-radius: var(--r-xl);
  background: rgba(30, 41, 59, .72);
  box-shadow: 0 18px 44px rgba(2, 6, 23, .55);
}

.adm-kartu__judul {
  margin: 0 0 var(--sp-2);
  font-size: var(--fs-xl);
  font-weight: 700;
  text-align: center;
  color: #f1f5f9;
}

.adm-kartu__sub {
  margin: 0 0 var(--sp-6);
  font-size: var(--fs-sm);
  text-align: center;
  color: #94a3b8;
}

/* Kendali form diwarnai ulang di dalam kartu gelap. Kelas .input/.label yang
   sama dipakai ulang supaya perilaku fokus, galat, dan ukuran sentuh tetap satu
   sumber — hanya warnanya yang ditimpa di sini. */
.adm-kartu .label { color: #cbd5e1; font-weight: 600; }

.adm-kartu .input {
  min-height: 50px;
  background: rgba(15, 23, 42, .7);
  border-color: rgba(148, 163, 184, .25);
  color: #f1f5f9;
}

.adm-kartu .input::placeholder { color: #7d8da3; }

.adm-kartu .input:focus {
  border-color: #34d399;
  outline-color: #34d399;
}

.adm-kartu .input-group__icon,
.adm-kartu .input-group__toggle { color: #64748b; }
.adm-kartu .input-group__toggle:hover { color: #cbd5e1; }

.adm-kartu__tombol {
  margin-top: var(--sp-2);
  /* Tombol masuk panel admin. Nilainya literal, bukan token: kartu admin berdiri
     di atas latar gelapnya sendiri yang tidak ikut tema pengguna. Warnanya tetap
     mengikuti brand supaya panel tidak terlihat milik produk lain. */
  background: linear-gradient(135deg, var(--c-brand) 0%, var(--c-brand-dark) 100%);
  border-color: var(--c-brand);
  color: #fff;
}

.adm-kartu__tombol:hover { filter: brightness(1.08); }

.adm-kartu .alert--error {
  background: rgba(220, 38, 38, .16);
  border-color: rgba(248, 113, 113, .45);
  color: #fecaca;
}

.adm-kartu__catatan {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-2);
  margin: var(--sp-5) 0 0;
  padding-top: var(--sp-4);
  border-top: 1px solid rgba(148, 163, 184, .16);
  font-size: var(--fs-xs);
  line-height: var(--lh-base);
  color: #94a3b8;
}

.adm-kartu__catatan .icon { flex: none; margin-top: 1px; }
.adm-kartu__catatan a { color: #34d399; font-weight: 600; }

/* --- Kaki --- */
.adm-masuk__kaki {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: var(--sp-2);
  margin-top: var(--sp-5);
  font-size: var(--fs-xs);

  /* #64748b hanya mencapai kontras 3.75:1 di atas latar ini — di bawah ambang
     WCAG AA (4.5:1) untuk teks sekecil ini. Nilai berikut mencapai 7.4:1. */
  color: #94a3b8;
}

.adm-masuk__pemisah { color: rgba(148, 163, 184, .3); }

.adm-masuk__lencana {
  padding: 2px var(--sp-2);
  border-radius: var(--r-full);
  background: rgba(148, 163, 184, .14);
  color: #cbd5e1;
  font-weight: 700;
}

/* --------------------------------------------- Rangka panel admin (layouts/admin) */
/* Sidebar aplikasi guru disembunyikan di bawah 1024px dan digantikan navigasi
   bawah. Panel admin tidak punya navigasi bawah, jadi ia butuh aturannya
   sendiri: di layar sempit sidebarnya berubah menjadi bilah mendatar di atas. */
/* Panel admin memakai ULANG kelas .sidebar, tetapi tidak ikut pindah ke cangkang
   boxed: ia tetap sidebar melayang selebar layar penuh. Sifat-sifat berikut dulu
   datang dari .sidebar dan harus ditulis di sini sejak sidebar guru kembali ke
   alur normal (docs/prd/modul/01-dashboard.md §4c) — tanpa ini panel admin
   melebar sepenuh viewport dan menimpa isinya. */
.adm-panel__sidebar {
  display: flex;
  position: fixed;
  inset: 0 auto 0 0;
  width: var(--sidebar-w);
  overflow-y: auto;
  z-index: 40;
  border: 0;
  border-right: 1px solid var(--c-border);
  border-radius: 0;
}

.adm-panel__label   { flex: 1; }
.adm-panel__keluar  { padding: var(--sp-3); }

/* Kop panel admin. Aturannya berdiri sendiri di sini — sidebar aplikasi guru
   memakai kop identitas sekolah, bentuk yang sama sekali berbeda, sehingga
   keduanya sengaja tidak berbagi kelas. */
.adm-panel__merek {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-5) var(--sp-4);
  background: #1f2937;
  color: var(--c-text-inverse);
}

.adm-panel__merek-judul { font-weight: 700; font-size: var(--fs-lg); }
.adm-panel__merek-sub   { font-size: var(--fs-xs); opacity: .85; }

/* Jarak tepi ditulis di sini, bukan diwarisi dari .main: sejak cangkang guru
   menjadi grid boxed, .main melepas seluruh padding-nya ke cangkang — dan panel
   admin tidak memakai cangkang itu. */
.adm-panel__isi {
  margin-left: var(--sidebar-w);
  padding: var(--sp-4);
  padding-bottom: var(--sp-8);
}

@media (min-width: 1024px) {
  .adm-panel__isi { padding: var(--sp-6); padding-bottom: var(--sp-8); }
}

@media (max-width: 1023px) {
  .adm-panel__sidebar {
    position: static;
    flex-direction: row;
    align-items: center;
    gap: var(--sp-2);
    width: 100%;
    height: auto;
    padding: var(--sp-2) var(--sp-3);
    overflow-x: auto;
  }

  .adm-panel__merek {
    flex: none;
    padding: var(--sp-2) var(--sp-3);
    border-radius: var(--r-md);
    border-bottom: 0;
  }

  /* Nama admin dilepas: di bilah mendatar ia memakan lebar yang dibutuhkan
     tautan menu, sementara identitas admin sudah jelas dari konteksnya. */
  .adm-panel__merek-sub { display: none; }

  .adm-panel__nav {
    flex: 1;
    flex-direction: row;
    gap: var(--sp-1);
    padding: 0;
    overflow-x: auto;
  }

  .adm-panel__nav .sidebar__link { flex: none; white-space: nowrap; }

  .adm-panel__keluar { flex: none; padding: 0; }
  .adm-panel__keluar .btn { width: auto; }

  .adm-panel__isi { margin-left: 0; }
}

@media (max-width: 560px) {
  /* Label menu dilepas, ikonnya tetap — tiga tujuan masih terbedakan dari
     bentuk ikonnya, dan judul halaman menegaskan yang sedang dibuka. */
  .adm-panel__label { display: none; }
  .adm-panel__merek-judul { font-size: var(--fs-sm); }
}

/* ==========================================================================
   Dashboard desktop (docs/prd/modul/01-dashboard.md §4c)

   Seluruh blok ini hanya berlaku >= 1024px. Di bawah itu tata letak mobile yang
   lama tetap dipakai apa adanya dan .dash tidak pernah tampil — keduanya dikirim
   dalam satu markup, dipilih CSS, sama seperti sidebar vs bottom navigation.
   ========================================================================== */

.dash        { display: none; }
.dash-mobile { display: block; }

@media (min-width: 1024px) {
  .dash        { display: block; }
  .dash-mobile { display: none; }
}

/* Baris kartu. Proporsi kolomnya mengikuti ISI, bukan simetri: kartu berubin
   empat, bertabel, dan berdonut butuh ruang lebih dari tetangganya.
   `minmax(0, …)` pada tiap track agar tabel & legenda panjang tidak memaksa
   kolomnya melebar melewati jatah. */
.dash__baris {
  display: grid;
  gap: var(--sp-4);
  margin-bottom: var(--sp-4);
}

.dash__baris--1 { grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr) minmax(0, 1.18fr); }
.dash__baris--2 { grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr); }
.dash__baris--3 { grid-template-columns: minmax(0, 1.1fr) minmax(0, 1.6fr) minmax(0, 1fr); }

/* Kartu dashboard: kolom flex agar tautan kaki selalu menempel di dasar kartu,
   berapa pun tinggi isi tetangganya dalam baris yang sama. */
.dash__kartu {
  display: flex;
  flex-direction: column;
  background: var(--c-surface);
  border: 1px solid var(--c-border);
  border-radius: var(--r-lg);
  padding: var(--sp-5);
}

.dash__kepala {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  margin-bottom: var(--sp-4);
}

/* Ikon kepala kartu memakai latar BERNADA dengan teks bernada pasangannya, bukan
   warna solid di atas latar bernada. Pasangan solid gagal WCAG AA di tema gelap
   (CHECKLIST.md §F), dan halaman ini menampilkan delapan kepala kartu sekaligus
   — pelanggarannya berlipat. */
.dash__ikon {
  display: grid;
  place-items: center;
  flex: none;
  width: 36px;
  height: 36px;
  border-radius: var(--r-md);
  background: var(--c-brand-light);
  color: var(--c-brand-teks);
}

.dash__ikon--info    { background: var(--c-info-bg);    color: var(--c-info-teks); }
.dash__ikon--success { background: var(--c-success-bg); color: var(--c-success-teks); }
.dash__ikon--warning { background: var(--c-warning-bg); color: var(--c-warning-teks); }

/* Angka & grafik bernada merek di dalam dashboard memakai `--c-brand-teks`.
   `.text-brand` global masih memakai warna solid, yang di tema gelap hanya
   mencapai 3,16:1 di atas permukaan kartu. */
.dash .text-brand { color: var(--c-brand-teks); }

.dash__judul {
  margin: 0;
  font-size: var(--fs-base);
  font-weight: 700;
  line-height: var(--lh-tight);
}

/* Tautan kaki kartu. `margin-top: auto` yang membuat seluruh kartu dalam satu
   baris berakhir pada garis yang sama. */
.dash__aksi {
  margin-top: auto;
  padding-top: var(--sp-4);
  font-size: var(--fs-sm);
  font-weight: 600;
}

/* ---- Kartu kepala halaman ---- */
.dash__sapaan {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-4);
  flex-wrap: wrap;
}

.dash__sapaan-judul {
  margin: 0;
  font-size: var(--fs-xl);
  font-weight: 700;
  line-height: var(--lh-tight);
}

.dash__sapaan-sub {
  margin: var(--sp-1) 0 0;
  font-size: var(--fs-sm);
  color: var(--c-text-muted);
}

.dash__kepala-aksi { display: flex; align-items: center; gap: var(--sp-3); }

/* Lonceng dengan lencana ANGKA di sudut: guru dapat menakar apakah tunggakannya
   satu hal kecil atau setumpuk sebelum memutuskan membukanya. */
.dash__lonceng {
  position: relative;
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border: 1px solid var(--c-border);
  border-radius: var(--r-md);
  color: var(--c-text-muted);
}

.dash__lonceng:hover { border-color: var(--c-brand); color: var(--c-brand-teks); text-decoration: none; }

/* Lencana angka bersama — dipakai lonceng desktop dan navigasi bawah mobile.
   `min-width` sama dengan tingginya supaya satu digit tetap bulat sempurna,
   sementara "9+" melebar sendiri menjadi pil tanpa memotong angkanya. */
.dash__lonceng-jumlah,
.bottomnav__lencana {
  position: absolute;
  display: grid;
  place-items: center;
  min-width: 18px;
  height: 18px;
  padding: 0 4px;
  border-radius: var(--r-full);
  background: var(--c-danger);
  border: 2px solid var(--c-surface);
  color: #fff;
  font-size: 10px;
  font-weight: 700;
  line-height: 1;
}

.dash__lonceng-jumlah { top: 2px; right: 2px; }

/* ---- Pemilih kelas di kartu sapaan (mobile) ----
   Nama kelas pada kartu merek ITU SENDIRI yang menjadi pemilihnya — inilah
   satu-satunya jalan berpindah kelas di mobile, dan ia menempati baris yang
   memang sudah dibaca sebagai "kelas apa yang sedang saya buka".

   Kendali di atas latar merek memakai lapisan GELAP, bukan putih: lapisan putih
   menerangkan warna merek di bawahnya sehingga teks putih di atasnya justru turun ke
   sekitar 4:1, sementara lapisan gelap membawanya ke sekitar 7:1. */
.hero-kelas {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  margin-bottom: var(--sp-2);
}

.hero-kelas__select {
  flex: 1;
  min-width: 0;
  min-height: var(--tap-min);
  padding: 0 var(--sp-3);
  border: 1px solid rgba(255, 255, 255, .55);
  border-radius: var(--r-md);
  background: rgba(0, 0, 0, .16);
  color: var(--c-brand-contrast);
  font-family: inherit;
  font-size: var(--fs-lg);
  font-weight: 700;
}

/* Daftar pilihannya dirender sistem operasi dengan warna teksnya sendiri,
   sehingga opsi dikembalikan ke latar terang agar tetap terbaca saat dibuka. */
.hero-kelas__select option { background: var(--c-surface); color: var(--c-text); }

.hero-kelas__ganti {
  flex: none;
  min-height: var(--tap-min);
  padding: 0 var(--sp-4);
  border: 0;
  border-radius: var(--r-md);
  background: var(--c-surface);
  color: var(--c-brand-teks);
  font-family: inherit;
  font-size: var(--fs-sm);
  font-weight: 600;
  cursor: pointer;
}

/* ---- Ubin angka di kartu Ringkasan Kelas ---- */
.dash__ubin {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--sp-2);
}

.dash__ubin > div {
  padding: var(--sp-3) var(--sp-2);
  border: 1px solid var(--c-border);
  border-radius: var(--r-md);
  text-align: center;
}

.dash__ubin-angka { font-size: var(--fs-xl); font-weight: 700; line-height: 1.1; }
.dash__ubin-label { font-size: var(--fs-xs); color: var(--c-text-muted); margin-top: 2px; }
.dash__ubin-sub   { font-size: 10px; color: var(--c-text-muted); }

/* ---- Angka besar + batang kemajuan (Jurnal Minggu Ini) ---- */
.dash__besar { font-size: var(--fs-3xl); font-weight: 700; line-height: 1; }
.dash__besar span { font-size: var(--fs-lg); color: var(--c-text-muted); font-weight: 600; }

/* ---- Grafik garis kehadiran ----
   SVG statis; koordinatnya dihitung di server sehingga grafik ini tetap
   tergambar tanpa satu baris JavaScript pun (FR-14). */
.dash__garis { width: 100%; height: auto; }
.dash__garis-sumbu { stroke: var(--c-border); stroke-width: 1; }
.dash__garis-label { font-size: 9px; fill: var(--c-text-muted); }
.dash__garis-isi   { fill: var(--c-brand-teks); opacity: .12; }
.dash__garis-jalur { fill: none; stroke: var(--c-brand-teks); stroke-width: 2; stroke-linejoin: round; }
.dash__garis-titik { fill: var(--c-brand-teks); }

/* ---- Baris rincian (Catatan Siswa, Jurnal Hari Ini) ---- */
.dash__rincian { display: flex; flex-direction: column; gap: var(--sp-2); }

.dash__rincian-baris {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  padding: var(--sp-2) 0;
  font-size: var(--fs-sm);
  border-bottom: 1px solid var(--c-border);
}

.dash__rincian-baris:last-child { border-bottom: 0; }

/* Pada kartu Jurnal Hari Ini tiap baris adalah tautan ke jurnal sesinya.
   Penandanya warna teks, bukan latar: barisnya tanpa jarak tepi mendatar,
   sehingga latar hover akan menempel pada garis pemisah di atas & bawahnya. */
a.dash__rincian-baris:hover { text-decoration: none; }
a.dash__rincian-baris:hover .truncate { color: var(--c-brand-teks); }

/* Baris yang BERPINDAH KELAS sekaligus membuka modulnya berupa tombol di dalam
   form POST — berpindah kelas mengubah keadaan sesi, dan GET yang mengubah
   keadaan dapat terpicu pramuat peramban. Tombolnya dilucuti agar terbaca sama
   persis dengan baris tautan di sebelahnya: yang membedakan keduanya adalah
   metode HTTP-nya, bukan penampilannya. */
.dash__rincian-form { display: contents; }

button.dash__rincian-tombol {
  width: 100%;
  background: none;
  border: 0;
  border-bottom: 1px solid var(--c-border);
  color: inherit;
  font: inherit;
  font-size: var(--fs-sm);
  text-align: left;
  cursor: pointer;
}

.dash__rincian-form:last-child button.dash__rincian-tombol { border-bottom: 0; }
button.dash__rincian-tombol:hover .truncate { color: var(--c-brand-teks); }
button.dash__rincian-tombol:focus-visible { outline: 2px solid var(--c-brand); outline-offset: 2px; }

/* ---- Legenda berdampingan (donut penilaian, daftar mapel) ---- */
.dash__legenda { display: flex; flex-direction: column; gap: var(--sp-2); font-size: var(--fs-sm); }

.dash__legenda-baris {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
}

.dash__titik {
  flex: none;
  width: 10px;
  height: 10px;
  border-radius: var(--r-full);
}

/* Warna mapel dipilih guru dan kontrasnya tidak dapat dijamin — dipakai sebagai
   keping saja, tidak pernah sebagai warna teks. */
.dash__keping {
  display: inline-block;
  flex: none;
  width: 8px;
  height: 8px;
  border-radius: 2px;
  margin-right: var(--sp-2);
}

/* ---- Tabel jadwal ---- */
.dash__tabel { width: 100%; border-collapse: collapse; font-size: var(--fs-sm); }

.dash__tabel th {
  padding: var(--sp-2) var(--sp-3);
  text-align: left;
  font-size: var(--fs-xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .03em;
  color: var(--c-text-muted);
  background: var(--c-surface-alt);
  border-bottom: 1px solid var(--c-border);
}

.dash__tabel td {
  padding: var(--sp-3);
  border-bottom: 1px solid var(--c-border);
  white-space: nowrap;
}

.dash__tabel tbody tr:last-child td { border-bottom: 0; }
.dash__tabel tbody tr:hover { background: var(--c-surface-alt); }

/* Seluruh baris menjadi tautan ke jurnal sesi itu — menghindari kolom kelima
   berisi tombol pada tabel yang justru berguna karena pendek (FR-3). */
.dash__tabel a { color: inherit; display: block; }
.dash__tabel a:hover { text-decoration: none; }

/* Sesi yang sedang berlangsung ditandai latar + garis kiri, bukan badge: ia
   satu-satunya baris yang perlu dibedakan, dan badge menuntut kolom sendiri. */
.dash__tabel tr.is-berlangsung { background: var(--c-brand-light); }
.dash__tabel tr.is-berlangsung td:first-child { box-shadow: inset 3px 0 0 var(--c-brand); }

/* ---- Footer ---- */
.dash__footer {
  padding: var(--sp-5) 0 0;
  text-align: center;
  font-size: var(--fs-xs);
  color: var(--c-text-muted);
}

/* ---- Cetak ----
   Blok ini WAJIB berada di akhir berkas, sesudah `.dash { display: none }` di
   atas: `@media` tidak menambah kekhususan, jadi aturan yang datang belakangan
   yang menang. Ditaruh di blok @media print utama (baris ~1435) ia justru kalah
   dan tidak berpengaruh apa pun. */
@media print {
  /* Kertas A4 potret setara ±794px — DI BAWAH ambang 1024px. Tanpa dua baris
     ini yang tercetak adalah tata letak mobile, bukan kartu yang dirancang
     untuk halaman ini. */
  .dash        { display: block; }
  .dash-mobile { display: none; }

  /* Tiga kartu berdampingan di A4 potret menyisakan kolom selebar ±5 cm. */
  .dash__baris     { display: block; }
  .dash__baris > * { margin-bottom: var(--sp-4); }

  .dash__kartu {
    break-inside: avoid;
    page-break-inside: avoid;
    border-color: #999;
  }

  /* Grafik CSS ikut tercetak — itulah alasan memilih conic-gradient & SVG
     alih-alih kanvas Chart.js. Peramban membuang latar bernada saat mencetak
     (`print-color-adjust: economy` adalah bawaannya), sehingga tanpa ini donut
     keluar sebagai lingkaran kosong dan batang kemajuan sebagai alur kosong.
     `.donut__hole` ikut disebut: bila latar putihnya tidak dicetak, gradien
     induknya menembus lubang dan donut menjadi cakram penuh. */
  .donut,
  .donut__hole,
  .progres__isi,
  .dash__titik,
  .dash__keping {
    print-color-adjust: exact;
    -webkit-print-color-adjust: exact;
  }
}
