/*
Theme Name: FMIPA Unpad
Theme URI: https://fmipa.unpad.ac.id
Author: Tim Pengembang FMIPA Unpad
Description: Tema custom Fakultas MIPA Universitas Padjadjaran. Dibangun generik (nama fakultas & warna via opsi) supaya bisa dipakai ulang fakultas lain. Lihat docs/ARSITEKTUR.md dan docs/BRAND-GUIDELINE.md di repo untuk spesifikasi lengkap.
Version: 0.3.0
Requires at least: 6.4
Requires PHP: 8.1
Text Domain: fmipa
License: Proprietary — milik FMIPA Unpad, tanpa kunci vendor.
*/

/* ==========================================================================
   1. Token warna & tipografi (turunan docs/BRAND-GUIDELINE.md §4-5)
   Nilai default di bawah adalah fallback FMIPA — bisa dioverride via opsi
   "Pengaturan Identitas" (lihat inc/class-fmipa-theme-options.php) supaya
   tema tetap generik untuk fakultas lain.
   ========================================================================== */
:root {
	--fmipa-green: #00B26B;
	--fmipa-green-dark: #008050;
	--fmipa-red: #ED1C24;
	--fmipa-red-dark: #D91820;
	--unpad-yellow: #FDB913;
	--fmipa-black: #111517;
	--fmipa-white: #FFFFFF;
	--fmipa-gray-50: #F7F8F8;
	--fmipa-gray-200: #E4E7E7;
	--fmipa-gray-500: #6B7280;

	/* "Ink" — hitam-kehijauan (bukan hitam netral) utk section gelap;
	   turunan --fmipa-green-dark, bukan warna baru di luar sistem brand. */
	--fmipa-ink: #071912;

	/* Merah tua — SHADE dari merah FMIPA, bukan warna baru. Hue-nya 357°,
	   sama persis dengan --fmipa-red #ED1C24 (357,7°); yang diturunkan cuma
	   lightness (52% -> 38%). Hubungannya ke --fmipa-red identik dengan
	   hubungan --fmipa-ink ke --fmipa-green-dark.

	   Alasannya kontras, bukan selera. Merah merek #ED1C24 tidak bisa jadi
	   bidang besar bertulisan: 4,38:1 dengan putih dan 4,19:1 dengan hitam —
	   gagal AA di KEDUA arah, jadi tidak ada teks yang bisa berdiri di
	   atasnya. Digelapkan ke #B0121A, teks putih dapat 7,12:1 dan ruang
	   sisanya cukup untuk teks redup (putih 80% = 4,95:1) yang di #D91820
	   (5,12:1) sudah tidak muat lagi. */
	--fmipa-red-deep: #B0121A;

	/* Scrim hero — hijau merek yang digelapkan, BUKAN --fmipa-ink.
	   Hue-nya sama persis dengan --fmipa-green (156°), jadi ini shade
	   dari warna merek, bukan warna baru di luar sistem. Dipisah dari
	   --fmipa-ink karena perannya beda: ink itu latar pita solid dengan
	   teks putih, scrim ini lapisan semi-transparan di atas foto/video.

	   Kegelapannya dipilih dari hitungan kontras, bukan selera. Pada
	   alpha gabungan yang dipakai di area deskripsi hero (0,67), teks
	   putih di atas piksel latar TERBURUK (putih penuh) mendapat:
	     #003D28  -> 4,68:1  lolos AA teks normal
	     #00553A  -> 3,87:1  GAGAL
	     #008050  -> 2,83:1  GAGAL telak
	   Patokannya piksel terburuk, bukan rata-rata: latarnya video, jadi
	   kecerahannya berubah tiap frame. Menaikkan alpha memang membuat
	   hijau yang lebih terang ikut lolos, tapi itu menutupi videonya —
	   justru hal yang mau ditampilkan. Format triplet (bukan hex) supaya
	   bisa dipakai sebagai rgba(var(--fmipa-hero-scrim), alpha). */
	--fmipa-hero-scrim: 0, 61, 40;
	--fmipa-ink-soft: #0F2A1F;
	--fmipa-ink-line: rgba(255,255,255,0.09);

	/* Latar utility bar (baris paling atas, di atas nav utama). Dulu
	   --fmipa-black — netral, jadi identitas fakultas baru muncul di bawah
	   garis header. Dipindah ke hijau merek supaya warna fakultas hadir di
	   piksel pertama halaman, pola yang sama dipakai fakultas lain di Unpad.

	   Nilainya hijau merek yang DIGELAPKAN — bukan --fmipa-green (#00B26B),
	   bukan pula --fmipa-green-dark (#008050). Hue-nya sama persis (156°),
	   jadi ini shade dari warna merek, bukan warna baru di luar sistem. Dua
	   alasan memilih yang gelap:
	     1. Peran. Bar ini bukan pita konten, melainkan bingkai utilitas di
	        atas header putih. Hijau terang di posisi itu bersaing dengan
	        tombol CTA hijau di header dan hero tepat di bawahnya.
	     2. Kontras. Teks putih di atasnya terukur:
	          #00B26B  ->  2,30:1  gagal telak
	          #008050  ->  4,99:1  lolos AA, tanpa ruang aman
	          #003D28  -> 11,70:1  lolos AAA
	          #003020  -> 14,50:1  lolos AAA dgn ruang lega  <- dipakai
	   Batas bawahnya --fmipa-ink (#071912): di situ hijaunya sudah tidak
	   terbaca lagi sebagai warna, cuma hitam. #003020 masih satu langkah di
	   atas batas itu — rasio G:B dijaga 1,5 (sama seperti #003D28) supaya
	   yang berubah hanya kegelapannya, bukan hue-nya.

	   Token tersendiri supaya fakultas lain yang memakai ulang tema ini bisa
	   menukarnya ke satu warna saja — mis. #3D080C untuk identitas merah. */
	--fmipa-utility-bar-bg: #003020;

	--fmipa-font: "Noto Sans", system-ui, -apple-system, "Segoe UI", sans-serif;
	--fmipa-font-headline: "Unpad Sans", "Noto Sans", system-ui, -apple-system, "Segoe UI", sans-serif;
	/* Angka data/statistik — kesan pembacaan instrumen presisi, bahasa visual
	   sains/matematika. Tumpukan monospace sistem, tanpa unduhan font baru. */
	--fmipa-font-mono: ui-monospace, "SF Mono", "Cascadia Code", "Roboto Mono", Consolas, monospace;

	/* Skala tipografi — SATU deret, seluruhnya fluid.
	   Sebelumnya h1/h2 fluid (clamp) tapi h3/h4 dipatok px. Akibatnya rasio
	   antar-tingkat berubah-ubah per viewport, dan di desktop muncul jurang:
	   terukur 48 -> 44 (1,09x) -> 20 (2,20x) -> 16 -> 16. Judul kartu, sub-judul,
	   dan teks body praktis tak terbedakan, sementara antara judul section dan
	   judul kartu ada lompatan lebih dari dua kali lipat.

	   Sesudah, rasio menaik bertahap dan tetap wajar di kedua ujung (angka di
	   bawah HASIL UKUR di browser, bukan pembacaan nilai clamp):
	     desktop 1440  68 / 44 / 28 / 18 / 16  -> 1,55  1,57  1,56  1,13
	     tablet   768  42 / 28 / 22 / 18 / 16  -> 1,51  1,27  1,22  1,13
	     ponsel   390  40 / 28 / 22 / 18 / 16  -> 1,43  1,27  1,22  1,13

	   Catatan: suku vw pada --fmipa-fs-h4 baru mengambil alih di atas ~1636px,
	   jadi di semua lebar layar yang realistis h4 duduk di nilai minimumnya
	   (18px). Itu memang diinginkan — rasionya terhadap body tetap 1,13 di mana
	   pun, dan tidak ada gunanya membuat label kecil ikut memuai. */
	--fmipa-fs-h1: clamp(2.5rem, 5.5vw, 4.25rem);
	--fmipa-fs-h2: clamp(1.75rem, 3.5vw, 2.75rem);
	--fmipa-fs-h3: clamp(1.375rem, 2vw, 1.75rem);
	/* Judul KARTU sengaja punya token sendiri, lebih kecil dari h3 dokumen.
	   h3 setingkat section ("Pakar Kami") berdiri di kolom selebar container
	   dan boleh 28px; judul kartu berdiri di kolom ~260px, dan pada 28px ia
	   membungkus jadi menara 4 baris — terlihat langsung di grid Program Studi.
	   Ukurannya soal LEBAR KOLOM, bukan tingkat heading, jadi dipisah tokennya
	   alih-alih menurunkan h3 global dan mengorbankan sub-judul section. */
	--fmipa-fs-card-title: clamp(1.125rem, 1.3vw, 1.375rem);
	--fmipa-fw-bold: 700;
	--fmipa-fw-extrabold: 800;
	--fmipa-fw-medium: 500;
	--fmipa-fw-regular: 400;
	--fmipa-tracking-tight: -0.02em;

	--fmipa-container: 1200px;
	/* Rel kedua, khusus baris-baris DI DALAM header. Nav utama tidak muat di
	   1200px (alasan terukur di .fmipa-site-header__inner), dan utility bar
	   di atasnya harus ikut rel yang sama: dua baris yang menempel vertikal
	   dibaca mata sebagai satu blok, jadi tepi kiri/kanan yang meleset 60px
	   per sisi terbaca sebagai bug, bukan keputusan desain. Yang tetap beda
	   adalah header vs konten halaman (1200px) — itu memang disengaja.

	   1320px SEMPAT dipakai dan terbukti 15,2px terlalu sempit: dengan menu
	   yang sekarang, nav utama butuh 841,6px (jumlah lebar 6 item 769,6px +
	   5 gap x 14,4px) sementara container 1320px cuma menyisakan 827px
	   untuknya (1320 - 64 padding - 189 logo - 208 CTA - 32 gap). Karena
	   kekurangannya ada pada NILAI MAKSIMUM container, memperlebar viewport
	   tidak pernah menolong — item terakhir ("Mahasiswa") membungkus ke baris
	   kedua di SEMUA lebar layar, termasuk 1920px, lalu terpotong tepi bawah
	   header. 1360px menyisakan 867px, jadi ada 25px kelonggaran.

	   KELONGGARANNYA CUMA 25px DAN ISINYA BISA DIUBAH ADMIN. Menambah satu
	   item nav atau memperpanjang satu label akan mematahkannya lagi. Cara
	   mengukur ulang, tempel di konsol pada lebar >=1360px:

	     ul=document.querySelector('.fmipa-nav-primary > ul');
	     g=parseFloat(getComputedStyle(ul).columnGap);
	     k=[...ul.children];
	     butuh=k.reduce((a,li)=>a+li.getBoundingClientRect().width,0)+g*(k.length-1);
	     console.log(butuh, ul.getBoundingClientRect().width);

	   Angka pertama harus lebih kecil dari angka kedua. Kalau tidak, naikkan
	   nilai di bawah ini DAN ambang media query nav (dua-duanya, lihat blok
	   "Ambang nav utama"). JANGAN pakai ul.scrollWidth untuk ini: nav memakai
	   justify-content:flex-end sehingga luapannya jatuh ke sisi KIRI, dan
	   luapan kiri tidak ikut terhitung di scrollWidth — ia melaporkan angka
	   yang selalu terlihat pas. */
	--fmipa-container-header: 1360px;
	--fmipa-radius: 0.5rem;
	--fmipa-radius-lg: 1rem;
	--fmipa-gap: clamp(3rem, 7vw, 6rem);

	--fmipa-shadow-sm: 0 1px 2px rgba(7,25,18,0.06), 0 1px 1px rgba(7,25,18,0.04);
	--fmipa-shadow-md: 0 8px 24px -8px rgba(7,25,18,0.16), 0 2px 6px -2px rgba(7,25,18,0.08);
	--fmipa-shadow-lg: 0 24px 48px -16px rgba(7,25,18,0.24);

	/* easeOutExpo — untuk umpan balik SENTUHAN (hover, fokus, tombol) yang
	   berdurasi 0,2-0,3s. Di rentang sependek itu kurva yang berat di depan
	   justru yang benar: responsnya terasa seketika. */
	--fmipa-ease: cubic-bezier(0.16, 1, 0.3, 1);

	/* easeOutQuart — untuk animasi MASUK saat digulir (geser section, garis
	   aksen judul, watermark). Dipisah dari --fmipa-ease karena masalahnya
	   berlawanan: di sini durasinya 0,7-0,9s, dan easeOutExpo menghabiskan
	   jaraknya jauh sebelum durasi itu selesai — terukur, geseran 24px/700ms
	   sudah tersisa <1px pada 316ms, jadi dua pertiga durasinya bergerak di
	   bawah ambang yang bisa dilihat mata. Dengan kurva ini jendela terlihat
	   naik ke 448ms, sejajar dengan kaskade kartu di fmipa-anim.js (454ms). */
	--fmipa-ease-masuk: cubic-bezier(0.25, 1, 0.5, 1);

	/* Abu-abu 600 — saudara langsung --fmipa-gray-500 yang sudah ada, bukan
	   keluarga warna baru. Dibutuhkan karena #6B7280 gagal AA (4,46:1) di
	   atas latar bertint terang yang dipakai sistem pita. */
	--fmipa-gray-600: #4B5563;

	/* Hijau 8% di atas putih — pita tint. Turunan palet, bukan warna baru. */
	--fmipa-green-tint: #EBF9F3;

	/* Token PITA (lihat §3a). Default di :root = tampilan terang biasa, jadi
	   komponen di LUAR pita (arsip, halaman detail) tetap seperti semula. */
	--fmipa-band-bg: var(--fmipa-white);
	--fmipa-band-fg: var(--fmipa-black);
	--fmipa-band-fg-muted: var(--fmipa-gray-600);
	--fmipa-band-accent: var(--fmipa-green-dark);
	--fmipa-band-link: var(--fmipa-green-dark);
	--fmipa-band-line: var(--fmipa-gray-200);
	--fmipa-band-focus: var(--fmipa-green-dark);
	--fmipa-band-btn-outline: var(--fmipa-green-dark);

	/* Skala spasi — sebelumnya cuma ada --fmipa-gap tunggal. Nilai fluid di
	   bawah persis menyamai angka yang selama ini di-hardcode di file ini,
	   jadi ini kodifikasi, bukan perubahan tampilan. */
	--fmipa-space-3xs: 0.25rem;
	--fmipa-space-2xs: 0.5rem;
	--fmipa-space-xs: 0.75rem;
	--fmipa-space-sm: 1rem;
	--fmipa-space-md: 1.5rem;
	--fmipa-space-lg: 2rem;
	--fmipa-space-xl: 3rem;
	--fmipa-space-2xl: 4rem;
	--fmipa-space-section: clamp(3rem, 7vw, 6rem);
	--fmipa-space-band: clamp(4rem, 9vw, 7.5rem);
	--fmipa-space-header: clamp(2rem, 4vw, 3.5rem);
	--fmipa-space-grid: clamp(1rem, 3vw, 2rem);

	/* Skala tipografi di bawah h3 + ukuran angka statistik raksasa. */
	--fmipa-fs-display: clamp(3.5rem, 9vw, 7.5rem);
	/* Ikut fluid supaya rasionya terhadap h3 dan body stabil lintas viewport
	   (lihat catatan skala di blok --fmipa-fs-h1 di atas). */
	--fmipa-fs-h4: clamp(1.125rem, 1.1vw, 1.25rem);
	--fmipa-fs-body: 1rem;
	--fmipa-fs-sm: 0.9375rem;
	--fmipa-fs-xs: 0.875rem;
	--fmipa-fs-2xs: 0.8125rem;
	--fmipa-fs-eyebrow: 0.75rem;
	--fmipa-lh-display: 0.95;
	--fmipa-tracking-display: -0.03em;
	--fmipa-tracking-caps: 0.06em;
	--fmipa-tracking-eyebrow: 0.14em;

	/* Token kartu — dikonsumsi .fmipa-card. Default di bawah = persis
	   tampilan lama, sehingga arsip/detail tidak berubah sama sekali;
	   section beranda bisa menugaskan ulang token ini (mis. kartu tanpa
	   chrome di atas pita warna) tanpa menyentuh .fmipa-card itu sendiri. */
	/* Kartu memisahkan diri dari latar lewat SATU alat: beda warna bidang.
	   Sebelumnya dipakai tiga sekaligus — garis 1px, bayangan, DAN sudut
	   membulat — untuk menyampaikan satu hal yang sama. Itu ciri kartu era
	   2018, dan REFERENSI-PSIKOLOGI.md §9a memang menulis "card putih tanpa
	   border/shadow tebal — flat".

	   Yang lebih parah: bidangnya putih di atas section putih, jadi terukur
	   13 dari 38 kartu beranda punya latar PERSIS SAMA dengan induknya —
	   garis itu memisahkan kartu dari... tidak ada apa-apa. Karena itu latar
	   bawaan kartu sekarang tint, bukan putih, dan pita yang sudah berwarna
	   membalikkannya jadi putih (lihat aturan per-pita di bawah). */
	--fmipa-card-bg: var(--fmipa-green-tint);
	--fmipa-card-fg: var(--fmipa-black);
	/* gray-600, bukan gray-500. Saat latar kartu masih putih, gray-500 lolos
	   tipis di 4,83. Begitu latarnya jadi tint (#EBF9F3) rasionya turun ke
	   4,46 — di BAWAH ambang AA 4,5 untuk teks normal. Terjaring sapuan QA,
	   dan memang regresi yang dibawa perubahan latar kartu itu sendiri.
	   gray-600 aman di kedua latar: 7,56 di putih, 6,97 di tint. */
	--fmipa-card-fg-muted: var(--fmipa-gray-600);
	--fmipa-card-link: var(--fmipa-green-dark);
	--fmipa-card-line: transparent;
	--fmipa-card-shadow: none;
	--fmipa-card-shadow-hover: none;
	--fmipa-card-radius: var(--fmipa-radius-lg);
	--fmipa-card-pad: 1.75rem;
	--fmipa-card-lift: -4px;
}

/* Tekstur "graph paper" tipis — bahasa visual presisi matematika. Murni CSS,
   nol request gambar tambahan.

   Garisnya membaca --fmipa-band-line, bukan --fmipa-ink-line: sejak warna
   pita dihitung dari posisi render, section bertekstur ini bisa mendarat di
   pita terang mana pun, dan garis versi ink (terang, untuk latar gelap) akan
   lenyap di sana. Lewat token, tiap pita menyuplai garisnya sendiri yang
   sudah serasi. Nilai untuk pita ink tetap --fmipa-ink-line, jadi tampilan
   section gelap yang sudah ada tidak berubah. */
.fmipa-grid-texture {
	background-image:
		linear-gradient(var(--fmipa-band-line) 1px, transparent 1px),
		linear-gradient(90deg, var(--fmipa-band-line) 1px, transparent 1px);
	background-size: 48px 48px;
}

/* SENGAJA tidak animasikan opacity (cuma transform) — teks section yang
   belum discroll ke viewport sempat OPACITY:0 cukup lama (nunggu observer
   atau jaring pengaman 2.5s di nav-toggle.js), dan alat yang mengambil
   snapshot DOM di jendela itu (Lighthouse a11y audit, screen reader cepat,
   dst.) membaca itu sbg teks kontras 0 vs latar — ketemu lewat audit
   Lighthouse (accessibility 100 -> 97 setelah fmipa-reveal dipasang luas).
   transform-only tetap dapat efek "geser masuk" tanpa risiko itu. */
@media (prefers-reduced-motion: no-preference) {
	.fmipa-reveal {
		transform: translateY(24px);
		transition: transform 0.8s var(--fmipa-ease-masuk);
	}
	.fmipa-reveal.is-visible {
		transform: translateY(0);
	}
}

/* ==========================================================================
   1a. Unpad Sans — typeface utama resmi (docs/BRAND-GUIDELINE.md §5), dipakai
   untuk headline (H1/H2, hero) sejak file diterima dari Dit. Pemasaran.
   Noto Sans tetap dipakai untuk body text (OFL, tidak butuh self-host
   berlisensi terpisah). @font-face DIDEKLARASIKAN DI theme.json (fontFace),
   bukan di sini — WP otomatis meng-generate-nya (termasuk font-display:swap)
   dan menyediakannya juga ke pemilih font block editor. Jangan duplikasi
   @font-face manual di sini.
   ========================================================================== */

/* ==========================================================================
   2. Reset ringkas
   ========================================================================== */
*, *::before, *::after { box-sizing: border-box; }

/* Elemen form dan tombol TIDAK mewarisi font dari induknya menurut spesifikasi
   — browser memberi mereka font default sendiri. Tanpa baris ini, setiap
   <button> yang bukan .fmipa-btn (mis. .fmipa-submenu-toggle di nav) jatuh ke
   Arial. Terukur: 89 elemen memakai Arial di beranda, di tengah halaman yang
   seluruhnya Noto Sans. .fmipa-btn sudah menambal ini sendiri, tapi tambalan
   per-komponen berarti tiap komponen baru mengulang bug yang sama. */
button, input, select, textarea, optgroup { font: inherit; color: inherit; }
html { -webkit-text-size-adjust: 100%; }
body {
	margin: 0;
	font-family: var(--fmipa-font);
	font-weight: var(--fmipa-fw-regular);
	color: var(--fmipa-black);
	background: var(--fmipa-white);
	line-height: 1.6;
}
img { max-width: 100%; height: auto; display: block; }
a { color: var(--fmipa-band-link); }
h1, h2, h3, h4 { font-weight: var(--fmipa-fw-bold); line-height: 1.25; margin: 0 0 0.75em; }
h1, h2 { font-family: var(--fmipa-font-headline); }
h1 { font-size: var(--fmipa-fs-h1); }
h2 { font-size: var(--fmipa-fs-h2); }
h3 { font-size: var(--fmipa-fs-h3); }
/* h4 sebelumnya TIDAK punya aturan font-size sama sekali, jadi ia jatuh ke
   default browser (1em = 16px) — persis seukuran teks body, sehingga nama
   pakar dan judul sub-kartu tidak terbedakan dari paragraf di sekitarnya.
   Token --fmipa-fs-h4 sendiri sudah ada tapi tidak pernah dipanggil. */
h4 { font-size: var(--fmipa-fs-h4); }
.screen-reader-text {
	position: absolute !important;
	width: 1px; height: 1px; overflow: hidden;
	clip: rect(1px, 1px, 1px, 1px);
	white-space: nowrap;
}
.skip-link {
	position: absolute; left: -9999px; top: 0; z-index: 100000;
	background: var(--fmipa-green-dark); color: var(--fmipa-white);
	padding: 0.75em 1.25em;
}
.skip-link:focus { left: 0.5em; top: 0.5em; }

/* ==========================================================================
   3. Layout & komponen bersama — dipakai lintas plugin (lihat CONVENTIONS
   yang dibagikan ke tiap agen pembangun plugin: kelas ini adalah kontrak,
   jangan diganti nama tanpa menyesuaikan seluruh plugin)
   ========================================================================== */
.fmipa-container {
	max-width: var(--fmipa-container);
	margin-inline: auto;
	padding-inline: clamp(1rem, 4vw, 2rem);
}
/* Ritme tiga tingkat, bukan satu jarak untuk semua.
   Terukur sebelumnya: 10 dari 12 section beranda memakai padding vertikal
   IDENTIK 96px. Tiap bagian halaman jadi bertempo sama persis, sehingga tidak
   ada satu pun yang terasa lebih penting — semuanya berteriak sama keras, jadi
   tidak ada yang terdengar. Ini pola "cookie-cutter section rhythm" yang
   memang jadi penanda halaman generik.

   Tingkatannya:
     seam    (--fmipa-space-md)      strip tipis, mis. akreditasi
     section (--fmipa-space-section) jarak normal, mayoritas section
     band    (--fmipa-space-band)    momen berani (pita hijau/ink) dapat napas
                                     lebih supaya benar-benar terbaca sebagai
                                     jeda besar, bukan section biasa berwarna

   Token --fmipa-space-band sudah ada sejak Fase 1 tapi tidak pernah dipakai;
   di sini ia akhirnya dihubungkan. */
.fmipa-section { padding-block: var(--fmipa-space-section); }
.fmipa-section--band-hijau,
.fmipa-section--band-merah,
.fmipa-section--band-ink { padding-block: var(--fmipa-space-band); }
.fmipa-section--seam { padding-block: var(--fmipa-space-md); }
.fmipa-section__header { margin-bottom: var(--fmipa-space-header); max-width: 62ch; }
.fmipa-section__header h2 { letter-spacing: var(--fmipa-tracking-tight); }
.fmipa-section__header p { color: var(--fmipa-band-fg-muted); }

/* ==========================================================================
   3a. Sistem PITA (band) — identitas per section
   ==========================================================================
   Tiap section beranda boleh mengambil latar penuhnya sendiri (pola "color
   band" ala sekolah sains Ivy League). Mekanismenya sengaja BUKAN override
   turunan per pita, melainkan PEWARISAN CUSTOM PROPERTY:

     .fmipa-section--band-*  ->  cuma menugaskan ulang --fmipa-band-*
     komponen                ->  cuma membaca --fmipa-band-*

   Karena custom property diwariskan ke bawah DOM, komponen di dalam pita
   otomatis me-resolve warna pita tanpa selector tambahan. Ini yang membuat
   "8 override x 5 pita = 40 aturan" runtuh jadi ~9 aturan generik, DAN
   membuat sistemnya kebal urutan muat stylesheet.

   Kontras tiap pasangan dihitung ulang (WCAG 2.x), bukan dikira-kira:
     putih  #FFFFFF + #111517 = 18,37:1
     mist   #F7F8F8 + #111517 = 17,26:1
     tint   #EBF9F3 + #111517 = 16,95:1   (muted #4B5563 = 6,97:1)
     hijau  #00B26B + #111517 =  6,63:1   (muted #0F2A1F = 5,53:1)
     ink    #071912 + #FFFFFF = 18,15:1
     merah  #B0121A + #FFFFFF =  7,12:1   (muted putih 80% = 4,95:1)

   CATATAN PENTING soal merah. Merah MEREK #ED1C24 tetap TIDAK BOLEH jadi
   latar pita: 4,19:1 dengan hitam dan 4,38:1 dengan putih — gagal AA di
   kedua arah sekaligus, jadi tidak ada warna teks yang bisa berdiri di
   atasnya. Yang dipakai pita merah adalah SHADE-nya, --fmipa-red-deep
   #B0121A (hue sama, lightness turun; lihat §1). Merah terang sendiri tetap
   aksen saja: garis, badge, angka display besar >=24px, supergrafik. */
/* background-COLOR, bukan shorthand `background`. Shorthand ikut menyetel
   background-image:none, dan aturan pita ini berdiri SETELAH .fmipa-grid-texture
   di file yang sama dengan spesifisitas sama — jadi tiap section yang memakai
   kedua kelas itu kehilangan teksturnya tanpa suara. Terukur: 3 section
   (trust, testimoni, dan CTA) mencantumkan .fmipa-grid-texture di markup-nya
   tapi getComputedStyle(...).backgroundImage ketiganya "none". */
.fmipa-section--band {
	background-color: var(--fmipa-band-bg);
	color: var(--fmipa-band-fg);
	position: relative;
	overflow: hidden;
}
.fmipa-section--band > .fmipa-container { position: relative; z-index: 1; }

/* Pita netral terang (alias .fmipa-section--alt yang sudah dipakai CTA). */
.fmipa-section--alt,
.fmipa-section--band-mist {
	--fmipa-band-bg: var(--fmipa-gray-50);
	--fmipa-band-fg: var(--fmipa-black);
	--fmipa-band-fg-muted: var(--fmipa-gray-600);
	--fmipa-band-accent: var(--fmipa-green-dark);
	--fmipa-band-link: var(--fmipa-green-dark);
	--fmipa-band-line: var(--fmipa-gray-200);
	--fmipa-band-focus: var(--fmipa-green-dark);
	--fmipa-band-btn-outline: var(--fmipa-green-dark);
	background-color: var(--fmipa-gray-50);
	/* Pita mist SENGAJA tidak membalik kartu jadi putih. Diukur: putih di atas
	   gray-50 hanya 1,06 — selisih 8/255 pada satu sumbu terang, dan tanpa
	   garis maupun bayangan itu praktis tak terlihat sebagai kartu. Kartu tint
	   (bawaan) di atas mist rasionya mirip TAPI bergeser rona, dan pergeseran
	   rona jauh lebih terbaca mata daripada selisih terang sekecil itu. */
}

/* Pita hijau — warna brand utama yang selama ini TIDAK PERNAH dipakai
   sebagai bidang besar, karena kita selalu mengasumsikan teks putih di
   atasnya (2,77:1, gagal). Dengan teks HITAM rasionya 6,63:1 dan lolos AA.
   Tombol primer di sini WAJIB ink, bukan --fmipa-green-dark: #008050 di
   atas #00B26B cuma 1,80:1 sehingga batas tombolnya lenyap. */
.fmipa-section--band-hijau {
	--fmipa-band-bg: var(--fmipa-green);
	--fmipa-band-fg: var(--fmipa-black);
	--fmipa-band-fg-muted: var(--fmipa-ink-soft);
	--fmipa-band-accent: var(--fmipa-ink);
	--fmipa-band-link: var(--fmipa-black);
	--fmipa-band-line: rgba(7,25,18,0.28);
	--fmipa-band-focus: var(--fmipa-black);
	--fmipa-band-btn-outline: var(--fmipa-black);
	--fmipa-card-bg: var(--fmipa-white);
}

/* Pita merah — momen aksi. Dipakai CTA penutup, dan sengaja cuma di sana:
   merah adalah warna aksen merek, jadi kalau ia muncul sebagai bidang besar
   lebih dari sekali ia berhenti menandai "ini yang harus diklik".

   ATURAN UNTUK TOMBOL YANG SUATU SAAT DITARUH DI SINI — kebalikan dari pita
   hijau. Di hijau tombol primer wajib gelap; di sini ia wajib PUTIH (label
   berwarna), karena semua warna tombol merek jatuh terlalu dekat dengan
   latarnya sendiri: hijau WhatsApp #0F7A46 di atas #B0121A cuma 1,32:1.
   Rasio serendah itu memang masih "kelihatan" oleh mata normal karena
   bedanya rona, bukan terang — dan justru itu masalahnya: pada protanopia/
   deuteranopia rona itu yang hilang duluan, dan tombolnya lenyap ke dalam
   latar. Putih di atas merah tua 7,12:1, aman di semua kondisi. */
.fmipa-section--band-merah {
	--fmipa-band-bg: var(--fmipa-red-deep);
	--fmipa-band-fg: var(--fmipa-white);
	--fmipa-band-fg-muted: rgba(255,255,255,0.80);
	/* Aksen = putih, bukan hijau merek. Hijau #00B26B di atas merah tua cuma
	   2,57:1 — di pita ini hijau tidak punya peran aksen sama sekali. */
	--fmipa-band-accent: var(--fmipa-white);
	--fmipa-band-link: var(--fmipa-white);
	/* 0,12 — jauh lebih rendah daripada pita hijau (0,28). Token ini juga
	   dipakai .fmipa-grid-texture sebagai garis kertas milimeter 48px, dan di
	   atas merah pekat garis putih naik jauh lebih menonjol daripada garis
	   gelap di atas hijau muda: pada 0,30 teksturnya berhenti jadi tekstur dan
	   berubah jadi kisi yang beradu dengan judulnya sendiri. */
	--fmipa-band-line: rgba(255,255,255,0.12);
	--fmipa-band-focus: var(--fmipa-white);
	/* 0,80 karena token ini juga jadi warna LABEL tombol outline, jadi yang
	   berlaku ambang teks 4,5:1 — bukan ambang komponen UI 3:1. Alpha 0,80
	   -> 4,95:1; alasan yang sama persis dicatat di pita ink di bawah. */
	--fmipa-band-btn-outline: rgba(255,255,255,0.80);
	--fmipa-card-bg: var(--fmipa-white);
}

/* Pita tint — hijau 8% di atas putih, untuk selang-seling yang lembut. */
.fmipa-section--band-tint {
	--fmipa-band-bg: var(--fmipa-green-tint);
	--fmipa-band-fg: var(--fmipa-black);
	--fmipa-band-fg-muted: var(--fmipa-gray-600);
	--fmipa-band-accent: var(--fmipa-green-dark);
	--fmipa-band-link: var(--fmipa-green-dark);
	--fmipa-band-line: #C7EEDE;
	--fmipa-band-focus: var(--fmipa-green-dark);
	--fmipa-band-btn-outline: var(--fmipa-green-dark);
	--fmipa-card-bg: var(--fmipa-white);
}

/* Pita gelap — alias .fmipa-section--ink yang sudah dipakai trust/testimoni.
   Blok struktural dipertahankan supaya markup lama tetap jalan apa adanya. */
.fmipa-section--ink,
.fmipa-section--band-ink {
	--fmipa-band-bg: var(--fmipa-ink);
	--fmipa-band-fg: var(--fmipa-white);
	--fmipa-band-fg-muted: rgba(255,255,255,0.70);
	--fmipa-band-accent: var(--fmipa-green);
	--fmipa-band-link: var(--fmipa-white);
	--fmipa-band-line: var(--fmipa-ink-line);
	--fmipa-band-focus: var(--fmipa-white);
	/* 0,55 bukan 0,40. Token ini dipakai untuk border DAN label tombol
	   outline, jadi yang berlaku adalah syarat yang lebih ketat: label itu
	   teks (4,5:1), bukan sekadar komponen UI (3:1). Pada alpha 0,40 label
	   "Lihat Semua Pakar" di pita ink hanya 3,79:1 — ditemukan Lighthouse,
	   dan sempat LOLOS dari audit sendiri karena skripnya mengabaikan alpha
	   dan menghitungnya sebagai putih penuh. Alpha 0,55 -> 6,3:1. */
	--fmipa-band-btn-outline: rgba(255,255,255,0.55);
	background-color: var(--fmipa-ink);
	color: var(--fmipa-white);
	position: relative;
	overflow: hidden;
}
.fmipa-section--ink > .fmipa-container { position: relative; z-index: 1; }

/* Seam — pita tipis yang perannya memisahkan dua section besar, bukan berdiri
   sebagai section setara. Padding vertikalnya dipangkas supaya terbaca sebagai
   garis pemisah bermuatan (strip akreditasi), bukan blok konten penuh. */
.fmipa-section--seam {
	padding-block: var(--fmipa-space-md, 1.5rem);
}

/* Angka statistik ukuran display (pola SEAS: angka raksasa, label kecil).
   Dipakai section "FMIPA dalam Angka" setelah dipecah dari blok trust lama.

   Tetap --fmipa-font-mono (stack sistem), BUKAN Unpad Sans: Unpad Sans dimuat
   dengan font-display:swap, dan numeral sebesar ini yang ter-swap menggeser
   tata letak tepat di layar pertama. Font sistem tidak pernah swap.

   UKURAN DAN LEBAR KOLOM DIPASANGKAN — kalau salah satu diubah, hitung ulang
   yang lain. Angka terpanjang di sini 4-5 karakter ditambah satuan; pada
   digit monospace lebarnya sekitar 0,6em per karakter. Percobaan pertama
   memakai --fmipa-fs-display penuh (maks 7,5rem = 120px) di grid 140px:
   hasilnya lima angka SALING MENUMPUK — "176orang" menabrak "17", "3000"
   menabrak "17". Kolom dilebarkan ke 300px (jadi 3 kolom di 1200px, bukan 5)
   dan ukurannya dibatasi 5,5rem, sehingga angka terlebar ~248px masih lega
   di dalam track ~385px. */
/* Selector digabung (.fmipa-grid.fmipa-stat-grid--display) supaya menang lewat
   SPECIFICITY, bukan urutan cetak. Ditulis sebagai kelas tunggal, aturan ini
   seri dengan .fmipa-grid--statistik milik plugin — dan karena stylesheet
   plugin dicetak sesudah tema, nilai 140px milik plugin-lah yang menang.
   Akibatnya nyata dan terukur: grid tetap 6 kolom @1440px, bukan 3, dan
   angka display kembali sempit. */
.fmipa-grid.fmipa-stat-grid--display {
	--fmipa-grid-min: 300px;
}
.fmipa-stat-grid--display .fmipa-stat__number {
	font-size: clamp(2.75rem, 6vw, 5.5rem);
	line-height: var(--fmipa-lh-display, 0.95);
}
.fmipa-stat-grid--display .fmipa-stat__satuan {
	font-size: 0.28em;
	margin-left: 0.35em;
	letter-spacing: var(--fmipa-tracking-caps, 0.04em);
}

/* Kartu tanpa chrome — isi kartu duduk langsung di atas pita (pola SEAS).
   Ortogonal terhadap warna pita, jadi kartu putih di atas pita ink yang
   sekarang tetap bisa dipertahankan; ini hanya berlaku kalau section-nya
   secara eksplisit meminta. */
.fmipa-section--cards-bare {
	--fmipa-card-bg: transparent;
	--fmipa-card-fg: var(--fmipa-band-fg);
	--fmipa-card-fg-muted: var(--fmipa-band-fg-muted);
	/* SENGAJA menunjuk --fmipa-band-fg, bukan --fmipa-band-link. Kartu di
	   sini transparan sehingga tautannya memang harus mengikuti pita — tapi
	   menulis `--fmipa-card-link: var(--fmipa-band-link)` akan membentuk
	   siklus (.fmipa-card menyetel --fmipa-band-link dari --fmipa-card-link),
	   dan properti kustom yang bersiklus jadi invalid saat dihitung. */
	--fmipa-card-link: var(--fmipa-band-fg);
	--fmipa-card-line: transparent;
	--fmipa-card-shadow: none;
	--fmipa-card-shadow-hover: none;
	--fmipa-card-radius: 0;
	--fmipa-card-pad: 0;
	--fmipa-card-lift: 0;
}

/* Judul section ALL-CAPS + perataan berselang-seling. text-transform, BUKAN
   huruf besar yang diketik di CMS — nama aksesibel diambil dari teks DOM,
   jadi pembaca layar tetap melafalkan kalimat normal. letter-spacing wajib:
   kapital tanpa tracking tidak terbaca di ukuran h2. */
.fmipa-section--caps .fmipa-section__header h2 {
	text-transform: uppercase;
	letter-spacing: var(--fmipa-tracking-caps);
}

/* PERATAAN KANAN DIHAPUS SELURUHNYA — semua judul section rata kiri.

   Riwayatnya: mula-mula :nth-child(even) membalik judul kiri/kanan di SETIAP
   section (metronom, sepuluh kali berturut-turut), lalu dipersempit jadi satu
   aksen di pita ink. Aksen itu pun ternyata salah, dan baru kelihatan setelah
   section-nya dilihat utuh sebagai satu gambar:

   1. Judul rata kanan sementara grid kartu di bawahnya rata kiri — terukur
      titik mulai 663px vs 152px. Satu section punya dua titik mulai berjarak
      511px, dan bidang kosong di antaranya terbaca sebagai kesalahan, bukan
      sebagai ruang bernapas.
   2. Deskripsi section ikut rata kanan. Paragraf rata kanan bertepi kiri
      bergerigi: tiap baris mulai di tempat berbeda, jadi mata kehilangan
      jangkar saat berpindah baris. Itu menukar keterbacaan dengan hiasan.

   Variasi antar-section sudah disediakan sistem pita (hijau/ink/tint/mist)
   dan tingkatan jarak. Itu sudah cukup; perataan tidak perlu ikut bekerja. */

/* Lebar minimum kolom lewat custom property, bukan angka mati di
   grid-template-columns. Dengan begini modifier seperti .fmipa-grid--statistik
   cukup menyetel SATU variabel dan tidak perlu menulis ulang seluruh
   deklarasi grid-template-columns — yang dulu jadi sumber bentrok: modifier
   dan aturan dasar sama-sama menyetel properti yang sama dengan specificity
   seri, jadi pemenangnya ditentukan urutan cetak stylesheet.

   min(var, 100%) menjaga kolom tidak pernah lebih lebar dari induknya di
   layar sempit (kalau tidak, minmax(300px,...) memaksa overflow di ponsel). */
.fmipa-grid {
	--fmipa-grid-min: 260px;
	--fmipa-grid-max: 1fr;
	display: grid;
	gap: clamp(1rem, 3vw, 2rem);
	grid-template-columns: repeat(auto-fit, minmax(min(var(--fmipa-grid-min), 100%), var(--fmipa-grid-max)));
}

/* Kuantitas: grid berisi 1-2 item saja. auto-fit mengempiskan track kosong,
   jadi satu kartu akan MELAR selebar container (terukur 1136px di 1440px) dan
   terlihat rusak. Batasi lebar maksimum track lalu rapatkan ke kiri.
   Sengaja lewat custom property yang BERBEDA dari modifier di atas, supaya
   keduanya tidak pernah berebut properti yang sama. Aturan ini tidak cocok
   pada >=3 item, jadi nol regresi untuk kasus grid yang paling sering. */
.fmipa-grid:has(> :last-child:nth-child(-n+2)) {
	--fmipa-grid-max: 400px;
	justify-content: start;
}

/* Kartu memakai token sendiri, dan WAJIB menyetel `color` berbarengan
   dengan `background`. Sebelumnya `.fmipa-card` cuma menyetel background
   putih tanpa color — di dalam .fmipa-section--ink (yang menyetel
   color:white) teks kartu mewarisi putih, jadi PUTIH DI ATAS PUTIH, 1:1.
   Efeknya kutipan + nama di kartu testimoni beranda benar-benar tidak
   terbaca (terlihat "kosong"); cuma baris meta yang selamat karena punya
   warna sendiri. Nilai default token di bawah = persis tampilan lama,
   jadi arsip/detail tidak berubah. Aturannya sekarang: jangan pernah
   menyetel background tanpa menyetel color di elemen yang sama. */
/* Kartu menugaskan ulang --fmipa-band-link ke warna tautannya sendiri.
   Ini menutup lubang kembar dari bug di atas: menyetel color kartu saja
   TIDAK cukup, karena aturan generik `a { color: var(--fmipa-band-link) }`
   lebih kuat daripada pewarisan. Di pita ink, --fmipa-band-link bernilai
   putih (benar untuk tautan yang duduk langsung di atas ink) — dan nilai itu
   ikut terbawa ke tautan DI DALAM kartu putih, sehingga judul kartu jadi
   putih di atas putih lagi. Terukur 1:1 pada judul bidang riset dan nama
   pakar di beranda.
   Karena custom property diwariskan, satu baris ini memperbaiki semua
   tautan di dalam kartu tanpa selector tambahan per komponen. */
.fmipa-card {
	/* Kolom flex supaya .fmipa-card__actions (margin-top:auto) menempel ke
	   DASAR kartu. Tanpa ini tombol berhenti tepat di bawah teks, dan karena
	   panjang teks tiap kartu berbeda, tombolnya mendarat di empat ketinggian
	   berbeda dalam satu baris — terlihat jelas di grid agenda. */
	display: flex;
	flex-direction: column;
	--fmipa-band-link: var(--fmipa-card-link);
	background: var(--fmipa-card-bg);
	color: var(--fmipa-card-fg);
	border: 1px solid var(--fmipa-card-line);
	border-radius: var(--fmipa-card-radius);
	padding: var(--fmipa-card-pad);
	box-shadow: var(--fmipa-card-shadow);
	transition: transform 0.3s var(--fmipa-ease), box-shadow 0.3s var(--fmipa-ease), border-color 0.3s var(--fmipa-ease);
}
/* Slot media kartu — rasio TETAP supaya tiap kartu dalam satu baris memulai
   judulnya di garis yang sama, punya gambar atau tidak. Dipakai bersama oleh
   kartu berita, agenda, dan layanan lewat fmipa_the_card_media(). */
/* Judul kartu TIDAK bergaris bawah secara default. Terukur: 17 dari 17 judul
   kartu di beranda (program, layanan, berita, agenda) tampil bergaris bawah,
   karena judulnya berupa <a> dan mewarisi garis bawah bawaan browser.

   Di dalam kartu, konteksnya sudah menyatakan judul itu bisa diklik: ia
   heading paling menonjol, berwarna aksen, dan seluruh kartunya menuju tujuan
   yang sama. Garis bawah permanen di setiap judul membuat grid terlihat
   seperti daftar tautan mentah, bukan kumpulan kartu. Garis bawah dikembalikan
   saat hover/fokus, jadi afordansinya tidak hilang — hanya berhenti berteriak.

   Tautan di dalam BADAN kartu tidak disentuh: di sana garis bawah justru satu-
   satunya penanda bahwa sepotong teks bisa diklik. */
.fmipa-card :is(h2, h3, h4) > a { text-decoration: none; }
.fmipa-card :is(h2, h3, h4) > a:hover,
.fmipa-card :is(h2, h3, h4) > a:focus-visible { text-decoration: underline; text-underline-offset: 3px; }

/* Media menempel ke TEPI kartu, bukan mengambang di dalam padding.
   Sebelumnya foto dikelilingi 28px padding kartu di keempat sisi, sehingga
   tiap kartu berita/agenda punya bingkai kosong di sekeliling gambarnya —
   ruang yang tidak menyampaikan apa pun, dan pola yang membuat kartu terbaca
   seperti widget lama. REFERENSI-PSIKOLOGI.md §9a menaruh foto 16:9 langsung
   di atas kartu. Padding hanya berlaku untuk teks.

   Sudut atas mengikuti sudut kartu, sudut bawah lurus, supaya potongannya
   menyatu dengan kartu alih-alih terlihat seperti kotak terpisah di dalamnya. */
.fmipa-card__media {
	display: block;
	aspect-ratio: 16 / 10;
	overflow: hidden;
	margin: calc(var(--fmipa-card-pad) * -1) calc(var(--fmipa-card-pad) * -1) var(--fmipa-space-sm, 1rem);
	border-radius: var(--fmipa-card-radius) var(--fmipa-card-radius) 0 0;
	background: var(--fmipa-green-tint, #EBF9F3);
	/* Dihapus DI SINI, di <a> pembungkusnya — bukan di placeholder di dalamnya.
	   text-decoration milik leluhur digambar menembus keturunannya dan tidak
	   bisa dibatalkan dari dalam, jadi menyetel none di .__media-placeholder
	   tidak berpengaruh apa pun (sudah dicoba, garisnya tetap ada). */
	text-decoration: none;
}
.fmipa-card__media img { width: 100%; height: 100%; object-fit: cover; display: block; }
.fmipa-card__media-placeholder {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 100%;
	height: 100%;
	color: var(--fmipa-band-accent, #008050);
	font-family: var(--fmipa-font-headline);
	font-size: clamp(2rem, 5vw, 3rem);
	font-weight: var(--fmipa-fw-bold, 700);
	line-height: 1;
	/* Placeholder duduk di dalam <a>, jadi ia mewarisi garis bawah tautan:
	   hasilnya huruf besar BERGARIS BAWAH di tengah kotak, yang terbaca
	   seperti gliph rusak — bukan seperti gambar yang belum ada. Terlihat
	   jelas saat satu kartu tanpa foto berdiri di antara kartu berfoto. */
	text-decoration: none;
	/* Diredam supaya kartu tanpa foto tidak lebih berteriak daripada kartu
	   yang benar-benar punya foto di sebelahnya. */
	opacity: 0.55;
}

/* Aksi kartu: tombol utama dulu, aksi tersier jadi tautan teks — BUKAN dua
   tombol setara. Sebelumnya "Simpan ke Kalender (.ics)" memakai
   .fmipa-btn--secondary yang berlatar merah penuh, jadi aksi paling tersier di
   kartu justru jadi elemen paling nyaring, empat kali dalam satu section, dan
   mengalahkan "Detail" yang merupakan aksi utama kartu. */
.fmipa-card__actions { display: flex; flex-wrap: wrap; align-items: center; gap: 0.75rem; margin-top: auto; }

.fmipa-btn--ghost {
	background: none;
	border-color: transparent;
	color: var(--fmipa-band-link, #008050);
	padding-inline: 0;
	box-shadow: none;
	text-decoration: underline;
	text-underline-offset: 3px;
}
.fmipa-btn--ghost:hover { background: none; box-shadow: none; transform: none; color: var(--fmipa-band-fg, #111517); }

.fmipa-card:hover {
	transform: translateY(var(--fmipa-card-lift));
	box-shadow: var(--fmipa-card-shadow-hover);
	border-color: transparent;
}
.fmipa-card__meta { font-size: 0.8125rem; color: var(--fmipa-card-fg-muted); margin: 0 0 0.35em; }
/* Kelas ini dipakai persis untuk JUDUL KARTU (kartu prodi, kartu pakar di
   arsip), bukan untuk heading setingkat section — jadi ia mengikuti token
   judul kartu. Lihat catatan --fmipa-fs-card-title. */
.fmipa-fs-h3 { font-size: var(--fmipa-fs-card-title); font-weight: var(--fmipa-fw-bold); }
/* Judul di dalam kartu apa pun mengikuti lebar kolomnya, bukan tingkat
   headingnya — mencakup kartu berita/agenda/layanan/riset yang memakai <h3>
   polos tanpa kelas utilitas. */
.fmipa-card h2,
.fmipa-card h3 { font-size: var(--fmipa-fs-card-title); }

/* Prose konten generik — single.php (berita)/page.php, the_content() apa
   adanya (prinsip #2 repo: jangan bongkar konten existing). Kelas ini
   dipakai lintas tema tapi belum pernah punya rule sampai sesi ini. */
.fmipa-content {
	max-width: 68ch;
	line-height: 1.75;
}
.fmipa-content > * + * { margin-top: 1.25em; }
.fmipa-content h2 { font-size: var(--fmipa-fs-h2); margin-top: 1.75em; }
.fmipa-content h3 { margin-top: 1.5em; }
.fmipa-content ul,
.fmipa-content ol { padding-left: 1.5em; }
.fmipa-content li + li { margin-top: 0.4em; }
.fmipa-content a { text-decoration-thickness: 1px; text-underline-offset: 2px; }
.fmipa-content blockquote {
	margin: 0;
	padding-left: 1.25em;
	border-left: 3px solid var(--fmipa-green-dark);
	color: var(--fmipa-gray-500);
	font-style: italic;
}
.fmipa-content img { border-radius: var(--fmipa-radius); }

.fmipa-pagination {
	display: flex;
	flex-wrap: wrap;
	gap: 0.5rem;
	margin-top: clamp(2rem, 4vw, 3rem);
}
.fmipa-pagination .page-numbers {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 2.5rem;
	height: 2.5rem;
	padding-inline: 0.5rem;
	border-radius: var(--fmipa-radius);
	border: 1px solid var(--fmipa-gray-200);
	color: var(--fmipa-black);
	text-decoration: none;
	transition: background-color 0.2s var(--fmipa-ease), color 0.2s var(--fmipa-ease);
}
.fmipa-pagination .page-numbers:hover { background: var(--fmipa-gray-50); }
.fmipa-pagination .page-numbers.current { background: var(--fmipa-green-dark); border-color: var(--fmipa-green-dark); color: var(--fmipa-white); }

.fmipa-btn {
	display: inline-flex;
	align-items: center;
	gap: 0.5em;
	padding: 0.8em 1.75em;
	border-radius: var(--fmipa-radius);
	font-weight: var(--fmipa-fw-bold);
	text-decoration: none;
	border: 2px solid transparent;
	cursor: pointer;
	font-family: inherit;
	font-size: 1rem;
	transition: transform 0.2s var(--fmipa-ease), box-shadow 0.2s var(--fmipa-ease), background-color 0.2s var(--fmipa-ease);
}
.fmipa-btn:hover { transform: translateY(-2px); }
.fmipa-btn:active { transform: translateY(0); }
/* WAJIB pakai varian -dark untuk tombol berteks putih — warna terang gagal
   kontras AA (lihat BRAND-GUIDELINE.md §4.4). Jangan pakai --fmipa-green /
   --fmipa-red langsung sebagai latar tombol bertulisan. */
.fmipa-btn--primary { background: var(--fmipa-green-dark); color: var(--fmipa-white); box-shadow: var(--fmipa-shadow-sm); }
.fmipa-btn--primary:hover { background: #006a43; color: var(--fmipa-white); box-shadow: var(--fmipa-shadow-md); }
.fmipa-btn--secondary { background: var(--fmipa-red-dark); color: var(--fmipa-white); box-shadow: var(--fmipa-shadow-sm); }
.fmipa-btn--secondary:hover { background: #b81219; color: var(--fmipa-white); box-shadow: var(--fmipa-shadow-md); }
.fmipa-btn--outline {
	background: transparent;
	border-color: var(--fmipa-green-dark);
	color: var(--fmipa-green-dark);
}
.fmipa-btn--outline:hover { background: var(--fmipa-green-dark); color: var(--fmipa-white); }
/* Tombol outline mengikuti pita lewat token, bukan override per pita. */
.fmipa-btn--outline { border-color: var(--fmipa-band-btn-outline); color: var(--fmipa-band-btn-outline); }
.fmipa-btn--outline:hover { background: var(--fmipa-band-btn-outline); color: var(--fmipa-band-bg); border-color: var(--fmipa-band-btn-outline); }
/* #1DA851 (WhatsApp brand green) gagal kontras AA (3.1:1) untuk teks putih —
   #0F7A46 tetap dalam keluarga hijau WhatsApp tapi lolos AA (5.39:1),
   ditemukan lewat audit Lighthouse aksesibilitas. */
.fmipa-btn--whatsapp { background: #0F7A46; color: var(--fmipa-white); box-shadow: var(--fmipa-shadow-sm); }
.fmipa-btn--whatsapp:hover { background: #0C6B3A; color: var(--fmipa-white); box-shadow: var(--fmipa-shadow-md); }

/* Tombol utama DI ATAS PITA BERANI (merah/ink/hijau). Warnanya tidak dipatok
   per pita, melainkan DIBALIK dari token pita: latar = warna teks pita,
   label = warna latar pita. Satu aturan ini menjalankan dua perintah yang
   selama ini cuma jadi catatan di §3a tanpa kelas yang memenuhinya — di pita
   merah tombol wajib PUTIH berlabel merah (7,12:1), di pita hijau tombol
   wajib GELAP berlabel hijau (6,63:1). .fmipa-btn--primary tidak bisa dipakai
   di kedua tempat itu: #008050 di atas merah tua 1,62:1 dan di atas hijau
   1,80:1 — batas tombolnya lenyap justru di section yang paling ingin diklik.

   Fallback ink/putih dipasang supaya kelas ini tetap masuk akal bila dipakai
   di luar pita mana pun (mis. di dalam kartu): tanpa itu ia mewarisi custom
   property kosong dan jadi tombol transparan tanpa label. */
.fmipa-btn--on-band {
	background: var(--fmipa-band-fg, #111517);
	color: var(--fmipa-band-bg, #FFFFFF);
	box-shadow: var(--fmipa-shadow-sm);
}
/* Hover tidak menggeser warna: tiap pita cuma punya SATU pasangan warna yang
   sudah dihitung kontrasnya, dan menggelapkan salah satunya berarti menghitung
   ulang enam pasangan sekaligus. Umpan baliknya diambil dari bayangan di sini
   plus angkatan translateY milik .fmipa-btn:hover. */
.fmipa-btn--on-band:hover { box-shadow: var(--fmipa-shadow-md); }

.fmipa-stat { text-align: center; }
/* Angka statistik membaca --fmipa-band-accent, BUKAN --fmipa-green langsung.
   Hijau mati begitu latarnya bukan ink: #00B26B di atas putih cuma 2,77:1 —
   gagal bahkan ambang 3:1 untuk teks besar — dan di atas pita hijau ia jadi
   1:1, hilang sama sekali. Lewat token, tiap pita menyuplai aksen yang sudah
   dihitung kontrasnya: ink -> hijau (6,55:1, sama persis seperti sekarang),
   hijau -> ink, terang -> hijau-gelap #008050 (5,00:1). */
.fmipa-stat__number {
	font-family: var(--fmipa-font-mono);
	font-variant-numeric: tabular-nums;
	font-size: clamp(2.25rem, 5vw, 3.25rem);
	font-weight: var(--fmipa-fw-bold);
	color: var(--fmipa-band-accent);
	letter-spacing: var(--fmipa-tracking-tight);
	display: block;
}
.fmipa-stat__label { font-size: var(--fmipa-fs-xs); color: var(--fmipa-band-fg-muted); text-transform: uppercase; letter-spacing: 0.04em; }
.fmipa-stat__icon { color: var(--fmipa-band-accent); }

.fmipa-supergraphic {
	display: block;
	transform: rotate(var(--rotate, 0deg)) scaleX(var(--flip, 1));
}

/* Watermark supergrafik besar — signature section gelap (trust, testimoni).
   0.1 lama nyaris tak kelihatan (footer pakai 0.9 dan gradiennya jelas
   ijo->merah — "Flame of Growth", lihat BRAND-GUIDELINE.md §6) sehingga
   nuansa merah brand nyaris hilang di 2 section paling gelap/menonjol di
   beranda. 0.18 masih tetap watermark (teks tetap dominan, elemen ini
   aria-hidden) tapi gradiennya kebaca. */
/* Watermark supergrafik. Opacity-nya IKUT PITA, bukan satu nilai untuk semua.
   0.18 dirancang untuk pita ink yang gelap — di sana ia terbaca sebagai
   tekstur samar. Begitu section pindah ke pita terang (testimoni kini mist),
   warna merah/hijau supergrafiknya menembus latar terang dan terbaca sebagai
   coreng yang nyasar, bukan tekstur. Di pita terang nilainya diturunkan jauh. */
.fmipa-section-watermark {
	position: absolute;
	top: 50%;
	right: -10%;
	transform: translateY(-50%);
	width: min(48vw, 560px);
	opacity: var(--fmipa-watermark-opacity, 0.06);
	pointer-events: none;
	z-index: 0;
}
.fmipa-section--ink,
.fmipa-section--band-ink { --fmipa-watermark-opacity: 0.18; }
.fmipa-section-watermark .fmipa-supergraphic { width: 100%; height: auto; }

/* ==========================================================================
   4. Header & footer
   ========================================================================== */
/* Utility bar — bar tipis di atas nav utama, pola 2-lapis header (lihat
   header.php). Hilang otomatis saat scroll lewat .fmipa-scrolled di body. */
.fmipa-utility-bar {
	background: var(--fmipa-utility-bar-bg);
	color: var(--fmipa-white);
	font-size: 0.8125rem;
	overflow: hidden;
	max-height: 40px;
	transition: max-height 0.2s ease, padding-block 0.2s ease, opacity 0.2s ease;
}
.fmipa-utility-bar__inner {
	/* Menimpa max-width dari .fmipa-container yang menempel di elemen yang
	   sama (header.php:37). Menang karena spesifisitasnya setara (0,1,0) tapi
	   letaknya lebih bawah di berkas ini — jangan dipindah ke atas blok
	   .fmipa-container. */
	max-width: var(--fmipa-container-header);
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 1rem;
	padding-block: 0.5rem;
}
.fmipa-utility-bar__unpad {
	display: inline-flex;
	align-items: center;
	gap: 0.5rem;
	color: var(--fmipa-white);
	text-decoration: none;
	font-weight: var(--fmipa-fw-medium);
}
.fmipa-utility-bar__unpad:hover { text-decoration: underline; }
/* Nama lengkap yang berlaku; bentuk pendeknya cadangan khusus layar sempit
   (dinyalakan di blok ≤480px). Urutan ini disengaja supaya kalau media
   query-nya gagal termuat, yang tampil adalah nama lengkap lembaganya. */
.fmipa-unpad-label--pendek { display: none; }
/* Lambang Unpad dipatok 20px, bukan diserahkan ke rasio gambarnya (192px
   persegi): tinggi bar dikunci max-height 40px untuk animasi collapse-saat-
   scroll, dan padding-block 0,5rem sudah memakan 16px. 20px menyisakan
   tepat 36px — sama dengan tinggi baris teks sebelumnya, jadi menambah
   lambang di sini TIDAK menggeser apa pun di bawahnya (nol CLS). Ganti
   angka ini berarti harus ikut menaikkan max-height di atas. */
.fmipa-utility-bar__logo { width: 20px; height: 20px; flex: 0 0 auto; }
/* align-items:center WAJIB, bukan `stretch` bawaan flexbox — inilah yang
   membuat teks utility bar sebaris. Item tanpa dropdown adalah <li>
   list-item biasa (tinggi = satu line box, 20,8px), sedangkan item
   BER-dropdown dipaksa jadi flex ber-min-height 1,5rem = 24px (lihat blok
   "Navigasi dropdown N-level") supaya tombol caret yang disuntik JS tidak
   menggeser halaman. Dengan `stretch`, li pendek ikut diregangkan ke 24px
   tapi baris teksnya tetap menempel di ATAS kotak, sementara li dropdown
   menaruh teksnya di TENGAH — selisih 1,59px, cukup terlihat sebagai menu
   "tidak sejajar". Centering menyamakan posisi glyph keduanya persis
   (terukur: semua tautan + label "Universitas Padjadjaran" mulai di y yang
   sama). Aturan kembarnya sudah ada di .fmipa-nav-primary > ul — itu sebabnya
   nav utama tidak pernah kena gejala ini. */
.fmipa-utility-nav > ul { list-style: none; display: flex; align-items: center; gap: 1rem; margin: 0; padding: 0; flex-wrap: wrap; }
/* Putih penuh, bukan rgba(255,255,255,0.7) seperti waktu latar bar masih
   --fmipa-black. Di atas hitam, putih 70% masih 8,6:1; di atas hijau merek
   yang lebih terang ia jatuh ke 3,6:1 — GAGAL AA teks normal. Putih penuh
   di atas --fmipa-utility-bar-bg terukur 14,5:1. Karena warna tidak lagi bisa
   dipakai sebagai penanda hover (sudah mentok putih), afordansi hover-nya
   pindah ke garis bawah. */
.fmipa-utility-nav a { color: var(--fmipa-white); text-decoration: none; transition: opacity 150ms var(--fmipa-ease); }
.fmipa-utility-nav a:hover { text-decoration: underline; }
.fmipa-utility-bar__unpad:focus-visible,
.fmipa-utility-nav a:focus-visible { outline: 2px solid var(--fmipa-white); outline-offset: 2px; border-radius: 2px; }
body.fmipa-scrolled .fmipa-utility-bar { max-height: 0; padding-block: 0; opacity: 0; }

/* Di ponsel, enam tautan utilitas membungkus jadi TIGA baris: bar utilitas
   terukur 109px dari viewport 844px, dan bersama header ~24% layar pertama
   habis untuk navigasi sekunder sebelum ada satu pun konten. Collapse-saat-
   scroll di atas tidak menolong, karena tinggi itu terjadi SEBELUM pengunjung
   sempat menggulir.

   Solusinya satu baris yang bisa digeser mendatar, bukan menyembunyikan
   tautannya: semuanya tetap terjangkau, tapi tingginya terkunci ~40px.
   overflow-x dibatasi di dalam <ul> ini saja, jadi halaman induk tidak ikut
   bisa digeser. -webkit-overflow-scrolling + scrollbar tipis supaya tetap
   terasa seperti strip, bukan seperti area konten.

   AMBANG 1199px, BUKAN 782px seperti semula. Di 783-1199px strip ini dulu
   tidak aktif, dan di sana bar utilitas gagal DIAM-DIAM: tautan membungkus
   3-4 baris sementara .fmipa-utility-bar dipatok max-height:40px +
   overflow:hidden, sehingga item terakhir terpotong habis tanpa scroll dan
   tanpa jalan apa pun untuk mencapainya. Terukur: 3 tautan hilang di 783px,
   2 di 900px, 1 sampai 1100px, dan bersih baru mulai 1200px — karena itu
   1199 dan bukan angka bulat yang enak dilihat. */
@media (max-width: 1199px) {
	/* min-width:0 pada <nav>-nya, BUKAN cuma overflow-x pada <ul> di dalamnya.
	   Tanpa ini strip geser di bawah tidak benar-benar berfungsi: <nav>
	   adalah flex item, dan flex item bawaannya min-width:auto — ia menolak
	   menyusut di bawah lebar min-content isinya. Terukur di viewport 390px
	   sebelum baris ini ada: <nav> mulai di x=213 dengan lebar 495px, jadi
	   ujungnya ada di x=708 — 318px di luar layar. overflow:hidden milik bar
	   memotongnya, sehingga menggeser <ul> hanya memindahkan isi di dalam
	   kotak yang sebagian besarnya memang tidak pernah terlihat. Hasilnya
	   tautan terakhir tidak bisa dicapai dengan cara apa pun.

	   Pola yang sama sudah dipakai .fmipa-nav-primary ("flex: 1 1 auto;
	   min-width: 0") di bagian nav utama — aturan ini cuma menutup tempat
	   yang terlewat. */
	.fmipa-utility-nav { min-width: 0; }
	.fmipa-utility-nav > ul {
		flex-wrap: nowrap;
		overflow-x: auto;
		scrollbar-width: none;
		-webkit-overflow-scrolling: touch;
	}
	.fmipa-utility-nav > ul::-webkit-scrollbar { display: none; }
	.fmipa-utility-nav > ul > li { flex: 0 0 auto; }
	/* Setelah daftar tautan jadi satu baris, sisa tingginya justru datang dari
	   "Universitas Padjadjaran" yang membungkus jadi dua baris (terukur 42px
	   tinggi di kotak selebar 73px) — ia flex sibling, jadi bar ikut setinggi
	   itu. nowrap membuatnya satu baris; daftar tautan di sebelahnya memang
	   menyempit, tapi itu tidak masalah karena sudah bisa digeser mendatar. */
	.fmipa-utility-bar__unpad { white-space: nowrap; }

	/* Penanda "masih ada lagi ke kanan". Strip di atas bisa digeser, tapi
	   scrollbar-nya sengaja disembunyikan — jadi tanpa aturan ini tautan
	   yang berada di luar layar (terukur di 390px: tinggal "Lab Terpadu" dan
	   "Alumni" yang terlihat dari enam item) tidak punya satu pun isyarat
	   bahwa ia ada. Strip yang terpotong rata di tepi terbaca sebagai daftar
	   yang memang cuma segitu.

	   mask-image, bukan gradien latar yang ditumpuk: latar bar sudah punya
	   dua kemungkinan warna (utility-bar-bg biasa dan versi transparan saat
	   di atas hero), dan gradien palsu harus menebak salah satunya. Mask
	   memudarkan tautannya sendiri, jadi ia benar di kedua latar. */
	.fmipa-utility-nav > ul {
		-webkit-mask-image: linear-gradient(to right, #000 calc(100% - var(--fmipa-strip-fade)), transparent);
		mask-image: linear-gradient(to right, #000 calc(100% - var(--fmipa-strip-fade)), transparent);
	}
}

/* Ambang 480px, bukan 782px yang dipakai strip di atas: sampai 480px nama
   lengkapnya masih menyisakan jendela strip yang layak (terukur 267px di
   480px), jadi memendekkannya lebih awal cuma membuang kejelasan tanpa
   ditukar apa pun. Di bawah 480px jendela itu jatuh ke bawah 160px dan
   pertukarannya jadi sepadan. */
@media (max-width: 480px) {
	.fmipa-unpad-label--panjang { display: none; }
	.fmipa-unpad-label--pendek { display: inline; }
}

/* Lebar pudar dijadikan custom property TERDAFTAR supaya nilainya bisa
   dianimasikan; custom property biasa hanya bisa berganti mendadak, tidak
   bisa diinterpolasi. */
@property --fmipa-strip-fade {
	syntax: '<length>';
	inherits: false;
	initial-value: 28px;
}

/* Pudarnya ikut hilang begitu strip digeser sampai mentok kanan. Tanpa ini
   pudarnya menetap, dan tautan TERAKHIR akan tampak separuh transparan
   selamanya di ujung gulir — terbaca sebagai salah render, bukan sebagai
   isyarat. Dipakai scroll-driven animation, jadi tanpa JS sama sekali.

   Dibungkus @supports dengan sengaja: Firefox belum mengirim scroll() secara
   default, dan di sana aturan ini dilewati sehingga pudarnya kembali statis
   seperti blok di atas. Itu memang penurunan yang benar — isyaratnya tetap
   ada, cuma tidak ikut menghilang di ujung. */
@supports (animation-timeline: scroll()) {
	@media (max-width: 1199px) {
		.fmipa-utility-nav > ul {
			animation: fmipa-strip-fade linear both;
			animation-timeline: scroll(self inline);
		}
	}
}
@keyframes fmipa-strip-fade {
	to { --fmipa-strip-fade: 0px; }
}

/* Dropdown level-1 utility bar melayang KELUAR dari box bar (position:
   absolute, top:100%) — overflow:hidden di atas (perlu utk animasi
   collapse-saat-scroll) akan memotongnya kalau tetap "hidden" saat ada
   submenu terbuka. Kelas ini ditoggle assets/js/nav-toggle.js persis saat
   itu saja, supaya animasi collapse normal tidak kena efek samping. */
.fmipa-utility-bar.has-open-submenu { overflow: visible; }

.fmipa-site-header {
	border-bottom: 1px solid var(--fmipa-gray-200);
	position: sticky;
	top: 0;
	background: var(--fmipa-white);
	z-index: 50;
	transition: box-shadow 0.2s ease;
}
.fmipa-site-header.is-scrolled { box-shadow: 0 2px 8px rgba(0,0,0,0.08); }
.fmipa-site-header__inner {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 1rem;
	padding-block: 0.75rem;
	transition: padding-block 0.2s ease;
}
.fmipa-site-header.is-scrolled .fmipa-site-header__inner { padding-block: 0.4rem; }
/* flex-shrink:0 WAJIB, dan ini bukan penyetelan gaya — tanpanya logo hilang
   sama sekali di ponsel. Terukur sebelum aturan ini ada: 0x0 px di viewport
   320px dan 360px, 8x2 px di 390px (iPhone 15), baru utuh mulai 600px.

   Sebabnya .fmipa-header-cta sudah punya flex-shrink:0 sementara logo tidak,
   jadi ketika baris header kekurangan ruang flexbox mengambilnya dari satu-
   satunya item yang boleh menyusut — logonya. Anggaran di 390px: padding 32
   + gap 32 + tombol Menu 110 + CTA 208 = 382 px, menyisakan 8 px untuk logo.

   Akibatnya header ponsel (beranda maupun halaman dalam, sebelum maupun
   sesudah scroll) tidak memuat satu pun penanda FMIPA; identitas yang
   tersisa cuma "Universitas Padjadjaran" di utility bar, yaitu nama INDUK,
   bukan fakultasnya. Ruang yang dulu dicuri dari logo sekarang diambil dari
   kedua tombol lewat blok "Baris header di ponsel" di bawah. */
.fmipa-site-logo { display: flex; align-items: center; gap: 0.5rem; text-decoration: none; color: var(--fmipa-black); font-weight: var(--fmipa-fw-extrabold); font-size: 1.125rem; flex-shrink: 0; }
.fmipa-site-logo img { max-height: 44px; width: auto; transition: max-height 0.2s ease; }
.fmipa-site-header.is-scrolled .fmipa-site-logo img { max-height: 32px; }
/* Baris header memakai container SENDIRI yang lebih lebar dari container isi
   halaman (1200px). Diukur, bukan dikira: dengan 6 item nav yang sudah
   diramping, isi baris header butuh ~1230px sementara container 1200px hanya
   menyediakan 1136px area isi — kurang, jadi item terakhir ("Mahasiswa")
   jatuh ke baris kedua.

   Yang memakan ruang bukan cuma labelnya: label 6 item hanya 601px, sedangkan
   5 tombol chevron dropdown memakan 120px sendiri (seperlima lebar nav).
   Chevron TIDAK dikecilkan karena 24x24 adalah ambang minimum target sentuh
   WCAG 2.5.8 — sama seperti alasan dot carousel dulu diperbesar.

   Header melebar dari isi halaman itu pola lazim dan tidak merusak
   keselarasan: header punya bidang putihnya sendiri, terpisah dari aliran
   konten di bawahnya. */
.fmipa-site-header__inner { max-width: var(--fmipa-container-header); }
.fmipa-nav-primary { flex: 1 1 auto; min-width: 0; }
/* gap 0.9rem, bukan 1.1rem: label menu berbahasa Indonesia panjang-panjang
   ("Penelitian dan Inovasi" saja 180px), jadi jarak antar-item adalah satu-
   satunya sumber ruang yang bisa ditekan tanpa mengecilkan teks. */
.fmipa-nav-primary > ul { list-style: none; display: flex; align-items: center; gap: 0.9rem; margin: 0; padding: 0; flex-wrap: wrap; row-gap: 0.5rem; justify-content: flex-end; }
.fmipa-nav-primary a {
	position: relative;
	display: inline-block;
	padding-block: 0.3rem;
	color: var(--fmipa-black);
	text-decoration: none;
	font-size: 0.9375rem;
	font-weight: var(--fmipa-fw-medium);
	letter-spacing: 0.01em;
	transition: color 150ms var(--fmipa-ease);
}
.fmipa-nav-primary a:hover { color: var(--fmipa-green-dark); }
/* Underline modern yang muncul dari tengah (bukan warna doang) — pola nav
   "editorial" umum di produk modern (Vercel/Linear/Stripe-style), lebih
   terasa "hidup" daripada cuma ganti warna teks. */
.fmipa-nav-primary a::after {
	content: '';
	position: absolute;
	left: 0;
	right: 0;
	bottom: 0;
	height: 2px;
	background: var(--fmipa-green-dark);
	border-radius: 1px;
	transform: scaleX(0);
	transition: transform 200ms var(--fmipa-ease);
}
.fmipa-nav-primary a:hover::after,
.fmipa-nav-primary a:focus-visible::after { transform: scaleX(1); }
.fmipa-header-cta { flex-shrink: 0; }
.fmipa-nav-toggle { display: none; }

/* Salinan menu utilitas di dalam panel menu (dicetak oleh
   fmipa_the_utility_menu_echo(), alasan terukurnya ada di sana).
   Tersembunyi secara bawaan dan dinyalakan hanya di ≤1199px — display:none
   sekaligus mengeluarkannya dari pohon aksesibilitas, jadi di lebar lebar
   pembaca layar tidak menjumpai menu yang sama dua kali. */
.fmipa-nav-utility-echo { display: none; }
/* Ikon hanya tampil di tempat ia MENGGANTIKAN label (≤600px), bukan
   mendampinginya. Terukur: ikon + gap 0.5em melebarkan tombol dari 110px ke
   138px, dan di 601px itu menyisakan 2px saja dari 601 (189 logo + 138
   tombol + 208 CTA + 32 gap + 32 padding = 599). Baris header di 601-650px
   praktis tanpa toleransi, padahal label teks di lebar itu sudah jelas
   sendiri — ikonnya tidak menambah kejelasan, cuma menambah lebar. */
.fmipa-nav-toggle__icon { display: none; width: 20px; height: 14px; flex: 0 0 auto; }
/* Hamburger <-> silang, dikemudikan aria-expanded milik tombolnya sendiri.
   Memakai opacity, bukan display: keduanya tetap menempati kotak yang sama
   sehingga pertukarannya bisa dilembutkan dan tidak ada pergeseran 1px pun
   saat menu dibuka. */
.fmipa-nav-toggle__bars,
.fmipa-nav-toggle__x { transition: opacity 150ms var(--fmipa-ease); }
.fmipa-nav-toggle__x { opacity: 0; }
.fmipa-nav-toggle[aria-expanded='true'] .fmipa-nav-toggle__bars { opacity: 0; }
.fmipa-nav-toggle[aria-expanded='true'] .fmipa-nav-toggle__x { opacity: 1; }
/* Label panjang yang berlaku, pendeknya cadangan khusus ponsel. Urutannya
   sengaja begini supaya kalau blok media di bawah gagal termuat, yang
   tampil adalah kalimat lengkap, bukan potongannya. */
.fmipa-cta-label--pendek { display: none; }

/* --------------------------------------------------------------------------
   Baris header di ponsel (≤600px) — anggaran ruang, bukan selera.

   Di 360px baris header hanya punya 328px isi bersih (360 dikurangi padding
   container 2x16) untuk tiga pekerjaan yang semuanya wajib: menyatakan ini
   situs siapa, membuka navigasi, dan mengajak mendaftar. Dengan ukuran
   desktop ketiganya butuh 382px — lebih besar dari layarnya, jadi ada yang
   harus mengalah. Yang dipilih mengalah di sini adalah LABEL kedua tombol,
   bukan logonya, karena label bisa diganti ikon/kata pendek tanpa kehilangan
   makna sementara logo yang menyusut kehilangan seluruh fungsinya.

   Anggaran sesudah aturan ini, di 360px:
     padding container   32
     logo (tinggi 32px)  138
     dua gap 12px         24
     tombol menu ikon     44
     CTA "Daftar"        ~80
     ------------------------
     total              ~318  <= 360, sisa ~42px

   Ambang 600px, bukan 782px: di 600px logo sudah utuh 189px dan ketiganya
   muat berlabel penuh (terukur). Menaikkannya ke 782px berarti membuang
   label yang sebenarnya masih muat.

   min-height 44px pada kedua tombol adalah ambang target sentuh WCAG 2.5.8.
   Tinggi lamanya 55px bukan hasil perancangan melainkan sisa padding tombol
   berukuran desktop (0.8em pada font 1rem); 44px memenuhi standar dan
   mengembalikan 11px ke tinggi header.
   -------------------------------------------------------------------------- */
@media (max-width: 600px) {
	.fmipa-site-header__inner { gap: 0.75rem; }
	.fmipa-site-logo img,
	.fmipa-site-header.is-scrolled .fmipa-site-logo img { max-height: 32px; }

	/* Ikon saja. Nama aksesibelnya aman karena tombolnya membawa aria-label
	   sendiri (lihat header.php) — display:none pada labelnya tidak
	   membuatnya jadi tombol tanpa nama. */
	.fmipa-nav-toggle__label { display: none; }
	.fmipa-nav-toggle__icon { display: block; }
	.fmipa-nav-toggle {
		min-width: 44px;
		min-height: 44px;
		padding: 0;
		justify-content: center;
		gap: 0;
	}

	.fmipa-header-cta .fmipa-btn {
		min-height: 44px;
		padding: 0.6em 1em;
		font-size: 0.9375rem;
	}
	.fmipa-cta-label--panjang { display: none; }
	.fmipa-cta-label--pendek { display: inline; }
}

/* Layar tersempit yang masih ditemui (Galaxy Fold tertutup, iPhone SE gen-1).
   Logo turun satu tingkat lagi ke 28px (=120px lebar) supaya total tetap di
   bawah 320px; di bawah nilai ini huruf "FMIPA" pada logo mulai tidak
   terbaca, jadi 28px adalah lantainya, bukan titik yang boleh diturunkan
   lagi kalau nanti ada elemen baru di baris ini. */
@media (max-width: 380px) {
	.fmipa-site-logo img,
	.fmipa-site-header.is-scrolled .fmipa-site-logo img { max-height: 28px; }
	.fmipa-header-cta .fmipa-btn { padding: 0.6em 0.85em; }
}

/* Gap dirapatkan supaya lebih banyak tautan muat dalam satu layar strip.
   max-height:130px yang dulu ada di sini SUDAH DIHAPUS, bukan terlupa: ia
   dipasang waktu tautan utilitas masih membungkus beberapa baris, dan sejak
   strip nowrap di atas berlaku isinya selalu satu baris (~37px: teks 21px +
   padding 2x8px). Membiarkannya berarti menyisakan aturan yang menjanjikan
   bar setinggi 130px padahal tidak pernah terjadi — dan komentarnya menyebut
   "6 item" sementara menunya kini 9. */
@media (max-width: 1199px) {
	.fmipa-utility-nav > ul { gap: 0.75rem; }

	/* Ambangnya 1199px, sama persis dengan ambang strip di atas, dan itu
	   disengaja: salinan ini dinyalakan tepat di lebar-lebar tempat bar
	   utilitas TIDAK sanggup menampilkan seluruh isinya sekaligus. Di
	   ≥1200px bar itu muat satu baris, jadi salinannya justru jadi
	   pengulangan yang tidak perlu. Gayanya diatur di blok ≤1359px. */
	.fmipa-nav-utility-echo { display: block; }
}

/* ==========================================================================
   4a. Navigasi dropdown N-level (nav utama + utility bar)
   ========================================================================== */
/* Struktur menu di-seed dari inc/nav-menu-seed.php demi paritas penuh dgn
   navigasi live fmipa.unpad.ac.id, yang bertingkat sampai 4 level (mis.
   Tentang FMIPA -> Sumber Daya Manusia -> Dosen per Departemen -> 8 link
   departemen). Toggle disuntik via assets/js/nav-toggle.js sebagai TOMBOL
   TERPISAH dari <a> (bukan meng-override klik pada link, krn banyak item
   induk juga punya destinasi asli sendiri) — interaksi klik eksplisit di
   semua kedalaman, bukan hover-only (catatan aksesibilitas J5,
   docs/REFERENSI-DESAIN.md, pola MIT EECS yang harus dihindari).
   Animasi buka/tutup pakai @starting-style + transition-behavior:
   allow-discrete pada `display` — cara modern (bukan JS rAF-hack) utk
   mengalihkan display:none<->block SEKALIGUS animasi opacity/transform,
   dan otomatis menunda `display:none` sampai animasi keluar selesai (jadi
   transisi tutup tidak terasa "dipotong"). --fmipa-ease dipakai ulang (bukan
   kurva baru) supaya gerakannya konsisten dgn tombol/kartu/reveal di
   seluruh situs. */
.fmipa-nav-primary li.menu-item-has-children,
.fmipa-utility-nav li.menu-item-has-children {
	position: relative;
	display: flex;
	align-items: center;
	flex-wrap: wrap;
	/* Ruang untuk .fmipa-submenu-toggle DIPESAN DI SINI, dan angkanya wajib
	   sama dengan tinggi tombol itu (1,5rem di aturan .fmipa-submenu-toggle
	   di bawah) — kalau salah satu diubah, ubah keduanya.

	   Alasannya: tombol toggle tidak ada di HTML server-render, melainkan
	   disuntik nav-toggle.js setelah first paint. Tanpa pemesanan ini baris
	   nav tumbuh 21px -> 24px begitu tombol masuk, .fmipa-utility-nav ikut
	   tumbuh 3px, dan seluruh #fmipa-main (tinggi ~800px) tergeser turun 3px.
	   Pergeseran kecil pada elemen sebesar itu berskor besar: CLS desktop
	   terukur 0,49 — nyaris seluruhnya dari satu pergeseran ini.

	   Cacat ini lolos berbulan-bulan karena semua gerbang Lighthouse proyek
	   dijalankan di profil MOBILE, dan di mobile nav ini tidak memakai
	   toggle yang sama. Ukur desktop juga. */
	min-height: 1.5rem;
}
.fmipa-nav-primary .sub-menu,
.fmipa-utility-nav .sub-menu {
	display: none;
	list-style: none;
	margin: 0;
	padding: 0;
	flex-basis: 100%;
	opacity: 0;
	transform: translateY(-4px);
	transition: opacity 160ms var(--fmipa-ease), transform 160ms var(--fmipa-ease), display 160ms allow-discrete;
}
/* Selector generik (tidak di-scope per level) — otomatis berlaku di
   kedalaman berapa pun, tidak perlu aturan terpisah per level nested. */
.fmipa-nav-primary li.is-submenu-open > .sub-menu,
.fmipa-utility-nav li.is-submenu-open > .sub-menu {
	display: block;
	opacity: 1;
	transform: translateY(0);
}
@starting-style {
	.fmipa-nav-primary li.is-submenu-open > .sub-menu,
	.fmipa-utility-nav li.is-submenu-open > .sub-menu {
		opacity: 0;
		transform: translateY(-4px);
	}
}

.fmipa-submenu-toggle {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 1.5rem;
	height: 1.5rem;
	flex: 0 0 auto;
	margin-inline-start: 0.1rem;
	padding: 0;
	border: 0;
	border-radius: 50%;
	background: transparent;
	color: inherit;
	cursor: pointer;
	transition: background-color 120ms var(--fmipa-ease), transform 120ms var(--fmipa-ease);
}
.fmipa-submenu-toggle:hover { background: rgba(0,0,0,0.06); }
.fmipa-submenu-toggle:active { transform: scale(0.88); }
.fmipa-submenu-toggle:focus-visible { outline: 2px solid var(--fmipa-band-focus); outline-offset: 1px; }
.fmipa-utility-nav .fmipa-submenu-toggle:hover { background: rgba(255,255,255,0.15); }
.fmipa-submenu-toggle svg {
	width: 0.7rem;
	height: 0.7rem;
	transition: transform 160ms var(--fmipa-ease);
}
.fmipa-submenu-toggle[aria-expanded="true"] svg { transform: rotate(180deg); }

@media (min-width: 783px) {
	/* Hanya panel level-1 yang melayang (posisi dihitung sekali); level ke-2
	   dst tetap dalam alur normal (indented) di DALAM panel yang sama —
	   menghindari perhitungan posisi flyout bertingkat yang rumit/rapuh. */
	.fmipa-nav-primary > ul > li.menu-item-has-children > .sub-menu,
	.fmipa-utility-nav > ul > li.menu-item-has-children > .sub-menu {
		position: absolute;
		top: 100%;
		left: 0;
		min-width: 260px;
		max-width: 340px;
		max-height: 70vh;
		overflow-y: auto;
		margin-top: 0.5rem;
		padding: 0.5rem;
		background: var(--fmipa-white);
		border: 1px solid var(--fmipa-gray-200);
		border-radius: var(--fmipa-radius, 0.5rem);
		box-shadow: var(--fmipa-shadow-md);
		transform-origin: top left;
		z-index: 60;
	}
	/* Panel level-1 datang dari trigger-nya (scale halus + geser), bukan
	   cuma fade — popover seharusnya terasa "muncul dari" pemicunya. */
	.fmipa-nav-primary > ul > li.menu-item-has-children > .sub-menu,
	.fmipa-utility-nav > ul > li.menu-item-has-children > .sub-menu {
		transform: translateY(-4px) scale(0.97);
	}
	.fmipa-nav-primary > ul > li.is-submenu-open > .sub-menu,
	.fmipa-utility-nav > ul > li.is-submenu-open > .sub-menu {
		transform: translateY(0) scale(1);
	}
	@starting-style {
		.fmipa-nav-primary > ul > li.is-submenu-open > .sub-menu,
		.fmipa-utility-nav > ul > li.is-submenu-open > .sub-menu {
			transform: translateY(-4px) scale(0.97);
		}
	}
	.fmipa-nav-primary .sub-menu a,
	.fmipa-utility-nav .sub-menu a {
		display: block;
		padding: 0.45rem 0.6rem;
		border-radius: 6px;
		color: var(--fmipa-black);
		font-weight: var(--fmipa-fw-medium);
		transition: background-color 120ms var(--fmipa-ease), color 120ms var(--fmipa-ease);
	}
	.fmipa-nav-primary .sub-menu a:hover,
	.fmipa-utility-nav .sub-menu a:hover {
		background: var(--fmipa-gray-50);
		color: var(--fmipa-green-dark);
	}
	.fmipa-nav-primary .sub-menu .fmipa-submenu-toggle,
	.fmipa-utility-nav .sub-menu .fmipa-submenu-toggle {
		color: var(--fmipa-black);
	}
	.fmipa-nav-primary .sub-menu .sub-menu,
	.fmipa-utility-nav .sub-menu .sub-menu {
		margin: 0.2rem 0 0.3rem 0.5rem;
		padding-left: 0.75rem;
		border-left: 2px solid var(--fmipa-gray-200);
	}
}

/* Gerakan minimal buat yang minta prefers-reduced-motion — tetap ada fade
   opacity (bantu persepsi buka/tutup) tapi tanpa transform/scale. */
@media (prefers-reduced-motion: reduce) {
	.fmipa-nav-primary .sub-menu,
	.fmipa-utility-nav .sub-menu,
	.fmipa-nav-primary > ul > li.menu-item-has-children > .sub-menu,
	.fmipa-utility-nav > ul > li.menu-item-has-children > .sub-menu {
		transition: opacity 120ms ease, display 120ms allow-discrete;
		transform: none !important;
	}
}

/* Latar footer = --fmipa-ink, BUKAN --fmipa-black.

   Alasannya konsistensi, bukan selera. Halaman ini punya tiga bidang gelap:
   utility bar di paling atas (#003020), pita ink di tengah (#071912), dan
   footer. Dua yang pertama hitam-kehijauan — shade dari hijau merek, hue 156°.
   Footer satu-satunya yang memakai hitam NETRAL #111517, jadi begitu ketiganya
   terlihat dalam satu gulungan, footer terbaca sebagai bidang milik sistem
   lain: halaman dibuka dengan warna fakultas dan ditutup dengan abu gelap
   generik. Dipindah ke --fmipa-ink, ketiganya jatuh di keluarga yang sama dan
   footer mengunci halaman dengan hue yang sama seperti pembukanya.

   Kontras tidak berubah berarti — teks putih 18,4:1 di #111517 dan 18,2:1 di
   #071912, dua-duanya jauh di atas AAA; --fmipa-gray-200 untuk teks redup
   16,1:1. Jadi ini murni penyelarasan warna, tanpa mengorbankan keterbacaan. */
.fmipa-site-footer { position: relative; overflow: hidden; background: var(--fmipa-ink); color: var(--fmipa-white); padding-block: var(--fmipa-gap); margin-top: var(--fmipa-gap); }
/* Jarak 96px di atas footer itu benar untuk halaman yang berakhir dengan teks
   di atas putih — ia memisahkan isi dari footer. Tapi kalau halaman berakhir
   dengan PITA berwarna, jarak yang sama berubah arti: yang tampil jadi strip
   putih terjepit antara pita dan footer hitam, dan pita penutup terbaca
   seperti blok yang terpotong sebelum halaman selesai. Beranda persis kasus
   itu — section terakhirnya CTA berpita. Kalau elemen terakhir <main> adalah
   pita, footer menempel langsung. */
#fmipa-main:has(> .fmipa-section--band:last-child) + .fmipa-site-footer { margin-top: 0; }
/* Konsekuensi dari footer yang kini se-warna dengan pita ink: kalau halaman
   KEBETULAN berakhir dengan pita ink, dua bidang #071912 bertemu tanpa jarak
   (aturan margin-top: 0 di atas) dan batas antara isi dan footer hilang sama
   sekali — bukan "menyatu mulus", melainkan pembaca kehilangan tanda bahwa
   halaman sudah selesai. Garis rambut ini mengembalikan batas itu tanpa
   memulihkan strip putih yang justru dihapus aturan di atas. Nilainya sama
   dengan garis .fmipa-footer-bottom (0,15) di bawah, jadi footer punya satu
   bobot garis pemisah, bukan satu nilai per tempat. */
#fmipa-main:has(> .fmipa-section--ink:last-child) + .fmipa-site-footer,
#fmipa-main:has(> .fmipa-section--band-ink:last-child) + .fmipa-site-footer { border-top: 1px solid rgba(255,255,255,0.15); }
.fmipa-site-footer a { color: var(--fmipa-white); }
/* Empat kolom dengan lebar EKSPLISIT, bukan auto-fit.
   Versi lama memakai repeat(auto-fit, minmax(200px,1fr)) dan jumlah kolomnya
   ikut berubah mengikuti area widget mana yang kebetulan terisi — sehingga
   lebar kolom tidak pernah stabil dan tata letaknya terlihat timpang (nama
   fakultas sempit, blok widget melebar). Sekarang isinya tetap empat, jadi
   gridnya boleh tetap juga. Kolom identitas dapat porsi lebih besar karena
   memuat nama fakultas yang panjang plus alamat. */
.fmipa-footer-grid {
	position: relative;
	display: grid;
	gap: clamp(1.5rem, 3vw, 2.5rem);
	grid-template-columns: 1.6fr 1fr 1fr 1.1fr;
	margin-bottom: 2.5rem;
}

/* Judul kolom footer punya skalanya SENDIRI dan tidak mewarisi h2/h3 dokumen.
   Sebelumnya judul di footer bisa tampil 44px — lebih besar daripada nama
   fakultas di sebelahnya — karena footer tidak pernah diberi skala sendiri.
   Bentuk label kecil ber-uppercase juga membedakannya dari judul konten:
   ini penanda kolom, bukan heading bacaan. */
.fmipa-footer-heading {
	font-weight: var(--fmipa-fw-bold);
	font-size: var(--fmipa-fs-xs);
	text-transform: uppercase;
	letter-spacing: var(--fmipa-tracking-caps);
	color: var(--fmipa-gray-200);
	margin: 0 0 1em;
}
/* Logo footer — versi satu warna putih dari logo header yang sama.

   CARA PUTIHNYA. brightness(0) menggencet ketiga kanal warna ke 0 (siluet
   hitam pekat, kanal alfa tidak ikut disentuh sehingga bentuk huruf dan
   latar transparannya utuh), lalu invert(1) membalik siluet itu ke putih
   pekat. Rangkaian dua langkah ini berlaku untuk warna sumber APA PUN —
   itulah sebabnya ia dipilih ketimbang menyiapkan berkas logo putih kedua:
   fakultas lain yang mengunggah logonya sendiri lewat Kustomisasi langsung
   dapat versi putih yang benar tanpa menyiapkan aset tambahan.

   YANG DIKORBANKAN, dan kenapa itu memang benar di sini: nyala oranye-hijau
   di atas huruf "i" ikut rata jadi putih. Itu bukan efek samping yang
   ditoleransi, melainkan yang diminta — logo satu warna di atas latar gelap
   justru cara resmi memakai lambang berwarna pada bidang gelap, karena versi
   berwarnanya kehilangan kontras: nyala oranye #F5A623 di atas --fmipa-ink
   cuma 8,6:1 pada bagian paling terang dan turun jauh di bawah itu pada
   gradien hijaunya, sementara putih pekat duduk di 18,2:1 merata.

   Tingginya 40px (bukan 44px seperti header): logo di footer adalah tanda
   penutup, bukan titik masuk navigasi, dan nama fakultas lengkap tepat di
   bawahnya sudah memikul tugas menyebut lembaga. width:auto menjaga rasio
   aspek berapa pun ukuran berkas yang diunggah admin. */
.fmipa-footer-logo {
	display: block;
	height: 40px;
	width: auto;
	max-width: 100%;
	margin-bottom: 1rem;
	filter: brightness(0) invert(1);
}
.fmipa-footer-nama { font-weight: var(--fmipa-fw-bold); font-size: var(--fmipa-fs-h4); margin: 0 0 0.25em; line-height: 1.3; }
.fmipa-footer-induk { margin: 0 0 0.75em; color: var(--fmipa-gray-200); }
.fmipa-footer-alamat { font-style: normal; font-size: var(--fmipa-fs-sm); color: var(--fmipa-gray-200); line-height: 1.6; }

/* Daftar tautan footer: tanpa bullet, tanpa garis bawah permanen.
   Versi lama memakai keluaran widget mentah — bullet cakram + tautan
   bergaris bawah — yang terbaca seperti dokumen belum ditata. */
.fmipa-footer-menu { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.6rem; }
.fmipa-footer-menu a { text-decoration: none; font-size: var(--fmipa-fs-sm); color: var(--fmipa-gray-200); transition: color 150ms var(--fmipa-ease); }
.fmipa-footer-menu a:hover,
.fmipa-footer-menu a:focus-visible { color: var(--fmipa-white); text-decoration: underline; }
.fmipa-footer-bottom { position: relative; border-top: 1px solid rgba(255,255,255,0.15); padding-top: 1.5rem; font-size: 0.875rem; color: var(--fmipa-gray-200); }
.fmipa-footer-credit { color: var(--fmipa-gray-200); text-decoration: none; transition: color 150ms var(--fmipa-ease); }
.fmipa-footer-credit:hover,
.fmipa-footer-credit:focus-visible { color: var(--fmipa-white); text-decoration: underline; }

.fmipa-social-icons { position: relative; display: flex; gap: 0.75rem; margin-bottom: 1.5rem; }
/* Varian footer. margin-bottom bawaan itu benar saat baris ikon berdiri di ATAS
   sesuatu — dulu ia mendahului grid. Sejak dipindah ke ekor kolom identitas,
   jaraknya harus balik arah: yang perlu dipisahkan sekarang alamat di atasnya,
   sedangkan 1,5rem di bawah cuma menambah ruang kosong menjelang batas grid.
   flex-wrap ditambahkan karena kolom identitas di ponsel jauh lebih sempit
   daripada lebar footer penuh tempat baris ini dulu berdiri. */
.fmipa-footer-social { flex-wrap: wrap; margin-top: 1.5rem; margin-bottom: 0; }
.fmipa-social-icons__item {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 36px;
	height: 36px;
	border-radius: 50%;
	border: 1px solid rgba(255,255,255,0.3);
	color: var(--fmipa-white);
	text-decoration: none;
	font-size: 0.75rem;
	font-weight: var(--fmipa-fw-bold);
}
.fmipa-social-icons__item:hover { background: var(--fmipa-green-dark); border-color: var(--fmipa-green-dark); color: var(--fmipa-white); }

.fmipa-footer-akreditasi ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.5rem; }
.fmipa-footer-akreditasi li { display: flex; flex-direction: column; font-size: 0.875rem; }
.fmipa-footer-akreditasi li span { color: var(--fmipa-gray-200); }

/* Supergrafik "Flame of Growth" — aksen dekoratif pojok kanan atas footer,
   tidak boleh menutupi konten/CTA (aturan resmi §6 brand guideline).

   opacity 0.9 dulu terlalu pekat: dengan sebagian bentuknya terpotong tepi
   atas footer, ia terbaca sebagai coreng merah-hijau-putih yang nyasar, bukan
   sebagai elemen desain. Diturunkan ke 0.18 — nilai yang SAMA dengan
   .fmipa-section-watermark, supaya supergrafik punya satu bobot yang konsisten
   di mana pun ia muncul, bukan satu nilai per tempat. */
.fmipa-footer-decoration {
	position: absolute;
	top: 0;
	right: -30px;
	width: clamp(140px, 18vw, 240px);
	height: auto;
	opacity: 0.18;
	pointer-events: none;
}
.fmipa-footer-decoration .fmipa-supergraphic {
	width: 100%;
	height: auto;
}

/* Footer di layar sempit. Sebelumnya terukur 911px dari viewport 844px —
   footer sendirian lebih tinggi daripada satu layar penuh. Kolom ditumpuk dua
   berdampingan (bukan satu per baris) untuk kolom tautan yang isinya pendek,
   dan jarak antar-blok dipadatkan. */
@media (max-width: 900px) {
	.fmipa-footer-grid { grid-template-columns: 1fr 1fr; gap: 1.5rem 1.25rem; }
	.fmipa-footer-col--identitas { grid-column: 1 / -1; }
}
@media (max-width: 480px) {
	.fmipa-footer-grid { gap: 1.25rem 1rem; }
	.fmipa-site-footer { padding-block: var(--fmipa-space-xl); }
	.fmipa-footer-decoration { display: none; }
}

/* Ambang nav utama 1359px, BUKAN 782px — dan BUKAN 1249px seperti sebelumnya.

   Angka 1249px lahir dari pengukuran yang isinya sudah tidak ada lagi: ia
   mengasumsikan label 6 item = 601px, chevron 120px, logo 184px, CTA 141px.
   Yang terukur sekarang: label+chevron 769,6px, logo 189px, CTA 208px. Menu
   di-seed ulang dari navigasi live (inc/nav-menu-seed.php) setelah angka itu
   ditulis, dan ambangnya tidak pernah ikut dihitung ulang.

   Akibatnya bukan sekadar meleset, melainkan terbalik: pada 1250-1359px nav
   memang tampil, tapi TIDAK PERNAH muat satu baris. Item terakhir
   ("Mahasiswa") jatuh ke baris kedua lalu terpotong tepi bawah header —
   terukur di 1440px, dan sama di 1920px karena kekurangannya ada pada nilai
   maksimum --fmipa-container-header, bukan pada lebar layar. Jadi ambang lama
   justru MENAMPILKAN nav persis di rentang yang tidak sanggup memuatnya.

   1359px = titik muat sesungguhnya. Nav butuh 841,6px; supaya ia dapat
   segitu, baris header perlu 841,6 + 189 logo + 208 CTA + 32 gap + 64 padding
   = 1334,6px, dan --fmipa-container-header (1360px) baru menyediakannya mulai
   viewport 1360px. Di 1360px nav dapat 867px — kelonggaran 25px.

   Mengecilkan font sempat dicoba sebagai alternatif dan ditolak dari hasil
   ukur: font 14px + gap 0.6rem cuma menurunkan ambang ~50px, karena logo,
   CTA, dan chevron adalah biaya tetap yang tidak ikut mengecil. Menukar
   keterbacaan seluruh nav demi 50px bukan pertukaran yang sepadan.

   Konsekuensinya laptop 1024-1359px memakai menu hamburger — termasuk 1280px
   yang sebelumnya "dapat" nav. Itu bukan penurunan: yang didapatnya dulu
   adalah nav dua baris yang terpotong, sekarang jadi menu hamburger yang
   utuh. Laptop 1366px, lebar desktop tersempit yang masih lazim, tetap dapat
   nav penuh. */
@media (max-width: 1359px) {
	.fmipa-nav-primary { display: none; }
	.fmipa-nav-toggle { display: inline-flex; }
	/* .fmipa-nav-primary tetap flex item di baris .fmipa-site-header__inner
	   (logo/toggle/CTA) — "width:100%" saja TIDAK membuatnya pindah ke baris
	   baru selebar viewport (masih terjepit di antara sibling flex-nya).
	   position:absolute keluar dari flex flow itu sepenuhnya, jadi panel
	   nav bisa benar2 selebar penuh, melayang di bawah header sticky
	   (.fmipa-site-header sudah position:sticky, jadi containing block-nya
	   pas). Ditemukan lewat pengujian nyata setelah menu jadi besar (117
	   item) -- sebelumnya nyaris tak pernah kepakai/keliatan bug-nya. */
	.fmipa-nav-primary {
		opacity: 0;
		transform: translateY(-6px);
		transition: opacity 180ms var(--fmipa-ease), transform 180ms var(--fmipa-ease), display 180ms allow-discrete;
	}
	.fmipa-nav-primary.is-open {
		display: block;
		position: absolute;
		top: 100%;
		left: 0;
		right: 0;
		width: auto;
		max-height: calc(100vh - 120px);
		overflow-y: auto;
		background: var(--fmipa-white);
		padding: 1rem;
		box-shadow: var(--fmipa-shadow-md);
		z-index: 70;
		opacity: 1;
		transform: translateY(0);
	}
	@starting-style {
		.fmipa-nav-primary.is-open {
			opacity: 0;
			transform: translateY(-6px);
		}
	}
	/* align-items:stretch MEMBATALKAN align-items:center yang diwarisi dari
	   .fmipa-nav-primary > ul. Di arah baris (desktop) `center` mengatur
	   sumbu vertikal dan memang dibutuhkan di sana; begitu arahnya berganti
	   jadi kolom, sumbu yang sama menjadi HORIZONTAL, sehingga tiap item
	   menyusut ke lebar teksnya lalu rata tengah. Untuk daftar setinggi ini
	   (6 item nav + 9 item layanan = 15 baris) tepi kiri yang bergerigi
	   membuat mata kehilangan jangkar tiap baris. Sekaligus menyamakan
	   perataan salinan menu utilitas di bawahnya, yang memang sudah stretch. */
	.fmipa-nav-primary.is-open > ul { flex-direction: column; gap: 0.75rem; align-items: stretch; }

	/* Salinan menu utilitas, ditampilkan hanya di ≤1199px (aturan di bawah).
	   Dipisah garis + judul, bukan disambung begitu saja ke daftar nav utama:
	   tanpa pemisah, sembilan tautan layanan terbaca seolah setara dengan
	   enam cabang akademik utama, dan panelnya jadi daftar 15 item tanpa
	   hierarki. */
	.fmipa-nav-utility-echo {
		margin-top: 1rem;
		padding-top: 1rem;
		border-top: 1px solid var(--fmipa-gray-200);
	}
	.fmipa-nav-utility-echo__judul {
		margin: 0 0 0.75rem;
		font-size: 0.75rem;
		font-weight: var(--fmipa-fw-bold);
		letter-spacing: 0.08em;
		text-transform: uppercase;
		color: var(--fmipa-gray-500);
	}
	.fmipa-nav-utility-echo > ul {
		list-style: none;
		margin: 0;
		padding: 0;
		display: flex;
		flex-direction: column;
		gap: 0.75rem;
	}
	.fmipa-nav-primary .sub-menu {
		margin: 0.35rem 0 0.35rem 0.5rem;
		padding-left: 0.75rem;
		border-left: 2px solid var(--fmipa-gray-200);
	}
}

/* Submenu utility bar mengikuti ambang STRIP (1199px), bukan ambang nav utama
   (1359px). Dulu dipatok 782px dengan alasan "tidak ada hubungannya dengan
   muat/tidaknya nav utama" — alasan itu masih benar, tapi angkanya sudah
   bukan 782 lagi: sejak strip geser naik ke 1199px, di 783-1199px submenu ini
   menggantung dari tautan di dalam strip, dan gaya bertingkatnya harus ikut
   ke sana supaya tampilannya tidak berganti di tengah rentang yang perilaku
   induknya sama persis. */
@media (max-width: 1199px) {
	.fmipa-utility-nav .sub-menu {
		margin: 0.35rem 0 0.35rem 0.5rem;
		padding-left: 0.75rem;
		border-left: 2px solid rgba(255,255,255,0.25);
	}
}

/* ==========================================================================
   5. Section admin-order placeholder & empty state
   ========================================================================== */
.fmipa-section-empty { color: var(--fmipa-gray-500); font-style: italic; }

/* ==========================================================================
   6. Arsip berita — sidebar kategori
   ========================================================================== */
.fmipa-archive-layout { display: grid; grid-template-columns: 220px 1fr; gap: clamp(1.5rem, 4vw, 3rem); align-items: start; }
.fmipa-category-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.25rem; }
.fmipa-category-list a { display: block; padding: 0.5em 0.75em; border-radius: var(--fmipa-radius); color: var(--fmipa-black); text-decoration: none; }
.fmipa-category-list a:hover { background: var(--fmipa-gray-50); }
.fmipa-category-list a.is-active { background: var(--fmipa-green-dark); color: var(--fmipa-white); font-weight: var(--fmipa-fw-bold); }
@media (max-width: 782px) {
	.fmipa-archive-layout { grid-template-columns: 1fr; }
	.fmipa-category-list { flex-direction: row; flex-wrap: wrap; }
}

/* ==========================================================================
   6b. Beranda — chip pilihan kategori "Berita & Insight"
   ==========================================================================

   Warnanya membaca token PITA (--fmipa-band-*), bukan hijau/putih yang
   dipatok: section berita bisa mendarat di pita mana pun tergantung urutan
   yang disusun admin (lihat inc/section-bands.php), dan chip berlatar hijau
   di atas pita hijau hilang sama sekali. Pola yang sama dipakai
   .fmipa-btn--outline.

   Catatan: .fmipa-category-list di blok 6 di atas sengaja TIDAK dipakai ulang
   — ia sidebar vertikal berwarna tetap di halaman arsip, sedangkan ini baris
   horizontal yang harus ikut pita. Kebutuhannya berbeda, bukan duplikasi. */
.fmipa-berita-filter { margin-bottom: var(--fmipa-space-md); }
.fmipa-chips {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-wrap: wrap;
	gap: var(--fmipa-space-2xs);
}
.fmipa-chip {
	display: inline-block;
	padding: 0.4em 1em;
	/* Garisnya --fmipa-band-btn-outline, BUKAN --fmipa-band-line. Token line
	   itu garis pemisah dekoratif — di pita ink alphanya 0,09 dan chip-nya
	   praktis tak bertepi, padahal ini kontrol yang bisa diklik. Token
	   btn-outline memang disiapkan untuk tepi kontrol dan sudah dijaga lolos
	   kontras di tiap pita (lihat catatan alpha di §pita). Efek sampingnya
	   disengaja: chip dan tombol "Lihat Semua ..." di section yang sama jadi
	   memakai bahasa garis yang persis sama. */
	border: 1px solid var(--fmipa-band-btn-outline);
	border-radius: 999px;
	color: var(--fmipa-band-fg);
	background: transparent;
	text-decoration: none;
	font-size: 0.9375rem;
	font-weight: var(--fmipa-fw-medium);
	line-height: 1.6;
}
.fmipa-chip:hover { color: var(--fmipa-band-btn-outline); }
/* Fokus keyboard ikut pita (pola sama dengan .fmipa-submenu-toggle): outline
   bawaan browser hitam hilang di atas pita ink dan pita merah. */
.fmipa-chip:focus-visible { outline: 2px solid var(--fmipa-band-focus); outline-offset: 2px; }
.fmipa-chip.is-active {
	background: var(--fmipa-band-btn-outline);
	border-color: var(--fmipa-band-btn-outline);
	color: var(--fmipa-band-bg);
	font-weight: var(--fmipa-fw-bold);
}

/* Grid diredupkan selama respons kategori baru ditunggu — penanda yang sama
   dengan filter arsip prodi, supaya klik terasa terjawab walau jaringan lambat. */
#fmipa-berita-grid[aria-busy="true"] { opacity: 0.5; }

/* ==========================================================================
   Header melayang di atas hero — body.fmipa-hero-atas
   ==========================================================================

   Pola dari referensi Fakultas Psikologi Unpad: bar utilitas tetap solid di
   paling atas, lalu navbar utama melayang TRANSPARAN di atas gambar hero yang
   naik sampai ke balik navbar. Yang menjaga keterbacaan navigasi bukan latar
   navbar-nya, melainkan ujung atas scrim hero yang dipekatkan (lihat
   fmipa-beranda.css bagian scrim).

   Kelas fmipa-hero-atas hanya terpasang kalau section pertama beranda memang
   hero (inc/template-tags.php) — begitu admin menggeser urutannya, header
   kembali solid sendiri.

   Semua di bawah ini dibatasi :not(.fmipa-scrolled). Begitu pengunjung
   menggulir 40px, header kembali putih solid dengan tulisan gelap seperti
   halaman lain: di bawah hero tidak ada lagi latar gelap yang menjamin teks
   putih terbaca. */

body.fmipa-hero-atas:not(.fmipa-scrolled) .fmipa-site-header {
	background: transparent;
	border-bottom-color: transparent;
	box-shadow: none;
	/* Tombol outline (toggle menu di ≤1359px) membaca token pita yang sama
	   seperti section — cukup tugaskan ulang tokennya, tidak perlu override
	   properti tombolnya satu per satu. */
	--fmipa-band-btn-outline: var(--fmipa-white);
	/* KEDUANYA wajib ditugaskan ulang, bukan cuma yang di atas.
	   .fmipa-btn--outline:hover MEMBALIK sepasang token: latar jadi
	   --fmipa-band-btn-outline dan labelnya jadi --fmipa-band-bg. Waktu cuma
	   token pertama yang diganti jadi putih, token kedua tetap #FFFFFF bawaan
	   :root, sehingga hover menghasilkan PUTIH DI ATAS PUTIH — tombolnya
	   berubah jadi kotak putih kosong. Terlihat paling telanjang pada toggle
	   menu di ponsel (isinya cuma ikon, jadi hover = kotak putih polos), tapi
	   label teks "Menu" di 601-1359px pun ikut hilang.

	   Nilainya diikatkan ke warna scrim hero, bukan ke hijau merek mana pun:
	   inilah warna yang benar-benar ada di belakang tombol ini. #003D28 di
	   atas putih terukur 12,4:1 — lolos AAA. */
	--fmipa-band-bg: rgb(var(--fmipa-hero-scrim, 0, 61, 40));
}

/* Scrim keterbacaan navbar. Ditempelkan pada HEADER, bukan pada hero:
   dengan begitu hero tidak perlu tahu ada navbar melayang di atasnya, dan
   scrim-nya hilang sendiri begitu header jadi solid saat di-scroll.

   Perlu ada karena scrim hero saja tidak cukup di jalur POSTER (video
   belum termuat, Save-Data, atau layar sempit): terhitung pada piksel
   latar terburuk, tautan nav putih di sisi kanan cuma 3,51:1 — di bawah
   ambang 4,5:1 teks normal. Dengan scrim ini jadi 9,14:1. Di jalur video
   scrim hero memang sudah cukup (7,12:1), tapi lapisan ini tidak
   merugikan di sana dan menjaga tampilannya sama di kedua jalur.

   Tingginya melebihi header supaya gradiennya punya ruang memudar; z-index
   negatif menaruhnya di belakang isi header tapi tetap di dalam stacking
   context milik header (z-index:50), jadi ia selalu di atas hero. */
body.fmipa-hero-atas:not(.fmipa-scrolled) .fmipa-site-header::after {
	content: "";
	position: absolute;
	inset: 0 0 auto 0;
	height: calc(var(--fmipa-header-h, 80px) + 6rem);
	background: linear-gradient(
		180deg,
		rgba(var(--fmipa-hero-scrim, 0, 61, 40), 0.85) 0%,
		rgba(var(--fmipa-hero-scrim, 0, 61, 40), 0.55) 45%,
		rgba(var(--fmipa-hero-scrim, 0, 61, 40), 0) 100%
	);
	pointer-events: none;
	z-index: -1;
}

/* Logo: warna asli DIPERTAHANKAN, keterbacaannya dijamin halo putih.

   Perlu ada sesuatu, karena tinta logo memang gelap di atas hero gelap:
   terukur dari berkasnya, 46% piksel bertintanya hijau tua (#306030-an) dan
   46% hitam, dengan aksen kuning/merah di bawah 4% — semuanya lenyap di atas
   scrim hijau. Halo putih tidak mengubah satu piksel pun warna logo; ia cuma
   menggambar tepi di sekelilingnya, dan itu cukup karena yang hilang memang
   BATAS bentuknya, bukan warnanya.

   drop-shadow, bukan box-shadow: logonya PNG dengan 77% piksel tembus, jadi
   halonya harus mengikuti bentuk huruf — box-shadow cuma menggambar kotak.
   Dua lapis 1px ditumpuk, bukan satu lapis 2px: lapis kedua membayangi hasil
   lapis pertama sehingga tepinya rapat dan pekat, sementara satu lapis lebar
   hanya menghasilkan kabut tipis. Lapis ketiga yang lebar dan lembut
   memisahkan logo dari foto ramai di belakangnya.

   CATATAN KEPATUHAN: BRAND-GUIDELINE.md §3.5 melarang "menambahkan efek
   (shadow/outline custom)" pada logo, sementara §3.4 justru menunjuk White
   Reverse untuk latar bergambar. Jadi ini penyimpangan sadar atas permintaan
   eksplisit, bukan kelalaian. Kalau Humas/audit borang mempersoalkannya,
   kembalinya satu baris: filter: brightness(0) invert(1). */
body.fmipa-hero-atas:not(.fmipa-scrolled) .fmipa-site-logo img {
	filter:
		drop-shadow(0 0 1px #fff)
		drop-shadow(0 0 1px #fff)
		drop-shadow(0 0 5px rgba(255, 255, 255, 0.7));
}
body.fmipa-hero-atas:not(.fmipa-scrolled) .fmipa-site-logo {
	color: var(--fmipa-white);
}

body.fmipa-hero-atas:not(.fmipa-scrolled) .fmipa-nav-primary > ul > li > a,
body.fmipa-hero-atas:not(.fmipa-scrolled) .fmipa-nav-primary > ul > li > .fmipa-submenu-toggle {
	color: var(--fmipa-white);
}
body.fmipa-hero-atas:not(.fmipa-scrolled) .fmipa-nav-primary > ul > li > a:hover {
	color: var(--fmipa-white);
}
/* Garis bawah hover ikut putih — --fmipa-green-dark (#008050) di atas scrim
   hijau gelap nyaris tidak terbaca sebagai garis. */
body.fmipa-hero-atas:not(.fmipa-scrolled) .fmipa-nav-primary > ul > li > a::after {
	background: var(--fmipa-white);
}
body.fmipa-hero-atas:not(.fmipa-scrolled) .fmipa-nav-primary > ul > li > .fmipa-submenu-toggle:hover {
	background: rgba(255, 255, 255, 0.15);
}

/* Panel dropdown & panel menu ponsel punya latar putih sendiri, jadi isinya
   TIDAK boleh ikut diputihkan — pembatasan "> ul > li >" di atas sudah
   menjaga itu, aturan ini cuma jaring pengaman kalau nanti selektornya
   dilonggarkan. */
body.fmipa-hero-atas .fmipa-nav-primary .sub-menu a,
body.fmipa-hero-atas .fmipa-nav-primary.is-open a {
	color: var(--fmipa-black);
}

/* Saat panel menu ponsel terbuka, header wajib solid: panelnya menempel
   persis di bawah header, dan navbar transparan di atasnya membuat batas
   antara keduanya lenyap. */
body.fmipa-hero-atas:not(.fmipa-scrolled):has(.fmipa-nav-primary.is-open) .fmipa-site-header {
	background: var(--fmipa-white);
	border-bottom-color: var(--fmipa-gray-200);
	--fmipa-band-btn-outline: var(--fmipa-green-dark);
	/* Ikut dikembalikan ke putih, sepasang dengan baris di atasnya. Begitu
	   panel terbuka header jadi solid putih, jadi hover harus kembali ke
	   "isi hijau, label putih" seperti di halaman biasa. Kalau hanya token
	   pertama yang dikembalikan, labelnya tetap hijau tua warisan header
	   transparan — hijau tua di atas isi hijau tua, hilang lagi. */
	--fmipa-band-bg: var(--fmipa-white);
}
body.fmipa-hero-atas:not(.fmipa-scrolled):has(.fmipa-nav-primary.is-open) .fmipa-site-logo img {
	filter: none;
}
/* Tautan nav kembali gelap saat panel terbuka. Aturan ini WAJIB ada dan
   wajib lewat :has() yang sama — bukan cukup mengandalkan aturan
   ".fmipa-nav-primary.is-open a" di atas. Terbukti saat pengujian di 375px:
   selektor putih "…:not(.fmipa-scrolled) .fmipa-nav-primary > ul > li > a"
   berbobot (0,3,4), sedangkan jaring pengamannya cuma (0,3,2), jadi yang
   menang tetap putih — dan seluruh isi panel putih di atas latar putih,
   hilang sama sekali. Versi ini berbobot (0,5,4) sehingga benar-benar
   mengambil alih. */
body.fmipa-hero-atas:not(.fmipa-scrolled):has(.fmipa-nav-primary.is-open) .fmipa-nav-primary > ul > li > a,
body.fmipa-hero-atas:not(.fmipa-scrolled):has(.fmipa-nav-primary.is-open) .fmipa-nav-primary > ul > li > .fmipa-submenu-toggle {
	color: var(--fmipa-black);
}
body.fmipa-hero-atas:not(.fmipa-scrolled):has(.fmipa-nav-primary.is-open) .fmipa-nav-primary > ul > li > a::after {
	background: var(--fmipa-green-dark);
}

/* ==========================================================================
   Tombol WhatsApp mengambang ("Konsultasi") — pojok kanan bawah
   ========================================================================== */

/* z-index 60, satu tingkat di atas .fmipa-site-header (50). Header sticky
   akan menutupi tombol ini saat pengguna men-scroll ke posisi di mana
   keduanya beririsan kalau nilainya lebih rendah. */
/* Dock: SATU elemen fixed di pojok kanan-bawah, isinya kolom. Anggotanya
   (widget bahasa, tombol WhatsApp) tidak perlu tahu tinggi satu sama lain —
   `gap` yang mengurus jarak, dan `align-items:flex-end` menjaga tepi kanan
   tetap lurus meski lebarnya berbeda. Ini menggantikan dua elemen fixed yang
   dulu berebut koordinat yang sama. */
.fmipa-float-dock {
	position: fixed;
	z-index: 60;
	right: max(1rem, env(safe-area-inset-right));
	bottom: max(1rem, env(safe-area-inset-bottom));
	display: flex;
	flex-direction: column;
	align-items: flex-end;
	gap: 0.625rem;
	/* Dock hanya bingkai; klik harus tembus ke halaman di sela-sela anggotanya,
	   jadi anggotanya sendiri yang mengaktifkan kembali pointer-events. */
	pointer-events: none;
}
.fmipa-float-dock > * { pointer-events: auto; }

.fmipa-wa-float {
	display: inline-flex;
	align-items: center;
	gap: 0.5rem;
	padding: 0.7rem 1.1rem;
	/* Sasaran sentuh minimum 44px (WCAG 2.5.5). Dipatok eksplisit, bukan
	   diserahkan ke padding: di breakpoint ponsel padding-nya mengecil dan
	   tingginya terukur jatuh ke 41px. */
	min-height: 44px;
	box-sizing: border-box;
	border-radius: 999px;
	/* Sama persis dengan .fmipa-btn--whatsapp: #1DA851 (hijau merek
	   WhatsApp) cuma 3,1:1 untuk teks putih — gagal AA. #0F7A46 masih dalam
	   keluarga hijau yang sama dan lolos 5,39:1. */
	background: #0F7A46;
	color: var(--fmipa-white);
	font-family: inherit;
	font-weight: var(--fmipa-fw-bold);
	font-size: 0.95rem;
	line-height: 1.2;
	text-decoration: none;
	box-shadow: var(--fmipa-shadow-md, 0 4px 16px rgba(0, 0, 0, 0.18));
	transition: transform 0.2s var(--fmipa-ease), box-shadow 0.2s var(--fmipa-ease), background-color 0.2s var(--fmipa-ease);
}
.fmipa-wa-float:hover,
.fmipa-wa-float:focus-visible {
	background: #0C6B3A;
	color: var(--fmipa-white);
	transform: translateY(-2px);
}
.fmipa-wa-float:focus-visible {
	outline: 3px solid var(--fmipa-white);
	outline-offset: -6px;
	box-shadow: 0 0 0 3px #0C6B3A, var(--fmipa-shadow-md, 0 4px 16px rgba(0, 0, 0, 0.18));
}
.fmipa-wa-float:active { transform: translateY(0); }
.fmipa-wa-float__icon { flex: 0 0 auto; }

/* Ponsel: pil dipersempit, tapi labelnya TETAP terlihat. Menyembunyikannya
   akan membuat nama aksesibel tombol tidak lagi punya padanan visibel
   (WCAG 2.5.3) — pola yang sudah dihindari juga di ikon sosial footer. */
@media (max-width: 480px) {
	.fmipa-wa-float {
		padding: 0.6rem 0.9rem;
		font-size: 0.875rem;
		gap: 0.4rem;
	}
}

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

@media print {
	.fmipa-wa-float { display: none; }
	.fmipa-float-dock { display: none; }
}

/* ==========================================================================
   Pemilih bahasa (GTranslate) di dalam dock
   ==========================================================================

   Plugin ini milik fakultas, bukan milik kita, dan ia memasang widget
   mengambangnya sendiri lengkap dengan `position: fixed`. Yang ditulis di sini
   HANYA presentasi: posisinya dilepas supaya ia tunduk pada dock, lalu bentuknya
   disamakan dengan tombol Konsultasi — radius pil yang sama, bayangan yang sama,
   tinggi 44px yang sama (WCAG 2.5.5), huruf tema yang sama. Perilaku
   menerjemahkannya tidak disentuh sedikit pun.

   Selektor sengaja dikurung di dalam .fmipa-float-dock: kalau plugin dicopot,
   tidak ada satu pun aturan di bawah ini yang menggantung, dan kalau widgetnya
   gagal dipindahkan (mis. JS mati), ia tetap tampil apa adanya seperti bawaan
   plugin — rusak-aman, bukan hilang. */
.fmipa-float-dock .gtranslate_wrapper { position: static; }
/* Yang benar-benar melayang bukan .gt_float_switcher, melainkan pembungkusnya:
   satu <div> TANPA KELAS di dalam .gtranslate_wrapper yang dipasangi
   `position:fixed; bottom:20px` oleh plugin. Selama ia fixed, .gtranslate_wrapper
   menciut jadi 0x0 — kolom flex dock menganggapnya tidak ada, dan switcher-nya
   melayang sendiri menimpa tombol Konsultasi.
   Diselektor lewat anak-langsung karena div itu memang tidak punya nama; `inset`
   dinolkan sekalian supaya bottom/right warisannya ikut lepas. */
.fmipa-float-dock .gtranslate_wrapper > div {
	position: static !important;
	inset: auto !important;
}
.fmipa-float-dock .gt_float_switcher {
	/* relative, bukan static: ia jadi jangkar bagi panel daftar bahasa yang
	   absolut di bawah. Static membuat panel mengukur diri terhadap viewport
	   dan mendarat menimpa pil ini. */
	position: relative !important;
	right: auto !important;
	bottom: auto !important;
	left: auto !important;
	top: auto !important;
	box-shadow: var(--fmipa-shadow-md, 0 4px 16px rgba(0, 0, 0, 0.18)) !important;
	border-radius: 999px !important;
	font-family: inherit !important;
	font-size: 0.95rem !important;
	font-weight: var(--fmipa-fw-bold) !important;
	background: var(--fmipa-white) !important;
	color: var(--fmipa-black) !important;
	overflow: visible !important;
}
.fmipa-float-dock .gt_float_switcher .gt-selected,
.fmipa-float-dock .gt_float_switcher > .gt-current-lang {
	min-height: 44px;
	display: flex !important;
	align-items: center;
	gap: 0.45rem;
	padding: 0 1.1rem !important;
	border-radius: 999px !important;
	background: transparent !important;
	box-shadow: none !important;
}
/* Daftar bahasa dibuka KE ATAS: dock menempel di dasar layar, jadi panel yang
   membuka ke bawah akan terpotong tepi jendela.
   ABSOLUTE, bukan relative. Bawaan plugin memakai `position:relative` dengan
   `bottom:100%`, dan pada elemen relative persentase itu dihitung dari tinggi
   DIRINYA SENDIRI — panel setinggi 90px cuma naik 90px, mendarat persis menimpa
   pil "ID" dan tombol Konsultasi di bawahnya. Sebagai elemen absolut terhadap
   .gt_float_switcher, `bottom: calc(100% + 0.5rem)` berarti "satu tinggi pil di
   atas pil, plus sela" — yang memang dimaksud.
   z-index harus di atas .gt-selected (888 dari plugin), kalau tidak pil-nya
   menimpa panel yang baru saja dibuka. */
.fmipa-float-dock .gt_float_switcher .gt_options {
	position: absolute !important;
	right: 0 !important;
	left: auto !important;
	bottom: calc(100% + 0.5rem) !important;
	top: auto !important;
	margin: 0 !important;
	z-index: 999 !important;
	min-width: 100% !important;
	width: max-content !important;
	background: var(--fmipa-white) !important;
	border-radius: 0.75rem !important;
	box-shadow: var(--fmipa-shadow-md, 0 4px 16px rgba(0, 0, 0, 0.18)) !important;
	overflow: hidden !important;
}
.fmipa-float-dock .gt_float_switcher .gt_options a {
	font-family: inherit !important;
	font-size: 0.9rem !important;
	padding: 0.55rem 1.1rem !important;
}
.fmipa-float-dock .gt_float_switcher .gt_options a:hover {
	background: var(--fmipa-green-soft, #E8F5EE) !important;
	color: var(--fmipa-green-dark, #008050) !important;
}
@media (max-width: 480px) {
	.fmipa-float-dock .gt_float_switcher { font-size: 0.875rem !important; }
	.fmipa-float-dock .gt_float_switcher .gt-selected,
	.fmipa-float-dock .gt_float_switcher > .gt-current-lang { padding: 0 0.9rem !important; }
}
