/*
 * Gaya khas beranda.
 *
 * Lima kelas diberi awalan `beranda`: ajakan, ajakanTeks, aksi, eyebrow, dan
 * lede. Nama-nama itu juga dipakai page.css (rangka halaman) dan kop.css, dan
 * ketiganya dimuat bersamaan di beranda. CSS Modules dulu mengacak setiap
 * nama sehingga tabrakan semacam ini mustahil; setelah jadi CSS biasa, yang
 * belakangan menimpa yang duluan TANPA galat apa pun.
 *
 * Nilainya tidak berubah sedikit pun — hanya namanya. Tabrakan dicari oleh
 * `npm run cek-css`.
 */
/*
  Beranda.

  Sikap visualnya: BERWIBAWA, bukan ramai. Ini situs lembaga guru besar —
  gerakan yang berlebihan justru mengurangi kesan seriusnya, dan sebagian besar
  pembacanya senior.

  Seluruh animasi di berkas ini dipagari `prefers-reduced-motion`. Yang tersisa
  saat animasi dimatikan tetap halaman yang utuh dan enak dibaca, bukan versi
  cacat — perubahan warna dan garis tetap ada, hanya gerakannya yang hilang.
*/

/*
  Hero: foto selebar layar dengan kartu merah menimpa di kiri.

  Sapuan gradien merah yang dulu ada di sini SUDAH DIBUANG. Ia dibuat sebagai
  pengganti sementara ketika belum ada foto sama sekali; setelah foto masuk,
  ia hanya menambah rona di belakang gambar hitam-putih.

  Latarnya dilebarkan ke seluruh layar dengan `box-shadow` + `clip-path`, sama
  seperti `.pita`, karena pembungkus halaman berbatas 76rem. Lihat alasan
  penolakan trik `100vw` pada catatan di sana.
*/
.hero {
  position: relative;
  min-height: clamp(26rem, 52vw, 34rem);
  display: flex;
  align-items: center;
  padding: 3rem 0;
  overflow: hidden;
  background: #0d0d0d;
  box-shadow: 0 0 0 100vmax #0d0d0d;
  clip-path: inset(0 -100vmax);
}

.heroFoto {
  position: absolute;
  inset: 0;
  z-index: 0;
}

.heroGambar {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity 1.1s ease-in-out;
}

.heroGambarAktif {
  opacity: 1;
}

/*
  Foto PERTAMA terlihat tanpa JavaScript.

  Kelas `heroGambarAktif` dipasang React setelah hidrasi. Tanpa aturan ini,
  pengunjung tanpa JavaScript — dan perayap mesin pencari — melihat bidang
  hitam kosong. `:first-child` berlaku sejak HTML server, jadi selalu ada satu
  foto yang tampak.
*/
.heroGambar:first-child {
  opacity: 1;
}

.heroGambarAktif ~ .heroGambar:first-child {
  opacity: 0;
}

/*
  Saput gelap: foto ini bukan latar polos, dan tulisan putih di atas wajah
  atau spanduk terang menjadi tidak terbaca tanpa peredup.
*/
.heroSaput {
  position: absolute;
  inset: 0;
  background: linear-gradient(
    100deg,
    rgb(0 0 0 / 0.82) 0%,
    rgb(0 0 0 / 0.55) 48%,
    rgb(0 0 0 / 0.35) 100%
  );
}

@media (prefers-reduced-motion: reduce) {
  .heroGambar {
    transition: none;
  }
}

/* ---------- Kendali slide ---------- */

.heroKendali {
  position: absolute;
  right: 1.5rem;
  bottom: 1.25rem;
  left: 1.5rem;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  pointer-events: none;
}

.heroKeterangan {
  margin: 0;
  max-width: 32rem;
  font-size: var(--t-mikro);
  line-height: 1.45;
  color: rgb(255 255 255 / 0.72);
}

.heroTombolGrup {
  display: flex;
  gap: 0.5rem;
  pointer-events: auto;
}

.heroTombol {
  display: grid;
  place-items: center;
  width: 2.3rem;
  height: 2.3rem;
  border: 0;
  border-radius: 50%;
  background: rgb(0 0 0 / 0.55);
  color: #fff;
  cursor: pointer;
  transition: background 0.16s ease;
}

.heroTombol:hover {
  background: var(--brand-700);
}

.heroTombol:focus-visible {
  outline: 2px solid #fff;
  outline-offset: 2px;
}

/*
  Kartu merah yang menimpa foto.

  Seluruh warna di dalamnya dipatok mati — `--brand-700` dan putih — BUKAN
  token tema. Kartu ini selalu berada di atas foto gelap, jadi di mode terang
  maupun gelap latarnya sama; memakai `--text` di sini menghasilkan tulisan
  hitam di atas merah tua.
*/
/*
  GARIS KIRI MERAH MUDA DIBUANG.

  Ia termasuk pola yang daftar slop sebut dengan namanya sendiri: "Colored Left
  Stripe, a thin colored vertical bar on the left edge of cards as decoration".
  Ia tidak menandai apa pun di sini, hanya menghias tepi.

  Penggantinya bukan hiasan lain, melainkan ruang: padding kiri dibuat lebih
  lega daripada kanan, sehingga blok teks punya margin optis yang disengaja dan
  kartunya terbaca sebagai pelat yang diletakkan di atas foto, bukan kotak yang
  kebetulan ada di sana.
*/
/*
  BIDANG MERAH HERO.

  `min-width: 0` BUKAN hiasan. `.hero` adalah flex, dan bawaan sebuah item flex
  adalah `min-width: auto` — artinya ia menolak menyusut di bawah lebar
  min-content isinya. Di layar 320px hasilnya terukur: bidang ini memuai
  menjadi 331px di dalam induk 269px, lalu 36px di sebelah kanannya dipotong
  diam-diam oleh `overflow: hidden` milik `.hero`. Tidak ada guliran mendatar
  yang muncul, jadi cacat ini tidak terlihat oleh pemeriksaan biasa — teksnya
  hanya hilang.

  Bantalan sisinya juga diturunkan. `.hero` sudah berada di dalam talang
  `.page` sebesar 1,5rem, sehingga bantalan 1,75rem di sini menumpuk menjadi
  55px dari tepi layar — 17% dari layar 320px habis untuk ruang kosong,
  sementara judulnya sendiri kekurangan tempat. Batas bawah clamp diturunkan
  ke 1rem; batas atasnya tidak diubah, jadi tampilan lebar tetap sama persis.
*/
.heroInner {
  position: relative;
  z-index: 1;
  min-width: 0;
  max-width: 36rem;
  padding: clamp(1.6rem, 3.2vw, 2.4rem) clamp(1rem, 3.5vw, 2.5rem) clamp(1.6rem, 3.2vw, 2.4rem)
    clamp(1rem, 4.5vw, 3.5rem);
  background: var(--brand-700);
  color: #fff;
}

/*
  PIL KAPSUL DIGANTI KAPITAL BERSPASI DI ATAS GARIS.

  Lencana kapsul adalah salah satu tanda yang paling mudah dikenali pada
  antarmuka buatan mesin, dan aturan proyek melarangnya dipakai tanpa fungsi.
  Di sini ia tidak menyatakan status apa pun; ia cuma menuliskan periode
  kepengurusan.

  Gantinya memakai gestur yang SUDAH menjadi identitas situs ini: garis di bawah
  tulisan, sama seperti garis 2px di bawah setiap kepala seksi. Hero karena itu
  berbicara dengan bahasa yang sama dengan bagian halaman lainnya, bukan dengan
  bahasa yang dipinjam dari tempat lain.
*/
.berandaEyebrow {
  /*
    Lebarnya sepanjang tulisan, bukan selebar kartu. Garis sepanjang kartu akan
    membelah pelat menjadi dua bidang; garis sependek tulisan terbaca sebagai
    penanda yang menempel pada tulisannya.
  */
  display: block;
  width: fit-content;
  margin: 0 0 1.5rem;
  padding: 0 0 0.75rem;
  border-bottom: 2px solid var(--brand-300);
  color: var(--brand-200);
  font-size: var(--t-mikro);
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
}

/*
  Blok tema gelap untuk `.berandaEyebrow` DIHAPUS seluruhnya — bukan diubah jadi
  token, melainkan dibuang, karena ia memang tidak pernah punya alasan untuk
  ada.

  Lencana ini duduk di dalam `.heroInner`, dan seperti tertulis di komentarnya
  di atas, kartu itu SELALU berlatar `--brand-700` di kedua tema. Latarnya
  tidak pernah berubah, jadi lencananya pun tidak punya alasan berubah.
  Mengubah warnanya menurut tema sistem hanya membuat dua tampilan berbeda
  untuk keadaan yang sama persis.

  Kerugiannya nyata, bukan teoretis:

  1. Kedua nilainya — `rgb(126 29 37 / .18)` dan `rgb(210 106 111 / .35)` —
     bukan bagian dari tangga `--brand-*` mana pun. Dua rona asing yang tidak
     pernah diukur kontrasnya, di luar globals.css.

  2. Nilai gelapnya JUSTRU LEBIH BURUK. Maroon 18% di atas merah #a80808
     nyaris tidak membedakan lencana dari kartunya, sementara nilai terangnya
     (hitam 18% dengan garis putih 32%) terbaca jelas. Pengguna bersistem
     gelap selama ini mendapat lencana yang hampir tak terlihat.

  3. Sebagai media query, ia tidak mengenal `[data-theme]` — memilih tema
     terang tidak mengembalikannya.

  Menghapusnya membuat satu tampilan untuk satu keadaan, dan yang tersisa
  adalah yang lebih terbaca.
*/

/*
  SKALA DISPLAY SUNGGUHAN, dan bagian beraksen turun ke barisnya sendiri.

  Ukuran lama, 2,6rem pada layar terbesar, adalah ukuran judul seksi, bukan
  ukuran hero. Serifnya sudah dipasang sejak awal tetapi tidak pernah diberi
  ruang untuk terlihat sebagai suara; pada ukuran itu ia hanya terbaca sebagai
  "judul yang agak besar".

  Kerapatan barisnya diturunkan karena huruf sebesar ini butuh baris yang lebih
  rapat, bukan lebih renggang. `text-wrap: balance` dilepas dari sini dan
  diserahkan ke pemenggalan yang disengaja di bawah.

  UKURANNYA DITAHAN DI 3,05rem, bukan dinaikkan sejauh mungkin. Pada 3,6rem
  judulnya pecah menjadi lima baris dan seluruh hero tumbuh menjadi 804px di
  layar setinggi 900px: 89 persen layar pertama habis untuk satu blok, dan
  tidak ada isi lain yang terlihat tanpa menggulir. Hero diukur dari isinya,
  bukan dari tinggi layar.
*/
/*
  BATAS BAWAHNYA 1,8rem, BUKAN 2rem — dan ini terukur, bukan selera.

  Di layar 320px, ruang yang tersisa untuk judul adalah 235px: 320 dikurangi
  talang `.page` (2x25,5px) dan bantalan `.heroInner` (2x17px). Kata terpanjang
  pada tagline yang dipakai sekarang, "Menghubungkan", tidak muat di situ pada
  2rem — huruf terakhirnya terpotong di tepi bidang merah, dan karena `.hero`
  memakai `overflow: hidden`, potongan itu hilang tanpa memunculkan guliran
  mendatar yang bisa menandainya.

  Cacat ini baru terlihat setelah `.heroInner` diberi `min-width: 0`. Sebelum
  itu, bidang merahnyalah yang memuai keluar layar, sehingga judulnya tampak
  utuh sementara yang terpotong adalah bidangnya.

  TERUKUR, lebar kata "Menghubungkan" pada huruf judul:
    34px  -> 277px   30,6px -> 248px   29px -> 235px   28px -> 226px
  Ruang yang tersedia di layar 320px adalah 235px, jadi batas amannya 29px.
  Batas bawah disetel 1,65rem (28px), menyisakan 9px kelonggaran.

  Suku tengahnya dinaikkan dari 4,2vw ke 7,5vw. Dengan 4,2vw, batas bawah
  berlaku sampai layar 810px — artinya tablet pun mendapat huruf sekecil
  ponsel. Pada 7,5vw ukurannya tumbuh mulus: 320px->28, 400px->30, 500px->37,
  600px->45, lalu menyentuh langit-langit 3,05rem di sekitar 692px. Ukuran
  terbesarnya TIDAK berubah, jadi tampilan desktop tetap persis sama.

  `overflow-wrap: break-word` tetap dipasang sebagai jaring terakhir. Tagline
  diisi dari /admin, dan tidak ada yang menjamin Sekretariat tidak menulis kata
  yang lebih panjang lagi. Lebih baik satu kata patah daripada satu kata hilang.
*/
.judul {
  margin: 0 0 1.25rem;
  font-size: clamp(1.65rem, 7.5vw, 3.05rem);
  line-height: 1.04;
  color: #fff;
  letter-spacing: -0.025em;
  text-wrap: pretty;
  overflow-wrap: break-word;
}

/* Bagian kunci taglinenya diberi warna merek, bukan seluruh judul. */
/*
  Aksen judul di atas kartu merah: merah MUDA, bukan `--primary`.
  Merah di atas merah tidak terbaca sama sekali.
*/
/*
  Bagian beraksen menjadi BARIS SENDIRI, bukan sambungan di tengah kalimat.

  Isi kedua medan ini datang dari /admin: "Menghubungkan kepakaran guru besar
  untuk" lalu "Indonesia Emas 2045". Selama keduanya mengalir dalam satu
  paragraf, bagian kedua hanya terbaca sebagai kata yang kebetulan berwarna
  lain. Diturunkan ke barisnya sendiri, ia menjadi pernyataan penutup, dan
  itulah memang isinya.

  `display: block` juga membuat pemenggalannya dapat diduga, sehingga judul
  tidak patah di tempat yang berbeda-beda setiap lebar layar.
*/
.judulAksen {
  display: block;
  color: var(--brand-200);
}

.berandaLede {
  margin: 0 0 2rem;
  font-size: clamp(0.98rem, 1.7vw, 1.08rem);
  line-height: 1.68;
  color: rgb(255 255 255 / 0.88);
  max-width: 34rem;
  text-wrap: pretty;
}

.berandaAksi {
  display: flex;
  flex-wrap: wrap;
  gap: 0.9rem;
}

/*
  SATU TITIK FOKUS, bukan dua tombol berbobot sama.

  Sebelumnya keduanya bidang penuh berukuran sama, sehingga tidak ada yang
  menang dan mata harus memilih sendiri. Sekarang yang utama tetap bidang putih
  pekat, dan yang kedua turun menjadi tautan teks bergaris bawah.

  Keduanya tetap dikendalikan dari /admin lewat medan yang sama; yang berubah
  hanya bobot tampilannya, bukan kontraknya.
*/
.tombolUtama,
.tombolKedua {
  text-decoration: none;
  font-weight: 700;
  transition: transform 0.18s ease, background-color 0.18s ease, border-color 0.18s ease,
    color 0.18s ease;
}

/*
  TINGGINYA DARI BANTALAN, BUKAN DARI `min-height`. JANGAN DIUBAH.

  Tombol ini `display: block` — lihat catatan di bawah tentang label panjang
  yang harus boleh mengalir membawa panahnya. Pada elemen blok, `min-height`
  hanya MEMANJANGKAN kotak ke bawah; ia tidak memusatkan isinya, dan
  `justify-content` tidak berlaku sama sekali karena tidak ada konteks flex.

  Pernah saya ganti menjadi `min-height: 4rem` dengan `padding: 0` demi
  menyeragamkan tinggi lewat token. Hasilnya TERUKUR rusak:

    tinggi tombol   68px
    udara di atas    2px
    udara di bawah  37px   <- label terjepit ke tepi atas

  Bantalan simetris 0,9rem mengembalikan 15,3px di atas dan di bawah. Tinggi
  yang dihasilkannya 64px, dan itu memang ukuran yang dikehendaki di sini.

  Token tinggi tombol tetap dipakai di tempat lain — di sana elemennya
  `inline-flex`, sehingga `align-items: center` benar-benar bekerja.
*/
.tombolUtama {
  padding: 0.9rem 2rem;
  border-radius: var(--r-kartu);
  font-size: var(--t-isi);
}

/*
  `align-self: center` supaya garis bawahnya tidak terlepas dari teksnya.

  Tombol ini berdiri di dalam `.berandaAksi` yang `display: flex`, bersebelahan dengan
  `.tombolUtama` yang lebih tinggi. Dengan `align-items: stretch` bawaan flex,
  ia ikut diregangkan sampai 64px, sementara isinya tetap mengalir dari tepi
  atas — dan `border-bottom` miliknya ikut turun ke dasar kotak yang
  diregangkan itu.

  TERUKUR sebelum diperbaiki: udara 15px di atas teks, 23px di bawahnya, jadi
  garisnya menggantung 8px lebih rendah daripada seharusnya dan terbaca seperti
  garis yang tidak berhubungan dengan tulisannya.
*/
.tombolKedua {
  align-self: center;
  padding: 0.9rem 0;
  font-size: var(--t-dasar);
}

/*
  Tombol DIBALIK karena kini berdiri di atas kartu merah.

  Tombol merah di atas bidang merah lenyap. Yang utama karena itu jadi bidang
  PUTIH dengan tulisan merah — kontras tertinggi yang tersedia di palet ini —
  dan yang kedua bergaris putih transparan.
*/
.tombolUtama {
  background: #fff;
  color: var(--brand-700);
  border: 2px solid #fff;
}

.tombolKedua {
  color: #fff;
  border-bottom: 2px solid rgb(255 255 255 / 0.45);
}

.tombolKedua:hover {
  border-bottom-color: #fff;
  transform: none;
}

.tombolUtama:hover {
  background: var(--brand-50);
  border-color: var(--brand-50);
  color: var(--brand-800);
  transform: translateY(-2px);
}



/*
  Panah mengalir BERSAMA teksnya, bukan sebagai saudara flex.

  Sebagai saudara flex ia terpusat vertikal terhadap seluruh tombol. Begitu
  labelnya pecah dua baris di layar sempit — dan "Telusuri Direktori Guru Besar"
  memang pecah di 360px — panahnya terlepas melayang di kanan, terpisah dari
  kata terakhir yang seharusnya ia tunjuk. Terbaca seperti tata letak yang
  rusak.

  Sebagai `inline-block` ia menempel pada kata terakhir ke mana pun kata itu
  jatuh, dan `transform` tetap berlaku sehingga gesernya saat hover tidak
  hilang.
*/
.panah {
  display: inline-block;
  margin-left: 0.15rem;
  transition: transform 0.18s ease;
}

/*
  Tombol hero memakai `display: block`, bukan `inline-flex` bawaan global.

  Aturan global memberi setiap `a` `display: inline-flex` demi target sentuh
  44px. Untuk tombol berlabel pendek itu tepat, tetapi di sini label panjang
  harus boleh mengalir dan membawa panahnya serta. Tinggi minimumnya dijaga
  padding, bukan `min-height`.
*/
.tombolUtama,
.tombolKedua {
  display: block;
  width: fit-content;
}

@media (max-width: 30rem) {
  /*
    Di layar sempit keduanya melebar penuh dan menumpuk. Tombol selebar kartu
    lebih mudah dikenai jempol daripada tombol yang lebarnya mengikuti panjang
    tulisan.
  */
  .berandaAksi {
    flex-direction: column;
    align-items: stretch;
    gap: 1rem;
  }

  .tombolUtama,
  .tombolKedua {
    width: 100%;
  }

  .tombolUtama {
    text-align: center;
  }
}

.tombolUtama:hover .panah,
.tombolKedua:hover .panah {
  transform: translateX(3px);
}

/* ---------- Deret angka ---------- */

/* ---------- Panel pencarian pakar ---------- */

.cariPanel {
  display: grid;
  gap: 1.5rem;
  align-items: center;
  padding: clamp(1.35rem, 3vw, 2rem);
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--r-kartu);
}

@media (min-width: 56rem) {
  .cariPanel {
    grid-template-columns: minmax(0, 22rem) minmax(0, 1fr);
    gap: 2.5rem;
  }
}

.cariJudul {
  margin: 0 0 0.4rem;
  font-size: var(--t-h3);
  letter-spacing: -0.015em;
}

.cariLede {
  margin: 0;
  font-size: var(--t-dasar);
  color: var(--text-muted);
}

.cariForm {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
}

/*
  Label disembunyikan SECARA VISUAL, bukan dihapus.
  Placeholder bukan pengganti label: ia lenyap begitu diketik, dan sebagian
  pembaca layar tidak membacakannya sama sekali.
*/
.cariLabel {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

.cariInput {
  flex: 1 1 16rem;
  min-width: 0;
  padding: 0.75rem 0.9rem;
  font: inherit;
  font-size: var(--t-dasar);
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-kartu);
}

.cariInput:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 1px;
  border-color: var(--primary);
}

.cariTombol {
  flex: none;
  justify-content: center;
  min-height: var(--tombol-h);
  padding: 0 1.5rem;
  font: inherit;
  font-weight: 700;
  font-size: var(--t-kecil);
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: #fff;
  background: var(--brand-700);
  border: 0;
  border-radius: var(--r-kartu);
  cursor: pointer;
  transition: background 0.16s ease;
}

.cariTombol:hover {
  background: var(--brand-800);
}

/* ---------- Deret angka ---------- */

/*
  Garis pemisah antar sel dibuat dari CELAH 1px di atas latar berwarna garis —
  bukan border per sel. Hemat, dan sudutnya membulat rapi.
*/
.angka {
  display: grid;
  gap: 1px;
  /*
    JANGAN menambahkan `padding` di sini.

    Latar elemen ini adalah warna garis pemisah, dan padding ikut terisi warna
    itu — bukan tersisa kosong. `padding-top: 2.5rem` yang sempat ada di sini menghasilkan balok abu setebal 2,5rem menggantung di atas angkanya, dan terbaca seperti bidang yang gagal dimuat. Jarak diatur lewat `margin`, yang tidak mengambil latar. */ margin-top: 3.5rem;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 10rem), 1fr));
  /*
    Latar berwarna garis + celah 1px = pemisah ANTAR sel. Tetapi itu saja
    tidak memberi bingkai LUAR, sehingga angkanya tampak mengambang di bidang
    putih. `border` menutup keempat sisinya, dan barulah blok ini terbaca
    sebagai satu kesatuan.
  */
  background: var(--border);
  border: 1px solid var(--border);
  border-radius: var(--r-kartu);
  overflow: hidden;
  position: relative;
  z-index: 1;
}

/* Garis pemisah dibuat dari gap 1px berlatar border — tidak perlu border per sel. */
/*
  Sel rata KIRI dengan garis merah tebal di tepinya, bukan rata tengah.

  Angka rata tengah tanpa keterangan terbaca seperti papan skor. Dengan
  keterangan satu baris di bawahnya, rata kiri jauh lebih mudah dipindai —
  mata menyusuri satu tepi, bukan melompat ke tengah tiap kolom.
*/
/*
  Sel diubah menjadi flex kolom supaya urutan LIHAT dapat dipisahkan dari
  urutan BACA.

  Markup-nya kini `dt` → `dd` → `dd`, satu-satunya susunan yang sah di dalam
  `<dl>`. Tetapi yang harus terlihat lebih dulu adalah ANGKANYA, bukan
  labelnya — itulah bentuk yang dikenali orang pada blok statistik. `order` di
  bawah menyelesaikannya tanpa mengorbankan keabsahan markup.
*/
.angkaSel {
  display: flex;
  flex-direction: column;
  padding: 1.5rem 1.25rem;
  background: var(--bg);
  border-left: 4px solid var(--brand-700);
  text-align: left;
}

.angkaNilai {
  order: 1;
  display: block;
  /*
    `margin: 0` WAJIB, bukan kosmetik. `<dd>` membawa `margin-inline-start: 40px` dari gaya bawaan peramban, dan tidak ada yang pernah meresetnya. Akibatnya angka besar ini menjorok 40px ke kanan sementara label dan keterangannya rata kiri — terukur 166px lawan 126px. Salah susun yang terlihat jelas, dan bertahan karena tidak ada yang menduga sebuah angka punya margin bawaan. */ margin: 0;
  font-size: var(--t-h1);
  font-weight: 800;
  line-height: 1;
  letter-spacing: -0.02em;
  color: var(--primary);
}

.angkaLabel {
  order: 2;
  display: block;
  margin-top: 0.4rem;
  font-size: var(--t-mikro);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text);
  line-height: 1.35;
}

.angkaKet {
  order: 3;
  /* Nol di kiri mematikan indentasi bawaan `<dd>`, sama seperti `.angkaNilai`. */
  margin: 0.4rem 0 0;
  font-size: var(--t-kecil);
  color: var(--text-muted);
  line-height: 1.45;
}

/* ---------- Bagian umum ---------- */

.bagian {
  margin-top: 4rem;
}

/*
  Latar berselang-seling SELEBAR LAYAR.

  Pembungkus halaman berbatas 76rem, jadi latar tidak bisa sekadar diberi
  `background` — ia akan berhenti di tepi pembungkus. Teknik yang lazim,
  `margin-inline: calc(50% - 50vw)`, ditolak di sini: `100vw` menghitung batang
  gulir sehingga memunculkan gulir mendatar beberapa piksel di Windows.

  `box-shadow` sebesar itu melukis warna jauh melewati tepi elemen TANPA
  memengaruhi tata letak, dan `clip-path` memangkasnya secara vertikal supaya
  tidak bocor ke bagian atas dan bawahnya.
*/
.pita {
  background: var(--bg-alt);
  box-shadow: 0 0 0 100vmax var(--bg-alt);
  clip-path: inset(0 -100vmax);
  padding-top: 3rem;
  padding-bottom: 3rem;
}

.bagianKepala {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  margin-bottom: 1.75rem;
  padding-bottom: 0.75rem;
  /*
    Garis TEBAL dan berwarna tinta, bukan abu tepi.
    Inilah yang membuat setiap bagian terbaca sebagai bab tersendiri, bukan
    sekadar tumpukan kartu yang mengalir tanpa jeda.
  */
  border-bottom: 2px solid var(--text);
}

.bagianJudul {
  margin: 0;
  font-size: var(--t-h2);
  letter-spacing: -0.02em;
  line-height: 1.1;
}

/*
  Judul beserta keterangannya, dikelompokkan menjadi satu kolom kiri.

  `.bagianKepala` menyusun anaknya dengan `justify-content: space-between`.
  Tanpa pembungkus ini, menambahkan satu paragraf akan membuatnya menjadi anak
  KETIGA dan terlempar ke tengah, di antara judul dan tautan. Dibungkus begini,
  kepala bagian tetap dua sisi seperti seluruh bagian lain di halaman ini.

  Pembungkusnya OPSIONAL: bagian yang tidak punya keterangan tetap memakai
  `.bagianKepala` apa adanya, jadi tidak ada satu pun bagian lain yang berubah.
*/
.bagianKepalaTeks {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  min-width: 0;
}

/*
  Lebarnya ditahan di 56ch. Baris teks yang terlalu panjang membuat mata
  kehilangan awal baris berikutnya — dan keterangan bagian justru yang paling
  sering dibaca sambil lalu.
*/
.bagianLede {
  margin: 0;
  max-width: 56ch;
  color: var(--text-muted);
  font-size: var(--t-dasar);
  line-height: 1.55;
  text-wrap: pretty;
}

/*
  Jeda yang lebih lega untuk bagian besar.

  Diagnosis gaya menemukan seluruh jarak antar-bagian berkerumun di angka yang
  hampir sama, sehingga tidak ada bagian yang terbaca lebih penting daripada
  yang lain. Bagian yang membawa keterangan sendiri adalah bab, bukan sekadar
  lanjutan daftar — dan ia diberi napas lebih panjang di atasnya.
*/
.bagianLega {
  margin-top: 6rem;
}

/*
  BERITA DAN AGENDA ADALAH SATU BAB, bukan dua seksi sejajar.

  Buktinya bukan selera saya, melainkan navigasi situs ini sendiri: pintasannya
  berlabel "Agenda & Berita", satu tombol untuk keduanya. Di beranda keduanya
  justru tampil sebagai dua seksi berkepala identik yang terpisah, dan satu-
  satunya pembeda antar-seksi di seluruh halaman ini adalah latar `.pita` yang
  berganti setiap seksi.

  Pergantian latar setiap seksi itu punya nama sendiri di daftar pola slop:
  "Alternating Background Only, the only variation between sections is flipping
  the background color every other section". Jadi variasi yang sudah ada di
  halaman ini justru variasi yang dilarang.

  Ketiga kelas di bawah menyatukan keduanya menjadi satu bidang berlatar utuh:
  yang pertama menutup bagian bawah bidang bab, yang kedua membuka lanjutannya
  tanpa jeda, dan yang ketiga memberi kepala lanjutan bobot yang lebih ringan
  supaya terbaca sebagai anak-bab, bukan bab baru.
*/
.pitaAwal {
  padding-bottom: 0;
}

/*
  Jaraknya lewat `padding`, BUKAN `margin`.

  `.pita` melukis latarnya dengan `box-shadow: 0 0 0 100vmax` lalu memangkasnya
  `clip-path: inset(0 -100vmax)`, dan pangkasan itu berhenti tepat di tepi
  elemen. Margin berada DI LUAR tepi itu, jadi jarak lewat margin akan
  menyisakan pita latar halaman di antara kedua bidang, tepat di tempat yang
  seharusnya menyatu.
*/
.pitaLanjut {
  margin-top: 0;
  padding-top: 2.25rem;
}

.bagianKepalaLanjut {
  border-bottom-width: 1px;
  border-bottom-color: var(--border);
}

.bagianJudulLanjut {
  font-size: var(--t-h3);
}

@media (max-width: 640px) {
  .bagianLega {
    margin-top: 4rem;
  }
}

/*
  Tautan lanjutan: kapital berspasi lebar dengan panah.

  Gaya ini sengaja BERBEDA jauh dari tautan biasa di dalam teks. Ia menandai
  "ada lanjutan di halaman lain", dan karena bentuknya khas, mata menemukannya
  tanpa harus membaca. Panahnya bergeser sedikit saat disentuh.
*/
.bagianTautan {
  color: var(--primary);
  font-weight: 700;
  font-size: var(--t-kecil);
  letter-spacing: 0.11em;
  text-transform: uppercase;
  text-decoration: none;
  white-space: nowrap;
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
}

.bagianTautan::after {
  content: '→';
  font-size: 1.05em;
  transition: transform 0.18s ease;
}

.bagianTautan:hover::after {
  transform: translateX(3px);
}

@media (prefers-reduced-motion: reduce) {
  .bagianTautan::after { transition: none; }
  .bagianTautan:hover::after { transform: none; }
}

.bagianTautan:hover {
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* ---------- Kartu bidang ---------- */

.kisi {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 1rem;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 17rem), 1fr));
}

/*
  Tiga kolom di layar lebar — disamakan dengan `limit: 3` pada kuerinya.

  Kedua pemakai kisi ini, Berita dan Policy Center, mengambil paling banyak
  TIGA baris dari basis data (lihat lib/beranda.ts). Sementara `auto-fill`
  menyediakan empat jalur pada lebar 1292px, sehingga satu petak SELALU kosong
  di kanan — bahkan ketika datanya sudah penuh. Petak kosong yang tidak pernah
  bisa terisi terbaca sebagai ada yang gagal dimuat, bukan sebagai ruang.

  Kalau limit kuerinya kelak diubah, angka di sini harus ikut diubah. Keduanya
  menyatakan hal yang sama dan harus tetap sepakat.
*/
@media (min-width: 60rem) {
  .kisi {
    grid-template-columns: repeat(3, 1fr);
  }
}

.kartuBidang {
  display: flex;
  gap: 0.9rem;
  align-items: flex-start;
  padding: 1.25rem 1.25rem;
  background: var(--bg-alt);
  border: 1px solid var(--border);
  border-radius: var(--r-kartu);
  transition: transform 0.18s ease, border-color 0.18s ease, box-shadow 0.18s ease;
}

.kartuBidang:hover {
  transform: translateY(-2px);
  border-color: var(--brand-300);
  box-shadow: var(--naik-angkat);
}

.roman {
  flex: none;
  display: grid;
  place-items: center;
  width: 2.1rem;
  height: 2.1rem;
  border-radius: var(--r-kartu);
  background: var(--primary-isi);
  color: #fff;
  font-size: var(--t-kecil);
  font-weight: 700;
  letter-spacing: 0.02em;
}

.namaBidang {
  margin: 0;
  font-size: var(--t-dasar);
  font-weight: 600;
  line-height: 1.45;
}

/* ---------- Kartu berita ---------- */

/*
  Perilaku angkatnya DIHAPUS dari sini dan diambil dari `.angkat`.

  Berkas ini dulu menyalin primitif itu utuh — transisi 0,18s yang sama,
  `translateY(-2px)` yang sama, `--brand-300` yang sama — tetapi dengan bayangan
  yang BERBEDA: `0 6px 18px rgb(0 0 0 / .07)`, sementara primitifnya memakai
  `0 8px 20px rgb(0 0 0 / .08)`. Selisih sekecil itu tidak terbaca sebagai
  variasi yang disengaja, hanya sebagai situs yang digarap beberapa tangan —
  dan ia menyumbang satu dari tujuh bayangan nyaris kembar yang ditemukan
  diagnosis gaya.

  Salinan itu juga tidak pernah benar-benar aktif: parameter map di page.tsx
  bernama `p` dan membayangi impor page.module.css, sehingga kartu berita
  tidak pernah mendapat `.klikPenuh` maupun `:focus-within` yang menyertainya.
  Sekarang keduanya datang dari primitifnya.
*/
.kartuBerita {
  display: flex;
  flex-direction: column;
  background: var(--bg-alt);
  border: 1px solid var(--border);
  border-radius: var(--r-kartu);
  overflow: hidden;
}

.gambar {
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  background: var(--surface-2);
}

/*
  Bidang pengganti ketika berita tidak punya sampul.

  Gradiennya punya tugas, bukan hiasan: ia menandai bahwa ini BUKAN gambar.
  Bidang rata satu warna terbaca sebagai foto yang gagal dimuat, dan kotak abu
  kosong terbaca sebagai kerusakan. Gradasi sangat samar dari basuhan merah ke
  bidang berselang membuatnya jelas sebagai bidang buatan, sekaligus tetap
  tenang supaya tidak bersaing dengan kartu yang memang punya foto.

  Arahnya 135 derajat, sama dengan bidang sejenis di halaman /berita, supaya
  keadaan "tanpa sampul" punya satu bahasa di seluruh situs.
*/
.gambarKosong {
  display: grid;
  place-items: center;
  width: 100%;
  aspect-ratio: 16 / 9;
  background: linear-gradient(135deg, var(--brand-wash), var(--bg-alt));
  color: var(--primary);
  font-weight: 700;
  font-size: var(--t-kecil);
  letter-spacing: 0.08em;
}

/*
  Blok media query tema gelap di sini DIHAPUS, dua sebab.

  (Frasa media query-nya sengaja tidak ditulis utuh: menghitung sisa cacat ini
  di seluruh proyek dilakukan dengan mencarinya, dan komentar yang memuatnya
  utuh akan ikut terhitung sebagai cacat.)

  1. CACAT TOGGLE TEMA. Media query itu tidak mengenal `[data-theme]`, jadi
     pengguna bersistem gelap yang memilih tema terang mendapat bidang gelap
     di dalam kartu terang — cacat yang sama dengan angka romawi bidang.

  2. WARNA LITERAL DI LUAR globals.css. `rgb(126 29 37 / 0.25)` bukan bagian
     dari tangga `--brand-*` mana pun; ia rona asing yang tidak pernah diukur
     kontrasnya. Skill §1 melarangnya, dan menggantinya dengan token justru
     MENGEMBALIKAN disiplin palet, bukan mengubahnya.

  `--brand-wash` sudah persis menjadi pasangan yang dibutuhkan: `--brand-50`
  saat terang dan `--brand-950` saat gelap. Di tema terang hasilnya identik
  dengan sebelumnya (`--bg-alt` memang bernilai `--surface-2`), jadi tidak ada
  yang berubah di sana. Satu aturan menggantikan dua.
*/

.isiKartu {
  padding: 1rem 1.25rem 1.25rem;
  display: flex;
  flex-direction: column;
  flex: 1;
}

/*
  Lencana jenis: bidang TINTA penuh, bukan pil bergaris.

  Warnanya sengaja tinta, bukan merah. Merah sudah dipakai untuk hal yang bisa
  DIKLIK — tautan, tombol, blok tanggal. Kalau lencana ikut merah, mata belajar
  bahwa merah tidak berarti apa-apa lagi. Lencana ini hanya keterangan, tidak
  membawa ke mana pun, jadi ia memakai tinta.

  Tema situs merah–putih–hitam, sehingga warna keempat untuk lencana ditolak.
*/
.jenis {
  align-self: flex-start;
  margin-bottom: 0.75rem;
  padding: 0.15rem 0.6rem;
  border-radius: var(--r-kecil);
  background: var(--text);
  color: var(--bg);
  font-size: var(--t-mikro);
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
}

.judulKartu {
  margin: 0 0 0.5rem;
  font-size: var(--t-isi);
  font-weight: 700;
  line-height: 1.4;
}

.judulKartu a {
  color: var(--text);
  text-decoration: none;
  min-height: auto;
}

.judulKartu a:hover {
  color: var(--primary);
}

/* Seluruh kartu dapat diklik lewat ::after, tanpa membungkus <a> di sekeliling
   elemen blok — struktur HTML tetap benar bagi pembaca layar. */
.judulKartu a::after {
  content: '';
  position: absolute;
  inset: 0;
}

/*
  `.kartuBerita` DIKELUARKAN dari selektor ini.

  Aturan ini adalah tipografi RINGKASAN — ukuran 0,89rem, warna redup, dan
  jarak bawah 0,9rem. Ikut menempel pada `.kartuBerita`, ia mengenai WADAH
  kartunya: kartu di dalam kisi ber-`gap` mendapat margin bawah 0,9rem
  tambahan, sehingga jarak antarbaris kartu menjadi lebih besar daripada jarak
  antarkolomnya.

  Cacat ini tidak pernah terlihat karena berita di basis data baru dua — semua
  muat dalam satu baris, dan margin bawah baris terakhir tidak ada
  pembandingnya. Ia baru akan muncul begitu PERGUBI mengisi beritanya.
*/
.ringkas {
  margin: 0 0 0.9rem;
  font-size: var(--t-dasar);
  line-height: 1.6;
  color: var(--text-muted);
}

/*
  Tanggal berpindah ke ATAS ringkasan dan ditebalkan.

  Sebelumnya ia terdorong ke kaki kartu oleh `margin: auto 0 0` dan disamarkan abu. Pada daftar berita, tanggal adalah hal kedua yang dicari orang setelah judul — mereka ingin tahu apakah ini kabar baru atau lama sebelum memutuskan membacanya. Menyembunyikannya di kaki membalik urutan itu. */ .tanggal { margin: 0 0 0.5rem;
  font-size: var(--t-kecil);
  font-weight: 700;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}

/* ---------- Agenda ---------- */

.daftarAgenda {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0.75rem;
}

.kartuAgenda {
  display: flex;
  gap: 1.25rem;
  align-items: center;
  padding: 1rem 1.25rem;
  background: var(--bg-alt);
  border: 1px solid var(--border);
  border-left: 4px solid var(--primary);
  border-radius: var(--r-kartu);
}

/*
  Aksen kiri DIPERTAHANKAN saat baris disentuh.

  `.angkat:hover` menetapkan `border-color` untuk SELURUH sisi menjadi
  `--brand-300`. Tanpa aturan di bawah ini, menyentuh baris agenda akan
  memudarkan garis merah 4px di kirinya menjadi merah muda — penanda terkuat
  baris itu justru meluruh tepat ketika ia sedang diperhatikan.

  Spesifisitasnya dinaikkan lewat `.daftarAgenda` menjadi (0,3,0) supaya pasti
  menang atas `.angkat:hover` (0,2,0), tanpa bergantung pada urutan pemuatan
  berkas modul — urutan yang tidak dijamin bundler.

  Hanya WARNANYA yang dipertahankan, tidak ditebalkan. Ubin bidang menebalkan
  aksennya karena di sana aksen itu satu-satunya penanda arah; di sini baris
  sudah punya blok tanggal merah pekat sebagai penanda, dan menambah gerak
  kedua hanya membuat ramai.
*/
.daftarAgenda .kartuAgenda:hover,
.daftarAgenda .kartuAgenda:focus-within {
  border-left-color: var(--primary);
}

/*
  Blok tanggal: bidang merah pekat bertulisan putih.

  Sebelumnya blok ini putih bergaris dengan angka merah, dan tenggelam di
  antara teks di sebelahnya. Dijadikan bidang penuh, ia berfungsi seperti
  penanda di tepi halaman — tanggal terbaca lebih dulu daripada judulnya,
  yang memang urutan yang dicari orang saat memindai daftar acara.

  Warnanya `--brand-700` mati, BUKAN `--primary`. Di mode gelap `--primary`
  berubah menjadi merah muda terang, dan tulisan putih di atasnya turun ke
  sekitar 2:1 — tidak terbaca. Merah tua tetap merah tua di kedua mode, dan
  putih di atasnya 7,77:1.
*/
.kalender {
  flex: none;
  display: grid;
  place-items: center;
  width: 3.6rem;
  padding: 0.6rem 0;
  border-radius: var(--r-kartu);
  background: var(--brand-700);
  color: #fff;
  text-align: center;
  line-height: 1.15;
}

.kalenderHari {
  font-size: var(--t-besar);
  font-weight: 800;
  color: #fff;
  font-variant-numeric: tabular-nums;
}

.kalenderBulan {
  font-size: var(--t-mikro);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: rgb(255 255 255 / 0.85);
}

.isiAgenda {
  min-width: 0;
}

.waktuAgenda {
  margin: 0.15rem 0 0;
  font-size: var(--t-kecil);
  color: var(--text-muted);
}

/* ---------- Keadaan kosong ---------- */

.kosong {
  padding: 2rem 1.5rem;
  border: 1px dashed var(--border);
  border-radius: var(--r-kartu);
  background: var(--bg-alt);
  text-align: center;
  color: var(--text-muted);
  font-size: var(--t-dasar);
  line-height: 1.7;
}

/* ---------- Ajakan bertindak ---------- */

/*
  Pita ajakan: foto bersaput merah, selebar layar.

  Fotonya sengaja tenggelam jauh di belakang saputan — ia bukan informasi,
  melainkan pengingat bahwa organisasi ini berisi orang. Karena itu tidak ada
  keterangan acara di sini, berbeda dengan hero: yang harus terbaca cuma
  ajakannya.

  Melebar ke seluruh layar dengan `box-shadow` + `clip-path`, sama seperti
  `.pita` dan `.hero`.
*/
/*
  FOTONYA DULU BERHENTI DI TENGAH PITA, DENGAN TEPI YANG TAJAM.

  Merah pita ini dilukis `box-shadow: 0 0 0 100vmax` yang tidak mengenal batas
  pembungkus, sehingga benar-benar selebar layar. Fotonya tidak: ia `::before`
  ber-`inset: 0`, jadi hanya seluas kotak elemen, dan pembungkus halaman
  berbatas 76rem. Selisihnya jatuh sebagai merah polos di kiri dan kanan.

  TERUKUR SEBELUM DIPERBAIKI:
    layar 1280px -> foto 1229px, merah polos   51px
    layar 1440px -> foto 1241px, merah polos  199px
    layar 1920px -> foto 1241px, merah polos  679px  (35% pita)

  Yang membuatnya terbaca sebagai kekeliruan bukan selisih itu sendiri,
  melainkan TEPINYA YANG TAJAM: foto berhenti mendadak di garis lurus, lalu
  merah rata melanjutkan. Mata membaca garis itu sebagai batas yang tidak
  disengaja.

  PERCOBAAN PERTAMA GAGAL DAN DICATAT DI SINI SUPAYA TIDAK DIULANG. Saya
  sempat membuang `overflow: hidden` dan memberi `::before` lebar `100vmax`
  yang dipusatkan, supaya fotonya benar-benar selebar layar. Di layar lebar
  hasilnya benar. Tetapi pada 834px dan 360px `vmax` mengambil TINGGI layar
  (900px), sehingga lapisan fotonya lebih lebar daripada layarnya — dan
  `clip-path` ternyata tidak menahan luberan gulir dari anak yang diposisikan
  absolut. Terukur: gulir mendatar muncul di kedua lebar itu. Satuan viewport
  memang tidak bisa dipakai di sini, persis seperti peringatan di berkas ini
  soal `100vw`.

  Yang dipakai sekarang tidak melebarkan apa pun: fotonya tetap seluas kotak
  elemen, tetapi dilarutkan ke dalam merah di kedua sisinya dengan `mask`.
  Tidak ada lagi garis tempat foto berhenti, jadi tidak ada lagi yang terbaca
  sebagai kekeliruan — dan tidak ada satu pun satuan viewport yang ditambahkan.
*/
.berandaAjakan {
  position: relative;
  margin-top: 4.5rem;
  padding: clamp(2.5rem, 6vw, 4rem) 2rem;
  background: var(--brand-800);
  box-shadow: 0 0 0 100vmax var(--brand-800);
  clip-path: inset(0 -100vmax);
  color: #fff;
  text-align: center;
  overflow: hidden;
}

.berandaAjakan::before {
  content: '';
  position: absolute;
  inset: 0;
  background-image: url('/hero/ajakan.webp');
  background-size: cover;
  background-position: center;
  /*
    Opasitas dinaikkan dari 0,28. Pada 0,28 orang-orang di foto hanya bayangan
    yang tidak bisa dikenali — ruangnya terpakai tetapi tidak ada yang
    tersampaikan. `mix-blend-mode: luminosity` dipertahankan karena itulah yang
    menjaga foto tetap satu rona dengan merek: yang diambil hanya terang-
    gelapnya, warnanya tetap merah pita.
  */
  opacity: 0.45;
  mix-blend-mode: luminosity;
  -webkit-mask-image: linear-gradient(
    to right,
    transparent 0%,
    #000 18%,
    #000 82%,
    transparent 100%
  );
  mask-image: linear-gradient(to right, transparent 0%, #000 18%, #000 82%, transparent 100%);
  pointer-events: none;
}

/*
  Saput gelap di belakang teks.

  Menaikkan opasitas foto ke 0,45 membuat orang-orangnya terlihat, tetapi
  sekaligus menaruh baju-baju terang tepat di belakang baris kedua lede. Teks
  putih di atas bidang terang itu kehilangan kontras.

  Menurunkan opasitas fotonya lagi hanya mengembalikan masalah yang pertama,
  jadi yang ditambahkan justru peredup yang mengikuti letak teks: paling pekat
  di tengah atas tempat judul dan lede berada, lalu hilang ke arah tepi supaya
  wajah-wajah di sisi kiri dan kanan tetap terlihat.

  Hitam beralfa, teknik dan bentuk yang sama dengan `.heroSaput` di berkas ini.
  Hitam memang bagian dari palet situs (merah-putih-hitam) dan tidak
  memperkenalkan rona keempat — peredup berwarna merah justru akan menumpuk
  rona di atas rona.
*/
.berandaAjakan::after {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(
    ellipse 58% 72% at 50% 40%,
    rgb(0 0 0 / 0.58) 0%,
    rgb(0 0 0 / 0.3) 55%,
    rgb(0 0 0 / 0) 100%
  );
  pointer-events: none;
}

.berandaAjakan > * {
  position: relative;
  z-index: 1;
}

/*
  Tombol di pita ini DIPUSATKAN; di hero tidak.

  `.tombolUtama` diberi `display: block; width: fit-content` supaya label
  panjang boleh mengalir membawa panahnya. Di hero itu benar — seluruh isinya
  memang rata kiri. Tetapi pita ajakan rata tengah, dan elemen blok selebar
  isinya tidak ikut terpusat oleh `text-align: center`: ia menempel ke kiri.

  TERUKUR SEBELUM DIPERBAIKI, pada layar 1440px: tombolnya 34px dari tepi kiri
  pita dan 939px dari tepi kanan, sementara judul dan ledenya persis di tengah.

  Aturannya dipagari `.berandaAjakan` (kekhususan 0,2,0) supaya hero tidak ikut
  berubah — di sana tombolnya harus tetap rata kiri.
*/
.berandaAjakan .tombolUtama {
  margin-inline: auto;
}

.ajakanJudul {
  margin: 0 0 0.75rem;
  font-size: var(--t-h2);
  letter-spacing: -0.02em;
  color: #fff;
}

.berandaAjakanTeks {
  margin: 0 auto 1.75rem;
  max-width: 36rem;
  color: rgb(255 255 255 / 0.88);
  line-height: 1.7;
}

/* ---------- Peringatan database ---------- */

.galat {
  margin-top: 2rem;
  padding: 1.25rem 1.5rem;
  border: 2px solid var(--primary);
  border-radius: var(--r-kartu);
  background: var(--bg-alt);
}

.galatJudul {
  margin: 0 0 0.4rem;
  font-weight: 700;
}

.galatTeks {
  margin: 0;
  color: var(--text-muted);
  font-size: var(--t-dasar);
}

/*
  MATIKAN SELURUH GERAKAN bila pengguna memintanya.

  Ditulis sebagai satu blok di akhir, bukan disebar per aturan, supaya tidak
  ada animasi baru yang lolos tanpa pagar ini.
*/
@media (prefers-reduced-motion: reduce) {
  /*
    `.kartuBerita` dikeluarkan dari kedua daftar ini.

    Gerakannya tidak lagi didefinisikan di berkas ini — ia datang dari primitif
    `.angkat`, yang membawa pagar `prefers-reduced-motion`-nya sendiri di
    page.module.css. Menyebutnya di sini hanya menyisakan selektor yang
    menunjuk aturan yang sudah tidak ada, dan selektor mati seperti itulah yang
    membuat orang berikutnya ragu apakah masih ada yang bergantung padanya.
  */
  .tombolUtama,
  .tombolKedua,
  .panah,
  .kartuBidang {
    transition: none;
  }

  .tombolUtama:hover,
  .tombolKedua:hover,
  .kartuBidang:hover {
    transform: none;
  }

  .tombolUtama:hover .panah,
  .tombolKedua:hover .panah {
    transform: none;
  }
}

/* ---------- Sampul terbitan (kartu publikasi) ---------- */

/*
  Bidang merah bergaya sampul, menggantikan gambar yang tidak ada.

  Produk kebijakan PERGUBI tidak punya gambar sampul — dokumennya PDF. Kartu
  dengan bidang kosong di atasnya terbaca seperti gambar yang gagal dimuat,
  jadi ruang itu diisi tipografi: jenis dokumen, tahun, judul, bidang
  pengusul, dan jumlah halaman. Seluruhnya data sungguhan.

  `aria-hidden` karena judul yang sama sudah ada sebagai tautan di bawahnya —
  tanpa itu pembaca layar mengumumkan judulnya dua kali.
*/
.sampul {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: 1.25rem;
  min-height: 14rem;
  padding: 1.25rem 1.25rem;
  background: var(--brand-700);
  color: #fff;
}

.sampulAtas {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  font-size: var(--t-mikro);
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.sampulJenis {
  padding: 0.15rem 0.5rem;
  border-radius: var(--r-kecil);
  background: rgb(0 0 0 / 0.22);
}

.sampulTahun {
  font-variant-numeric: tabular-nums;
  color: rgb(255 255 255 / 0.8);
}

.sampulJudul {
  margin: 0;
  font-family: var(--font-judul), Georgia, serif;
  font-size: var(--t-sedang);
  font-weight: 700;
  line-height: 1.28;
  letter-spacing: -0.01em;
  text-wrap: balance;
}

.sampulKaki {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  padding-top: 0.6rem;
  border-top: 1px solid rgb(255 255 255 / 0.28);
  font-size: var(--t-mikro);
  color: rgb(255 255 255 / 0.85);
}

/* Tautan penutup kartu; klik sebenarnya ditangani .klikPenuh dari judul. */
.bacaTautan {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  margin-top: auto;
  padding-top: 0.9rem;
  font-size: var(--t-mikro);
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--primary);
}

.bacaTautan::after {
  content: '→';
  font-size: 1.05em;
}

/* ---------- Ubin bidang (kisi 4 kolom) ---------- */

.kisiBidang {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 1rem;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 13rem), 1fr));
}

/*
  Jumlah kolomnya DIPATOK pada pembagi 8, bukan dibiarkan `auto-fill`.

  Bidangnya selalu delapan — angkanya ditetapkan Bagian C Template Program
  Kerja, bukan daftar yang tumbuh. `auto-fill` menghasilkan 5 kolom di layar
  lebar, sehingga baris kedua terisi 3 dan menyisakan dua petak kosong di
  kanan. Lubang itu terbaca sebagai kisi yang kebetulan jadi, bukan yang
  disusun.

  Dengan 4 kolom di desktop dan 2 di tablet, kedelapan ubin selalu mengisi
  barisnya penuh: 4+4, lalu 2+2+2+2, lalu satu kolom di ponsel. Nilai
  `auto-fill` di atas tetap menjadi cadangan untuk lebar di antaranya.
*/
@media (min-width: 40rem) {
  .kisiBidang {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (min-width: 60rem) {
  .kisiBidang {
    grid-template-columns: repeat(4, 1fr);
  }
}

/*
  Ubin TEGAK, bukan kartu mendatar.

  Rujukan memakai kisi gambar berlabel di sini. PERGUBI belum punya gambar
  bertema untuk kedelapan bidang, dan mengisi ruang itu dengan foto acak akan
  lebih buruk daripada tidak sama sekali. Sebagai gantinya angka romawi
  dibesarkan menjadi unsur grafis — proporsinya sama dengan kisi bergambar,
  tetapi tidak berpura-pura ada foto yang tidak ada.
*/
/*
  KEDELAPAN UBIN SENGAJA SERAGAM.

  Aturan proyek melarang kartu yang seluruhnya identik TANPA alasan hierarki
  yang tertulis. Alasannya di sini justru kebalikan dari hierarki: kedelapan
  bidang kepengurusan adalah sederajat, dan datanya membuktikannya. Koleksi
  `divisions` hanya memuat `roman`, `slug`, `name`, dan `sortOrder`; tidak ada
  medan prioritas, bobot, atau peringkat, dan `sortOrder` hanya urutan tampil.

  Angka romawi I sampai VIII adalah penanda identitas menurut Template Program
  Kerja, bukan urutan kepentingan. Membesarkan salah satu ubin berarti mengarang
  hierarki yang tidak ada di organisasinya.

  Variasi komposisi di situs ini dikerjakan ANTAR bab, bukan di dalam satu
  himpunan yang sederajat. Lihat DESIGN.md bagian "Kedelapan bidang ditampilkan
  sederajat".
*/
.ubinBidang {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  min-height: 12rem;
  padding: 1.25rem 1.25rem 1.25rem;
  background: var(--bg-alt);
  border: 1px solid var(--border);
  border-radius: var(--r-kartu);
  overflow: hidden;
}

/*
  Aksen merah dipindahkan dari `border-top` ke pseudo-element.

  ALASANNYA BUKAN SELERA, MELAINKAN CACAT. Primitif `.angkat` mengubah
  `border-color` SELURUH sisi menjadi `--brand-300` saat kartunya disentuh.
  Selama aksennya berupa `border-top`, menyentuh ubin justru MEMUDARKAN garis
  merahnya menjadi merah muda — persis kebalikan dari yang seharusnya terjadi.
  Sebagai pseudo-element ia lepas dari jangkauan aturan itu, sehingga dapat
  menguat, bukan meluruh.

  Warnanya memakai peran semantik `--primary`, bukan `--brand-700` tetap. Di
  tema terang keduanya bernilai sama persis sehingga tampilannya tidak berubah
  sedikit pun; di tema gelap `--brand-700` nyaris tak terlihat di atas #1c1c1e,
  sedangkan `--primary` memang dipilih agar terbaca di sana.
*/
.ubinBidang::before {
  content: '';
  position: absolute;
  inset: 0 0 auto;
  height: 3px;
  background: var(--primary);
  transition:
    height 320ms cubic-bezier(0.22, 0.61, 0.36, 1),
    background-color 320ms cubic-bezier(0.22, 0.61, 0.36, 1);
}

.ubinBidang:hover::before,
.ubinBidang:focus-within::before {
  height: 5px;
  background: var(--primary-hover);
}

/*
  Ubin bidang terangkat 4px selama 320 ms — lebih dalam dan lebih lambat
  daripada kartu lain di situs ini, yang tetap 2px/0,18s.

  DILINGKUPI SENGAJA, TIDAK DIUBAH DI PRIMITIFNYA. `.angkat` dipakai delapan
  halaman; menaikkan nilainya di sana akan menyeret berita, agenda, program,
  publikasi, direktori, dan policy center ikut berubah — padahal yang diminta
  hanya kisi bidang. Aturan proyek (`pergubi-ui` §6) juga mematok angkat kartu
  di 2px, jadi pengecualian ini harus terlihat sebagai pengecualian, bukan
  diselundupkan menjadi aturan baru.

  SPESIFISITASNYA DINAIKKAN LEWAT `.kisiBidang`, bukan lewat `!important`.
  `.angkat:hover` bernilai (0,2,0); tanpa induk tambahan, aturan di bawah ini
  akan seri dengannya dan pemenangnya ditentukan urutan pemuatan berkas modul —
  sesuatu yang tidak dijamin bundler. Dengan `.kisiBidang` nilainya (0,3,0) dan
  hasilnya pasti.
*/
.kisiBidang .ubinBidang {
  transition:
    transform 320ms cubic-bezier(0.22, 0.61, 0.36, 1),
    border-color 320ms cubic-bezier(0.22, 0.61, 0.36, 1),
    box-shadow 320ms cubic-bezier(0.22, 0.61, 0.36, 1);
}

.kisiBidang .ubinBidang:hover,
.kisiBidang .ubinBidang:focus-within {
  transform: translateY(-4px);
}

.ubinRoman {
  font-family: var(--font-judul), Georgia, serif;
  font-size: 2.6rem;
  font-weight: 700;
  line-height: 1;
  letter-spacing: -0.02em;
  color: var(--roman);
  /* `span` bawaannya inline, dan `transform` tidak berlaku pada elemen inline. */
  display: inline-block;
  transform-origin: left center;
  transition:
    transform 320ms cubic-bezier(0.22, 0.61, 0.36, 1),
    color 320ms cubic-bezier(0.22, 0.61, 0.36, 1);
}

.ubinBidang:hover .ubinRoman,
.ubinBidang:focus-within .ubinRoman {
  transform: translateY(-2px) scale(1.05);
  color: var(--roman-kuat);
}

.ubinNama {
  margin: auto 0 0;
  font-size: var(--t-dasar);
  font-weight: 700;
  line-height: 1.35;
  text-wrap: balance;
}

.ubinNama a {
  color: var(--text);
  text-decoration: none;
  transition: color 320ms cubic-bezier(0.22, 0.61, 0.36, 1);
}

/*
  Judul menyala saat SELURUH UBIN disentuh, bukan hanya ketika kursor kebetulan
  tepat di atas hurufnya. Ubin ini memang dapat diklik di mana saja lewat
  `.klikPenuh`; menyalakan judul hanya pada `a:hover` membuat sebagian besar
  permukaannya terasa mati padahal seluruhnya aktif.
*/
.ubinBidang:hover .ubinNama a,
.ubinBidang:focus-within .ubinNama a {
  color: var(--primary);
}

/*
  Penanda ajakan — memberi tahu bahwa ubin ini menuju suatu tempat.

  IA SELALU MENEMPATI RUANGNYA, bahkan ketika tak terlihat. Kalau ruangnya baru
  diambil saat ia muncul, seluruh kisi akan bergeser setiap kali kursor
  melewati satu ubin. Yang beranimasi hanya opasitas dan pergeseran, tidak
  pernah tinggi elemennya.

  Panahnya bergeser 3px — angka yang sama persis dengan `.bagianTautan` di atas,
  supaya kedua ajakan di halaman ini bergerak dengan ukuran yang sama.
*/
.ubinAksi {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  color: var(--primary);
  font-size: var(--t-mikro);
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  opacity: 0;
  transform: translateY(4px);
  transition:
    opacity 320ms cubic-bezier(0.22, 0.61, 0.36, 1),
    transform 320ms cubic-bezier(0.22, 0.61, 0.36, 1);
}

.ubinAksi::after {
  content: '→';
  font-size: 1.05em;
  transition: transform 320ms cubic-bezier(0.22, 0.61, 0.36, 1);
}

.ubinBidang:hover .ubinAksi,
.ubinBidang:focus-within .ubinAksi {
  opacity: 1;
  transform: none;
}

.ubinBidang:hover .ubinAksi::after,
.ubinBidang:focus-within .ubinAksi::after {
  transform: translateX(3px);
}

/*
  Di perangkat sentuh TIDAK ADA hover — penanda yang hanya muncul saat disentuh
  berarti tidak pernah muncul sama sekali di ponsel dan tablet. Di sana ia
  ditampilkan tetap, karena fungsinya justru memberi tahu bahwa ubin ini dapat
  diketuk.
*/
@media (hover: none) {
  .ubinAksi {
    opacity: 1;
    transform: none;
  }
}

/*
  Di satu kolom, tingginya dikembalikan ke 10,5rem — nilai aslinya.

  Angka 12rem dinaikkan untuk memberi tempat penanda aksi tanpa membuat kisi
  bergeser. Pada kisi berkolom banyak ubinnya memang mendekati bujur sangkar
  sehingga tinggi itu wajar; begitu ubinnya selebar layar, `margin-top: auto` pada judul melempar romawi dan judul ke ujung yang berjauhan dan menyisakan ruang mati sekitar 130px di tengah. Isinya sendiri hanya butuh ±10rem, jadi slack-nya dibuang di lebar yang justru paling mahal untuk digulir. */ @media (max-width: 39.99rem) { .ubinBidang { min-height: 10.5rem;
  }
}

/*
  MATIKAN GERAKAN UBIN BIDANG bila pengguna memintanya.

  Keadaan akhirnya tetap dicapai — penanda ajakan tetap terlihat, angka romawi
  tetap menguat — yang dihapus hanya perjalanannya. Menyembunyikan penandanya
  akan menghilangkan informasi, bukan sekadar animasi.
*/
@media (prefers-reduced-motion: reduce) {
  .kisiBidang .ubinBidang,
  .ubinBidang::before,
  .ubinRoman,
  .ubinNama a,
  .ubinAksi,
  .ubinAksi::after {
    transition: none;
  }

  /*
    Spesifisitasnya WAJIB sama dengan aturan yang dimatikan, yaitu (0,3,0).
    Pagar bawaan `.angkat:hover { transform: none }` di page.module.css hanya
    bernilai (0,2,0) — ia kalah dari `.kisiBidang .ubinBidang:hover` di atas,
    sehingga tanpa baris ini ubin bidang tetap terangkat meskipun pengguna
    sudah meminta gerakan dimatikan.
  */
  .kisiBidang .ubinBidang:hover,
  .kisiBidang .ubinBidang:focus-within {
    transform: none;
  }

  .ubinBidang:hover .ubinRoman,
  .ubinBidang:focus-within .ubinRoman {
    transform: none;
  }

  .ubinBidang:hover .ubinAksi::after,
  .ubinBidang:focus-within .ubinAksi::after {
    transform: none;
  }

  .ubinAksi {
    transform: none;
  }
}

