/* ==========================================================================
   HPSA Live Track — tampilan
   Susunan halaman tetap sama seperti kerangka website (logo, remah roti,
   kartu tile, tabel nilai bertingkat), tetapi dibuat lebih lembut: kartu
   putih dengan bayangan tipis, sudut membulat, warna hijau khas Bina Ilmi,
   dan gerak halus saat disentuh kursor.
   ========================================================================== */

/* Huruf Plus Jakarta Sans dimuat lewat <link> di index.html supaya tidak
   menghambat tampilnya halaman bila jaringan sekolah lambat. */

:root {
  /* hijau khas Bina Ilmi */
  --green-900: #0b3d24;
  --green-800: #14582f;
  --green-700: #1e7040;
  --green-600: #2f8b52;
  --green-500: #4aa568;
  --green-300: #a8dcae;
  --green-200: #cdeccf;
  --green-100: #e6f5e8;
  --green-050: #f3fbf4;

  --gold-600: #d8a800;
  --gold-500: #f5d423;
  --gold-100: #fdf6d4;

  --ink-900: #16221b;
  --ink-800: #26332c;
  --ink-600: #55645c;
  /* --ink-400 dulu #8a9791. Ia dipakai untuk SELURUH teks redup — nomor baris
     tabel, jumlah data, keterangan di bawah isian — dan rasio kontrasnya cuma
     3,04 : 1, sedangkan WCAG AA menuntut 4,5 : 1 untuk teks biasa. Di layar HP
     yang kena silau matahari, ini yang pertama hilang, dan yang hilang itu
     justru nomor urut siswa.
     Nilai baru: 5,22 di kertas putih, 4,90 di kanvas, 4,62 di hijau muda —
     ketiganya lolos. Ke-37 pemakaiannya semuanya warna teks (36 color + 1 fill
     pada label grafik), jadi tidak ada garis atau ikon yang ikut menggelap. */
  --ink-400: #617067;
  --ink-200: #c8d2cd;

  --line:   #e2ebe5;
  --line-2: #d3e0d8;
  --paper:  #ffffff;
  --canvas: #f4f9f5;
  --tile:   #ffffff;

  --danger:    #c0392b;
  --danger-bg: #fdecea;
  /* --warn dulu #b9770e: 3,68 di putih dan 3,39 di lencananya sendiri —
     keduanya di bawah AA. Nilai baru 5,28 dan 4,87. */
  --warn:      #96600b;
  --warn-bg:   #fdf5e4;
  --ok:        #1e7040;
  --ok-bg:     #e6f5e8;

  --r-xs: 7px;
  --r-sm: 11px;
  --r:    16px;
  --r-lg: 22px;
  --r-pill: 999px;

  --sh-1: 0 1px 2px rgba(16,40,28,.05), 0 1px 3px rgba(16,40,28,.05);
  --sh-2: 0 2px 4px rgba(16,40,28,.05), 0 6px 16px rgba(16,40,28,.07);
  --sh-3: 0 8px 18px rgba(16,40,28,.10), 0 18px 40px rgba(16,40,28,.10);
  --ring: 0 0 0 3px rgba(47,139,82,.22);
  /* Sorot berwarna di bawah tombol utama. Sebelumnya ada ENAM ragam yang
     hampir sama — .24 .26 .28 .30 .32 .34 pada empat jarak buram berbeda —
     dan tidak satu pun perbedaannya terlihat mata. Dua saja sudah cukup:
     keadaan diam dan keadaan disentuh. */
  /* Dua baris di bawah pernah tertulis `--glow: var(--glow)` — rujukan ke
     dirinya sendiri. CSS menganggap lingkaran seperti itu TIDAK SAH pada saat
     nilai dihitung, sehingga setiap `box-shadow: var(--glow)` diam-diam jatuh
     ke `unset` dan seluruh tombol utama kehilangan bayangan hijaunya. Tidak
     ada galat di konsol, tidak ada uji yang gagal — hanya tombol yang lebih
     datar daripada yang dirancang. */
  --glow:       0 4px 14px rgba(20,88,47,.28);
  --glow-hover: 0 7px 18px rgba(20,88,47,.32);
  --glow-gold:  0 4px 14px rgba(178,138,0,.30);

  /* ------------------------------------------------------------------
     RONA 2026 — kaca dan denyut
     Aksen "neon fungsional" TIDAK memakai warna baru: ia hijau sekolah yang
     diberi cahaya. Dengan begitu tanda "hidup" dan lencana yang menyala tetap
     terbaca sebagai Bina Ilmi, bukan sebagai aplikasi lain.
     ------------------------------------------------------------------ */
  --live:      #19b45a;                       /* hijau denyut, lebih terang dari --green-600 */
  --live-dim:  rgba(25,180,90,.16);
  --glass:     rgba(255,255,255,.66);         /* panel kaca */
  --glass-brd: rgba(255,255,255,.78);         /* garis tepi kaca */
  --blur:      saturate(1.5) blur(16px);
  --sorot-ok:    0 0 0 1px rgba(30,112,64,.16), 0 0 12px rgba(25,180,90,.28);
  --sorot-warn:  0 0 0 1px rgba(150,96,11,.18), 0 0 12px rgba(216,168,0,.26);
  --sorot-bahaya:0 0 0 1px rgba(192,57,43,.18), 0 0 12px rgba(192,57,43,.24);
  /* Garis dalam setipis rambut pada panel bertekanan; dulu .13 dan .14. */
  --line-in:    inset 0 0 0 1px rgba(47,139,82,.14);
  /* lebar kolom isi halaman; lihat blok SATU KOLOM ISI di bawah */
  --kolom: 1180px;

  /* ------------------------------------------------------------------
     TANGGA UKURAN HURUF

     Sebelum ini ada 56 nilai font-size berbeda di dua berkas, dan di layar
     terbaca sebagai 38 ukuran: 14,88px di sebelah 14,72px di sebelah 15,36px.
     Selisih sepersekian piksel itu tidak pernah terlihat sebagai "salah",
     tetapi terbaca sebagai halaman yang tidak tenang.

     Sebabnya sederhana: rem dihitung dari AKAR peramban (16px), sedangkan
     badan halaman ini 15px. Jadi .93rem bukan 14px melainkan 14,88px, dan
     .84rem menjadi 13,44px. Setiap angka yang ditulis meleset dari yang
     dibayangkan penulisnya.

     Delapan langkah di bawah dipilih supaya jatuh TEPAT di piksel bulat pada
     akar 16px. Nilai terkecil 12px — sebelumnya ada teks 8,8px.
     ------------------------------------------------------------------ */
  --t-2xs: 0.75rem;    /* 12px — lencana, label sangat kecil        */
  --t-xs:  0.8125rem;  /* 13px — keterangan, petunjuk di bawah isian */
  --t-sm:  0.875rem;   /* 14px — teks pendamping, isi tabel padat    */
  --t-md:  0.9375rem;  /* 15px — badan halaman                       */
  --t-lg:  1.0625rem;  /* 17px — H3, judul panel, teks pengantar     */
  --t-xl:  1.1875rem;  /* 19px — angka ringkasan                     */
  --t-2xl: 1.3125rem;  /* 21px — H2                                  */
  --t-3xl: 1.75rem;    /* 28px — H1, judul halaman                   */

  --sans: 'Plus Jakarta Sans', 'Segoe UI', Roboto, system-ui, -apple-system, sans-serif;
  --mono: ui-monospace, Consolas, Menlo, monospace;

  --ease: cubic-bezier(.22,.68,.36,1);
}

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; min-height: 100%; }

body {
  font-family: var(--sans);
  font-size: var(--t-md);
  line-height: 1.55;
  color: var(--ink-900);
  background:
    radial-gradient(1100px 520px at 88% -12%, #e2f5e6 0%, transparent 62%),
    radial-gradient(900px 480px at -10% 30%, #eef9f0 0%, transparent 60%),
    radial-gradient(760px 420px at -8% 108%, #fdf6d4 0%, transparent 58%),
    var(--canvas);
  background-attachment: fixed;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

a { color: var(--green-700); text-underline-offset: 3px; }

::selection { background: var(--green-200); }

:focus-visible {
  outline: none;
  box-shadow: var(--ring);
  border-radius: var(--r-sm);
}

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

/* ==========================================================================
   LAYAR PEMUATAN (splash)
   Logo sekolah di tengah, dikelilingi cincin berputar, dengan bilah kemajuan
   tipis di bawahnya. Semuanya CSS murni supaya tampil seketika.
   ========================================================================== */
.boot {
  min-height: 100vh;
  display: grid; place-content: center; justify-items: center;
  gap: 1.15rem; text-align: center; padding: 2rem;
  animation: fade-in .3s var(--ease) both;
}
.boot-mark {
  position: relative;
  width: 132px; height: 132px;
  display: grid; place-content: center;
}
.boot-mark img {
  width: 92px; height: auto; max-height: 92px; object-fit: contain;
  animation: breathe 2.2s var(--ease) infinite;
}
.boot-mark .ring {
  position: absolute; inset: 0;
  border-radius: 50%;
  border: 3px solid var(--green-100);
  border-top-color: var(--green-700);
  border-right-color: var(--gold-500);
  animation: spin 1.15s linear infinite;
}
.boot-word { display: flex; align-items: baseline; gap: .5rem; line-height: 1; }
.boot-word .hpsa {
  font-size: var(--t-2xl); font-weight: 800; letter-spacing: .06em; color: var(--gold-600);
}
.boot-word .live {
  font-size: var(--t-lg); font-weight: 800; letter-spacing: .12em; color: var(--green-700);
}
.boot-bar {
  width: 190px; height: 5px; border-radius: var(--r-pill);
  background: var(--green-100); overflow: hidden;
}
.boot-bar span {
  display: block; height: 100%; width: 42%; border-radius: var(--r-pill);
  background: linear-gradient(90deg, var(--gold-500), var(--green-600));
  animation: boot-slide 1.35s var(--ease) infinite;
}
.boot-note { margin: 0; color: var(--ink-400); font-size: var(--t-xs); }

@keyframes spin { to { transform: rotate(360deg) } }
@keyframes fade-in { from { opacity: 0 } to { opacity: 1 } }
@keyframes boot-slide {
  0%   { transform: translateX(-110%) }
  100% { transform: translateX(255%) }
}
@keyframes breathe { 0%,100% { opacity:.55; transform:scale(.95) } 50% { opacity:1; transform:scale(1.04) } }

/* ==========================================================================
   PITA KAKI
   ========================================================================== */
.footer-strip {
  margin-top: auto;
  padding: 1.4rem 1.75rem 1.6rem;
  display: flex; align-items: center; gap: .7rem; flex-wrap: wrap;
}
.footer-strip .bar {
  height: 6px; border-radius: var(--r-pill); flex: 1 1 120px; min-width: 60px;
  background: linear-gradient(90deg, var(--gold-500) 0 20%, #8dc63f 20% 44%, var(--green-700) 44% 100%);
  opacity: .85;
}
.footer-strip .site {
  background: var(--green-800); color: #fff;
  padding: .25rem .85rem; border-radius: var(--r-pill);
  font-size: var(--t-2xs); font-style: italic; font-weight: 500; white-space: nowrap;
}
.footer-strip .dots { letter-spacing: 3px; color: var(--green-500); font-weight: 900; font-size: var(--t-2xs); }

/* ==========================================================================
   HALAMAN LOGIN
   ========================================================================== */
.login-page {
  min-height: 100vh; display: flex; flex-direction: column;
  position: relative; overflow-x: hidden;
}
/* Latar halaman masuk — foto gedung sekolah beserta selubung peredamnya —
   dinyatakan SEKALI di tambahan.css. Berkas ini sempat ikut menuliskannya pada
   ronde 88, dan aturan di sana (yang menang belakangan) menimpanya diam-diam:
   fotonya tidak pernah tampil, tanpa satu pun galat.

   Kurung tutup yatim sisa penghapusan itu sempat lolos ke dist dan hampir
   terbit: SATU "}" berlebih yang menutup blok berikutnya lebih awal dan
   membuang seluruh aturan sesudahnya. CSS tidak pernah mengeluh soal ini —
   yang menangkapnya hitungan kurung sebelum penerbitan. */
/* Aurora: dua cahaya besar yang MELAYANG sangat pelan — cukup untuk terasa
   hidup, terlalu pelan untuk disadari. Yang meminta gerak dikurangi mendapat
   keduanya diam di tempat. */
.login-page::before, .login-page::after {
  content: ''; position: absolute; border-radius: 50%; pointer-events: none; z-index: 0;
}
.login-page::before {
  width: 640px; height: 640px; top: -220px; right: -180px;
  background: radial-gradient(circle, rgba(74,165,104,.14), rgba(25,180,90,.05) 45%, transparent 68%);
  animation: aurora-a 16s var(--ease) infinite alternate;
}
.login-page::after {
  width: 520px; height: 520px; bottom: -190px; left: -160px;
  background: radial-gradient(circle, rgba(245,212,35,.22), rgba(245,212,35,.08) 45%, transparent 68%);
  animation: aurora-b 19s var(--ease) infinite alternate;
}
@keyframes aurora-a { to { transform: translate(-46px, 34px) scale(1.06); } }
@keyframes aurora-b { to { transform: translate(40px, -30px) scale(1.05); } }
.login-page > * { position: relative; z-index: 1; }

.login-top {
  display: flex; justify-content: space-between; align-items: center;
  padding: 1.1rem 1.9rem 0; gap: 1rem;
}
.brand-logo {
  height: 46px; width: auto; display: block; max-width: 100%;
  /* Tanpa ini, di baris kepala yang penuh sesak `max-width:100%` menekan
     LEBAR gambar sementara tingginya tetap dipatok — dan logo sekolah
     tampil penyok. contain menjaga rasionya: ia mengecil, tidak menggepeng. */
  object-fit: contain; object-position: left center;
}
/* Logo di kepala aplikasi adalah TOMBOL menuju beranda. Tombolnya sendiri
   tidak terlihat — yang terlihat tetap logonya — tetapi ia dapat ditekan,
   dapat dijangkau dengan Tab, dan sasaran sentuhnya 44px seperti tombol lain. */
.brand-home {
  background: none; border: 0; padding: 0; margin: 0; cursor: pointer;
  display: inline-flex; align-items: center; min-height: 44px;
  border-radius: 8px;
}
.brand-home:focus-visible { outline: 2px solid var(--green-600); outline-offset: 3px; }
.brand-home:hover .brand-logo { opacity: .85; }
.brand-tagline { height: 24px; width: auto; display: block; max-width: 100%; }

.login-body {
  flex: 1; display: flex; flex-direction: column; align-items: center;
  justify-content: center; padding: 1rem 1.5rem 1.6rem; gap: .35rem;
}

.wordmark { text-align: center; line-height: .92; user-select: none; animation: rise .6s var(--ease) both; }
.wordmark .hpsa {
  font-size: clamp(2.3rem, 5vw, 3.4rem); font-weight: 800; letter-spacing: .04em;
  background: linear-gradient(180deg, #ffe25c 0%, var(--gold-500) 55%, var(--gold-600) 100%);
  -webkit-background-clip: text; background-clip: text; color: transparent;
  filter: drop-shadow(0 3px 0 rgba(0,0,0,.06));
}
.wordmark .live {
  font-size: clamp(1.3rem, 3vw, 2.05rem); font-weight: 800; letter-spacing: .03em;
  color: var(--green-800);
}
/* Di atas foto, huruf tanpa bayangan larut ke dalam langit dan atap kuning.
   Bayangan putih tipis mengembalikan tepinya tanpa membuatnya tampak timbul. */
.login-page .wordmark .hpsa { filter: drop-shadow(0 2px 6px rgba(255,255,255,.75)); }
.login-page .wordmark .live { text-shadow: 0 1px 8px rgba(255,255,255,.9); }
.login-page .login-sub { text-shadow: 0 1px 6px rgba(255,255,255,.85); }
.login-sub {
  margin: .35rem 0 1.15rem; text-align: center; max-width: 34rem;
  color: var(--ink-600); font-size: var(--t-xs);
  animation: rise .6s .05s var(--ease) both;
}

.login-card {
  background: rgba(255,255,255,.82);
  -webkit-backdrop-filter: var(--blur);
  backdrop-filter: var(--blur);
  border: 1px solid var(--glass-brd);
  border-radius: 26px;
  box-shadow: var(--sh-3), inset 0 1px 0 rgba(255,255,255,.85);
  padding: 1.7rem 1.7rem 1.3rem;
  width: min(384px, 100%);
  animation: rise .6s .1s var(--ease) both;
}
.login-card .avatar-icon {
  width: 64px; height: 64px; margin: -2.7rem auto .75rem;
  border-radius: 50%;
  background: linear-gradient(160deg, var(--green-600), var(--green-800));
  color: #fff;
  display: grid; place-content: center;
  box-shadow: var(--glow-hover), 0 0 0 6px rgba(255,255,255,.9), 0 0 22px rgba(25,180,90,.35);
}
.login-card .avatar-icon svg { width: 34px; height: 34px; display: block; }

.login-greet {
  margin: 0 0 1.1rem; text-align: center;
  color: var(--ink-600); font-size: var(--t-xs);
}

.login-form { display: flex; flex-direction: column; }

.login-field { display: block; margin-bottom: .75rem; }
.login-field .lbl {
  display: block; margin-bottom: .35rem;
  font-size: var(--t-2xs); font-weight: 600; letter-spacing: .03em;
  text-transform: uppercase; color: var(--ink-600);
}
.login-field .box {
  display: flex; align-items: center; gap: .55rem;
  border: 1.5px solid rgba(211,224,216,.9); border-radius: var(--r-pill);
  background: rgba(255,255,255,.7); padding: 0 .5rem 0 .95rem;
  transition: border-color .16s var(--ease), box-shadow .16s var(--ease), background .16s;
}
.login-field .box:hover { border-color: var(--green-300); }
.login-field .box:focus-within {
  border-color: var(--green-500); background: #fff;
  box-shadow: var(--ring), 0 0 14px rgba(25,180,90,.18);
}
.login-field .ic { display: grid; place-content: center; color: var(--green-700); flex: none; }
.login-field .ic svg { width: 19px; height: 19px; display: block; }
.login-field input {
  flex: 1; min-width: 0; border: 0; background: transparent; outline: none;
  font: inherit; color: var(--ink-900); padding: .72rem 0;
}
.login-field input::placeholder { color: var(--ink-400); }
.login-field .peek {
  flex: none; border: 0; background: transparent; cursor: pointer;
  color: var(--ink-400); padding: .4rem; border-radius: 50%;
  display: grid; place-content: center; transition: color .16s, background .16s;
}
.login-field .peek:hover { color: var(--green-700); background: var(--green-100); }
.login-field .peek svg { width: 19px; height: 19px; display: block; }

.login-caps {
  display: none; margin: -.35rem 0 .55rem;
  font-size: var(--t-2xs); color: var(--warn); font-weight: 600; text-align: center;
}
.login-caps.on { display: block; }

.login-error {
  display: none; align-items: center; gap: .55rem;
  margin: .1rem 0 .85rem; padding: .6rem .85rem;
  border-radius: var(--r); border: 1px solid #f3c9c3;
  background: var(--danger-bg); color: var(--danger);
  font-size: var(--t-xs); font-weight: 500; text-align: left;
}
.login-error.on { display: flex; animation: shake .35s var(--ease); }
.login-error .ic {
  flex: none; width: 20px; height: 20px; border-radius: 50%;
  background: var(--danger); color: #fff;
  display: grid; place-content: center;
  font-size: var(--t-2xs); font-weight: 800;
}
@keyframes shake { 25% { transform: translateX(-4px) } 75% { transform: translateX(4px) } }

.btn-login {
  width: 100%; margin-top: .25rem; padding: .72rem;
  border: 0; border-radius: var(--r-pill);
  background: linear-gradient(180deg, var(--green-700), var(--green-800));
  color: #fff; font: inherit; font-weight: 700; letter-spacing: .01em;
  cursor: pointer; box-shadow: var(--glow);
  transition: transform .12s var(--ease), box-shadow .16s, filter .16s;
  display: flex; align-items: center; justify-content: center; gap: .55rem;
}
.btn-login { position: relative; overflow: hidden; }
/* Kilau tipis yang menyapu saat kursor hinggap — sekali, bukan berulang. */
.btn-login::after {
  content: ''; position: absolute; top: 0; bottom: 0; left: -60%; width: 40%;
  background: linear-gradient(105deg, transparent, rgba(255,255,255,.28), transparent);
  transform: skewX(-18deg); pointer-events: none;
}
.btn-login:hover:not(:disabled) {
  filter: brightness(1.09); box-shadow: var(--glow-hover); transform: translateY(-1px);
}
.btn-login:hover:not(:disabled)::after { animation: sapu-kilau .7s var(--ease); }
@keyframes sapu-kilau { to { left: 120%; } }
.btn-login:active:not(:disabled) { transform: translateY(1px); }
.btn-login:disabled { opacity: .75; cursor: progress; box-shadow: none; }
.btn-login.busy::before {
  content: ''; width: 15px; height: 15px; flex: none;
  border-radius: 50%; border: 2px solid rgba(255,255,255,.35); border-top-color: #fff;
  animation: spin .7s linear infinite;
}

.link-btn {
  margin: .7rem auto 0; display: block;
  border: 0; background: none; cursor: pointer;
  font: inherit; font-size: var(--t-xs); font-weight: 600; color: var(--green-700);
  padding: .3rem .5rem; border-radius: var(--r-sm);
  transition: color .15s, background .15s;
}
.link-btn:hover { color: var(--green-900); background: var(--green-100); }

.login-hint { text-align: center; color: var(--ink-600); font-size: var(--t-2xs); margin: 1.1rem 0 0; }

/* Pada layar pendek, pita kaki dirapatkan agar kartu tidak terdorong keluar. */
.login-page .footer-strip { padding: .9rem 1.75rem 1rem; }

@media (max-height: 760px) {
  .login-top { padding: .8rem 1.9rem 0; }
  .brand-logo { height: 40px; }
  .brand-tagline { height: 21px; }
  .wordmark .hpsa { font-size: clamp(2rem, 4vw, 2.7rem); }
  .wordmark .live { font-size: clamp(1.15rem, 2.4vw, 1.7rem); }
  .login-sub { margin-bottom: .9rem; }
  .login-card { padding: 1.5rem 1.6rem 1.2rem; }
  .login-hint { margin-top: .8rem; }
  .login-page .footer-strip { padding: .6rem 1.75rem .7rem; }
}

@media (max-width: 560px) {
  .login-top { padding: 1.1rem 1.1rem 0; flex-direction: column; gap: .5rem; }
  .brand-logo { height: 44px; }
  .brand-tagline { height: 22px; }
  .login-card { padding: 1.8rem 1.3rem 1.4rem; border-radius: var(--r-lg); }
  .login-sub { margin-bottom: 1.3rem; font-size: var(--t-xs); }
}

/* ==========================================================================
   KERANGKA APLIKASI
   ========================================================================== */
.app { min-height: 100vh; display: flex; flex-direction: column; }

.app-header {
  position: sticky; top: 0; z-index: 30;
  display: flex; justify-content: space-between; align-items: center;
  padding: .7rem 1.75rem; gap: 1rem;
  background: var(--glass);
  -webkit-backdrop-filter: var(--blur);
  backdrop-filter: var(--blur);
  border-bottom: 1px solid rgba(226,235,229,.7);
  box-shadow: 0 1px 12px rgba(16,40,28,.04);
}
.app-header .brand-logo { height: 40px; }
.app-header .brand-tagline { height: 22px; opacity: .9; }
.header-left { display: flex; align-items: center; gap: 1.3rem; }

/* ---------- menu pengguna ---------- */
.user-menu { position: relative; }
.user-button {
  display: flex; align-items: center; gap: .6rem;
  background: none; border: 1px solid transparent; border-radius: var(--r-pill);
  padding: .3rem .7rem .3rem .35rem; font: inherit; cursor: pointer; color: var(--ink-900);
  transition: background .16s, border-color .16s;
}
.user-button:hover { background: var(--green-050); border-color: var(--line); }
.user-button .name { font-weight: 600; font-size: var(--t-md); }
.user-button .caret { font-size: var(--t-2xs); color: var(--ink-400); }

.avatar {
  width: 38px; height: 38px; border-radius: 50%; flex: none;
  display: grid; place-content: center; overflow: hidden;
  background: linear-gradient(145deg, var(--green-500), var(--green-800));
  color: #fff; font-weight: 700; font-size: var(--t-xs); letter-spacing: .02em;
  box-shadow: inset 0 0 0 2px rgba(255,255,255,.55);
}
.avatar img { width: 100%; height: 100%; object-fit: cover; display: block; }
.avatar.lg { width: 104px; height: 104px; font-size: 2rem; }
.avatar.xl { width: 132px; height: 132px; font-size: 2.6rem; }

.user-drop {
  position: absolute; right: 0; top: calc(100% + .55rem); z-index: 40;
  background: var(--paper); border: 1px solid var(--line);
  border-radius: var(--r); min-width: 254px;
  box-shadow: var(--sh-3); overflow: hidden;
  animation: pop .16s var(--ease);
}
@keyframes pop { from { opacity: 0; transform: translateY(-6px) scale(.98) } }
.user-drop .who {
  padding: .9rem 1rem; display: flex; gap: .7rem; align-items: center;
  border-bottom: 1px solid var(--line); background: var(--green-050);
}
.user-drop .who b { display: block; font-weight: 700; font-size: var(--t-md); }
.user-drop .who span { font-size: var(--t-xs); color: var(--ink-600); }
.user-drop button, .user-drop a {
  display: flex; gap: .6rem; align-items: center; width: 100%;
  padding: .7rem 1rem; background: none; border: 0; font: inherit;
  cursor: pointer; color: var(--ink-800); text-decoration: none; text-align: left;
  transition: background .14s;
}
.user-drop button:hover, .user-drop a:hover { background: var(--green-050); }
.user-drop .sep { height: 1px; background: var(--line); }
.user-drop .danger { color: var(--danger); }

/* ---------- remah roti ---------- */
.crumbs {
  padding: 1rem 1.75rem .1rem;
  font-size: var(--t-sm); color: var(--ink-400);
  display: flex; align-items: center; flex-wrap: wrap; gap: .1rem;
}
.crumbs a {
  color: var(--ink-600); text-decoration: none; cursor: pointer;
  padding: .18rem .5rem; border-radius: var(--r-sm);
  transition: background .14s, color .14s;
}
.crumbs a:hover { background: var(--green-100); color: var(--green-800); }
.crumbs .sep { margin: 0 .1rem; color: var(--ink-200); }
.crumbs .here { color: var(--ink-900); font-weight: 600; padding: .18rem .5rem; }

/* --------------------------------------------------------------------------
   SATU KOLOM ISI
   Sebelumnya .page selebar layar dan tiap blok memusatkan dirinya sendiri di
   lebar masing-masing: pemberitahuan 780, kartu 940 atau 1010, panel 900,
   riwayat 880. Di layar 1440 hasilnya bertingkat-tingkat — judul mentok di
   tepi kiri, kartu mengambang di tengah, tabel di lebar ketiga. Sekarang
   seluruh halaman memakai satu kolom, dan blok mengikuti kolom itu.
   -------------------------------------------------------------------------- */
.page {
  flex: 1; width: 100%; max-width: var(--kolom); margin-inline: auto;
  padding: .6rem 1.75rem 2rem; animation: rise .34s var(--ease) both;
}

/* Halaman yang isinya hanya kartu pilihan.
   Dulu isinya dipusatkan tegak (justify-content: center) agar tidak
   menggantung di atas. Akibatnya justru muncul ruang kosong sampai 271 piksel
   DI ATAS judul, dan judulnya terlepas jauh dari remah jejak. Sekarang isinya
   tetap mulai dari atas, hanya diberi jarak napas yang terbatas. */
.page.chooser {
  display: flex; flex-direction: column; justify-content: flex-start;
  padding-top: clamp(.6rem, 4vh, 2.6rem);
  padding-bottom: 4rem;
}
/* Sisa ruangnya dibagi, bukan ditumpuk seluruhnya di bawah.
   Halaman pemilih memang pendek: judul, satu kalimat, beberapa kartu. Di layar
   laptop isinya berhenti di sepertiga atas dan menyisakan ruang kosong
   menganga sampai ke kaki halaman — layar yang terbaca "belum selesai memuat".
   Ruang bebasnya kini dibagi 2 : 3, condong kuat ke atas, dengan batas tegas di
   atas supaya judulnya tidak pernah terlepas jauh dari remah jejak seperti
   ketika halaman ini pernah dipusatkan penuh (dulu 271 piksel). */
.page.chooser::before,
.page.chooser::after { content: ''; display: block; }
@media (min-height: 620px) {
  .page.chooser::before { flex: 2 1 0; max-height: 6vh; }
  .page.chooser::after { flex: 3 1 0; }
}
@keyframes rise { from { opacity: 0; transform: translateY(10px) } }

/* --------------------------------------------------------------------------
   HIERARKI JUDUL

   Sebelum ini H1 terukur 21–22px dan H2 justru 22–23px — judul tingkat dua
   LEBIH BESAR daripada tingkat satu. Akibatnya mata tidak punya tangga untuk
   memindai halaman: semuanya tampak sama penting, jadi tidak ada yang menonjol.
   H3 pun bercabang tiga (16, 17, dan 18px) tergantung siapa yang menulisnya.

   Sekarang ketiganya ditetapkan sekali di sini, dengan jarak yang cukup jauh
   untuk terbaca sebagai tingkatan: 28 → 21 → 17 → 15.
   -------------------------------------------------------------------------- */
h1 { font-size: var(--t-3xl); font-weight: 800; letter-spacing: -.015em; line-height: 1.2; }
h2 { font-size: var(--t-2xl); font-weight: 800; letter-spacing: -.01em;  line-height: 1.25; }
h3 { font-size: var(--t-lg);  font-weight: 700; line-height: 1.35; }
h4 { font-size: var(--t-md);  font-weight: 700; line-height: 1.4; }

.page-title {
  text-align: center; font-size: var(--t-3xl); font-weight: 800;
  letter-spacing: -.015em; line-height: 1.2; margin: .7rem 0 1.5rem;
}
.page-lead {
  text-align: center; color: var(--ink-600); font-size: var(--t-md);
  margin: -1rem 0 2rem;
}

.meta-list {
  margin: 0 0 1.5rem; display: inline-grid; gap: .3rem .8rem;
  background: var(--paper); border: 1px solid var(--line);
  border-radius: var(--r); padding: .9rem 1.2rem; box-shadow: var(--sh-1);
}
.meta-list div { display: flex; gap: .5rem; font-size: var(--t-md); }
.meta-list dt { width: 122px; flex: none; color: var(--ink-600); }
.meta-list dd { margin: 0; font-weight: 600; }
.meta-list dt::after { content: ':'; float: right; color: var(--ink-200); }

/* ==========================================================================
   TILE
   ========================================================================== */
/* Petak, bukan aliran. Jumlah kolomnya (--tile-kolom) dihitung ui.js dari
   lebar yang benar-benar tersedia, lalu dibagi seimbang: enam kartu yang
   hanya muat lima menjadi 3 + 3, bukan 5 + 1. */
.tiles {
  display: grid;
  grid-template-columns: repeat(var(--tile-kolom, 1), max-content);
  gap: 1.15rem; justify-content: center; align-items: stretch;
  margin: 0 auto; max-width: 940px;
}

.tile {
  position: relative;
  background: var(--tile); border: 1px solid var(--line); border-radius: var(--r-lg);
  cursor: pointer; font: inherit; color: var(--ink-900); text-decoration: none;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: .7rem; text-align: center; box-shadow: var(--sh-1);
  transition: transform .18s var(--ease), box-shadow .18s var(--ease),
              border-color .18s, background .18s;
}
.tile::after {
  content: ''; position: absolute; inset: 0; border-radius: inherit;
  background: linear-gradient(160deg, rgba(47,139,82,.06), transparent 55%);
  opacity: 0; transition: opacity .18s;
}
.tile:hover { transform: translateY(-3px); box-shadow: var(--sh-3); border-color: var(--green-300); }
.tile:hover::after { opacity: 1; }
.tile:active { transform: translateY(-1px); }

.tile.icon { width: 194px; height: 194px; padding: 1.5rem 1rem; }
.tile.icon .glyph {
  width: 76px; height: 76px; border-radius: var(--r-lg);
  display: grid; place-content: center; font-size: 2.4rem; line-height: 1;
  background: linear-gradient(150deg, var(--green-100), var(--green-200));
  box-shadow: var(--line-in);
  transition: transform .2s var(--ease);
}
.tile.icon:hover .glyph { transform: scale(1.06) rotate(-2deg); }
.tile.icon .label { font-weight: 700; font-size: var(--t-sm); letter-spacing: .015em; }

.tile.block { min-width: 214px; padding: 1.25rem 2rem; font-weight: 700; font-size: var(--t-lg); }
.tile.block .sub { font-weight: 500; font-size: var(--t-2xs); color: var(--ink-600); }

.tile.square { width: 168px; height: 168px; font-weight: 700; gap: .1rem; }
.tile.square .top { font-size: var(--t-md); color: var(--ink-600); font-weight: 600; }
.tile.square .big {
  font-size: 3.1rem; line-height: 1; font-weight: 800;
  background: linear-gradient(180deg, var(--green-600), var(--green-800));
  -webkit-background-clip: text; background-clip: text; color: transparent;
}

.tile.pill { border-radius: var(--r-pill); padding: .95rem 2.1rem; font-weight: 700; min-width: 200px; }
.tile.pill.wide { min-width: 330px; }

.tile.current { border-color: var(--green-700); box-shadow: var(--sh-2), var(--ring); }

/* ---------- baris tile + bar kemajuan ---------- */
.tile-rows { display: flex; flex-direction: column; gap: .85rem; max-width: 940px; margin: 0 auto; }
.tile-row {
  display: grid; grid-template-columns: 250px 1fr auto; gap: 1.2rem; align-items: center;
  background: var(--paper); border: 1px solid var(--line); border-radius: var(--r-lg);
  padding: .55rem .9rem .55rem .55rem; box-shadow: var(--sh-1);
  transition: box-shadow .18s, border-color .18s, transform .18s var(--ease);
}
.tile-row:hover { box-shadow: var(--sh-2); border-color: var(--green-300); transform: translateY(-1px); }
.tile-row .tile { width: 100%; min-width: 0; box-shadow: none; border-color: transparent; background: var(--green-050); }
.tile-row .tile:hover { transform: none; box-shadow: none; background: var(--green-100); }
@media (max-width: 720px) {
  .tile-row { grid-template-columns: 1fr; gap: .6rem; }
  .tile-row .pct { text-align: right; }
}

.progress {
  background: var(--green-100); border-radius: var(--r-pill); height: 16px; overflow: hidden;
  box-shadow: inset 0 1px 2px rgba(16,40,28,.06);
}
.progress > span {
  display: block; height: 100%; border-radius: var(--r-pill);
  background: linear-gradient(90deg, var(--green-500), var(--green-700));
  transition: width .5s var(--ease);
}
.progress.slim { height: 10px; }
.pct { white-space: nowrap; font-size: var(--t-sm); color: var(--ink-600); font-weight: 600; }

/* ==========================================================================
   TABEL NILAI (susunan bertingkat sesuai kerangka)
   ========================================================================== */
.table-wrap {
  overflow-x: auto; padding: 2px 2px 8px;
  scrollbar-width: thin;
}
.table-wrap::-webkit-scrollbar { height: 9px; }
.table-wrap::-webkit-scrollbar-thumb { background: var(--ink-200); border-radius: var(--r-pill); }

table.grid {
  border-collapse: separate; border-spacing: 0;
  margin: 0 auto; font-size: var(--t-md);
  background: var(--paper);
  border-radius: var(--r); overflow: hidden;
  box-shadow: var(--sh-2);
}
table.grid th, table.grid td {
  border-right: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  padding: .62rem 1rem; text-align: center; white-space: nowrap;
}
table.grid th:last-child, table.grid td:last-child { border-right: 0; }
table.grid tbody tr:last-child td { border-bottom: 0; }
table.grid thead th {
  background: var(--green-050); font-weight: 700; color: var(--green-900);
  font-size: var(--t-sm); letter-spacing: .01em;
}
table.grid thead tr:first-child th { background: var(--green-100); }
table.grid th.blank { background: transparent !important; border-right: 0; border-bottom: 0; }
table.grid th.group { cursor: pointer; transition: background .16s; }
table.grid th.group:hover { background: var(--green-200); }
table.grid td.name, table.grid th.name { text-align: left; font-weight: 500; }
table.grid tbody tr { transition: background .14s; }
table.grid tbody tr:nth-child(even) td { background: #fcfdfc; }
table.grid tbody tr:hover td { background: var(--green-050); }
table.grid td.calc { font-weight: 700; color: var(--green-800); background: #f7fbf8 !important; }
table.grid td.calc.below { color: var(--danger); }
table.grid td.disabled { background: repeating-linear-gradient(135deg,#fafafa,#fafafa 6px,#f2f2f2 6px,#f2f2f2 12px) !important; }
table.grid input[type=number] {
  width: 74px; border: 1px solid transparent; border-radius: var(--r-sm);
  background: transparent; font: inherit; text-align: center; padding: .28rem;
  transition: border-color .14s, background .14s, box-shadow .14s;
  -moz-appearance: textfield;
}
table.grid input[type=number]::-webkit-outer-spin-button,
table.grid input[type=number]::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
table.grid input[type=number]:hover { border-color: var(--line-2); background: #fff; }
table.grid input[type=number]:focus { outline: none; border-color: var(--green-500); background: #fff; box-shadow: var(--ring); }
table.grid td.empty-note { color: var(--ink-400); padding: 2.4rem 1rem; }

/* ---------- tabel daftar ---------- */
table.list {
  border-collapse: separate; border-spacing: 0; width: 100%; max-width: 1080px; margin: 0 auto;
  background: var(--paper); border: 1px solid var(--line);
  border-radius: var(--r); overflow: hidden; box-shadow: var(--sh-2);
}
table.list th {
  background: var(--green-050); color: var(--green-900); font-weight: 700;
  padding: .8rem 1.1rem; text-align: left; font-size: var(--t-xs);
  letter-spacing: .04em; text-transform: uppercase;
  border-bottom: 1px solid var(--line);
}
table.list td {
  padding: .78rem 1.1rem; border-bottom: 1px solid var(--line); font-size: var(--t-md);
}
table.list tbody tr { transition: background .14s; }
table.list tbody tr:hover td { background: var(--green-050); }
table.list tbody tr:last-child td { border-bottom: 0; }
table.list td.no { text-align: center; width: 68px; color: var(--ink-400); }
table.list .act-links { display: flex; gap: 1.4rem; }
table.list .act-links button {
  background: none; border: 0; font: inherit; font-weight: 600; cursor: pointer;
  color: var(--green-700); padding: 0; transition: color .14s;
}
table.list .act-links button:hover { color: var(--green-900); text-decoration: underline; }
table.list .act-links button.danger { color: var(--danger); }
table.list .kosong { text-align: center; color: var(--ink-400); padding: 2.4rem; }

/* lencana status */
.badge {
  display: inline-block; padding: .16rem .6rem; border-radius: var(--r-pill);
  font-size: var(--t-2xs); font-weight: 700; background: var(--green-100); color: var(--green-800);
}
.badge.ok { background: var(--ok-bg); color: var(--ok); }
.badge.danger { background: var(--danger-bg); color: var(--danger); }
.badge.warn { background: var(--warn-bg); color: var(--warn); }
.badge.grey { background: #eef1ef; color: var(--ink-600); }

/* ==========================================================================
   TOMBOL
   ========================================================================== */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: .45rem;
  background: var(--paper); border: 1px solid var(--line-2); border-radius: var(--r-pill);
  padding: .58rem 1.35rem; font: inherit; font-weight: 600; font-size: var(--t-md);
  cursor: pointer; color: var(--ink-800); text-decoration: none; white-space: nowrap;
  box-shadow: var(--sh-1);
  transition: transform .12s var(--ease), box-shadow .16s, background .16s, border-color .16s, color .16s;
}
.btn:hover:not(:disabled) { background: var(--green-050); border-color: var(--green-300); color: var(--green-800); box-shadow: var(--sh-2); }
.btn:active:not(:disabled) { transform: translateY(1px); box-shadow: var(--sh-1); }
.btn:disabled { opacity: .45; cursor: not-allowed; box-shadow: none; }

.btn.primary {
  background: linear-gradient(180deg, var(--green-700), var(--green-800));
  color: #fff; border-color: transparent; box-shadow: var(--glow);
}
.btn.primary:hover:not(:disabled) { filter: brightness(1.08); color: #fff; box-shadow: var(--glow-hover); }

.btn.gold {
  background: linear-gradient(180deg, #ffe25c, var(--gold-500));
  color: #4a3b00; border-color: transparent; box-shadow: var(--glow-gold);
}
.btn.gold:hover:not(:disabled) { filter: brightness(1.05); color: #3d3000; }

.btn.danger { color: var(--danger); border-color: #f0c8c3; }
.btn.danger:hover:not(:disabled) { background: var(--danger-bg); color: var(--danger); border-color: #e6a79f; }

.btn.sm { padding: .35rem 1rem; font-size: var(--t-xs); }
.btn.ghost { background: transparent; box-shadow: none; border-color: transparent; }

.toolbar { display: flex; gap: .7rem; flex-wrap: wrap; margin-bottom: 1.5rem; align-items: center; }
.toolbar.right { justify-content: flex-end; }
.toolbar.center { justify-content: center; }

/* chip */
.chips { display: flex; gap: .5rem; align-items: center; flex-wrap: wrap; }
.chips > span:first-child { color: var(--ink-600); font-size: var(--t-sm); }
.chip {
  background: var(--paper); border: 1px solid var(--line-2); border-radius: var(--r-pill);
  padding: .35rem 1.05rem; font: inherit; font-size: var(--t-sm); font-weight: 600;
  cursor: pointer; color: var(--ink-800); box-shadow: var(--sh-1);
  transition: background .16s, border-color .16s, color .16s, transform .12s var(--ease);
}
.chip:hover { background: var(--green-050); border-color: var(--green-300); color: var(--green-800); }
.chip:active { transform: translateY(1px); }
.chip.add { border-style: dashed; color: var(--green-700); }
.chip.on {
  background: linear-gradient(180deg, var(--green-700), var(--green-800));
  color: #fff; border-color: transparent; box-shadow: var(--glow);
}

/* ==========================================================================
   DIALOG
   ========================================================================== */
.backdrop {
  position: fixed; inset: 0; background: rgba(11,40,25,.42);
  backdrop-filter: blur(3px);
  display: grid; place-items: center; z-index: 90; padding: 1rem;
  animation: fade .18s var(--ease);
}
@keyframes fade { from { opacity: 0 } }

/* saat ditutup, dialog memudar sejenak sebelum benar-benar dilepas */
.backdrop.closing { animation: fade-out .14s var(--ease) both; pointer-events: none; }
.backdrop.closing .dialog, .backdrop.closing .alert-box { transform: scale(.98); transition: transform .14s var(--ease); }
@keyframes fade-out { to { opacity: 0 } }

.dialog {
  background: var(--paper); border-radius: var(--r-lg);
  width: min(600px, 100%); max-height: 88vh; overflow: auto;
  box-shadow: var(--sh-3); animation: rise .24s var(--ease) both;
}
.dialog.narrow { width: min(420px, 100%); }
.dialog.wide   { width: min(860px, 100%); }
.dialog-head {
  display: flex; justify-content: space-between; align-items: center;
  padding: 1.1rem 1.35rem; border-bottom: 1px solid var(--line);
  font-size: var(--t-lg); font-weight: 700;
  position: sticky; top: 0; background: var(--paper); z-index: 1;
}
.dialog-head button {
  background: none; border: 0; font-size: var(--t-xl); line-height: 1; cursor: pointer;
  color: var(--ink-400); width: 34px; height: 34px; border-radius: 50%;
  transition: background .14s, color .14s;
}
.dialog-head button:hover { background: var(--green-050); color: var(--ink-900); }
.dialog-body { padding: 1.4rem 1.35rem; }
.dialog-foot { padding: 0 1.35rem 1.35rem; display: flex; justify-content: flex-end; gap: .7rem; }

.alert-box {
  background: var(--paper); border-radius: var(--r-lg); box-shadow: var(--sh-3);
  min-width: 310px; max-width: 400px; padding: 1.8rem 1.6rem 1.3rem; text-align: center;
  animation: rise .24s var(--ease) both;
}
.alert-box .mark {
  width: 56px; height: 56px; margin: 0 auto .9rem; border-radius: 50%;
  background: var(--ok-bg); color: var(--ok);
  display: grid; place-content: center; font-size: 1.6rem;
}
.alert-box p { margin: 0 0 1.2rem; font-weight: 600; }
.alert-box button {
  background: linear-gradient(180deg, var(--green-700), var(--green-800));
  color: #fff; border: 0; border-radius: var(--r-pill);
  padding: .5rem 2.2rem; font: inherit; font-weight: 700; cursor: pointer;
  box-shadow: var(--glow);
}

/* ==========================================================================
   FORMULIR
   ========================================================================== */
.field { margin-bottom: 1.15rem; }
.field > label {
  display: block; font-size: var(--t-xs); font-weight: 700; letter-spacing: .02em;
  color: var(--ink-600); margin-bottom: .35rem; padding-left: .2rem;
  text-transform: uppercase;
}
.field input, .field select, .field textarea {
  width: 100%; padding: .62rem 1rem; font: inherit;
  border: 1px solid var(--line-2); border-radius: var(--r-pill);
  background: #fbfdfb; color: var(--ink-900);
  transition: border-color .16s, box-shadow .16s, background .16s;
}
.field textarea { border-radius: var(--r); min-height: 78px; resize: vertical; }
.field input:focus, .field select:focus, .field textarea:focus {
  outline: none; border-color: var(--green-500); box-shadow: var(--ring); background: #fff;
}
.field input:disabled, .field select:disabled { background: #f1f4f2; color: var(--ink-400); }
.field .hint { font-size: var(--t-2xs); color: var(--ink-400); margin-top: .3rem; padding-left: 1rem; }
.field.err input, .field.err select { border-color: var(--danger); box-shadow: 0 0 0 3px rgba(192,57,43,.14); }

.form-2col { display: grid; grid-template-columns: 1fr 1fr; gap: 0 2rem; }
@media (max-width: 720px) { .form-2col { grid-template-columns: 1fr; } }

.card {
  background: var(--paper); border: 1px solid var(--line);
  border-radius: var(--r-lg); box-shadow: var(--sh-2); padding: 1.6rem;
}
.card + .card { margin-top: 1.2rem; }
.card h3 { margin: 0 0 1.1rem; }   /* ukuran & tebalnya ikut h3 sedunia */

/* unggah berkas */
.dropzone {
  border: 2px dashed var(--line-2); border-radius: var(--r);
  padding: 2.2rem 1rem; text-align: center; background: #fbfdfb;
  transition: border-color .16s, background .16s;
}
.dropzone.hover { border-color: var(--green-500); background: var(--green-050); }
.dropzone .big { font-weight: 700; }
.dropzone small { display: block; color: var(--ink-400); font-size: var(--t-xs); margin-top: .2rem; }

/* ==========================================================================
   GRAFIK BATANG NILAI SISWA
   ========================================================================== */
.score-bars {
  display: flex; flex-direction: column; gap: 1.5rem;
  max-width: 880px; margin: 1.6rem auto 0;
  background: var(--paper); border: 1px solid var(--line);
  border-radius: var(--r-lg); box-shadow: var(--sh-2); padding: 1.9rem 1.7rem;
}
.score-bar { display: grid; grid-template-columns: 116px 1fr; gap: 1.1rem; align-items: center; }
.score-bar .tag {
  background: var(--green-050); border: 1px solid var(--line);
  border-radius: var(--r-sm); padding: .5rem .4rem; text-align: center;
  font-size: var(--t-md); font-weight: 700; color: var(--green-900);
}
.score-bar .track { position: relative; }
.score-bar .out { position: absolute; right: 0; top: -1.35rem; font-size: var(--t-sm); font-weight: 700; color: var(--ink-600); }
.score-bar .progress { height: 20px; }
.score-bar.total .tag { background: var(--green-700); color: #fff; border-color: transparent; }
.score-bar.total .progress > span { background: linear-gradient(90deg, var(--gold-500), var(--green-600)); }
@media (max-width: 560px) { .score-bar { grid-template-columns: 88px 1fr; } }

/* ==========================================================================
   KEADAAN KOSONG, MEMUAT, PEMBERITAHUAN
   ========================================================================== */
.empty-state {
  text-align: center; color: var(--ink-600); padding: 3rem 1rem;
  max-width: 520px; margin: 0 auto;
}
.empty-state .mark {
  width: 74px; height: 74px; margin: 0 auto 1.1rem; border-radius: var(--r-lg);
  background: var(--green-100); color: var(--green-700);
  display: grid; place-content: center; font-size: 2rem;
}
.empty-state b { display: block; color: var(--ink-900); font-size: var(--t-lg); margin-bottom: .35rem; }

.skeleton {
  max-width: 940px; margin: 0 auto; display: flex; flex-direction: column; gap: .8rem;
}
.skeleton .bar {
  height: 58px; border-radius: var(--r); background: var(--paper);
  border: 1px solid var(--line);
  background-image: linear-gradient(100deg, transparent 20%, rgba(47,139,82,.07) 40%, transparent 60%);
  background-size: 250% 100%;
  animation: shimmer 1.3s linear infinite;
}
.skeleton .bar:nth-child(2) { animation-delay: .12s }
.skeleton .bar:nth-child(3) { animation-delay: .24s }
@keyframes shimmer { from { background-position: 180% 0 } to { background-position: -60% 0 } }

.notice {
  max-width: 780px; margin: 0 auto 1.5rem; padding: .85rem 1.15rem;
  background: var(--warn-bg); border: 1px solid #f0dcae; border-left: 4px solid var(--warn);
  border-radius: var(--r-sm); font-size: var(--t-sm); color: #6d4a08;
}
.notice.err { background: var(--danger-bg); border-color: #f0c8c3; border-left-color: var(--danger); color: #8c2b20; }
.notice.info { background: var(--green-050); border-color: var(--green-200); border-left-color: var(--green-700); color: var(--green-900); }

.search-box { display: flex; gap: .4rem; justify-content: flex-end; margin-bottom: 1.2rem; }
.search-box input {
  border-radius: var(--r-pill); border: 1px solid var(--line-2);
  padding: .5rem 1.1rem; background: var(--paper); font: inherit; min-width: 240px;
  box-shadow: var(--sh-1); transition: border-color .16s, box-shadow .16s;
}
.search-box input:focus { outline: none; border-color: var(--green-500); box-shadow: var(--ring); }
.search-box button { background: none; border: 0; cursor: pointer; font-size: var(--t-lg); color: var(--ink-400); }

/* ---------- toast ---------- */
.toast-host {
  position: fixed; right: 1.2rem; bottom: 1.2rem; z-index: 100;
  display: flex; flex-direction: column; gap: .55rem; max-width: 340px;
}
.toast {
  background: var(--ink-900); color: #fff; padding: .7rem 1.05rem;
  border-radius: var(--r-sm); font-size: var(--t-sm); font-weight: 500;
  box-shadow: var(--sh-3); animation: slidein .22s var(--ease);
}
.toast.ok { background: var(--green-700); }
.toast.danger { background: var(--danger); }
@keyframes slidein { from { opacity: 0; transform: translateX(14px) } }

/* ==========================================================================
   HALAMAN PROFIL
   ========================================================================== */
.profile-grid { display: grid; grid-template-columns: 300px 1fr; gap: 1.4rem; max-width: 960px; margin: 0 auto; }
@media (max-width: 800px) { .profile-grid { grid-template-columns: 1fr; } }

.profile-card { text-align: center; }
.profile-card .avatar { margin: 0 auto 1rem; }
.profile-card h2 { margin: 0 0 .2rem; font-size: var(--t-xl); }
.profile-card .role { color: var(--ink-600); font-size: var(--t-sm); margin-bottom: 1.2rem; }
.profile-card .unit-badges { display: flex; gap: .4rem; justify-content: center; flex-wrap: wrap; margin-bottom: 1.3rem; }
.avatar-actions { display: flex; gap: .5rem; justify-content: center; flex-wrap: wrap; }

.avatar-drop {
  position: relative; display: inline-block; border-radius: 50%; cursor: pointer;
}
.avatar-drop .overlay {
  position: absolute; inset: 0; border-radius: 50%;
  background: rgba(11,40,25,.55); color: #fff;
  display: grid; place-content: center; font-size: var(--t-2xs); font-weight: 700;
  opacity: 0; transition: opacity .18s;
}
.avatar-drop:hover .overlay { opacity: 1; }

/* ==========================================================================
   LAIN-LAIN
   ========================================================================== */
.muted { color: var(--ink-400); }
.small { font-size: var(--t-sm); }
.center { text-align: center; }
.hide { display: none !important; }
.stack > * + * { margin-top: 1rem; }
.spacer { height: 1.6rem; }

@media (max-width: 720px) {
  .app-header { padding: .6rem 1rem; }
  .app-header .brand-tagline { display: none; }
  .app-header .brand-logo { height: 32px; }
  .user-button .name { display: none; }
  .crumbs, .page { padding-left: 1rem; padding-right: 1rem; }
  .tile.icon { width: 152px; height: 152px; }
  .tile.icon .glyph { width: 60px; height: 60px; font-size: 1.9rem; }
  .footer-strip { padding: 1rem; }
}

@media print {
  .app-header, .crumbs, .toolbar, .footer-strip, .btn, .chips, .search-box { display: none !important; }
  body { background: #fff; }
  .page { padding: 0; animation: none; }
  table.grid, table.list, .score-bars, .meta-list { box-shadow: none; }
  table.grid { font-size: .8rem; }
}

/* ==========================================================================
   PENGAJUAN LUPA PASSWORD (layar Kelola Akun)
   ========================================================================== */
.reset-panel {
  border: 1px solid #f2e2b6;
  background: linear-gradient(180deg, #fffdf4, #fdf9ec);
  border-radius: var(--r-lg);
  padding: 1.1rem 1.2rem 1.2rem;
  margin-bottom: 1.8rem;
  box-shadow: var(--sh-1);
  animation: rise .45s var(--ease) both;
}
.reset-panel .head {
  display: flex; align-items: center; gap: .85rem; margin-bottom: .9rem;
}
.reset-panel .head .mark {
  flex: none; width: 40px; height: 40px; border-radius: var(--r-sm);
  background: var(--gold-100); border: 1px solid #f0e0ae;
  display: grid; place-content: center; font-size: var(--t-xl);
}
.reset-panel .head strong { display: block; color: var(--ink-900); }
.reset-panel table.list { background: transparent; box-shadow: none; }

/* ==========================================================================
   GERAK & INTERAKSI
   Semua transisi memakai satu kurva yang sama supaya terasa satu kesatuan.
   Seluruhnya otomatis mati bila pengguna memilih "kurangi gerak" di sistem.
   ========================================================================== */
html { scroll-behavior: smooth; }

/* pergantian halaman: isi baru naik sedikit sambil memudar masuk */
.page-swap { animation: page-in .32s var(--ease) both; }
@keyframes page-in {
  from { opacity: 0; transform: translateY(10px) }
  to   { opacity: 1; transform: none }
}

/* tile & kartu muncul berurutan, bukan serentak */
.tiles > * { animation: rise .42s var(--ease) both; }
.tiles > *:nth-child(1) { animation-delay: .00s }
.tiles > *:nth-child(2) { animation-delay: .05s }
.tiles > *:nth-child(3) { animation-delay: .10s }
.tiles > *:nth-child(4) { animation-delay: .15s }
.tiles > *:nth-child(5) { animation-delay: .20s }
.tiles > *:nth-child(6) { animation-delay: .25s }
.tiles > *:nth-child(n+7) { animation-delay: .28s }

/* baris tabel menyala lembut saat disorot */
table.list tbody tr { transition: background .16s var(--ease); }
table.grid tbody tr:hover td { background: var(--green-050); }

/* riak lembut saat tombol ditekan */
.btn, .tile, .btn-login { position: relative; overflow: hidden; }
.btn::after, .tile::after, .btn-login::after {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(circle at var(--rx, 50%) var(--ry, 50%),
              rgba(255,255,255,.55), transparent 45%);
  opacity: 0; transition: opacity .45s var(--ease);
}
.btn:active::after, .tile:active::after, .btn-login:active::after {
  opacity: 1; transition: none;
}

/* input & pilihan ikut memakai kurva yang sama */
input, select, textarea {
  transition: border-color .16s var(--ease), box-shadow .16s var(--ease), background .16s var(--ease);
}

/* kembali ke atas */
.to-top {
  position: fixed; right: 1.2rem; bottom: 1.2rem; z-index: 40;
  width: 44px; height: 44px; border-radius: 50%;
  border: 1px solid var(--line-2); background: rgba(255,255,255,.92);
  backdrop-filter: blur(6px);
  color: var(--green-800); font-size: var(--t-lg); cursor: pointer;
  box-shadow: var(--sh-2);
  display: grid; place-content: center;
  opacity: 0; transform: translateY(12px) scale(.9); pointer-events: none;
  transition: opacity .22s var(--ease), transform .22s var(--ease), background .16s;
}
.to-top.on { opacity: 1; transform: none; pointer-events: auto; }
.to-top:hover { background: #fff; color: var(--green-900); }

@media print { .to-top { display: none !important; } }

/* ==========================================================================
   KEPALA HALAMAN: KEADAAN JARINGAN & LONCENG
   ========================================================================== */
.header-right { display: flex; align-items: center; gap: .5rem; }

/* ---------- penanda jaringan ---------- */
.net-pill {
  display: flex; align-items: center; gap: .45rem;
  padding: .3rem .8rem; border-radius: var(--r-pill);
  font-size: var(--t-2xs); font-weight: 600; white-space: nowrap;
  background: var(--gold-100); color: #7a5c00; border: 1px solid #f0e0ae;
  animation: pop .2s var(--ease);
}
.net-pill.off { background: var(--danger-bg); color: #8c2b20; border-color: #f3c9c3; }
.net-pill .dot {
  width: 8px; height: 8px; border-radius: 50%; background: currentColor;
  animation: breathe 1.6s var(--ease) infinite;
}

/* ---------- lonceng ---------- */
.bell { position: relative; }
.bell-button {
  position: relative; width: 40px; height: 40px; border-radius: 50%;
  border: 1px solid transparent; background: none; cursor: pointer;
  display: grid; place-content: center; font-size: var(--t-xl);
  transition: background .16s, border-color .16s, transform .16s var(--ease);
}
.bell-button:hover { background: var(--green-050); border-color: var(--line); }
.bell-button:active { transform: scale(.94); }
.badge-count {
  position: absolute; top: 2px; right: 1px; min-width: 18px; height: 18px;
  padding: 0 5px; border-radius: var(--r-pill);
  background: var(--danger); color: #fff;
  font-size: var(--t-2xs); font-weight: 800; line-height: 18px; text-align: center;
  box-shadow: 0 0 0 2px var(--paper);
  animation: pop .2s var(--ease);
}

.bell-drop {
  position: absolute; right: 0; top: calc(100% + .55rem); z-index: 45;
  width: min(370px, calc(100vw - 2rem));
  background: var(--paper); border: 1px solid var(--line);
  border-radius: var(--r); box-shadow: var(--sh-3); overflow: hidden;
  animation: pop .16s var(--ease);
}
.bell-head {
  display: flex; align-items: center; justify-content: space-between; gap: .6rem;
  padding: .8rem 1rem; border-bottom: 1px solid var(--line);
  background: var(--green-050);
}
.bell-head .link {
  border: 0; background: none; cursor: pointer; padding: .2rem .35rem;
  font: inherit; font-size: var(--t-2xs); font-weight: 600; color: var(--green-700);
  border-radius: var(--r-sm); transition: background .15s, color .15s;
}
.bell-head .link:hover { background: var(--green-100); color: var(--green-900); }

.bell-list { max-height: min(60vh, 420px); overflow-y: auto; }

.bell-item {
  width: 100%; display: flex; gap: .75rem; align-items: flex-start; text-align: left;
  padding: .8rem 1rem; border: 0; border-bottom: 1px solid var(--line);
  background: none; font: inherit; cursor: pointer;
  transition: background .15s var(--ease);
}
.bell-item:last-child { border-bottom: 0; }
.bell-item:hover { background: var(--green-050); }
.bell-item.unread { background: #f7fcf8; box-shadow: inset 3px 0 0 var(--green-600); }
.bell-item .ico {
  flex: none; width: 34px; height: 34px; border-radius: var(--r-sm);
  display: grid; place-content: center; font-size: var(--t-md);
  background: var(--green-100);
}
.bell-item.warn .ico { background: var(--warn-bg); }
.bell-item.ok   .ico { background: var(--ok-bg); }
.bell-item .body { display: flex; flex-direction: column; gap: .12rem; min-width: 0; }
.bell-item .t { font-weight: 600; font-size: var(--t-sm); color: var(--ink-900); }
.bell-item .d { font-size: var(--t-xs); color: var(--ink-600); line-height: 1.4; }
.bell-item .w { font-size: var(--t-2xs); color: var(--ink-400); }

.bell-empty { padding: 2.2rem 1rem; text-align: center; color: var(--ink-400); }
.bell-empty .mark { font-size: 1.7rem; display: block; margin-bottom: .5rem; }
.bell-empty p { margin: 0; font-size: var(--t-sm); }

/* ==========================================================================
   PENYIMPANAN OTOMATIS
   ========================================================================== */
.save-bar { flex-wrap: wrap; align-items: center; }
.save-state {
  margin-right: auto; display: flex; align-items: center; gap: .45rem;
  font-size: var(--t-xs); color: var(--ink-600); font-weight: 500;
}
.save-state::before {
  content: ''; width: 8px; height: 8px; border-radius: 50%;
  background: var(--ink-200); flex: none;
}
.save-state.busy::before { background: var(--gold-500); animation: breathe 1s var(--ease) infinite; }
.save-state.ok::before    { background: var(--green-600); }
.save-state.local::before { background: var(--warn); }
.save-state.err::before   { background: var(--danger); }
.save-state.local { color: var(--warn); font-weight: 600; }
.save-state.err   { color: var(--danger); font-weight: 600; }

/* sel nilai di luar rentang */
table.grid input.bad {
  color: var(--danger); font-weight: 700;
  background: var(--danger-bg); border-radius: var(--r-xs);
  box-shadow: 0 0 0 2px rgba(192,57,43,.25);
}

.notice.warn {
  background: var(--warn-bg); border-color: #f0dcb0;
  border-left-color: var(--warn); color: #7a5c00;
}

/* ==========================================================================
   MENYESUAIKAN LAYAR: PONSEL, TABLET, LAPTOP
   Tiga patokan lebar: <560 ponsel, 561–900 tablet, >900 laptop/desktop.
   Yang berubah bukan hanya ukuran huruf — tata letaknya ikut disusun ulang
   supaya tidak ada yang perlu digeser ke samping kecuali tabel nilai.
   ========================================================================== */

/* ---------- tablet ---------- */
@media (max-width: 900px) {
  .app-header { padding: .6rem 1.1rem; }
  .header-left { gap: .8rem; }
  .page, .crumbs { padding-left: 1.2rem; padding-right: 1.2rem; }
  .profile-grid { grid-template-columns: 1fr; }
  .tiles { gap: 1rem; }
  .net-pill .txt { display: none; }
  .net-pill { padding: .3rem .5rem; }
}

/* ---------- ponsel ---------- */
@media (max-width: 560px) {
  body { font-size: var(--t-sm); }

  /* Kepala halaman HP: yang dilaporkan sekolah "sesak banget, tidak ada
     jarak, logo gepeng". Jarak antar benda dinaikkan (.15 -> .3rem) dan
     ruangnya DIBELI dari hiasan, bukan dari sasaran sentuh: panah ▼ di
     tombol pengguna disembunyikan (avatarnya sendiri tombolnya), bantalan
     tombol dirapatkan, dan logo — dengan object-fit di atas — mengecil
     seperlunya tanpa berubah bentuk. */
  .app-header { padding: .5rem .7rem; gap: .55rem; }
  .app-header .brand-home { min-width: 0; flex: 0 1 auto; }
  .app-header .brand-logo { height: 30px; }
  .header-right { gap: .3rem; flex: none; }
  .bell-button { width: 36px; height: 36px; font-size: var(--t-lg); }
  .user-button { padding: .25rem .2rem; }
  .user-button .caret { display: none; }
  .unit-button .caret { display: none; }
  .avatar { width: 32px; height: 32px; font-size: var(--t-2xs); }

  .crumbs { font-size: var(--t-2xs); gap: .3rem; overflow-x: auto; white-space: nowrap;
            padding-bottom: .5rem; scrollbar-width: none; }
  .crumbs::-webkit-scrollbar { display: none; }

  .page { padding-left: .9rem; padding-right: .9rem; }
  /* Judul turun satu langkah di layar sempit — 28px memakan hampir seperempat
     tinggi layar HP sebelum satu baris data pun terlihat. Tangganya tetap:
     21 → 19 → 17. */
  h1, .page-title { font-size: var(--t-2xl); }
  h2 { font-size: var(--t-xl); }
  h3 { font-size: var(--t-lg); }

  /* tile menjadi satu kolom lebar penuh — jauh lebih mudah ditekan jempol */
  /* Satu kolom penuh: jumlah kolom hasil hitungan diabaikan di sini. */
  .tiles { grid-template-columns: 1fr; gap: .7rem; }
  .tile.icon, .tile.block, .tile.square, .tile.pill {
    width: 100%; height: auto; min-height: 66px;
    flex-direction: row; justify-content: flex-start; gap: .9rem;
    padding: .85rem 1rem; text-align: left;
  }
  .tile.icon .glyph { width: 42px; height: 42px; font-size: var(--t-2xl); margin: 0; }
  .tile .label { font-size: var(--t-md); }

  /* tombol memenuhi lebar, tidak berdesakan */
  .toolbar { flex-wrap: wrap; gap: .5rem; }
  .toolbar .btn { flex: 1 1 auto; justify-content: center; }
  .save-state { order: -1; width: 100%; margin-bottom: .3rem; }

  /* tabel nilai digulir ke samping, bukan diperkecil sampai tak terbaca */
  table.grid { font-size: var(--t-2xs); }
  table.grid th, table.grid td { padding: .45rem .55rem; }
  table.grid input { width: 44px; }
  .table-wrap { margin-left: -.9rem; margin-right: -.9rem; padding-left: .9rem; padding-right: .9rem; }
  /* Petunjuk geser hanya untuk tabel yang MEMANG digulir.
     Tabel daftar (table.list) berubah menjadi kartu bertumpuk beberapa baris
     di bawah ini, jadi ia tidak bergeser ke mana pun — tetapi petunjuknya
     tetap tercetak di kakinya, menyuruh menggeser sesuatu yang tidak bergerak.
     Yang benar-benar melebar hanya tabel nilai dan legger (table.grid). */
  .table-wrap:has(table.grid)::after {
    content: 'geser ke samping →'; display: block;
    font-size: var(--t-2xs); color: var(--ink-400); text-align: right; padding-top: .35rem;
  }

  /* daftar berubah menjadi kartu bertumpuk, bukan tabel sempit */
  table.list, table.list tbody, table.list tr, table.list td { display: block; width: 100%; }
  table.list thead { display: none; }
  table.list tr {
    border: 1px solid var(--line); border-radius: var(--r);
    margin-bottom: .7rem; padding: .6rem .8rem; background: var(--paper);
    box-shadow: var(--sh-1);
  }
  table.list td { border: 0; padding: .28rem 0; display: flex; gap: .6rem; }
  table.list td::before {
    content: attr(data-label); flex: none; min-width: 92px;
    color: var(--ink-400); font-size: var(--t-2xs); font-weight: 600;
  }
  table.list td.act { padding-top: .5rem; }
  table.list .act-links { gap: 1rem; }

  .dialog { width: 100%; max-height: 92vh; border-radius: var(--r-lg) var(--r-lg) 0 0; }
  .backdrop { align-items: flex-end; padding: 0; }
  .bell-drop { position: fixed; left: .6rem; right: .6rem; width: auto; top: 58px; }
  .footer-strip { padding: .9rem; }
  .footer-strip .dots { display: none; }
  .to-top { right: .8rem; bottom: .8rem; }
}

/* Layar tersempit (≤390px): ruang untuk logo dibeli sekali lagi — ikon 🏫
   pada pil unit menepi (teks "SDB"-nya yang membawa makna), bantalan tepi
   dirapatkan, dan logo turun ke 26px supaya tampil UTUH dengan rasionya,
   bukan besar tapi terjepit. */
@media (max-width: 390px) {
  .app-header { padding-inline: .55rem; }
  .unit-button .ic { display: none; }
  .app-header .brand-logo { height: 26px; }
}

/* ---------- perangkat sentuh: sasaran tekan lebih besar ----------
   40 piksel adalah angka lama. Blok yang sama di tambahan.css memakai 44, dan
   selama dua angka itu hidup berdampingan yang berlaku hanyalah yang kebetulan
   terbaca belakangan — pernah satu kali .btn diam-diam turun kembali ke 40 di
   seluruh perangkat sentuh karena satu baris tersunting keliru di sana.
   Keduanya kini menyebut angka yang sama. */
@media (hover: none) {
  .btn, .chip, .bell-button, .user-button { min-height: 44px; }
  table.list .act-links button { padding: .3rem 0; }
  .tile:hover { transform: none; }
}
