/**
 * Lapisan GERAK beranda — fmipa-motion.css
 * ==========================================================================
 * Satu berkas untuk semua animasi masuk (reveal berjenjang), parallax, dan
 * umpan balik hover di section beranda. Dipisah dari style.css supaya
 * seluruh keputusan gerak bisa dibaca — atau dicabut — di satu tempat.
 *
 * TIGA ATURAN YANG MENGIKAT SELURUH BERKAS INI
 *
 * A. Animasi masuk TIDAK PERNAH memakai `transform`. Semuanya memakai
 *    properti mandiri `translate` / `scale`. Alasannya bukan selera menulis:
 *    komponen yang sudah ada memakai `transform` untuk hover (.fmipa-card
 *    naik -4px, .fmipa-dept-card__media img membesar, .fmipa-btn naik 2px).
 *    Kalau animasi masuk ikut menulis `transform`, aturan reveal yang
 *    selectornya lebih spesifik akan MEMATIKAN hover itu diam-diam. Properti
 *    mandiri disusun browser sebelum `transform`, jadi keduanya berlaku
 *    bersamaan — tanpa saling menimpa dan tanpa perang spesifisitas.
 *    Browser tanpa dukungan `translate` (pra-2022) cuma kehilangan
 *    animasinya; kontennya tetap mendarat di tempat yang benar.
 *
 *    KHUSUS `scale`, aturan itu tidak cukup dijaga dari sisi CSS saja. Motion
 *    menggolongkan `scale` sebagai properti transform, jadi menganimasikannya
 *    langsung akan menulis `transform` inline dan MEMATIKAN hover — terverifikasi
 *    menghasilkan `transform: none` pada atribut style. Karena itu nilainya
 *    dialirkan lewat custom property: JS menganimasikan --fmipa-skala, CSS di
 *    sini yang memetakannya ke `scale: var( --fmipa-skala, ... )`. Pola yang
 *    sama dipakai parallax lewat --fmipa-parallax. Penjelasan penuh ada di
 *    fmipa-anim.js §SKALA.
 *
 * B. TEKS tidak pernah dianimasikan dengan opacity. Ini melanjutkan
 *    keputusan yang sudah tercatat di style.css §.fmipa-reveal: elemen
 *    berteks yang sempat opacity:0 sambil menunggu observer terbaca oleh
 *    audit sebagai teks kontras 0 (terukur: Lighthouse a11y 100 -> 97). Yang
 *    boleh memudar di sini hanya lapisan GAMBAR — foto kartu, foto
 *    departemen, watermark supergrafik — yang tidak membawa teks sama
 *    sekali. Blok teks tetap memakai geser-masuk saja, seperti sectionnya.
 *
 * C. Semuanya berdiri di dalam @media (prefers-reduced-motion: no-preference),
 *    dan setiap keadaan awal digantung pada penanda .fmipa-motion-on yang
 *    dicetak tema di <head>. Yang MENCABUT penanda itu adalah
 *    assets/js/fmipa-anim.js, pada setiap jalur gagal yang mungkin: Motion
 *    tidak termuat dari CDN, tidak ada wadah di halaman ini, atau halaman
 *    sedang dicetak. Begitu penanda lepas, seluruh keadaan awal di berkas ini
 *    berhenti berlaku sekaligus. Tidak ada konten yang bisa tersangkut
 *    tersembunyi gara-gara berkas ini.
 *
 * D. PEMBAGIAN TUGAS. Berkas ini memegang keadaan AWAL; keadaan akhirnya
 *    dijalankan Motion di assets/js/fmipa-anim.js. Pengecualiannya dua, dan
 *    keduanya tetap murni CSS karena Motion tidak bisa menyentuhnya atau
 *    tidak perlu: garis aksen judul (blok 3 — pseudo-element ::after) dan
 *    watermark supergrafik (blok 2 — menempel di <section>, bukan di dalam
 *    wadah). Keduanya masih memakai .fmipa-reveal.is-visible dari
 *    assets/js/nav-toggle.js, dan untuk keduanya pemicu setinggi <section>
 *    memang tepat: mereka duduk di puncak section, bukan 330px di bawahnya.
 * ========================================================================== */

@media (prefers-reduced-motion: no-preference) {

	/* ======================================================================
	   1. Keadaan AWAL kaskade — keadaan akhirnya milik Motion
	   ======================================================================
	   RIWAYAT — blok ini dulu memuat keadaan awal DAN akhir, dirantai ke
	   .fmipa-reveal milik <section> lewat selector .fmipa-reveal.is-visible.
	   Susunan itu punya cacat geometri yang membuat seluruh kaskadenya tidak
	   pernah terlihat: pemicu .fmipa-reveal menyala saat baru padding atas
	   section yang masuk layar, sementara gridnya duduk ~330px lebih ke bawah.
	   Terukur pada viewport 1440x900, saat .is-visible dipasang puncak grid
	   masih di y ~930-1000 — di luar layar. Pada kecepatan gulir wajar
	   (700 px/detik) kartunya sudah selesai bergerak sebelum terlihat.

	   Sekarang pemicunya dipindah ke WADAH-nya sendiri dan dijalankan
	   assets/js/fmipa-anim.js lewat Motion (inView + stagger). Yang tertinggal
	   di CSS hanya keadaan AWAL — dan itu memang harus tinggal di sini, bukan
	   ikut disetel JS: JS jalan di footer, sesudah halaman tergambar, jadi
	   kartu akan sempat tampil di posisi akhir lalu meloncat balik ke posisi
	   awal. Kedipan itu lebih mengganggu daripada tidak ada animasi.

	   >> DAFTARNYA GANDA, DAN ITU DISENGAJA. Pengelompokan wadah di bawah harus
	   sama dengan peta PETA (wadah -> preset) di assets/js/fmipa-anim.js. CSS
	   tidak bisa membaca array JS, dan JS tidak boleh menulis keadaan awal
	   (alasan di atas), jadi satu-satunya cara menjaga keduanya sinkron adalah
	   menyebutkannya di dua tempat. Menambah section baru = menambah wadahnya di
	   KEDUA berkas, DI BLOK PRESET YANG SAMA.

	   Digantung pada .fmipa-motion-on, penanda yang dicetak tema di <head>
	   saat JS hidup (fmipa_motion_flag()). fmipa-anim.js MENCABUT penanda itu
	   pada tiap jalur gagal — Motion tidak termuat, tidak ada wadah, atau saat
	   halaman dicetak — sehingga keadaan awal berhenti berlaku dan halaman
	   tampil utuh. Tanpa mekanisme itu, satu kegagalan CDN berarti beranda
	   yang seluruh fotonya hilang permanen.

	   Anaknya digarap lewat selector STRUKTURAL (> * dari wadahnya), bukan
	   lewat kelas yang harus ditempel satu per satu di markup delapan plugin —
	   sejalan dengan kontrak fmipa_render_section_{slug} yang memang tidak
	   menuntut plugin tahu apa pun soal tema.

	   Sengaja dieja satu per satu, bukan dijaring pola seperti [class*="-grid"]:
	   pola itu ikut menangkap .fmipa-grid-texture — kelas TEKSTUR LATAR yang
	   menempel di <section> itu sendiri — dan akibatnya .fmipa-container yang
	   menggeser, bukan kartunya. */
	/* Properti mandiri `translate` dan `scale`, BUKAN `transform` — aturan A di
	   kepala berkas. Motion menulis properti yang sama sebagai gaya inline saat
	   menganimasikan, jadi gaya inline itulah yang menang di sini; hover
	   ber-`transform` milik .fmipa-card tetap utuh karena browser menyusun
	   `translate` dan `scale` sebelum `transform`, bukan menggantikannya.

	   TIAP BLOK DI BAWAH ADALAH CERMIN SATU PRESET di fmipa-anim.js, dan
	   angkanya harus persis sama dengan JARAK/SKALA di sana. Kalau berbeda,
	   isinya meloncat di frame pertama (CSS lebih jauh) atau menyisakan celah
	   permanen (JS lebih jauh). Peta wadah->preset ada di fmipa-anim.js §PETA;
	   alasan tiap bentuk ada di docs/GERAK-BERANDA.md. */

	/* preset `naik` — judul section, dan grid angka yang TIDAK BOLEH diskalakan
	   (hitung-naik mengukur lebar dengan getBoundingClientRect; leluhur yang
	   sedang diskalakan membuat kuncian lebarnya meleset). */
	.fmipa-motion-on :is(
		.fmipa-section__header,
		.fmipa-angka__grid
	) > * {
		translate: 0 44px;
	}

	/* preset `mekar` — grid kartu. Tumbuh sambil naik. */
	.fmipa-motion-on :is(
		.fmipa-grid,
		.fmipa-dept-grid,
		.fmipa-riset-bidang
	) > * {
		translate: 0 52px;
		scale: var( --fmipa-skala, 0.94 );
	}

	/* preset `pita` — pita akreditasi, masuk dari kiri searah baca. */
	.fmipa-motion-on .fmipa-akreditasi-strip > * {
		translate: -36px 0;
	}

	/* preset `gelombang` — dinding logo mitra. */
	.fmipa-motion-on .fmipa-mitra-wall > * {
		translate: 0 30px;
		scale: var( --fmipa-skala, 0.88 );
	}

	/* preset `sisi` — blok dua kolom menutup seperti buku.

	   :nth-child, bukan urutan larik: fmipa-anim.js sengaja membaca posisi
	   nth-child dari DOM untuk menentukan arah, justru supaya cocok dengan
	   aturan ini. Di section CTA anak pertamanya dibuang penyaring
	   wadah-bersarang, sehingga indeks larik dan nth-child berbeda satu — dan
	   kalau JS memakai indeks lariknya, CSS dan JS akan menarik berlawanan
	   arah pada elemen yang sama. */
	.fmipa-motion-on :is(
		.fmipa-kredibilitas-block,
		.fmipa-kenali-grid,
		.fmipa-testimoni-block,
		.fmipa-section-cta
	) > *:nth-child(odd) {
		translate: -44px 0;
	}
	.fmipa-motion-on :is(
		.fmipa-kredibilitas-block,
		.fmipa-kenali-grid,
		.fmipa-testimoni-block,
		.fmipa-section-cta
	) > *:nth-child(even) {
		translate: 44px 0;
	}

	/* preset `hero` — satu-satunya yang dipicu MUAT, bukan gulir, karena hero
	   sudah di layar sejak frame pertama.

	   :first-child WAJIB: hero ini korsel. Kalau seluruh slide memegang keadaan
	   awal, slide kedua yang tidak pernah dianimasikan akan muncul tergeser
	   28px dan tetap begitu. Yang digeser cuma __content — __media (foto latar,
	   kandidat LCP halaman) sengaja tidak disentuh sama sekali. */
	.fmipa-motion-on .fmipa-hero-slide:first-child .fmipa-hero-slide__content > * {
		translate: 0 28px;
	}

	/* Di layar sempit, dua preset yang bergerak MENDATAR diputar jadi vertikal.
	   Bukan karena ponsel lemah: gerak mendatar di layar 390px berisiko
	   memunculkan scrollbar horizontal, dan tata letak keduanya di sana memang
	   sudah menumpuk vertikal — arah mendatar jadi tidak punya arti apa pun. */
	@media (max-width: 767px) {
		.fmipa-motion-on .fmipa-akreditasi-strip > *,
		.fmipa-motion-on :is(
			.fmipa-kredibilitas-block,
			.fmipa-kenali-grid,
			.fmipa-testimoni-block,
			.fmipa-section-cta
		) > *:is(:nth-child(odd), :nth-child(even)) {
			translate: 0 24px;
		}
	}

	/* Cabang yang MEMUAT wadah lain tidak ikut digeser induknya.
	   Tanpa ini offsetnya berlipat: di section CTA, .fmipa-section__header
	   duduk di dalam .fmipa-section-cta__lead yang merupakan anak langsung
	   wadah .fmipa-section-cta. __lead bergeser 44px sambil membawa
	   headernya, lalu judul di dalamnya bergeser 44px lagi relatif terhadap
	   __lead — 88px untuk satu judul, sementara seluruh halaman lain 44px.

	   :has() dipakai karena inilah satu-satunya cara CSS menyatakan "elemen
	   yang mengandung X". Pasangannya ada di fmipa-anim.js, yang melewati
	   cabang yang sama saat menganimasikan; kalau hanya salah satu yang
	   dipasang, cabangnya tersangkut 44px (CSS saja) atau tetap berlipat
	   (JS saja).

	   Browser tanpa :has() (pra-2023) cuma kembali ke perilaku berlipat itu —
	   judulnya menempuh jarak lebih jauh, tidak ada yang hilang atau macet. */
	.fmipa-motion-on :is(
		.fmipa-section__header,
		.fmipa-grid,
		.fmipa-dept-grid,
		.fmipa-akreditasi-strip,
		.fmipa-riset-bidang,
		.fmipa-angka__grid,
		.fmipa-testimoni-block,
		.fmipa-mitra-wall,
		.fmipa-kenali-grid,
		.fmipa-section-cta,
		.fmipa-kredibilitas-block
	) > *:has( :is(
		.fmipa-section__header,
		.fmipa-grid,
		.fmipa-dept-grid,
		.fmipa-akreditasi-strip,
		.fmipa-riset-bidang,
		.fmipa-angka__grid,
		.fmipa-testimoni-block,
		.fmipa-mitra-wall,
		.fmipa-kenali-grid,
		.fmipa-section-cta,
		.fmipa-kredibilitas-block
	) ) {
		translate: none;
		/* `scale` ikut dinetralkan sejak preset `mekar`/`gelombang` ada. Tanpa
		   baris ini, cabang luar yang memuat wadah lain akan menyusut 6%
		   sambil membawa seluruh isinya — termasuk wadah di dalamnya yang
		   sedang menjalankan kaskadenya sendiri — dan tidak ada satu pun
		   animasi yang akan mengembalikannya ke 1. */
		scale: 1;
	}

	/* ======================================================================
	   2. Keadaan AWAL fade — HANYA lapisan gambar (lihat aturan B di kepala)
	   ======================================================================
	   Keempat pemilih ini semuanya duduk DI DALAM salah satu wadah di blok 1,
	   jadi fade-nya ikut pemicu wadahnya dan tidak butuh pengamat sendiri —
	   fmipa-anim.js menganimasikannya bersamaan dengan kaskade kartunya. */
	.fmipa-motion-on :is(
		.fmipa-card__media img,
		.fmipa-dept-card__media img,
		.fmipa-kredibilitas-block__media img,
		.fmipa-akreditasi-badge img,
		.fmipa-mitra-wall__item img
	) {
		opacity: 0;
	}

	/* >> JANGAN TAMBAHKAN `filter` DI SINI. Blur-masuk sempat dipasang untuk
	   preset `mekar` dan dicabut lagi setelah terukur merusak.

	   `filter` tidak berkomposisi: satu deklarasi menimpa seluruh rantai
	   sebelumnya, tidak seperti `translate` yang berdampingan dengan
	   `transform`. Dan `filter` di sini BUKAN lahan kosong — plugin sudah
	   memakainya pada elemen yang sama, untuk alasan yang bukan hiasan:

	     fmipa-prodi.css   .fmipa-dept-card__media img -> brightness(1.22)
	                       saturate(1.05), karena foto dokumentasi sarpras
	                       banyak yang gelap dan jatuh jadi bidang hitam di
	                       bawah veil.
	     fmipa-beranda.css .fmipa-kenali__sampul -> brightness(0.88), dan
	                       BERUBAH jadi 0.7 saat hover.

	   Aturan di blok ini spesifisitasnya lebih tinggi daripada milik plugin,
	   jadi `filter: blur(...)` di sini akan menghapus perlakuan itu bahkan
	   sebelum animasinya jalan. Terverifikasi: filter terhitung jatuh dari
	   `brightness(1.22) saturate(1.05)` menjadi `blur(5px)` saja, dan
	   gejalanya cuma "fotonya kok agak gelap" — tidak terbaca sebagai bug
	   animasi oleh siapa pun.

	   Kalau blur-masuk benar-benar diinginkan nanti, jalannya adalah kontrak
	   baru: plugin yang menulis `filter: blur(var(--fmipa-blur, 0)) ...`
	   sendiri, sehingga tema cukup menganimasikan variabelnya. Itu menyentuh
	   plugin, jadi keputusannya di luar berkas ini. */

	/* Watermark supergrafik TIDAK ikut Motion. Ia menempel di <section>, bukan
	   di dalam wadah mana pun, dan opacity akhirnya ikut pita warna (0,18 di
	   pita ink, 0,06 di pita terang, lihat style.css) — bukan 1 seperti gambar
	   lain. Karena ia duduk di puncak section, pemicu .fmipa-reveal justru
	   TEPAT untuknya, jadi ia tetap diurus observer di nav-toggle.js. */
	.fmipa-motion-on .fmipa-reveal .fmipa-section-watermark {
		opacity: 0;
		transition: opacity 880ms var(--fmipa-ease-masuk, ease-out);
	}
	.fmipa-motion-on .fmipa-reveal.is-visible .fmipa-section-watermark {
		opacity: var(--fmipa-watermark-opacity, 0.06);
	}

	/* ======================================================================
	   3. Garis aksen judul section — ditarik dari kiri saat section masuk
	   ======================================================================
	   Satu-satunya elemen baru yang ditambahkan lapisan ini. Perannya memberi
	   judul section sesuatu yang bergerak: tanpa itu, judul jadi satu-satunya
	   bagian section yang diam total sementara kartunya berkaskade, dan
	   bagian yang diam di tengah gerakan terbaca seperti belum selesai
	   memuat.

	   Warnanya --fmipa-band-accent, jadi otomatis benar di pita mana pun
	   section mendarat (sistem pita, style.css §3a) — bukan satu warna yang
	   dipatok lalu salah begitu admin menggeser urutan section.

	   Dikurung di dalam .fmipa-reveal supaya hanya section beranda yang
	   dapat; header section di halaman lain tidak berubah. */
	.fmipa-reveal .fmipa-section__header h2::after {
		content: "";
		display: block;
		width: 3.25rem;
		height: 3px;
		margin-top: 0.7rem;
		border-radius: 2px;
		background: var(--fmipa-band-accent, #008050);
		transform-origin: left center;
	}
	/* Keadaan awal DAN pemicunya keduanya digantung di .fmipa-motion-on, dan
	   itu yang membuat aturan ini aman. `is-masuk` dipasang fmipa-anim.js saat
	   headernya masuk layar — kalau Motion tidak pernah termuat, kelas itu
	   tidak pernah datang. Tanpa penjagaan penanda, garisnya akan tersangkut
	   di scale 0 selamanya. Dengan penjagaan ini, hilangnya penanda mencabut
	   scale:0 sekaligus, dan garisnya tampil penuh seperti tanpa animasi. */
	.fmipa-motion-on .fmipa-reveal .fmipa-section__header h2::after {
		scale: 0 1;
		transition: scale 800ms 120ms var(--fmipa-ease-masuk, ease-out);
	}
	.fmipa-motion-on .fmipa-reveal .fmipa-section__header.is-masuk h2::after { scale: 1 1; }
	/* Judul yang memang disembunyikan dari mata (strip akreditasi memakai
	   .screen-reader-text supaya sectionnya tetap punya heading) tidak boleh
	   menumbuhkan garis: ::after-nya ikut terpotong ke kotak 1px milik
	   .screen-reader-text dan muncul sebagai titik nyasar di pojok.

	   Hari ini h2 semacam itu kebetulan berdiri di luar .fmipa-section__header,
	   jadi aturan di atas tidak menjangkaunya dan penjaga ini belum menahan
	   apa pun. Ia tetap ditulis — begitu ada section yang membungkus judul
	   sr-only-nya di dalam header (susunan yang lebih rapi, dan sangat mungkin
	   dilakukan nanti), garisnya akan muncul tanpa ada yang mencarinya. */
	.fmipa-reveal h2.screen-reader-text::after { content: none; }

	/* ======================================================================
	   4. Parallax — dikendalikan assets/js/fmipa-motion.js
	   ======================================================================
	   JS hanya menulis SATU nilai per elemen: --fmipa-parallax (dalam px).
	   Bentuk akhirnya diputuskan di sini. Pembagian itu disengaja — kalau
	   nanti gerakannya mau dimatikan atau dibalik arahnya, tidak ada JS yang
	   perlu disentuh.

	   Kelas .fmipa-parallax-on dipasang JS di <html> saat lapisan ini
	   benar-benar aktif. Overscan gambar (scale) MENGGANTUNG pada kelas itu,
	   bukan pada media query: tanpa JS, overscan cuma memotong gambar tanpa
	   memberi apa pun sebagai gantinya. */
	.fmipa-section-watermark { translate: 0 var(--fmipa-parallax, 0px); }

	.fmipa-parallax-on .fmipa-angka__bg img,
	.fmipa-parallax-on .fmipa-hero-slide__media img {
		/* Ruang lebih supaya geseran vertikal tidak menyingkap tepi kosong di
		   pucuk/dasar bidang. Hitungannya: amplitudo terbesar yang dipakai
		   fmipa-motion.js adalah 72px total (±36px). Bidang terpendek yang
		   memakainya adalah latar "FMIPA dalam Angka", ~600px — 16% darinya
		   memberi 96px kelebihan, ±48px di tiap sisi. Sisa 12px itu marginnya. */
		scale: 1.16;
		translate: 0 var(--fmipa-parallax, 0px);
	}
	.fmipa-parallax-on .fmipa-kredibilitas-block__media img,
	.fmipa-parallax-on .fmipa-section-cta__maskot-img {
		translate: 0 var(--fmipa-parallax, 0px);
	}

	/* ======================================================================
	   5. Umpan balik hover
	   ======================================================================
	   Aturan yang dipegang seluruh blok ini: setiap keadaan :hover ditulis
	   BERSAMA :focus-within / :focus-visible. Grid beranda dijelajahi dengan
	   Tab juga, dan umpan balik yang cuma muncul untuk tetikus berarti
	   pengguna papan ketik menavigasi kartu yang tidak pernah membalas. */

	/* Foto kartu membesar pelan di dalam bingkainya. Slot medianya sudah
	   overflow:hidden (style.css), jadi yang bergerak hanya isinya. */
	.fmipa-card__media img {
		transition: transform 520ms var(--fmipa-ease, ease-out);
	}
	.fmipa-card:hover .fmipa-card__media img,
	.fmipa-card:focus-within .fmipa-card__media img {
		transform: scale(1.06);
	}

	/* Kartu terangkat saat difokus papan ketik, bukan cuma saat ditunjuk
	   tetikus — .fmipa-card:hover sudah ada di style.css, ini pasangannya
	   yang belum pernah ditulis. */
	.fmipa-card:focus-within {
		transform: translateY(var(--fmipa-card-lift));
		box-shadow: var(--fmipa-card-shadow-hover);
		border-color: transparent;
	}

	/* Kartu departemen: fotonya sudah membesar saat hover (fmipa-prodi.css).
	   Yang ditambahkan di sini cuma angkatan kartunya, supaya ia membalas
	   dengan bahasa yang sama seperti .fmipa-card di section lain. */
	.fmipa-dept-card {
		transition: transform 320ms var(--fmipa-ease, ease-out), box-shadow 320ms var(--fmipa-ease, ease-out);
	}
	.fmipa-dept-card:hover,
	.fmipa-dept-card:focus-within {
		transform: translateY(-4px);
		box-shadow: var(--fmipa-shadow-md, 0 12px 32px rgba(7, 25, 18, 0.22));
	}

	/* Badge akreditasi — strip ini bukan tautan, jadi angkatannya sengaja
	   lebih kecil daripada kartu: ia menandai "ini satu satuan yang bisa
	   dibaca", bukan menjanjikan halaman tujuan. */
	.fmipa-akreditasi-badge {
		transition: transform 260ms var(--fmipa-ease, ease-out);
	}
	.fmipa-akreditasi-badge:hover { transform: translateY(-2px); }

	/* Baris bidang riset bergeser ke kanan — arah yang sama dengan tujuan
	   tautannya. Warna namanya sudah berubah saat hover (fmipa-riset.css). */
	.fmipa-riset-bidang__tautan {
		transition: translate 240ms var(--fmipa-ease, ease-out);
	}
	.fmipa-riset-bidang__tautan:hover,
	.fmipa-riset-bidang__tautan:focus-visible { translate: 5px 0; }

	/* Pembungkus nilai angka yang dibuat fmipa-motion.js saat animasi
	   hitung-naik berjalan. Lebarnya DIKUNCI ke lebar angka akhir sebelum
	   hitungan dimulai, jadi berapa pun digit yang sedang tampil, elemen ini
	   tidak pernah berubah ukuran dan satuan di sebelahnya tidak bergeser —
	   syarat yang membuat animasi ini boleh dipasang kembali (riwayatnya ada
	   di section-trust.php). Angka rata tengah di dalam kuncian itu supaya
	   pertumbuhannya terbaca simetris, bukan merayap ke satu sisi. */
	.fmipa-stat__nilai {
		display: inline-block;
		text-align: center;
	}

	/* Statistik: yang membesar saat hover cuma IKONNYA. Angkanya tidak ikut —
	   ukuran teksnya menentukan lebar kolom, dan menskalakannya saat kursor
	   lewat memindahkan tetangganya. */
	.fmipa-stat__icon {
		display: inline-block;
		transition: scale 300ms var(--fmipa-ease, ease-out);
	}
	.fmipa-stat:hover .fmipa-stat__icon { scale: 1.15; }

	/* Tombol putar video CTA — kontrol terbesar di section penutup, jadi ia
	   boleh membalas paling jelas. */
	.fmipa-section-cta__video-play {
		transition: scale 300ms var(--fmipa-ease, ease-out);
	}
	.fmipa-section-cta__video-play:hover,
	.fmipa-section-cta__video-play:focus-visible { scale: 1.03; }

	/* Petak Instagram: gambarnya membesar di dalam petaknya sendiri. */
	.fmipa-sosmed-ig-grid img {
		transition: transform 480ms var(--fmipa-ease, ease-out);
	}
	.fmipa-sosmed-ig-grid a:hover img,
	.fmipa-sosmed-ig-grid a:focus-visible img { transform: scale(1.07); }

	/* Tombol: keadaan hover-nya sudah ada (naik 2px). Yang ditambahkan cuma
	   pasangan papan ketiknya. */
	.fmipa-btn:focus-visible { transform: translateY(-2px); }
}

/* ==========================================================================
   Yang minta gerak diredam
   ==========================================================================
   Tidak ada aturan yang perlu dibatalkan di sini — SELURUH berkas berdiri di
   dalam @media (prefers-reduced-motion: no-preference), jadi pada preferensi
   'reduce' lapisan ini seolah tidak pernah dimuat: kartu langsung di posisi
   akhir, gambar langsung tampak, hover cuma berganti warna seperti sebelum
   berkas ini ada. fmipa-motion.js pun keluar lebih awal pada preferensi yang
   sama, jadi --fmipa-parallax tidak pernah ditulis.
   ========================================================================== */
