/**
 * fmipa-beranda — CSS section hero/trust/agenda.
 * Memakai token warna & class bersama dari tema fmipa (lihat style.css
 * tema): --fmipa-green(-dark), --fmipa-red(-dark), --fmipa-black,
 * --fmipa-white, --fmipa-font, --fmipa-radius, --fmipa-gap,
 * .fmipa-container/.fmipa-section/.fmipa-grid/.fmipa-card/.fmipa-btn dan
 * .fmipa-stat. Plugin ini TIDAK mendefinisikan ulang class tersebut.
 *
 * CATATAN: daftar class di atas dulu diakhiri tanda bintang yang menempel
 * langsung pada garis miring penutup baris. Rangkaian dua karakter itu
 * MENUTUP blok komentar ini lebih awal (di karakter ke-323). Akibatnya sisa
 * teks komentar ikut diperlakukan sebagai CSS, dan selector rusak yang
 * terbentuk menelan aturan ".fmipa-hero { }" tepat di bawahnya — aturan itu
 * TIDAK PERNAH diterapkan sejak file ini dibuat. Baru ketahuan saat hero
 * butuh position:relative + overflow:hidden sebagai containing block video:
 * tanpa keduanya, iframe YouTube lolos keluar dari hero dan judulnya bocor
 * di atas header. Jangan pernah menaruh tanda bintang persis sebelum garis
 * miring di dalam komentar CSS.
 */

/* ==========================================================================
   Hero carousel (slide_hero) — perbaikan bug B6 "headline terpotong mobile"
   ========================================================================== */

.fmipa-hero {
	padding: 0;
	overflow: hidden;
	position: relative;
}

/* Semua slide ditumpuk di SATU sel grid, jadi tinggi carousel selalu setinggi
   slide TERPANJANG dan tidak berubah saat berputar. Sebelumnya slide non-aktif
   display:none sehingga tinggi hero mengikuti slide yang sedang tampil — begitu
   ada >1 slide dengan panjang teks berbeda, hero berubah tinggi tiap rotasi dan
   seluruh isi halaman di bawahnya ikut bergeser (CLS 0,183; performance turun
   ke 92). Tidak terlihat sebelumnya karena DB cuma punya 1 slide.

   visibility:hidden (bukan display:none) dipilih supaya slide tetap menempati
   ruang grid — dan tetap aman secara aksesibilitas, karena visibility:hidden
   juga mengeluarkan isinya dari accessibility tree sekaligus membuat CTA di
   dalamnya tidak bisa difokus keyboard. */
/* Tinggi hero diikat ke viewport, bukan ke angka tetap 420px.
   Terukur sebelumnya: hero hanya 492px di viewport 900px — 55%, sehingga pita
   hijau section berikutnya sudah mulai SEBELUM fold dan hero terbaca sebagai
   strip letterbox, bukan sebagai pembuka halaman.

   Satuan svh (small viewport height), bukan vh: di ponsel, vh dihitung dari
   viewport TANPA bilah URL browser, jadi hero ber-100vh selalu terpotong saat
   bilah itu tampil. svh memakai tinggi terkecil, jadi isinya tidak pernah
   tertutup.

   Batas atas 760px supaya di layar sangat tinggi hero tidak berubah jadi
   dinding kosong; batas bawah 520px menjaga ruang untuk headline + CTA di
   ponsel. */
.fmipa-hero-carousel {
	position: relative;
	display: grid;
	min-height: clamp(520px, 72svh, 760px);
}

.fmipa-hero-slide {
	grid-area: 1 / 1;
	position: relative;
	min-height: clamp(520px, 72svh, 760px);
	visibility: hidden;
	/* TIDAK pakai height tetap + overflow:hidden pada konten — akar bug B6
	   lama adalah headline dipaksa masuk kotak berukuran tetap. Di sini
	   tinggi mengikuti konten (min-height saja), teks selalu punya ruang. */
}

.fmipa-hero-slide.is-active {
	visibility: visible;
}

.fmipa-hero-slide__media {
	position: absolute;
	inset: 0;
	z-index: 0;
}

.fmipa-hero-slide__media img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
}

.fmipa-hero-slide__media::after {
	content: "";
	position: absolute;
	inset: 0;
	/* Scrim dua arah supaya teks putih tetap kontras di atas foto apa pun —
	   BRAND-GUIDELINE.md §4.4.

	   Versi lama hanya gradien vertikal 0,35 -> 0,65 dan itu TIDAK cukup:
	   diukur dari piksel yang benar-benar dirender di belakang headline,
	   rata-rata latarnya memang aman (7,23:1) tapi 5% piksel paling terang —
	   dinding gedung yang kena matahari — hanya mencapai 2,75:1, di bawah
	   ambang 3:1 untuk teks besar. Rata-rata menyembunyikan titik gagalnya,
	   jadi yang dipakai sebagai patokan adalah persentil terburuk.

	   Lapisan horizontal ditambahkan karena teks hero rata KIRI: menggelapkan
	   sisi kiri menaikkan kontras tepat di tempat teks berada, tanpa
	   memudarkan seluruh foto seperti kalau alpha vertikalnya dinaikkan rata.
	   Pola ini sama dengan overlay hero psikologi.

	   Titik tengahnya ikut dibuka bersama scrim video (0,40 -> 0,16 vertikal;
	   0,28 -> 0,08 horizontal) supaya tidak ada lompatan terang saat video
	   fade-in menggantikan poster; halo teks di bawah yang menggantikan
	   perannya sebagai penjaga kontras.

	   Diukur dari tangkapan layar yang benar-benar dirender pada foto poster
	   terpasang — piksel latar terburuk tepat di bawah glyph, halo sudah ikut
	   terhitung: headline 4,30:1 (ambang 3:1), deskripsi 6,60:1 (ambang
	   4,5:1). Perhatikan arahnya: scrim turun tiga kali berturut-turut
	   (0,40 -> 0,34 -> 0,24 -> 0,16) tapi angka kontrasnya JUSTRU naik
	   (4,13 -> 3,46 -> 4,04 -> 4,30) begitu halo masuk dan dikuatkan. Itu
	   bukan kebetulan: gelap yang dipasang tepat di sekeliling huruf jauh
	   lebih efisien daripada gelap yang dipasang sebidang gambar. */
	background:
		linear-gradient(180deg, rgba(var(--fmipa-hero-scrim, 0, 61, 40), 0.55) 0%, rgba(var(--fmipa-hero-scrim, 0, 61, 40), 0.16) 45%, rgba(var(--fmipa-hero-scrim, 0, 61, 40), 0.75) 100%),
		linear-gradient(90deg, rgba(var(--fmipa-hero-scrim, 0, 61, 40), 0.72) 0%, rgba(var(--fmipa-hero-scrim, 0, 61, 40), 0.08) 58%, rgba(var(--fmipa-hero-scrim, 0, 61, 40), 0.05) 100%);
}

/* ==========================================================================
   Hero penuh sampai ke balik navbar — body.fmipa-hero-atas
   ==========================================================================

   Kelas body dan variabel --fmipa-header-h keduanya disuplai TEMA
   (inc/template-tags.php + assets/js/nav-toggle.js). Kalau tema lain yang
   dipakai, tidak ada satu pun aturan di bawah ini yang aktif dan hero
   kembali duduk normal di bawah header — plugin ini tidak pernah memaksa.

   Nilai cadangan 80px hanya menjaga tampilan kalau JS gagal dimuat; angka
   sebenarnya selalu hasil ukur, karena tinggi header berubah menurut lebar
   layar, ukuran font pengguna, dan zoom. */

body.fmipa-hero-atas .fmipa-hero {
	margin-top: calc(-1 * var(--fmipa-header-h, 80px));
}

/* Tinggi hero = SISA LAYAR di bawah bar utilitas, bukan clamp bertopi 760px.
   Dengan hero yang naik ke balik navbar, satu-satunya yang masih memakan
   tinggi di atasnya adalah bar utilitas — jadi mengurangi tingginya membuat
   tepi bawah hero jatuh persis di tepi bawah layar. Layar pertama habis
   untuk hero, tidak ada potongan pita berikutnya yang mengintip.

   Ini MEMBATALKAN topi 760px yang dipasang sebelumnya dengan alasan 'di
   layar sangat tinggi hero jangan jadi dinding kosong'. Alasan itu tidak
   hilang — hero 1440px di monitor tinggi memang lapang — tapi diputuskan
   kalah oleh permintaan hero setinggi layar penuh. Kalau nanti terasa
   terlalu lega, yang dipasang kembali cukup min() di sini, bukan clamp
   yang lama.

   min-height, bukan height: kalau headline membungkus panjang di layar
   pendek (ponsel lanskap), kotaknya tetap boleh tumbuh alih-alih memotong
   isinya. svh dipertahankan supaya bilah URL browser ponsel tidak pernah
   menutupi bagian bawah hero. */
body.fmipa-hero-atas .fmipa-hero-carousel,
body.fmipa-hero-atas .fmipa-hero-slide {
	min-height: calc(100svh - var(--fmipa-utility-h, 40px));
}

/* Isi hero dipusatkan vertikal. Wajib begitu tingginya jadi setinggi layar:
   dengan isi tetap menempel di atas, hero 990px hanya terisi 550px teratas
   dan menyisakan ~440px kosong di bawah headline — terbaca sebagai halaman
   yang belum selesai dimuat, bukan sebagai komposisi.

   Padding atas (yang sudah memuat tinggi navbar) sengaja DIPERTAHANKAN
   meski isinya dipusatkan: di layar pendek, pusat vertikal saja bisa
   menaruh headline tepat di belakang navbar. Padding itu jadi jarak aman
   minimum, sekaligus menggeser teks sedikit di bawah pusat — sesuai
   referensi, headline-nya memang duduk agak ke bawah. */
body.fmipa-hero-atas .fmipa-hero-slide {
	display: grid;
	align-content: center;
}

/* Isi hero didorong turun persis sebesar tarikan di atas. Tanpa ini
   headline naik 80px dan duduk tepat di belakang navbar — komposisinya
   berubah, bukan cuma latarnya. Ditulis sebagai penjumlahan dengan
   padding aslinya supaya nilai clamp yang sudah ada tetap berlaku. */
body.fmipa-hero-atas .fmipa-hero-slide__content {
	padding-top: calc(clamp(2.5rem, 8vw, 5rem) + var(--fmipa-header-h, 80px));
}

/* ==========================================================================
   Hero latar video (mode 'video')
   ========================================================================== */

/* Lapisan video duduk DI ATAS poster (z-index 1 vs 0) dan MULAI TRANSPARAN.
   Ia baru ditampilkan setelah iframe benar-benar termuat (kelas
   .is-video-playing dipasang JS pada event `load` iframe).

   Kenapa opacity 0 wajib: elemen mount ini ikut dicetak di HTML awal, jadi
   kalau ia opaque sejak awal, background ink-nya menutupi poster SEJAK FRAME
   PERTAMA — persis membatalkan alasan poster dipakai sebagai elemen LCP, dan
   menyisakan hero berupa kotak gelap permanen kalau YouTube tak terjangkau.
   (Bug ini sempat tayang: terukur videoLayerBg rgb(7,25,18), opacity 1,
   z-index 1, padahal iframe belum ada sama sekali.)

   Menampilkan lapisan (bukan mem-fade poster) juga arah yang benar: `load`
   cuma berarti dokumen iframe termuat, bukan videonya berputar. Kalau kita
   mem-fade poster di event itu lalu autoplay diblokir, hasilnya hero kosong.
   Dengan arah ini tiap jalur punya gambar:
     video jalan          -> lapisan tampil, menutupi poster
     autoplay diblokir    -> lapisan tampil, YouTube menampilkan thumbnail-nya
     iframe gagal muat    -> lapisan tetap transparan, poster asli yang tampil
     video dilewati       -> iframe tak pernah dibuat, poster asli yang tampil
   (reduced-motion / Save-Data / layar sempit) */
.fmipa-hero--video .fmipa-hero-video {
	position: absolute;
	inset: 0;
	z-index: 1;
	overflow: hidden;
	background: rgb(var(--fmipa-hero-scrim, 0, 61, 40));
	pointer-events: none;
	opacity: 0;
}

.fmipa-hero--video.is-video-playing .fmipa-hero-video {
	opacity: 1;
	transition: opacity 0.6s var(--fmipa-ease, ease);
}

@media (prefers-reduced-motion: reduce) {
	.fmipa-hero--video.is-video-playing .fmipa-hero-video { transition: none; }
}

.fmipa-hero--video .fmipa-hero-video iframe {
	position: absolute;
	top: 50%;
	left: 50%;
	/* 16:9 di-cover ke area hero apa pun rasionya: ambil yang terbesar antara
	   lebar-penuh dan tinggi-penuh, mirip object-fit:cover untuk iframe yang
	   tidak mendukung object-fit. */
	width: max(100%, 177.7778vh);
	height: max(100%, 56.25vw);
	transform: translate(-50%, -50%);
	border: 0;
	pointer-events: none;
}

/* Gradient overlay pola psikologi: gelap di atas -> transparan di tengah ->
   gelap lagi di bawah, supaya headline putih dan tombol tetap terbaca tanpa
   kotak solid. Ditumpuk di atas video, di bawah konten. */
.fmipa-hero--video .fmipa-hero-video::after {
	content: "";
	position: absolute;
	inset: 0;
	/* Titik tengah sengaja dibuka lagi atas permintaan (vertikal 0,52 -> 0,46;
	   horizontal 0,32 -> 0,24 di 60%): dengan nilai lama video praktis tak
	   terlihat dan hero terbaca sebagai bidang hijau polos.

	   Yang TIDAK ikut diturunkan: pangkal kiri gradien horizontal (0,74) dan
	   ujung atas/bawah gradien vertikal. Teks hero rata KIRI, jadi
	   perlindungan kontrasnya datang dari kolom kiri — bukan dari
	   menggelapkan seluruh bidang.

	   Seberapa jauh boleh dibuka bukan selera, ada batasnya. Patokan yang
	   dipakai: isi latar di sini VIDEO, kecerahannya berubah tiap frame, jadi
	   dihitung batas TERBURUK yang mungkin — frame PUTIH TOTAL di belakang
	   glyph. Diukur pada mask glyph sungguhan (hasil selisih dua tangkapan
	   layar: normal vs teks color:transparent), bukan pada kotak blok yang
	   kebanyakan kosong di kanan:

	     scrim 0,52 / 0,32, tanpa halo    headline 4,12:1   deskripsi 8,61:1
	     scrim 0,32 / 0,14, tanpa halo    headline 2,21:1   ← GAGAL 3:1
	     scrim 0,32 / 0,14, halo sedang   headline 3,52:1   deskripsi 8,40:1
	     scrim 0,20 / 0,08, halo sedang   headline 2,6 :1   ← GAGAL 3:1
	     scrim 0,20 / 0,08, halo kuat     headline 3,21:1   deskripsi 9,63:1

	   Baris 2 dan 4 itu alasan halo teks ada, dan alasan halo itu dikuatkan
	   waktu pusatnya dibuka lagi (lihat blok text-shadow di bawah). Scrim
	   seterbuka ini TIDAK boleh dipakai tanpa halo yang sepadan: cabut
	   text-shadow-nya dan headline langsung jatuh ke 2,2:1.

	   Batas berikutnya ada di ~0,18/0,07 (3,11:1) dengan halo yang sekarang.
	   Mau lebih terang lagi berarti halonya yang harus naik dulu — dan pada
	   satu titik halo itu berhenti terbaca sebagai gelap-lembut dan mulai
	   terbaca sebagai noda di belakang huruf. Ukur ulang dengan cara yang
	   sama: frame putih total, mask glyph, persentil terburuk. */
	/* Ujung bawah ditutup RAPAT (0,85 -> 1) di 20% terakhir. Ini bukan urusan
	   kontras teks, melainkan menutupi subtitle & label yang MENYATU di gambar
	   video profil ("Universitas Padjadjaran", "mathematics", "Physics").
	   Teks itu bukan trek caption — trek caption-nya sudah dibuang lewat
	   unloadModule di JS, dan uji frame beku membuktikan teks ini tetap
	   tercetak sesudahnya, sementara caption asli muncul sebagai baris
	   terpisah di bawahnya.

	   Memotong frame (zoom + geser) sempat dicoba dan ditolak: teks itu duduk
	   di ~87% tinggi frame, bukan di tepi, jadi membuangnya butuh zoom ~1,4x —
	   sisi kiri-kanan ikut hilang, ketajaman turun, dan angka zoom-nya berbeda
	   tiap rasio viewport. Scrim tidak punya satu pun kelemahan itu. */
	background:
		linear-gradient(180deg, rgba(var(--fmipa-hero-scrim, 0, 61, 40), 0.80) 0%, rgba(var(--fmipa-hero-scrim, 0, 61, 40), 0.20) 45%, rgba(var(--fmipa-hero-scrim, 0, 61, 40), 0.85) 80%, rgba(var(--fmipa-hero-scrim, 0, 61, 40), 1) 92%),
		linear-gradient(90deg, rgba(var(--fmipa-hero-scrim, 0, 61, 40), 0.74) 0%, rgba(var(--fmipa-hero-scrim, 0, 61, 40), 0.08) 60%, rgba(var(--fmipa-hero-scrim, 0, 61, 40), 0.02) 100%);
}

/* Scrim milik poster SENGAJA dibiarkan hidup (tidak di-display:none seperti
   versi sebelumnya). Selama lapisan video masih transparan — dan itu keadaan
   awal setiap kali halaman dimuat — scrim inilah satu-satunya yang menjamin
   kontras teks putih di atas foto. Tidak ada risiko dobel-gelap: begitu
   lapisan video tampil, ia opaque dan menutupi poster berikut scrim-nya,
   jadi hanya satu scrim yang pernah terlihat pada satu waktu. */

.fmipa-hero--video .fmipa-hero-slide__content { position: relative; z-index: 2; }

.fmipa-hero-slide__content {
	position: relative;
	z-index: 1;
	display: flex;
	flex-direction: column;
	gap: 1rem;
	padding-block: clamp(2.5rem, 8vw, 5rem);
	color: var(--fmipa-white, #fff);
}

.fmipa-hero-slide:not(:has(.fmipa-hero-slide__media)) .fmipa-hero-slide__content {
	color: var(--fmipa-black, #111517);
}

/* Halo teks — pengganti sebagian tugas scrim, dipasang saat pusat hero dibuka
   lebih terang untuk kedua kalinya.

   Sebabnya aritmetika, bukan selera: scrim itu lapisan SEBIDANG. Menaikkan
   kontras headline dengannya berarti menggelapkan seluruh frame, termasuk
   bagian yang justru ingin dilihat. Bayangan teks bekerja LOKAL — hanya
   beberapa piksel di sekeliling glyph yang gelap — jadi kontras naik tepat di
   tempatnya dibutuhkan dan gambarnya tetap terbuka. Itulah yang membuat
   pusat frame boleh turun 0,46 -> 0,32 -> 0,20 tanpa headline jatuh di
   bawah 3:1.

   Radius sengaja besar (44px) dan alfa-nya menyusul, bukan sebaliknya: halo
   sempit + pekat terbaca sebagai garis timbul murahan, sementara halo lebar
   membaur jadi gelap-lembut yang tidak kentara sebagai efek. Nilai sekarang
   (0,80 @44px untuk headline, 0,70 @28px untuk deskripsi) adalah versi
   dikuatkan — dipasang bersamaan dengan pembukaan pusat scrim yang ketiga
   (0,32 -> 0,20); dengan halo versi sebelumnya, scrim setipis itu menghasilkan
   headline 2,6:1, gagal ambang 3:1.

   Dipasang HANYA pada slide yang punya media. Di slide tanpa gambar teksnya
   berwarna gelap di atas latar terang — bayangan gelap di sana justru
   mengotori huruf. */
.fmipa-hero-slide:has(.fmipa-hero-slide__media) .fmipa-hero-slide__headline,
.fmipa-hero--video .fmipa-hero-slide__headline {
	text-shadow:
		0 1px 4px rgba(0, 26, 17, 0.55),
		0 10px 44px rgba(0, 26, 17, 0.8);
}

.fmipa-hero-slide:has(.fmipa-hero-slide__media) .fmipa-hero-slide__deskripsi,
.fmipa-hero--video .fmipa-hero-slide__deskripsi {
	text-shadow:
		0 1px 3px rgba(0, 26, 17, 0.5),
		0 6px 28px rgba(0, 26, 17, 0.7);
}

.fmipa-hero-slide__headline {
	/* Memakai token h1 tema, BUKAN clamp lokal sendiri.
	   Versi lama memakai clamp(1.75rem, 6vw, 3rem) yang mentok di 48px —
	   lebih KECIL daripada --fmipa-fs-h1 milik temanya sendiri (maks 68px),
	   dan cuma 1,09x lebih besar dari judul section (44px). Akibatnya kalimat
	   terpenting di seluruh situs tampil seukuran label section rutin, dan
	   hero kehilangan kehadiran sebagai pembuka halaman.

	   word-break/hyphens dipertahankan: judul panjang tetap harus utuh dan
	   tidak boleh overflow di breakpoint mana pun. */
	font-size: var(--fmipa-fs-h1);
	/* 1.12, dan SENGAJA bukan --fmipa-lh-display (0,95). Token itu dibuat untuk
	   angka statistik raksasa yang selalu satu baris; dipakai pada headline
	   yang membungkus 4 baris, ekor huruf 'g'/'y' baris pertama hampir
	   menyentuh kepala huruf baris berikutnya. Headline hero harus tetap rapat
	   supaya terbaca sebagai satu blok, tapi tidak sampai bertabrakan. */
	line-height: 1.12;
	letter-spacing: var(--fmipa-tracking-display, -0.02em);
	font-weight: var(--fmipa-fw-extrabold, 800);
	margin: 0;
	/* 24ch: ukuran baris yang benar untuk tipe display — headline hero dipindai
	   sebagai satu blok, bukan dibaca sebagai paragraf.
	   Diukur, bukan dikira: di desktop 1440px container (1136px) yang justru
	   mengikat lebih dulu, jadi 24ch dan 42ch menghasilkan jumlah baris yang
	   sama persis (4). Yang benar-benar berbeda hanya nilai di bawah ~24ch.
	   Jadi angka ini aman untuk headline pendek maupun panjang. */
	max-width: 24ch;
	overflow-wrap: break-word;
	word-break: break-word;
	hyphens: auto;
	text-wrap: balance;
}

.fmipa-hero-slide__deskripsi {
	font-size: clamp(1rem, 2.5vw, 1.25rem);
	max-width: 56ch;
	margin: 0;
	overflow-wrap: break-word;
}

.fmipa-hero-slide__cta-group {
	display: flex;
	flex-wrap: wrap;
	gap: 0.75rem;
	margin-top: 0.5rem;
}

.fmipa-hero-slide__cta {
	width: max-content;
	max-width: 100%;
}

.fmipa-hero-carousel__controls {
	position: absolute;
	inset-inline: 0;
	bottom: 1rem;
	z-index: 2;
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 1rem;
}

.fmipa-hero-carousel__prev,
.fmipa-hero-carousel__next {
	background: rgba(255, 255, 255, 0.85);
	color: var(--fmipa-black, #111517);
	border: none;
	border-radius: 999px;
	width: 2.25rem;
	height: 2.25rem;
	font-size: 1.25rem;
	line-height: 1;
	cursor: pointer;
}

.fmipa-hero-carousel__prev:hover,
.fmipa-hero-carousel__next:hover {
	background: var(--fmipa-white, #fff);
}

.fmipa-hero-carousel__dots {
	display: flex;
	gap: 0.5rem;
}

/* Titik indikator: yang TERLIHAT tetap kecil (10px, sesuai pola referensi),
   tapi AREA SENTUHNYA dibesarkan lewat kotak transparan di elemen button-nya
   sendiri — WCAG 2.5.8 mensyaratkan minimal 24×24 CSS px. Sebelumnya button
   ini persis 10×10 dan gagal audit `target-size`; tidak pernah ketahuan
   karena kontrol carousel hanya dirender saat slide >1, dan DB baru punya
   1 slide. Visual dipindah ke ::before supaya kotak sentuh tidak ikut
   terlihat. */
.fmipa-hero-carousel__dot {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 24px;
	min-height: 44px;
	border: none;
	background: none;
	cursor: pointer;
	padding: 0;
	-webkit-tap-highlight-color: transparent;
}

.fmipa-hero-carousel__dot::before {
	content: "";
	display: block;
	width: 0.625rem;
	height: 0.625rem;
	border-radius: 999px;
	background: rgba(255, 255, 255, 0.55);
	transition: width 0.2s var(--fmipa-ease, ease), background-color 0.2s var(--fmipa-ease, ease);
}

/* Titik aktif jadi pil memanjang — pola indikator referensi
   (REFERENSI-PSIKOLOGI.md §2), bukan sekadar berganti warna. */
.fmipa-hero-carousel__dot.is-active::before {
	width: 1.5rem;
	background: var(--fmipa-white, #fff);
}

.fmipa-hero-carousel__dot:focus-visible {
	outline: 2px solid var(--fmipa-white, #fff);
	outline-offset: 2px;
	border-radius: 4px;
}

@media (max-width: 600px) {
	.fmipa-hero-carousel,
	.fmipa-hero-slide {
		min-height: 360px;
	}

	.fmipa-hero-slide__content {
		padding-inline: 1rem;
	}

	.fmipa-hero-slide__headline {
		max-width: 100%;
	}
}

/* ==========================================================================
   Trust — statistik + akreditasi
   ========================================================================== */

/* Menyetel VARIABEL, bukan menulis ulang grid-template-columns. Versi lama
   menulis ulang properti itu dan karenanya berebut dengan aturan .fmipa-grid
   milik tema pada specificity yang seri — pemenangnya bergantung urutan cetak
   stylesheet, dan selama ini modifier ini kalah sehingga jadi dead code. */
.fmipa-grid--statistik {
	--fmipa-grid-min: 140px;
	/* Tanpa margin-bottom. Dulu ada untuk memberi jarak ke strip akreditasi
	   yang menempel di bawahnya DI DALAM section yang sama. Sejak keduanya
	   jadi section terpisah, margin itu menumpuk di atas padding section dan
	   menyisakan bidang kosong lebar di dasar pita hijau. */
}

.fmipa-stat__icon {
	display: block;
	font-size: 1.75rem;
	width: 1.75rem;
	height: 1.75rem;
	margin: 0 auto 0.5rem;
	/* Token pita, bukan hijau-gelap mati: #008050 di atas pita hijau #00B26B
	   hanya 1,80:1 — ikonnya praktis lenyap. */
	color: var(--fmipa-band-accent, #008050);
}

.fmipa-stat__satuan {
	font-size: 0.6em;
	margin-left: 0.15em;
}

.fmipa-akreditasi-strip {
	display: flex;
	flex-wrap: wrap;
	gap: 1rem;
}

/* Badge memakai token KARTU, bukan hex putih langsung. Menyetel background
   tanpa menyetel color adalah akar bug "teks tak terlihat": badge ini duduk
   di dalam pita ink yang mewariskan color:white, lalu memasang latar putih
   sendiri — hasilnya .fmipa-akreditasi-badge__nama tercetak putih di atas
   putih, rasio 1:1, benar-benar tak terbaca. Terukur di beranda produksi,
   bukan dugaan. Ini bug kedua dengan pola sama setelah kartu testimoni.
   Dengan token kartu, warna latar dan warna teks selalu berpasangan dan
   ikut menyesuaikan pita mana pun badge ini ditempatkan. */
.fmipa-akreditasi-badge {
	display: flex;
	align-items: center;
	gap: 0.75rem;
	background: var(--fmipa-card-bg, #fff);
	color: var(--fmipa-card-fg, #111517);
	border-radius: var(--fmipa-radius, 0.5rem);
	padding: 0.75rem 1rem;
	border-left: 4px solid var(--fmipa-green-dark, #008050);
	flex: 1 1 260px;
}

.fmipa-akreditasi-badge img {
	width: 48px;
	height: 48px;
	object-fit: contain;
	flex-shrink: 0;
}

.fmipa-akreditasi-badge__body {
	display: flex;
	flex-direction: column;
	gap: 0.15rem;
	font-size: 0.875rem;
}

.fmipa-akreditasi-badge__nama {
	font-size: 0.95rem;
}

/* Pengingat visual kedaluwarsa: hijau (aktif), kuning (segera), merah
   (kedaluwarsa) — abu untuk yang belum diisi tanggalnya. Sejak badge hanya
   memuat logo + judul, warna garis kiri ini SATU-SATUNYA sisa sinyal masa
   berlaku di front-end; aturan .fmipa-akreditasi-badge__meta/__status yang
   dulu mewarnai teksnya ikut dihapus karena elemennya tidak dicetak lagi. */
.fmipa-akreditasi-badge--aktif {
	border-left-color: var(--fmipa-green-dark, #008050);
}

.fmipa-akreditasi-badge--segera {
	border-left-color: #b78103;
}

.fmipa-akreditasi-badge--kedaluwarsa {
	border-left-color: var(--fmipa-red-dark, #d91820);
}

.fmipa-akreditasi-badge--tidak-diketahui {
	border-left-color: var(--fmipa-gray-500, #999);
}

/* ==========================================================================
   Kolaborator Institusi dan Industri — dinding logo
   ==========================================================================
   Tiga keputusan yang saling bergantung di blok ini:

   1. TINGGI SERAGAM, bukan lebar seragam. Logo mitra datang dengan rasio yang
      liar — ada yang lebar sekali (wordmark), ada yang nyaris bujur sangkar
      (lambang). Menyamakan lebarnya membuat wordmark mengerut jadi setrip
      tipis; menyamakan tingginya membuat semuanya terbaca pada bobot optis
      yang mirip, dan itulah yang dicari mata saat memindai dinding logo.

   2. GRID BUKAN FLEX. Baris terakhir flex-wrap yang isinya dua logo akan
      merenggang mengisi selebar container dan terlihat seperti kesalahan.
      Grid menahan setiap logo di kolomnya.

   3. Logo tampil BERWARNA PENUH. Trik grayscale-lalu-berwarna-saat-hover
      sempat jadi kebiasaan, tapi di sini ia merugikan: separuh mitra dikenali
      justru dari warna mereknya, dan hover tidak ada di layar sentuh — jadi
      di ponsel logonya permanen kelabu. */
.fmipa-mitra-wall {
	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
	gap: var(--fmipa-space-sm, 1rem);
}

/* Ubin ini PUTIH TETAP, bukan --fmipa-card-bg yang ikut berganti per pita.
   Alasannya berkas, bukan estetika: logo yang dipegang admin hampir selalu JPG
   berlatar putih — dari delapan logo contoh yang dipasang, delapan-delapannya
   begitu. Di atas ubin mint (nilai --fmipa-card-bg bawaan) tiap logo muncul
   sebagai persegi putih di dalam kartu hijau muda, dan yang terbaca mata
   justru kotak putihnya, bukan logonya.

   Warna teks tetap dipasang BERPASANGAN dengan latarnya (gray-600 di atas
   putih). Menyetel background tanpa menyetel color adalah pola bug yang sudah
   dua kali terjadi di repo ini — kartu testimoni dan badge akreditasi,
   keduanya berakhir sebagai teks putih di atas putih di dalam pita gelap.

   Garis rambutnya membaca --fmipa-band-line, jadi ubin putih tetap punya tepi
   di pita putih maupun mist (tanpa garis, putih di atas gray-50 cuma selisih
   8/255 — praktis tak terlihat sebagai kartu), dan tetap aman kalau admin
   menggeser section ini ke pita hijau/ink/merah. */
.fmipa-mitra {
	display: flex;
	align-items: center;
	justify-content: center;
	height: 100%;
	min-height: 156px;
	/* Padding sengaja kecil (0,75rem, bukan 1rem). Berkas logo umumnya sudah
	   membawa marginnya sendiri di dalam gambar; menumpuk padding ubin di atas
	   margin bawaan berkas membuat logo mengambang di tengah kotak besar. */
	padding: 0.75rem;
	background: var(--fmipa-white, #fff);
	color: var(--fmipa-gray-600, #4B5563);
	border: 1px solid var(--fmipa-band-line, #E4E7E7);
	border-radius: var(--fmipa-radius, 0.5rem);
	text-align: center;
	text-decoration: none;
}

/* KOTAK LOGO MENGAMBIL SELURUH AREA UBIN, bukan sekadar max-height.

   Versi pertama memasang max-height dan membiarkan lebar mengikuti. Itu benar
   untuk wordmark memanjang, tapi salah untuk logo bujur sangkar — dan logo
   bujur sangkar justru mayoritas: dua belas berkas contoh semuanya 340x340.
   Dengan batas tinggi, logo bujur sangkar dirender sebesar tingginya saja di
   dalam ubin yang jauh lebih lebar, sisa lebar menganggur, dan seluruh dinding
   terbaca sebagai deretan logo kuyu.

   Sekarang <img> mengisi lebar DAN tinggi area dalam ubin, dan object-fit:
   contain yang memutuskan bagaimana isinya duduk: logo bujur sangkar terisi
   setinggi kotak, wordmark memanjang terisi selebar kotak. Satu aturan, dua
   rasio, tidak ada yang terpotong — logo yang terpangkas lebih buruk daripada
   logo kecil.

   Catatan operasional: seberapa besar logo TERLIHAT tidak sepenuhnya ditentukan
   CSS di sini, melainkan seberapa rapat berkasnya dipangkas. Dua belas logo
   contoh dipangkas dulu dari kanvas 340x340 ke kotak isi sebenarnya (rata-rata
   menyusut ~40%) sebelum diunggah; tanpa langkah itu, ubin sebesar apa pun
   tetap menampilkan logo mengambang di tengah bidang putih. Petunjuk ini sudah
   ada di meta box admin. */
.fmipa-mitra__logo {
	width: 100%;
	/* Kotak bujur sangkar, BUKAN height:100%. height:100% di sini diam-diam
	   luruh jadi auto (induk flex-nya tinggi otomatis), sehingga tinggi ubin
	   akhirnya ditentukan rasio berkas: logo tinggi-kurus membuat ubinnya
	   menjulang dan baris grid jadi tidak sama tinggi. aspect-ratio memberi
	   kotak yang ukurannya kita tentukan sendiri, lalu object-fit yang
	   menyesuaikan isinya. max-height mengunci batas atasnya untuk kasus
	   sebaliknya — layar sangat lebar dengan sedikit kolom, tempat ubin bisa
	   melebar jauh melewati ukuran wajar sebuah logo. */
	aspect-ratio: 1 / 1;
	max-height: 132px;
	object-fit: contain;
}

/* Nama sebagai pengganti logo yang belum diunggah — bukan pendamping logo.
   Lihat komentar di section-mitra.php: nama + logo bersamaan mengubah dinding
   logo jadi dinding teks kecil. */
.fmipa-mitra__nama {
	font-size: 0.9rem;
	font-weight: 600;
	line-height: 1.3;
	/* Mewarisi color ubin (gray-600 di atas putih, 7,5:1). TIDAK mengambil
	   token pita: ubin putih tidak ikut berganti latar per pita, jadi teks yang
	   membaca --fmipa-band-fg akan mencetak putih di atas putih begitu admin
	   memindahkan section ini ke pita ink atau merah. */
	color: inherit;
}

/* Umpan balik hover HANYA untuk kartu yang benar-benar bisa diklik (<a>).
   Kartu tanpa tautan dicetak sebagai <span> dan tidak ikut aturan ini —
   kartu yang bergerak saat disentuh padahal tidak ke mana-mana adalah janji
   palsu. */
a.fmipa-mitra {
	transition: transform 0.2s ease, border-color 0.2s ease;
}

a.fmipa-mitra:hover,
a.fmipa-mitra:focus-visible {
	transform: translateY(var(--fmipa-card-lift, -4px));
	border-color: var(--fmipa-band-accent, #008050);
}

@media (prefers-reduced-motion: reduce) {
	a.fmipa-mitra {
		transition: none;
	}
	a.fmipa-mitra:hover,
	a.fmipa-mitra:focus-visible {
		transform: none;
	}
}

@media (max-width: 480px) {
	/* Di ponsel, minmax(150px) menyisakan satu kolom pada layar 360px dan
	   dinding logo berubah jadi kolom panjang berisi 24 kartu. Dua kolom
	   dengan logo lebih pendek tetap terbaca dan memangkas tingginya separuh. */
	.fmipa-mitra-wall {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
	.fmipa-mitra {
		min-height: 128px;
	}
	.fmipa-mitra__logo {
		max-height: 104px;
	}
}


/* ==========================================================================
   Narasi Kredibilitas — 1 foto + 2 paragraf + CTA
   ========================================================================== */
.fmipa-kredibilitas-block {
	display: grid;
	grid-template-columns: minmax(0, 2fr) minmax(0, 3fr);
	gap: clamp(1.5rem, 4vw, 3rem);
	align-items: center;
	margin-top: clamp(2rem, 5vw, 3.5rem);
}
/* Baris judul + supergrafik. Bukan elemen absolut di atas konten, melainkan dua
   kolom yang saling mendorong.

   Ini keputusan yang diambil SETELAH dua versi absolut gagal terukur. Versi
   pojok kanan-bawah: di 1024px huruf paragraf mendarat di atas pita merah,
   kontras 2,29:1. Versi pojok kanan-atas: lolos di banyak lebar tapi jebol di
   850px. Akar masalahnya sama, dan bukan soal angka yang kurang pas -- ruang
   kosong yang dipakai supergrafik bukan fungsi dari lebar layar melainkan dari
   PANJANG PARAGRAF dan tinggi foto. Terukur, pita kosong di atas blok teks
   menyusut 354px (>=1440px) menjadi 143px (783px), dan akan berubah lagi begitu
   admin menyunting narasinya di menu Statistik. Rumus vw apa pun yang dipaskan
   hari ini punya tanggal kedaluwarsa.

   Sebagai elemen aliran, supergrafik mendorong alih-alih menimpa: tumpang tindih
   dengan teks menjadi mustahil secara struktur, tanpa satu pun angka ajaib.
   Judul memakai min-width:0 supaya ia yang mengalah saat sempit, bukan
   supergrafiknya yang gepeng (flex-shrink:0). */
.fmipa-kredibilitas__head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: clamp(1rem, 4vw, 3rem);
}
.fmipa-kredibilitas__head .fmipa-section__header {
	min-width: 0;
	/* Jarak ke bawah sudah disuplai margin-top .fmipa-kredibilitas-block; dibiarkan
	   dobel, baris judul jadi mengambang jauh dari isinya. */
	margin-bottom: 0;
}
/* Supergrafik duduk di POJOK KANAN-BAWAH section. Tiga baris di bawah inilah
   yang membawanya ke sana, dan ketiganya bekerja tanpa satu angka pun:
     - margin-top:auto  memakan seluruh sisa tinggi kolom teks, jadi ia jatuh ke
       dasar. Kolom itu meregang setinggi foto (perilaku bawaan grid), dan sisa
       ruang itulah yang selama ini kosong di bawah tombol CTA.
     - align-self:flex-end mendorongnya ke tepi kanan kolom.
     - width tetap dibatasi supaya ia dekorasi, bukan ilustrasi kedua.
   Karena ia elemen aliran, memanjangkan paragraf hanya menggeser turun titik
   awalnya -- tidak pernah menimpa huruf. Itu bedanya dengan versi absolut yang
   dibuang; lihat catatan panjang di section-trust.php. */
.fmipa-kredibilitas__flame {
	flex: 0 0 auto;
	margin-top: auto;
	align-self: flex-end;
	width: min(26vw, 260px);
	/* 0.72, bukan 0.06 milik .fmipa-section-watermark. Nilai serendah itu ada di
	   sana karena watermark membentangkan seluruh gradien DI BAWAH teks; di sini
	   tidak ada satu huruf pun yang lewat di atasnya, jadi warna merek tidak
	   perlu dipudarkan untuk membeli keterbacaan yang sudah didapat gratis dari
	   tata letak. Tetap di bawah 1 supaya ia tidak menyaingi tombol CTA. */
	opacity: 0.72;
}
.fmipa-kredibilitas__flame .fmipa-supergraphic {
	width: 100%;
	height: auto;
}
.fmipa-kredibilitas-block__media img {
	width: 100%;
	height: auto;
	border-radius: var(--fmipa-radius, 0.5rem);
	object-fit: cover;
	aspect-ratio: 4 / 5;
}
.fmipa-kredibilitas-block__text { display: flex; flex-direction: column; gap: 1rem; }
.fmipa-kredibilitas-block__lead { font-weight: var(--fmipa-fw-bold, 700); font-size: 1.125rem; margin: 0; }
/* Paragraf sekunder membaca --fmipa-band-fg-muted, jadi ia otomatis benar di
   pita mana pun blok ini mendarat. Sebelumnya nilainya dipatok
   --fmipa-gray-500 (dirancang untuk latar terang) plus SATU override khusus
   .fmipa-section--ink. Dua-duanya kalah begitu section trust pindah ke pita
   hijau: gray-500 di atas #00B26B cuma 1,75:1 — terukur, teks nyaris hilang.
   Satu token menggantikan dua aturan sekaligus dan tidak perlu ditambah lagi
   tiap kali ada pita baru. */
.fmipa-kredibilitas-block__text p:not(.fmipa-kredibilitas-block__lead) { margin: 0; color: var(--fmipa-band-fg-muted, #6b7280); }
.fmipa-kredibilitas-block .fmipa-btn { align-self: flex-start; }

@media (max-width: 782px) {
	.fmipa-kredibilitas-block { grid-template-columns: 1fr; }
}

/* ==========================================================================
   Agenda
   ========================================================================== */

.fmipa-grid--agenda {
	grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
}

/* Tanggal adalah bidang UTAMA sebuah agenda — ia yang menjawab "masih sempat
   tidak?" dan ia yang jadi kunci urutan. Sebelumnya tampil sebagai teks
   sekunder biasa (bobot medium, ukuran badan) yang tenggelam di bawah foto,
   sehingga kartu agenda terbaca persis seperti kartu berita. Diberi bentuk
   eyebrow supaya terbaca sebagai label waktu, bukan sebagai kalimat. */
.fmipa-card__meta--tanggal {
	font-size: var(--fmipa-fs-eyebrow, 0.75rem);
	font-weight: var(--fmipa-fw-bold, 700);
	letter-spacing: var(--fmipa-tracking-eyebrow, 0.14em);
	text-transform: uppercase;
	color: var(--fmipa-band-accent, var(--fmipa-green-dark, #008050));
	margin-bottom: 0.35rem;
}

/* Aturan .fmipa-card__actions dihapus dari sini — tema sudah memilikinya
   (display:flex, wrap, gap, margin-top:auto).

   Yang lama menyetel margin-top: 0.75rem dan, karena selectornya lebih
   spesifik (0,2,0 vs 0,1,0) sekaligus dicetak sesudah tema, ia MENGALAHKAN
   margin-top:auto milik tema. Akibatnya blok tombol berhenti tepat di bawah
   teks; karena panjang deskripsi tiap agenda berbeda, tombolnya mendarat di
   ketinggian berbeda-beda dalam satu baris — terukur rentang 100px antar
   kartu. margin-top:auto milik tema yang mendorongnya ke dasar kartu. */

/* ==========================================================================
   "FMIPA dalam Angka" — mode foto latar
   ==========================================================================
   Aktif hanya kalau admin memilih foto di Statistik -> Latar Foto & Catatan.
   Tanpa foto, section ini tetap memakai sistem pita tema dan seluruh blok di
   bawah ini tidak pernah cocok dengan satu elemen pun.

   ANGKA KONTRAS DI SINI BUKAN SELERA. Foto adalah latar terburuk yang bisa
   dipilih untuk teks: kecerahannya beda tiap piksel, dan admin bisa mengganti
   fotonya kapan saja tanpa memberi tahu siapa pun. Jadi semua rasio dihitung
   pada PIKSEL TERBURUK (foto putih penuh, mis. langit terang), bukan rata-rata:

     scrim 0,62 + panel 0,68  -> alpha gabungan 0,878, luminansi latar 0,130
       putih 0,92 pada label  -> 5,5:1   (label kecil butuh 4,5:1)  LOLOS
       #FDB913 pada angka     -> 3,5:1   (angka >=36px butuh 3:1)   LOLOS
     scrim 0,82 di pucuk section (judul h2 duduk di luar panel)
       putih pada judul       -> 4,4:1   (judul >=28px butuh 3:1)   LOLOS

   Menurunkan salah satu alpha berarti menghitung ulang ketiganya. */

.fmipa-section--angka-foto {
	/* Menugaskan ulang token PITA, bukan mewarnai tiap elemen satu per satu.
	   .fmipa-stat__number sudah membaca --fmipa-band-accent dan
	   .fmipa-stat__label membaca --fmipa-band-fg-muted (style.css §7), jadi
	   mode ini cukup menyuplai nilainya. */
	--fmipa-band-bg: transparent;
	--fmipa-band-fg: #fff;
	--fmipa-band-fg-muted: rgba(255,255,255,0.92);
	/* Kuning Unpad, warna aksen angka pada referensi unpad.ac.id — sudah ada
	   di palet tema (--unpad-yellow), bukan warna baru. Hijau merek tidak
	   dipakai di sini: #00B26B di atas latar segelap ini hanya 2,4:1. */
	--fmipa-band-accent: var(--unpad-yellow, #FDB913);
	--fmipa-band-link: #fff;
	--fmipa-band-line: rgba(255,255,255,0.18);
	--fmipa-band-focus: #fff;

	position: relative;
	/* isolation, bukan sekadar z-index: menahan ::after scrim dan foto di
	   stacking context section ini sendiri, sehingga section tetangga (mis.
	   dropdown menu yang menjulur) tidak pernah tertimbun di bawahnya. */
	isolation: isolate;
	overflow: hidden;
	color: #fff;
	/* Warna dasar sebelum foto termuat (loading=lazy) — tanpa ini ada satu
	   frame teks putih di atas putih saat section masuk viewport. */
	background: var(--fmipa-ink, #071912);
	padding-block: var(--fmipa-space-band, 6rem);
}

.fmipa-section--angka-foto > .fmipa-container {
	position: relative;
	z-index: 1;
}

.fmipa-angka__bg {
	position: absolute;
	inset: 0;
	z-index: 0;
}

.fmipa-angka__bg img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: center;
}

.fmipa-angka__bg::after {
	content: "";
	position: absolute;
	inset: 0;
	/* Lebih gelap di pucuk karena judul section duduk di luar panel dan hanya
	   dilindungi scrim ini. */
	background: linear-gradient(
		180deg,
		rgba(7,25,18,0.82) 0%,
		rgba(7,25,18,0.62) 38%,
		rgba(7,25,18,0.72) 100%
	);
}

.fmipa-angka__panel {
	background: rgba(7,25,18,0.68);
	/* backdrop-filter mengaburkan FOTO di belakang panel, bukan isinya —
	   inilah yang membuat angka terbaca sebagai satu bidang tenang di atas
	   foto yang tetap tajam di tepinya. Browser tanpa dukungan (Firefox lama)
	   tetap aman: latar rgba di atas sudah menanggung seluruh syarat kontras
	   sendirian, blur cuma penyedap. */
	-webkit-backdrop-filter: blur(8px) saturate(1.1);
	backdrop-filter: blur(8px) saturate(1.1);
	border: 1px solid rgba(255,255,255,0.14);
	border-radius: var(--fmipa-radius-lg, 1rem);
	padding: clamp(1.75rem, 4vw, 3rem) clamp(1.25rem, 4vw, 3rem);
}

/* Flex, BUKAN grid auto-fit. Dengan grid, sisa baris terakhir menempel ke
   kiri: lima angka di grid 4 kolom jadi "4 + 1 yatim di pojok kiri". Flex
   dengan justify-content:center membuat baris yang tidak penuh tetap di
   tengah, jadi berapa pun jumlah angka yang ditambah admin, panelnya tetap
   terbaca seimbang. flex-basis pakai clamp berbasis persen supaya ponsel
   dapat 2 kolom (40% dari ~311px = 124px) sementara desktop berhenti di
   12rem dan menghasilkan 4-5 kolom. */
.fmipa-angka__grid {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: clamp(1.75rem, 3.5vw, 2.75rem) clamp(1rem, 2.5vw, 2rem);
}

.fmipa-angka__grid > .fmipa-stat {
	flex: 1 1 clamp(8rem, 40%, 12rem);
	max-width: 16rem;
}

/* Angka lebih besar dari ukuran dasar .fmipa-stat__number, tapi TIDAK sebesar
   .fmipa-stat-grid--display (5,5rem): di dalam kolom selebar ~200px, ukuran
   display membuat "35.000+" membungkus jadi dua baris. */
.fmipa-angka__grid .fmipa-stat__number {
	font-size: clamp(2.5rem, 4.5vw, 3.5rem);
	line-height: var(--fmipa-lh-display, 0.95);
}

.fmipa-angka__grid .fmipa-stat__satuan {
	font-size: 0.45em;
	margin-left: 0.1em;
}

.fmipa-angka__grid .fmipa-stat__label {
	display: block;
	margin-top: 0.6rem;
	/* Label di sini TIDAK di-uppercase (berbeda dengan .fmipa-stat__label
	   dasar): "QS Asia University Ranking" dan "Publikasi Internasional Dosen"
	   panjang, dan kapital semua di kolom 200px menambah tinggi barisnya
	   sampai tiga baris. */
	text-transform: none;
	letter-spacing: 0;
	font-size: var(--fmipa-fs-sm, 0.9375rem);
	line-height: 1.35;
}

/* Catatan ikut token pita, BUKAN putih mati: section ini masih dipakai
   dalam mode pita (hijau, teks hitam) kalau admin belum memilih foto, dan
   putih di atas hijau #00B26B cuma 2,1:1 — catatannya praktis lenyap. Warna
   putih hanya berlaku di dalam panel foto, tempat latarnya memang gelap. */
.fmipa-angka__catatan {
	margin: clamp(1.5rem, 3vw, 2.25rem) 0 0;
	font-size: var(--fmipa-fs-xs, 0.875rem);
	color: var(--fmipa-band-fg-muted);
}

.fmipa-angka__panel .fmipa-angka__catatan {
	text-align: center;
	color: rgba(255,255,255,0.82);
}

/* ==========================================================================
   Kenali FMIPA dan Unpad — dua facade video berdampingan
   ==========================================================================
   Dua kartu SEJAJAR dan berukuran sama, bukan satu video besar + satu kecil.
   Keduanya menjawab pertanyaan yang sama pada dua tingkat lembaga ("fakultas"
   dan "universitas yang menaunginya"), dan begitu salah satunya dibuat lebih
   besar, pengunjung membaca yang kecil sebagai pelengkap — padahal calon
   mahasiswa yang belum kenal Unpad justru butuh yang kedua lebih dulu. */
.fmipa-kenali-grid {
	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
	/* min() di dalam minmax() bukan gaya-gayaan: lantai 320px yang telanjang
	   tetap berlaku walau kolomnya cuma punya 288px (viewport 320px dikurangi
	   padding container), dan grid meluber 32px ke kanan — terukur sebagai
	   halaman yang bisa digeser mendatar di ponsel kecil. min() membuat
	   lantainya menyerah pada lebar yang benar-benar tersedia. */
	grid-template-columns: repeat(auto-fit, minmax(min(320px, 100%), 1fr));
	gap: clamp(1.5rem, 4vw, 2.5rem);
	align-items: start;
}

.fmipa-kenali {
	display: flex;
	flex-direction: column;
	gap: 1rem;
	/* min-width:0 wajib pada anak grid: tanpa ini sampul 1280px menetapkan
	   lebar minimum kolomnya sendiri dan grid meluber melewati container. */
	min-width: 0;
}

/* Bingkai video. Sudut membulat harus meng-clip ISI-nya, bukan cuma kotaknya:
   sampul dan iframe sama-sama anak persegi yang akan menonjol keluar di
   keempat sudutnya tanpa overflow:hidden. */
.fmipa-kenali__video {
	position: relative;
	aspect-ratio: 16 / 9;
	border-radius: var(--fmipa-radius-lg, 1rem);
	overflow: hidden;
	background: var(--fmipa-ink, #071912);
	box-shadow: var(--fmipa-shadow-md, 0 10px 30px rgba(7, 25, 18, 0.18));
}

/* Tombolnya SEBESAR bingkai, bukan lingkaran kecil di tengah — target
   sentuhnya jadi seluruh sampul, dan glif putar tinggal penanda visual. */
.fmipa-kenali__play {
	display: block;
	width: 100%;
	height: 100%;
	padding: 0;
	border: 0;
	background: none;
	cursor: pointer;
	border-radius: inherit;
}

.fmipa-kenali__sampul {
	width: 100%;
	height: 100%;
	/* cover, bukan contain: kalau maxresdefault tidak ada dan sampulnya turun
	   ke hqdefault yang berasio 4:3, contain akan menampilkan pita hitam
	   bawaan YouTube di dalam bingkai kita sendiri. */
	object-fit: cover;
	display: block;
	filter: brightness(0.88);
	transition: transform 0.4s var(--fmipa-ease, ease), filter 0.3s ease;
}
.fmipa-kenali__play:hover .fmipa-kenali__sampul {
	filter: brightness(0.7);
	transform: scale(1.03);
}

/* Glif putar. Segitiga dibuat dari border, bukan berkas gambar atau font
   ikon — bentuk sesederhana ini tidak layak satu request sendiri. */
.fmipa-kenali__ikon {
	position: absolute;
	top: 50%;
	left: 50%;
	transform: translate(-50%, -50%);
	width: clamp(3rem, 6vw, 4.25rem);
	aspect-ratio: 1;
	border-radius: 50%;
	background: var(--fmipa-white, #fff);
	box-shadow: 0 6px 20px rgba(7, 25, 18, 0.35);
	transition: transform 0.3s var(--fmipa-ease, ease);
}
.fmipa-kenali__ikon::before {
	content: '';
	position: absolute;
	top: 50%;
	left: 50%;
	/* 54%, bukan 50%: segitiga tampak berat ke kiri kalau dipusatkan pada
	   kotak pembatasnya — mata membaca pusat MASSA-nya. */
	transform: translate(-54%, -50%);
	border-style: solid;
	border-width: 0.55em 0 0.55em 0.9em;
	/* Segitiga memakai hijau tua, bukan hijau terang merek: di dalam cakram
	   putih ia berperan sebagai ikon di atas putih, dan #00B26B di sana cuma
	   2,3:1 sementara --fmipa-green-dark 5,0:1. */
	border-color: transparent transparent transparent var(--fmipa-green-dark, #008050);
	font-size: clamp(0.75rem, 1.4vw, 1rem);
}
.fmipa-kenali__play:hover .fmipa-kenali__ikon {
	transform: translate(-50%, -50%) scale(1.08);
}

@media (prefers-reduced-motion: reduce) {
	.fmipa-kenali__sampul,
	.fmipa-kenali__play:hover .fmipa-kenali__sampul,
	.fmipa-kenali__ikon,
	.fmipa-kenali__play:hover .fmipa-kenali__ikon {
		transition: none;
		transform: none;
	}
	.fmipa-kenali__ikon,
	.fmipa-kenali__play:hover .fmipa-kenali__ikon {
		transform: translate(-50%, -50%);
	}
}

/* Cincin fokus digambar KE DALAM (outline-offset negatif). Tombolnya mengisi
   penuh bingkai ber-overflow:hidden, jadi outline yang mengarah ke luar akan
   terpotong habis oleh clip induknya dan pengguna keyboard tidak melihat apa
   pun. Dua cincin, bukan satu: sampulnya foto sembarang yang bisa saja terang
   di tepi, sehingga cincin putih tunggal bisa hilang di atasnya. */
.fmipa-kenali__play:focus-visible {
	outline: 3px solid var(--fmipa-white, #fff);
	outline-offset: -3px;
	box-shadow: inset 0 0 0 6px rgba(7, 25, 18, 0.55);
}

.fmipa-kenali__iframe {
	width: 100%;
	height: 100%;
	border: 0;
	display: block;
}

.fmipa-kenali__isi {
	display: flex;
	flex-direction: column;
	gap: 0.5rem;
	align-items: flex-start;
}

.fmipa-kenali__judul {
	margin: 0;
	font-size: var(--fmipa-fs-h3, 1.375rem);
	line-height: 1.25;
}

/* Deskripsi membaca --fmipa-band-fg-muted, jadi ia otomatis benar di pita
   mana pun section ini mendarat — warna pita dihitung dari posisi render,
   bukan dipatok, sehingga nilai tetap di sini pasti salah suatu saat. */
.fmipa-kenali__deskripsi {
	margin: 0;
	color: var(--fmipa-band-fg-muted, #6b7280);
}

.fmipa-kenali__tautan {
	margin-top: 0.25rem;
}
