/* ===========================================================================
   Halaman depan satuan kerja
   ---------------------------------------------------------------------------
   Rancangannya di docs/mockup-berita.html Bagian A3. Satu kendala menentukan
   seluruhnya, dan angkanya hasil pengukuran 13 Agustus 2026: 47 dari 69 situs
   OPD punya kurang dari 50 tulisan, 20 puskesmas rata-rata hanya 17, dan dua
   situs benar-benar kosong.

   Karena itu tulang punggung halaman ini BUKAN berita, melainkan identitas,
   kontak, dan layanan — tiga hal yang selalu ada. Berita menempel di atasnya
   sebagai bagian yang boleh kosong tanpa membuat halamannya terlihat gagal.

   Menumpang seluruh token portal.css; tidak ada warna baru.
   =========================================================================== */

/* --- Identitas ----------------------------------------------------------- */

.o-kepala {
    background: var(--latar-tinggi);
    border-bottom: 1px solid var(--garis);
    padding: 20px 0;
}
.o-kepala .bungkus { display: grid; gap: 14px; }

.o-atas { display: flex; gap: 15px; align-items: flex-start; }

/* Keping tempat logo duduk. Dipatok terang di KEDUA tema, mengikuti alasan
   yang sudah ditulis di portal.css: logo satuan kerja dibuat untuk latar
   putih, dan banyak yang bertinta gelap dengan latar tembus pandang — di atas
   panel gelap logo seperti itu akan lenyap. */
.o-lambang {
    width: 58px; height: 58px; flex: none;
    border-radius: 13px;
    background: var(--ikon-kartu);
    border: 1px solid var(--ikon-kartu-garis);
    display: grid; place-items: center;
    font-weight: 800; font-size: 17px;
    color: var(--ikon-kartu-teks);
    letter-spacing: -0.02em;
    overflow: hidden;
}
.o-lambang img { width: 100%; height: 100%; object-fit: contain; }

.o-nama { display: grid; gap: 6px; min-width: 0; }
.o-nama h1 {
    margin: 0;
    font-size: clamp(19px, 2.8vw, 25px);
    line-height: 1.25;
    letter-spacing: -0.012em;
    text-wrap: balance;
}
.o-baris { display: flex; flex-wrap: wrap; gap: 7px 12px; align-items: center; font-size: 12.5px; }
.o-jenjang {
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--teks-lembut);
    border: 1px solid var(--garis-tegas);
    border-radius: 999px;
    padding: 3px 10px;
}
.o-induk { color: var(--teks-lembut); }

.o-tugas { margin: 0; font-size: 14.5px; color: var(--teks-lembut); max-width: 68ch; }

.o-aksi { display: flex; gap: 9px; flex-wrap: wrap; }
.o-tombol {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    font-size: 13.5px;
    font-weight: 600;
    padding: 10px 16px;
    border-radius: 10px;
    text-decoration: none;
    border: 1px solid var(--utama-kuat);
    background: var(--utama-kuat);
    color: var(--teks-balik);
    min-height: 44px;
}
.o-tombol:hover { filter: brightness(1.08); }
.o-tombol.kedua {
    background: var(--latar-tinggi);
    color: var(--teks);
    border-color: var(--garis-tegas);
}
.o-tombol.kedua:hover { border-color: var(--utama); color: var(--utama-kuat); filter: none; }
.o-tombol svg { width: 15px; height: 15px; flex: none; }

/* --- Kontak -------------------------------------------------------------- */

/* Diletakkan tinggi di halaman, bukan di kaki: pada halaman satuan kerja
   pemerintah inilah yang paling sering dicari pengunjung. */
.o-fakta {
    display: grid;
    gap: 1px;
    background: var(--garis);
    border: 1px solid var(--garis);
    border-radius: var(--lengkung);
    overflow: hidden;
    margin: 0;
}
@media (min-width: 620px) { .o-fakta { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 940px) { .o-fakta { grid-template-columns: repeat(4, 1fr); } }
.o-fakta > div { background: var(--latar-tinggi); padding: 13px 15px; }
.o-fakta dt {
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.07em;
    text-transform: uppercase;
    color: var(--teks-lembut);
    margin: 0 0 4px;
}
.o-fakta dd { margin: 0; font-size: 13.5px; line-height: 1.5; }
.o-fakta dd a { color: var(--utama-kuat); }

.o-perbarui { font-size: 12px; color: var(--teks-lembut); margin: 10px 0 0; }

/* Kontak duduk di dalam .o-muka, jadi jarak ke kartu profil di atasnya
   miliknya sendiri — bukan lagi warisan padding .o-badan seperti dulu.

   position: relative WAJIB, dan bukan demi menggeser apa pun. Tirai adalah
   elemen berposisi absolut yang mendahuluinya di dalam DOM, dan dalam urutan
   pelukisan CSS elemen berposisi selalu jatuh DI ATAS isi blok biasa —
   sekalipun ia lebih dulu ditulis. Tanpa baris ini, tirai 82% menutupi kartu
   kontak beserta tulisannya: kartunya menghitam dan baris "Data satuan kerja
   diperbarui" yang bertinta putih justru terbaca kelabu gelap. Sudah terlihat
   langsung sebelum diperbaiki. .o-kepala dan .o-profil lolos hanya karena
   keduanya kebetulan sudah berposisi lebih dulu. */
.o-kontak { margin-top: 22px; position: relative; z-index: 2; }

/* --- Bagian -------------------------------------------------------------- */

.o-badan { padding: 26px 0 34px; }

/* Bagian pertama tidak lagi didahului kontak di dalam pembungkus yang sama,
   jadi jaraknya sudah diberi padding .o-badan di atas. Tanpa ini keduanya
   bertumpuk dan "Berita terbaru" terlempar 52px ke bawah. */
.o-badan > .bungkus > .o-bagian:first-child { margin-top: 0; }
.o-bagian { margin-top: 26px; }
.o-bagian-kepala {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
    margin-bottom: 12px;
}
.o-bagian-kepala h2 { margin: 0; font-size: 17px; letter-spacing: -0.005em; }
.o-jumlah {
    font-size: 12px;
    font-weight: 700;
    color: var(--teks-lembut);
    background: var(--latar-lembut);
    border-radius: 999px;
    padding: 2px 9px;
    font-variant-numeric: tabular-nums;
    margin-left: 6px;
}
.o-semua { font-size: 13px; color: var(--utama-kuat); font-weight: 600; }

/* --- Keadaan kosong ------------------------------------------------------ */

/* Dinyatakan terus terang, lalu diberi jalan lain. Bukan kerangka abu-abu,
   bukan ilustrasi, bukan "segera hadir". Ini keadaan mayoritas OPD, jadi ia
   dirancang lebih hati-hati daripada keadaan idealnya. */
.o-kosong {
    border: 1px dashed var(--garis-tegas);
    border-radius: var(--lengkung);
    background: var(--latar-lembut);
    padding: 22px 20px;
    display: grid;
    gap: 9px;
}
.o-kosong strong { font-size: 15px; }
.o-kosong p { margin: 0; font-size: 13.5px; color: var(--teks-lembut); max-width: 58ch; }
.o-kosong .o-aksi { padding-top: 4px; }

/* --- Penanda tahap berikutnya -------------------------------------------- */

.o-nanti {
    border: 1px solid var(--garis);
    border-left: 3px solid var(--garis-tegas);
    border-radius: 10px;
    background: var(--latar-tinggi);
    padding: 12px 15px;
    font-size: 13px;
    color: var(--teks-lembut);
    margin-top: 26px;
}
.o-nanti strong { color: var(--teks); }

/* --- Navigasi satuan kerja ----------------------------------------------- */

/* Tanpa JavaScript sama sekali: submenu memakai <details>, yang membuka dan
   menutup sendiri di seluruh peramban modern, termasuk dengan papan ketik. */
.o-nav {
    background: var(--latar-tinggi);
    border-bottom: 1px solid var(--garis);
}
/* Melipat ke baris berikutnya, TIDAK menggulir mendatar.

   overflow-x: auto menjadikan baris ini wadah gulir, dan wadah gulir memotong
   apa pun yang melayang keluar darinya — termasuk menu jatuh. Lebih halus
   lagi: menyetel satu sumbu saja membuat sumbu satunya ikut berubah dari
   visible menjadi auto, jadi pemotongan terjadi ke bawah walaupun yang diatur
   hanya arah mendatar. Diukur pada beranda dinkes: menu jatuh setinggi 280px
   berada seluruhnya di luar baris setinggi 49px — terpotong seluruhnya, bukan
   sebagian, sehingga terlihat seolah menunya tidak pernah terbuka.

   Melipat baris menyelesaikannya tanpa JavaScript, sesuai keputusan pada
   _navigasi.blade.php bahwa navigasi ini bekerja tanpa skrip sama sekali. */
.o-nav-gulir { display: flex; flex-wrap: wrap; gap: 2px; align-items: stretch; }

.o-nav-butir {
    flex: none;
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 12px 12px;
    font-size: 13.5px;
    font-weight: 600;
    color: var(--teks);
    text-decoration: none;
    border-bottom: 3px solid transparent;
    white-space: nowrap;
    min-height: 44px;
    cursor: pointer;
    list-style: none;
}
.o-nav-butir::-webkit-details-marker { display: none; }
.o-nav-butir:hover { color: var(--utama-kuat); }
.o-nav-butir[aria-current="page"] { color: var(--utama-kuat); border-bottom-color: var(--utama-kuat); }
.o-nav-panah { font-size: 9px; color: var(--teks-lembut); }

.o-nav-lipat { position: relative; flex: none; }
.o-nav-jatuh {
    position: absolute;
    z-index: 30;
    top: 100%;
    left: 0;
    min-width: 250px;
    background: var(--latar-tinggi);
    border: 1px solid var(--garis);
    border-radius: 0 0 11px 11px;
    box-shadow: var(--bayang-2);
    padding: 7px;
    display: grid;
    gap: 1px;
}
.o-nav-jatuh a {
    display: block;
    padding: 8px 10px;
    font-size: 13px;
    border-radius: 7px;
    color: var(--teks);
    text-decoration: none;
}
.o-nav-jatuh a:hover { background: var(--latar-lembut); color: var(--utama-kuat); }

/* Di layar sempit daftar lipat tidak melayang, melainkan mendorong isi ke
   bawah. Menu melayang di ponsel selalu berakhir terpotong tepi layar. */
@media (max-width: 640px) {
    .o-nav-jatuh { position: static; min-width: 0; box-shadow: none; border: 0; }

    /* Di sini menggulir mendatar aman: daftar lipatnya tidak lagi melayang,
       jadi tidak ada yang bisa terpotong wadah gulir. */
    .o-nav-gulir { flex-wrap: nowrap; overflow-x: auto; }
}

/* --- Kartu layanan & prosedur -------------------------------------------- */

.o-layanan { display: grid; gap: 10px; }
@media (min-width: 560px) { .o-layanan { grid-template-columns: 1fr 1fr; } }
@media (min-width: 880px) { .o-layanan { grid-template-columns: repeat(3, 1fr); } }
.o-kartu {
    border: 1px solid var(--garis);
    border-radius: 11px;
    background: var(--latar-tinggi);
    padding: 13px 14px;
    display: grid;
    gap: 5px;
    align-content: start;
    text-decoration: none;
    color: inherit;
}
.o-kartu:hover { border-color: var(--utama); }
.o-kartu b { font-size: 14px; }
.o-kartu span { font-size: 12.5px; color: var(--teks-lembut); }

.p-langkah { counter-reset: langkah; list-style: none; padding: 0; margin: 0 0 18px; }
.p-langkah li {
    counter-increment: langkah;
    position: relative;
    padding: 2px 0 2px 38px;
    margin-bottom: 11px;
    font-size: 15.5px;
    line-height: 1.7;
}
.p-langkah li::before {
    content: counter(langkah);
    position: absolute;
    left: 0; top: 2px;
    width: 26px; height: 26px;
    border-radius: 50%;
    background: var(--utama-kuat);
    color: var(--teks-balik);
    display: grid; place-items: center;
    font-size: 13px; font-weight: 700;
    font-variant-numeric: tabular-nums;
}

.p-pejabat { display: flex; gap: 16px; align-items: center; margin-bottom: 18px; }
.p-pejabat img { width: 96px; height: 120px; object-fit: cover; border-radius: 11px; flex: none; }
.p-nama { margin: 0; font-size: 18px; font-weight: 700; }
.p-jabatan { margin: 3px 0 0; font-size: 14px; color: var(--teks-lembut); }

.data-kip { width: 100%; border-collapse: collapse; font-size: 13.5px; background: var(--latar-tinggi); }
.data-kip th {
    text-align: left;
    font-size: 11.5px;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--teks-lembut);
    padding: 10px 12px;
    border-bottom: 1px solid var(--garis);
    background: var(--latar-lembut);
    white-space: nowrap;
}
.data-kip td { padding: 10px 12px; border-bottom: 1px solid var(--garis); vertical-align: top; }
.tabel-gulir { overflow-x: auto; border: 1px solid var(--garis); border-radius: 10px; }

/* --- Daftar dokumen ------------------------------------------------------ */

/* Tahun sebagai judul kelompok, bukan bagian nama dokumen. Dari medan `tahun`
   inilah pengelompokan dibangkitkan — dan itu yang menggantikan lima butir
   menu LKJ 2021 sampai LKJ 2025 dengan satu halaman. */
.d-tahun {
    font-size: 13px;
    font-weight: 700;
    letter-spacing: 0.05em;
    color: var(--teks-lembut);
    margin: 20px 0 8px;
    font-variant-numeric: tabular-nums;
}
.d-daftar { display: grid; gap: 8px; }
.d-butir {
    display: flex;
    align-items: center;
    gap: 12px;
    border: 1px solid var(--garis);
    border-radius: 10px;
    background: var(--latar-tinggi);
    padding: 12px 14px;
    text-decoration: none;
    color: inherit;
    min-height: 44px;
}
.d-butir:hover { border-color: var(--utama); }
.d-butir .jenis {
    flex: none;
    font-size: 10px;
    font-weight: 800;
    letter-spacing: 0.04em;
    color: var(--bahaya);
    border: 1px solid var(--bahaya);
    border-radius: 5px;
    padding: 3px 6px;
}
.d-butir .nm { flex: 1 1 auto; min-width: 0; font-size: 14px; font-weight: 600; }
.d-butir .ukuran {
    flex: none;
    font-size: 12.5px;
    color: var(--teks-lembut);
    font-variant-numeric: tabular-nums;
}

/* ===========================================================================
   Kepala halaman berlatar gambar
   ---------------------------------------------------------------------------
   Dua keadaan, dan keduanya harus utuh sendiri:

   .berfoto      admin sudah mengunggah gambar. Teksnya menjadi terang di atas
                 tirai gelap.
   .o-latar-N    belum ada gambar. Latar hias bertingkat, teksnya tetap gelap
                 seperti semula.

   Sebagian besar dari ~50 satuan kerja tidak akan pernah mengunggah gambar,
   jadi keadaan KEDUA-lah yang paling sering dilihat orang — bukan keadaan
   idealnya.
   =========================================================================== */

.o-kepala { position: relative; overflow: hidden; }

/* --- Ada gambarnya --------------------------------------------------------

   Latarnya dipikul .o-muka, pembungkus kepala DAN kartu profil — bukan kepala
   itu sendiri. Sebabnya sederhana: kartu profil bukan anak kepala melainkan
   saudaranya, dan sebuah elemen tidak dapat melatari saudaranya. Selama latar
   masih menempel di kepala, gambar selalu berhenti di tepi bawah kepala dan
   kartu hanya bisa menindihnya beberapa piksel.

   Dengan latar naik ke induk keduanya, gambar meluas melewati kepala dan
   kartunya duduk PENUH di atasnya. .o-kepala tetap punya position: relative
   dari aturan di atas, jadi ia dan kartunya sama-sama melukis di atas tirai
   yang mendahuluinya di dalam DOM.
   -------------------------------------------------------------------------- */

/* SENGAJA tanpa overflow: hidden, tidak seperti .o-kepala di atasnya. Kartu
   profil kini anak pembungkus ini, dan tepi bawah pembungkus berimpit dengan
   tepi bawah kartu pada keadaan tanpa foto — kliping apa pun di sini akan
   memotong bayangan kartunya. Tidak ada yang perlu dikliping: tirai dan hias
   sama-sama inset: 0, dan gambar latar sudah dibatasi kotaknya sendiri. */
.o-muka { position: relative; }

.o-muka.berfoto {
    background-image: var(--o-latar);
    background-size: cover;
    background-position: center;

    /* Warna dasar di bawah gambar. Terlihat hanya selama gambar belum termuat,
       dan itu justru saat paling menentukan: tanpa warna dasar, tirai gelap
       menutupi latar HALAMAN yang terang, dan teks putih di atasnya sempat tak
       terbaca sepersekian detik pada sambungan lambat. */
    background-color: var(--latar-lembut);
}

/* Gambar dipaku ke layar, bukan ke halaman: saat digulir, kepala dan kartu
   bergerak naik sementara gambarnya tinggal di tempat.

   DIBATASI pada tetikus dan layar lebar, dan itu bukan kehati-hatian yang
   berlebihan. background-attachment: fixed tidak pernah bekerja pada Safari
   iOS — di sana ia diam-diam diperlakukan sebagai scroll, dan pada peramban
   seluler lain yang menurutinya, setiap piksel gulir memaksa lapisan latar
   digambar ulang. Yang didapat bukan efek, melainkan gulir tersendat pada
   perangkat yang paling tidak sanggup menanggungnya.

   Perhatikan juga akibat sampingnya: dengan fixed, `cover` mengukur diri pada
   VIEWPORT, bukan pada kotak ini. Itu memang yang diinginkan di sini — gambar
   tetap seukuran layar sementara mukanya memanjang menurut panjang sambutan. */
@media (min-width: 700px) and (hover: hover) {
    .o-muka.berfoto { background-attachment: fixed; }
}

/* Kepala kehilangan latar dan garis bawahnya sendiri begitu ada foto: keduanya
   milik keadaan tanpa foto, dan di sini keduanya hanya akan menutupi gambar
   yang baru saja dipasang di belakangnya. */
.o-muka.berfoto .o-kepala {
    background: none;
    border-bottom: 0;
    padding: 34px 0 30px;
}

/* Ruang bagi kartu yang duduk di bawahnya. 54px — jarak yang sama dengan yang
   dulu dihasilkan tindihan 76-22, supaya irama dari tombol terbawah ke tepi
   kartu tidak berubah hanya karena cara melatarinya berganti. */
.o-muka.berfoto.berprofil .o-kepala { padding-bottom: 54px; }

/* Kaki muka. Gambar berhenti TEGAS di sini, tanpa larut lebih dulu.

   Sebelumnya kakinya 52px dan 44px di antaranya dipakai melarutkan gambar ke
   warna halaman. Larutan itu dilepas: pada muka yang sudah memuat kepala,
   kartu profil, dan kartu kontak, ia tidak lagi terbaca sebagai peralihan
   melainkan sebagai bidang kabur di kaki halaman — dan pinggirnya yang tidak
   pernah benar-benar selesai justru membuat susunannya terlihat tidak rapi.
   Garis lurus mengakhirinya lebih bersih.

   Dua hal ikut sederhana karena itu. Kaki tidak perlu lagi lebih panjang
   daripada daerah larut, jadi cukup 24px; dan baris "Data satuan kerja
   diperbarui" yang bertinta putih tidak lagi punya cara menghilang, sebab
   tidak ada lagi bagian tirai yang berakhir di warna terang. */
.o-muka.berfoto.berprofil { padding-bottom: 24px; }

@media (max-width: 699px) {
    .o-muka.berfoto.berprofil .o-kepala { padding-bottom: 22px; }
    .o-muka.berfoto.berprofil { padding-bottom: 20px; }
}

/* Tepi bawah gambar kini garis tegas, dan garis itu perlu diberi jarak sendiri
   sebelum "Berita terbaru" — 10px yang dulu cukup karena didahului larutan
   kini membuat judulnya seperti menempel pada tepi gambar. */
.o-muka.berfoto.berprofil + .o-badan { padding-top: 28px; }

/* Tirai gelap di atas fotonya.

   Wajib ada, bukan hiasan. Foto kegiatan mana pun memuat daerah terang dan
   gelap sekaligus, sehingga teks yang kontrasnya cukup di satu sudut menjadi
   tak terbaca di sudut lain. Tirai menyeragamkan dasarnya lebih dulu, sehingga
   kontrasnya dapat dijamin tanpa bergantung pada foto yang diunggah siapa pun.

   Lebih gelap di kaki daripada di kepala: nama satuan kerja dan tombolnya ada
   di bawah, dan di situlah teks paling banyak.

   Kepekatannya dihitung dari keadaan TERBURUK, bukan dari foto contoh: foto
   putih bersih. Pada 62% di kepala, dasarnya menjadi rgb(101 109 117) dan
   teks putih di atasnya berkontras 5,3:1 — lulus WCAG AA untuk teks biasa
   (4,5:1). Pada 58% angkanya 4,6:1, lulus tetapi tanpa sisa sama sekali,
   sehingga satu foto lebih terang saja sudah menjatuhkannya. Inilah gunanya
   tirai: jaminannya tidak bergantung pada foto yang diunggah siapa pun. */
.o-latar-tirai {
    position: absolute;
    inset: 0;
    background: linear-gradient(180deg, rgb(6 20 32 / 62%), rgb(6 20 32 / 82%));
}

/* Begitu kartu profil ikut duduk di atas gambar, tirai harus menempuh jarak
   yang jauh lebih panjang — dan perhentiannya tidak boleh lagi ditulis dalam
   persen. Persen di sini berarti "sekian bagian dari tinggi muka", dan tinggi
   muka ikut berubah menurut panjang sambutan yang ditulis admin: pada sambutan
   panjang, 100% jatuh jauh di bawah kepala, dan kepekatan yang menjamin
   kontras teks kepala tidak pernah tercapai di tempat teks itu berada.
   Karena itu perhentiannya dipatok piksel dari ATAS untuk kepala, dan piksel
   dari BAWAH untuk kakinya; hanya bagian tengah — di belakang kartu, yang
   tidak memuat teks apa pun — yang dibiarkan memanjang bebas.

   200px kira-kira setinggi kepala berisi lambang, nama, dan tombol. Sampai di
   situ kepekatannya sudah 82%, sama seperti sebelumnya. Di atasnya tidak
   pernah lebih terang dari 62%, sehingga jaminan 5,3:1 yang dihitung di atas
   tetap berlaku apa adanya. Sesudahnya ia RATA sampai ke tepi bawah: tidak ada
   perhentian keempat yang melarutkannya ke warna halaman, dan justru karena
   itu tidak ada bagian tirai yang dapat menelan tulisan putih di kakinya. */
.o-muka.berprofil .o-latar-tirai {
    background: linear-gradient(180deg,
        rgb(6 20 32 / 62%) 0,
        rgb(6 20 32 / 82%) 200px);
}

@media (max-width: 699px) {
    .o-muka.berprofil .o-latar-tirai {
        background: linear-gradient(180deg,
            rgb(6 20 32 / 62%) 0,
            rgb(6 20 32 / 82%) 170px);
    }
}

.o-muka.berfoto .o-kepala .bungkus { position: relative; }

.o-muka.berfoto .o-kepala,
.o-muka.berfoto .o-kepala h1 { color: var(--teks-balik); }
.o-muka.berfoto .o-induk,
.o-muka.berfoto .o-tugas { color: rgb(255 255 255 / 88%); }
.o-muka.berfoto .o-jenjang {
    background: rgb(255 255 255 / 18%);
    color: var(--teks-balik);
    border-color: rgb(255 255 255 / 28%);
}

/* Tombol kedua di atas foto perlu tepi sendiri; tepi abu-abunya lenyap. */
.o-muka.berfoto .o-tombol.kedua {
    color: var(--teks-balik);
    border-color: rgb(255 255 255 / 55%);
    background: rgb(255 255 255 / 12%);
}
.o-muka.berfoto .o-tombol.kedua:hover { background: rgb(255 255 255 / 22%); }

/* --- Belum ada gambarnya --------------------------------------------------
   Latar hias, bukan foto. Sengaja tipis: ia menandai halaman satuan kerja
   tanpa berpura-pura menjadi foto yang belum ada, dan tidak menyentuh warna
   teks sehingga kontras bakunya tetap berlaku. */
.o-kepala[class*="o-latar-"]::before {
    content: "";
    position: absolute;
    inset: 0;

    /* Pola titik di atas dua gradien. Gradien saja terbaca sebagai warna latar
       yang kebetulan tidak rata — bukan sebagai latar yang dirancang. Polanya
       yang membuatnya terbaca sebagai hiasan, dan ia berupa SVG sebaris:
       nol permintaan jaringan, nol berkas, dan tidak ada gambar pihak ketiga
       yang membocorkan alamat IP pengunjung ke luar. */
    background:
        url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='34' height='34'%3E%3Ccircle cx='17' cy='17' r='1.6' fill='%230d2c48' fill-opacity='0.13'/%3E%3C/svg%3E"),
        radial-gradient(60% 130% at var(--o-x-satu, 88%) var(--o-y-satu, -14%),
            var(--o-hias) 0%, transparent 64%),
        radial-gradient(46% 108% at var(--o-x-dua, 2%) var(--o-y-dua, 120%),
            var(--o-hias-dua) 0%, transparent 60%);
}
.o-kepala[class*="o-latar-"] { padding: 30px 0 26px; }
.o-kepala[class*="o-latar-"] .bungkus { position: relative; }

/* Keenam ragam hanya menggeser LETAK gradiennya, tidak lagi warnanya.

   Warna kini milik tema yang dipilih admin. Sebelumnya warna ditentukan di sini
   menurut slug, dan akibatnya terlihat begitu tema ada: admin memilih marun lalu
   kepalanya berhias ungu. Yang dipilih admin harus menang; ragam per-satuan-kerja
   cukup datang dari letaknya, sehingga dua OPD bertema sama tetap tidak kembar. */
.o-latar-1 { --o-x-satu: 88%; --o-y-satu: -14%; --o-x-dua:  2%; --o-y-dua: 120%; }
.o-latar-2 { --o-x-satu: 12%; --o-y-satu: -18%; --o-x-dua: 92%; --o-y-dua: 112%; }
.o-latar-3 { --o-x-satu: 62%; --o-y-satu: -22%; --o-x-dua: 10%; --o-y-dua:  96%; }
.o-latar-4 { --o-x-satu: 98%; --o-y-satu:  40%; --o-x-dua: 24%; --o-y-dua: -20%; }
.o-latar-5 { --o-x-satu:  4%; --o-y-satu:  34%; --o-x-dua: 76%; --o-y-dua: 118%; }
.o-latar-6 { --o-x-satu: 44%; --o-y-satu: 128%; --o-x-dua: 86%; --o-y-dua: -16%; }

/* --- Petak empat kolom pada halaman depan satuan kerja --------------------
   Halaman ini tidak punya bilah sisi, jadi tiga kartu sebaris menjadi 449px
   masing-masing dan tampak jauh lebih besar daripada kartu di halaman berita
   yang 343px. Empat kolom mengembalikannya ke ukuran yang sebanding.

   Tangganya dimulai dari dua, bukan langsung empat: empat kartu berdampingan
   pada 900px membuat masing-masing selebar 200px, dan judul berita OPD
   umumnya panjang. */
@media (min-width: 620px)  { .o-petak-4 { grid-template-columns: 1fr 1fr; } }
@media (min-width: 1100px) { .o-petak-4 { grid-template-columns: repeat(4, 1fr); } }

/* --- Galeri satuan kerja --------------------------------------------------
   Butir pertama dibuat lebih besar dan menempati dua lajur. Alasannya bukan
   selera: admin menaruh yang terpenting di urutan pertama — foto kepala dinas
   atau baner kegiatan — dan petak yang seragam menyembunyikan urutan itu
   sehingga yang terpenting terlihat setara dengan poster biasa.

   Rasio dipatok supaya delapan gambar dengan perbandingan berbeda tidak
   menghasilkan petak bergerigi. Yang tidak sesuai rasio dipangkas di tengah,
   bukan diregangkan: meregangkan foto orang mengubah wajahnya.
   =========================================================================== */

.o-galeri { display: grid; gap: 12px; grid-template-columns: 1fr; }

@media (min-width: 560px)  { .o-galeri { grid-template-columns: 1fr 1fr; } }
@media (min-width: 900px)  { .o-galeri { grid-template-columns: repeat(4, 1fr); } }

.o-galeri-butir {
    margin: 0;
    border: 1px solid var(--garis-lembut);
    border-radius: 11px;
    background: var(--latar-tinggi);
    overflow: hidden;
    display: grid;

    /* Gambar mengambil sisa ruang, keterangan menempel di dasar. Kebalikan
       dari "auto 1fr": dengan urutan itu, kartu yang tingginya disamakan
       tetangganya menyisakan ruang kosong DI BAWAH keterangan - lubang yang
       sama seperti pada kartu berita, dan sama tidak sengajanya. */
    grid-template-rows: 1fr auto;
}
.o-galeri-butir img {
    display: block;
    width: 100%;
    aspect-ratio: 4 / 3;

    /* height:100% mengalahkan aspect-ratio saat barisnya lebih tinggi - itulah
       yang dimaui: rasio menentukan tinggi MINIMUM kartu, dan bila butir utama
       di sebelahnya lebih tinggi, gambar kecil ikut memanjang alih-alih
       meninggalkan lubang. */
    height: 100%;
    min-height: 0;
    object-fit: cover;
    background: var(--latar-lembut);
}
.o-galeri-butir figcaption {
    padding: 9px 11px 10px;
    font-size: 12.5px;
    line-height: 1.4;
    color: var(--teks-lembut);
}

/* Butir pertama: dua lajur, dan gambarnya lebih lapang. */
@media (min-width: 560px) {
    .o-galeri-butir.utama { grid-column: span 2; }
    .o-galeri-butir.utama img { aspect-ratio: 16 / 10; }
    .o-galeri-butir.utama figcaption { font-size: 13.5px; color: var(--teks); font-weight: 600; }
}

/* ===========================================================================
   Halaman profil satuan kerja
   ---------------------------------------------------------------------------
   Dua kolom: isi profil di kiri, identitas ringkas di bilah sisi kanan.

   Identitas sengaja DIULANG dari beranda. Pengunjung yang mendarat di sini dari
   mesin pencari tidak melewati beranda lebih dulu, dan alamat serta jam layanan
   adalah yang paling sering dicari — memaksanya berpindah halaman dulu untuk
   menemukan itu adalah kegagalan, bukan kerapian.
   =========================================================================== */

.p-kepala {
    background: var(--latar-tinggi);
    border-bottom: 1px solid var(--garis);
    padding: 18px 0 20px;
}
.p-jejak { font-size: 12.5px; color: var(--teks-lembut); margin-bottom: 7px; }
.p-jejak a { color: inherit; }
.p-kepala h1 {
    margin: 0;
    font-size: clamp(20px, 3vw, 27px);
    line-height: 1.25;
    letter-spacing: -0.012em;
    text-wrap: balance;
}

.p-badan { padding: 22px 0 34px; }
.p-tata { display: grid; gap: 24px; align-items: start; }
@media (min-width: 940px) { .p-tata { grid-template-columns: minmax(0, 1fr) 304px; } }

.p-utama { display: grid; gap: 22px; align-content: start; }

/* --- Pimpinan -------------------------------------------------------------
   Foto di kiri pada layar lebar, di atas pada layar sempit. Lebarnya dipatok
   supaya foto potret dan foto lanskap menghasilkan blok yang sama tingginya —
   foto pejabat datang dalam kedua bentuk, dan tanpa rasio tetap halamannya
   berubah tinggi hanya karena siapa yang mengunggah. */
.p-pimpinan {
    display: grid;
    gap: 16px;
    border: 1px solid var(--garis);
    border-radius: var(--lengkung);
    background: var(--latar-tinggi);
    padding: 16px;
}
@media (min-width: 620px) { .p-pimpinan { grid-template-columns: 208px minmax(0, 1fr); } }

.p-foto {
    border-radius: 11px;
    overflow: hidden;
    background: var(--latar-lembut);
    aspect-ratio: 3 / 4;
    display: grid;
    place-items: center;
}
.p-foto img { width: 100%; height: 100%; object-fit: cover; display: block; }
.p-foto span {
    font-size: 46px;
    font-weight: 800;
    color: var(--teks-lembut);
    letter-spacing: -0.03em;
}

.p-pimpinan-isi { display: grid; gap: 8px; align-content: start; }
.p-jabatan {
    margin: 0;
    font-size: 11.5px;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--utama-kuat);
}
.p-pimpinan-isi h2 {
    margin: 0;
    font-size: clamp(17px, 2.2vw, 21px);
    line-height: 1.3;
    letter-spacing: -0.01em;
}

/* Sambutan berupa prosa, jadi lebarnya dibatasi baris — bukan dibiarkan
   selebar kolomnya. Alasannya sama dengan .a-teks pada berita. */
.p-sambutan { max-width: 62ch; }
.p-sambutan p { margin: 0 0 11px; font-size: 14.5px; line-height: 1.7; color: var(--teks-lembut); }
.p-sambutan p:last-child { margin-bottom: 0; }
.p-sambutan strong { color: var(--teks); }

/* --- Bagian biasa --------------------------------------------------------- */

.p-bagian {
    border: 1px solid var(--garis);
    border-radius: var(--lengkung);
    background: var(--latar-tinggi);
    padding: 16px 18px 18px;
}
.p-bagian h2 {
    margin: 0 0 10px;
    font-size: 11.5px;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--teks-lembut);
}
.p-prosa { margin: 0; font-size: 15px; line-height: 1.7; max-width: 68ch; }

.p-tautan { margin: 0; padding: 0; list-style: none; display: grid; gap: 1px; }
.p-tautan a {
    display: block;
    padding: 9px 11px;
    border-radius: 8px;
    font-size: 14px;
    font-weight: 600;
    color: inherit;
    text-decoration: none;
}
.p-tautan a:hover { background: var(--latar-lembut); color: var(--utama-kuat); }
.p-tautan a::after { content: " \203A"; color: var(--teks-lembut); }

.p-kosong {
    border: 1px dashed var(--garis-tegas);
    border-radius: var(--lengkung);
    background: var(--latar-tinggi);
    padding: 22px 20px;
    text-align: center;
}
.p-kosong strong { display: block; margin-bottom: 6px; }
.p-kosong p { margin: 0 0 6px; font-size: 14px; color: var(--teks-lembut); }

/* --- Bilah sisi identitas ------------------------------------------------- */

.p-kartu {
    border: 1px solid var(--garis);
    border-radius: var(--lengkung);
    background: var(--latar-tinggi);
    padding: 16px;
    display: grid;
    gap: 10px;
}
@media (min-width: 940px) { .p-sisi { position: sticky; top: 14px; } }

/* Keping logo dipatok terang di kedua tema, mengikuti alasan yang sudah
   ditulis pada .o-lambang: logo satuan kerja dibuat untuk latar putih. */
.p-lambang {
    width: 52px; height: 52px;
    border-radius: 12px;
    background: var(--ikon-kartu);
    border: 1px solid var(--ikon-kartu-garis);
    display: grid; place-items: center;
    font-weight: 800; font-size: 16px;
    color: var(--ikon-kartu-teks);
}
.p-lambang img { width: 100%; height: 100%; object-fit: contain; }

.p-nama { margin: 0; font-size: 14px; font-weight: 700; line-height: 1.35; }
.p-jenjang {
    margin: 0;
    font-size: 11px;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: var(--teks-lembut);
}

.p-data { margin: 4px 0 0; display: grid; gap: 10px; }
.p-data dt {
    font-size: 10.5px;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--teks-lembut);
    margin-bottom: 2px;
}
.p-data dd { margin: 0; font-size: 13.5px; line-height: 1.5; }

/* ===========================================================================
   Balok profil di puncak halaman depan
   ---------------------------------------------------------------------------
   Kartunya menindih tepi bawah kepala. Bukan hiasan: tanpa itu, kepala berfoto
   dan kartu putih di bawahnya terbaca sebagai dua halaman yang ditempel, dan
   mata berhenti di garis batasnya alih-alih terus membaca.

   Tindihan hanya diberikan pada layar >=700px. Di ponsel kartunya selebar layar
   dan foto pimpinan sudah menumpuk di atas teks, sehingga tindihan hanya
   menyisakan ruang kosong di atas kartu tanpa menyambungkan apa pun.
   =========================================================================== */

.o-profil { background: var(--latar); }

/* Di atas foto, kartunya tidak lagi menindih apa pun: gambar sudah meluas ke
   belakangnya, jadi tidak ada batas yang perlu disamarkan. Latar sepia bagian
   ini pun harus dilepas — warna halaman yang legap di sini justru akan
   menutupi gambar yang baru saja dipasang di belakangnya. */
.o-muka.berfoto .o-profil {
    background: none;
    margin-top: 0;
    position: relative;
    z-index: 2;
}

@media (min-width: 700px) {
    /* Tindihan 22px, bukan 34px. Yang lebih dalam membuat kartu terasa menempel
       pada tombol di atasnya alih-alih menyambung ke kepalanya: tindihan cukup
       untuk menyatukan dua bidang, sisanya hanya memakan jarak baca. */
    .o-profil { margin-top: -22px; position: relative; z-index: 2; }

    /* Ruang bawah kepala HANYA ditambah ketika kartu profilnya benar-benar ada.
       Tanpa syarat itu, satuan kerja yang profilnya belum diisi mendapat kepala
       menjulang dengan ruang kosong di bawah tombolnya — menyisakan tempat bagi
       kartu yang tidak pernah muncul. Diukur: 76 - 22 memberi jarak 54px dari
       tombol terbawah ke tepi kartu.

       Tinggal keadaan TANPA foto yang memakai tindihan ini. Yang berfoto tidak
       lagi menindih apa pun sejak latarnya meluas ke belakang kartu; ruang
       bawahnya diatur .o-muka.berfoto.berprofil di blok kepala.

       Ragamnya tetap disebut namanya. Menulis .o-kepala saja tidak berlaku:
       .o-kepala[class*="o-latar-"] bernilai dua pemilih, sehingga ia
       mengalahkan .o-kepala berapa pun urutannya. */
    .o-kepala.berprofil[class*="o-latar-"] { padding-bottom: 76px; }
}

.o-profil-kartu {
    border: 1px solid var(--garis);
    border-radius: var(--lengkung);
    background: var(--latar-tinggi);
    box-shadow: var(--bayang-1);
    padding: 16px;
    display: grid;
    gap: 16px;
}

/* ===========================================================================
   Kartu kaca — HANYA di atas foto
   ---------------------------------------------------------------------------
   Bukan warna baru: keduanya var(--latar-tinggi) tiap tema, hanya diberi alfa.
   Ditulis sebagai rgb() harfiah dan bukan color-mix() supaya nilainya dapat
   dibaca langsung saat menghitung kontras di bawah.

   KACANYA GELAP, dan itulah yang memungkinkannya setembus ini. Alasannya
   bukan selera melainkan aritmetika, dan sama persis dengan alasan iOS memakai
   kaca gelap begitu panelnya duduk di atas media:

   Di belakang kartu tirai sudah memekat 82%, jadi apa pun foto yang diunggah,
   yang mengintip lewat kaca selalu bidang GELAP — susunannya terkurung di
   #0d141c sampai #33393f. Kaca putih di atas dasar segelap itu ikut menggelap
   menjadi kelabu, dan tinta gelap di atasnya kehilangan kontras secepat
   ketembusannya ditambah. Dihitung untuk ketujuh tema:

       kaca putih   teks gelap   aksen tema (--utama-kuat)
       76%          8,63         4,60   lulus, tetapi mentok
       68%          7,01         3,74   gagal
       60%          5,60         2,99   gagal jauh

   Artinya kaca putih tidak dapat dibuat lebih tembus tanpa mengorbankan
   keterbacaan. Kaca GELAP membalik seluruh hitungan itu: dasar yang gelap
   justru menjadi kawan, dan tulisan putih di atasnya bertahan 13:1 bahkan
   pada 34% — dua kali lebih tembus daripada kaca putih yang paling tembus
   sekalipun, dengan sisa kontras tiga kali lipat.

       kaca gelap   putih   putih 88%   putih 72%
       34%          13,3    10,7        7,7
       38%          13,7    10,9        7,9

   Diambil 36%. Yang membatasi sekarang bukan lagi kontras, melainkan mata:
   di bawah itu bentuk foto di belakang mulai bersaing dengan barisan teksnya.

   Kartu ini karena itu SATU-SATUNYA bidang di portal yang tidak mengikuti tema
   terang/gelap pengguna. Ia tidak duduk di atas halaman, ia duduk di atas foto,
   dan yang menentukan warnanya adalah apa yang ada di belakangnya.
   =========================================================================== */

/* Nilainya TIDAK bercabang menurut tema terang/gelap. Lihat alasannya di
   kepala blok: yang menentukan warna kartu ini adalah tirai di belakangnya,
   dan tirai itu sama gelapnya di kedua tema. */
:root {
    --kaca-isi   : rgb(10 22 32 / 36%);

    /* Bibir kaca. Kaca sungguhan menangkap cahaya di tepinya, dan tanpa itu
       bidang setembus ini terbaca sebagai lubang, bukan sebagai benda. */
    --kaca-tepi  : rgb(255 255 255 / 26%);
    --kaca-kilap : rgb(255 255 255 / 14%);

    /* Tinta di atas kaca. Putih penuh hanya untuk yang memang harus paling
       dulu terbaca; sisanya diredupkan supaya kartunya punya tingkatan, bukan
       satu dinding putih. Yang paling redup pun masih 7,7:1. */
    --kaca-tinta        : rgb(255 255 255 / 94%);
    --kaca-tinta-lembut : rgb(255 255 255 / 76%);
}

.o-muka.berfoto .o-profil-kartu {
    background:
        linear-gradient(180deg, var(--kaca-kilap), transparent 46%),
        var(--kaca-isi);
    border-color: var(--kaca-tepi);
    border-radius: 20px;
    color: var(--kaca-tinta);

    /* Bibir dalam di sisi atas, bukan hanya tepi 1px. Inilah yang membuat
       lengkungnya terbaca sebagai ketebalan kaca, bukan sebagai garis. */
    box-shadow:
        inset 0 1px 0 rgb(255 255 255 / 30%),
        0 10px 30px rgb(3 10 16 / 34%);

    -webkit-backdrop-filter: blur(14px) saturate(180%);
    backdrop-filter: blur(14px) saturate(180%);
}

/* Seluruh tinta di dalamnya ikut dibalik. Yang gelap di sini bukan lagi
   kartunya melainkan latarnya, dan warna tema tidak dipakai sama sekali:
   --utama-kuat setiap tema adalah warna GELAP untuk latar terang, dan di atas
   kaca gelap ia justru yang paling dulu hilang. */
.o-muka.berfoto .o-pimpinan-nama,
.o-muka.berfoto .o-sambutan strong { color: #fff; }
.o-muka.berfoto .o-sambutan p { color: var(--kaca-tinta); }
.o-muka.berfoto .o-pimpinan-jabatan,
.o-muka.berfoto .o-tugas-blok h3 { color: var(--kaca-tinta-lembut); }
.o-muka.berfoto .o-tugas-blok p { color: var(--kaca-tinta); }
.o-muka.berfoto .o-tugas-blok { border-top-color: rgb(255 255 255 / 18%); }

/* Tautan kehilangan warna sebagai penanda, jadi garis bawahnya WAJIB: tanpa
   itu ia hanya teks putih di antara teks putih. */
.o-muka.berfoto .o-profil-lanjut a {
    color: #fff;
    text-decoration: underline;
    text-underline-offset: 3px;
}

/* Keping foto pimpinan ikut menjadi kaca. Legap di sini akan terbaca sebagai
   tambalan putih di tengah bidang tembus. Monogramnya 44px — teks besar,
   ambangnya 3:1 — dan pada putih 70% ia 7,6:1. */
.o-muka.berfoto .o-pimpinan-foto { background: rgb(255 255 255 / 10%); }
.o-muka.berfoto .o-pimpinan-foto span { color: rgb(255 255 255 / 70%); }

/* --- Kartu kontak, kaca yang sama ---------------------------------------
   Alamat, telepon, surel, dan jam layanan kini ikut duduk di atas gambar.
   Membiarkannya legap putih di sana berarti dua kartu bersebelahan dengan dua
   bahasa berbeda; lebih buruk lagi, kartu putih pekat tepat di bawah kaca
   membuat kacanya terbaca sebagai kartu yang gagal termuat.

   Angkanya menumpang hitungan yang sama persis: kepekatan dan tinta diambil
   dari token yang sama, jadi tidak ada rasio kedua yang perlu dijaga. */
.o-muka.berfoto .o-fakta {
    background: rgb(255 255 255 / 14%);   /* garis pemisah antarsel */
    border-color: var(--kaca-tepi);
    border-radius: 20px;
    box-shadow:
        inset 0 1px 0 rgb(255 255 255 / 24%),
        0 10px 30px rgb(3 10 16 / 30%);
    -webkit-backdrop-filter: blur(14px) saturate(180%);
    backdrop-filter: blur(14px) saturate(180%);
}
.o-muka.berfoto .o-fakta > div { background: var(--kaca-isi); }
.o-muka.berfoto .o-fakta dt { color: var(--kaca-tinta-lembut); }
.o-muka.berfoto .o-fakta dd { color: var(--kaca-tinta); }

/* Sama seperti tautan profil: tanpa warna sebagai penanda, garis bawahnya yang
   menjadikannya tautan. Nomor telepon dan surel justru yang paling sering
   diketuk di ponsel, jadi ia tidak boleh menyamar sebagai teks biasa. */
.o-muka.berfoto .o-fakta dd a {
    color: #fff;
    text-decoration: underline;
    text-underline-offset: 3px;
}

/* Baris ini satu-satunya yang duduk LANGSUNG di atas foto, tanpa kaca di
   bawahnya — dan karena itu tintanya TIDAK memakai --kaca-tinta-lembut.
   Kepekatan 76% dihitung untuk teks yang berdiri di atas kaca, tempat kacanya
   sendiri sudah meratakan dasarnya; di atas foto telanjang, dasarnya masih
   beragam meskipun tirai sudah menggelapkannya, dan huruf 12px pada kepekatan
   itu terbaca redup walau angkanya lulus. 88% mengembalikannya. */
.o-muka.berfoto .o-perbarui { color: rgb(255 255 255 / 88%); }

/* Tanpa backdrop-filter, kartu setembus ini hanya menampilkan foto tajam di
   balik tulisan — bukan kaca, melainkan tulisan di atas foto. Peramban yang
   tidak mendukungnya mendapat panel gelap legap: tintanya sudah terlanjur
   putih, jadi jaring pengamannya harus gelap, BUKAN --latar-tinggi. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
    .o-muka.berfoto .o-profil-kartu,
    .o-muka.berfoto .o-fakta > div { background: rgb(11 22 31 / 94%); }
}

/* Kontras tinggi mematikan kacanya, sejalan dengan .sorot-kilau dan .tokoh di
   portal.css: efek yang bekerja dengan menipiskan beda antara isi dan latarnya
   adalah persis yang diminta hilang oleh mode ini. Panelnya diratakan menjadi
   gelap legap — bukan dikembalikan ke putih, sebab tinta di dalamnya putih dan
   panel putih akan menghapusnya sama sekali. */
:root[data-kontras="tinggi"] .o-muka.berfoto .o-profil-kartu {
    background: #0b1620;
    border-color: rgb(255 255 255 / 85%);
    box-shadow: none;
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
    animation: none;
}
:root[data-kontras="tinggi"] .o-muka.berfoto .o-pimpinan-foto { background: rgb(255 255 255 / 16%); }

:root[data-kontras="tinggi"] .o-muka.berfoto .o-fakta {
    background: rgb(255 255 255 / 85%);   /* garis pemisah, bukan isi selnya */
    border-color: rgb(255 255 255 / 85%);
    box-shadow: none;
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
}
:root[data-kontras="tinggi"] .o-muka.berfoto .o-fakta > div { background: #0b1620; }

/* Mengambang. Naik perlahan, lalu turun melewati titik diamnya sedikit sebelum
   menetap — lewatan 1,5px itulah yang membuatnya terbaca sebagai benda yang
   mendarat, bukan sebagai kotak yang digeser naik-turun.

   6px, dan 7 detik. Yang bergerak di sini adalah empat paragraf teks yang
   sedang dibaca orang, bukan hiasan: pada simpangan lebih besar atau irama
   lebih cepat, mata terus mengoreksi baris yang sedang diikutinya.

   prefers-reduced-motion tidak perlu ditulis di sini. Aturan menyeluruh di
   portal.css sudah memaksa animation-iteration-count menjadi 1 dan durasinya
   0,01ms, sehingga kartunya langsung diam di posisi akhir — yang kebetulan
   sama dengan posisi awalnya. */
@keyframes o-kartu-apung {
    0%   { transform: translateY(0); }
    50%  { transform: translateY(-6px); }
    78%  { transform: translateY(1.5px); }
    100% { transform: translateY(0); }
}

.o-muka.berfoto .o-profil-kartu {
    animation: o-kartu-apung 7s ease-in-out infinite;
}

/* Foto pimpinan di kiri, sambutan dan tugas fungsi di kanan. Lebar lajur foto
   dipatok supaya foto potret dan lanskap menghasilkan blok yang sama tingginya:
   foto pejabat datang dalam kedua bentuk, dan tanpa rasio tetap halamannya
   berubah tinggi hanya karena siapa yang mengunggahnya. */
@media (min-width: 700px) {
    .o-profil-kartu { grid-template-columns: 188px minmax(0, 1fr); gap: 20px; padding: 18px; }
}

.o-pimpinan { display: grid; gap: 10px; align-content: start; }

.o-pimpinan-foto {
    border-radius: 12px;
    overflow: hidden;
    background: var(--latar-lembut);
    aspect-ratio: 3 / 4;
    display: grid;
    place-items: center;
}
.o-pimpinan-foto img { width: 100%; height: 100%; object-fit: cover; display: block; }
.o-pimpinan-foto span {
    font-size: 44px;
    font-weight: 800;
    letter-spacing: -0.03em;
    color: var(--teks-lembut);
}

/* Di ponsel foto tidak setinggi 3:4 — foto sepertiga layar penuh mendorong
   seluruh isinya keluar layar sebelum satu kata terbaca. */
@media (max-width: 699px) {
    .o-pimpinan { grid-template-columns: 96px minmax(0, 1fr); gap: 13px; align-items: center; }
    .o-pimpinan-foto { aspect-ratio: 1 / 1; border-radius: 50%; }
    .o-pimpinan-foto span { font-size: 30px; }
}

.o-pimpinan-jabatan {
    margin: 0 0 3px;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.07em;
    text-transform: uppercase;
    color: var(--utama-kuat);
}
.o-pimpinan-nama {
    margin: 0;
    font-size: 15px;
    font-weight: 700;
    line-height: 1.35;
    letter-spacing: -0.01em;
}

.o-profil-isi { display: grid; gap: 15px; align-content: start; }

/* Sambutan berupa prosa, jadi lebarnya dibatasi baris — bukan dibiarkan selebar
   kolomnya. Alasannya sama dengan .a-teks pada halaman berita. */
.o-sambutan { max-width: 64ch; }
.o-sambutan p { margin: 0 0 11px; font-size: 14.5px; line-height: 1.7; }
.o-sambutan p:first-child { font-size: 15.5px; }
.o-sambutan p:last-child { margin-bottom: 0; }
.o-sambutan strong { font-weight: 700; }

/* Tugas dan fungsi dipisahkan garis, bukan kartu tersendiri: ia bagian dari
   profil yang sama, dan kartu di dalam kartu menambah tepi tanpa menambah arti. */
.o-tugas-blok { border-top: 1px solid var(--garis); padding-top: 13px; }
.o-tugas-blok h3 {
    margin: 0 0 6px;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--teks-lembut);
}
.o-tugas-blok p { margin: 0; font-size: 14.5px; line-height: 1.7; max-width: 68ch; }

.o-profil-lanjut { margin: 0; }
.o-profil-lanjut a { font-size: 13.5px; font-weight: 600; }

/* Kepala tanpa tindihan perlu jarak bawah sendiri supaya tombolnya tidak
   berhimpitan dengan kartu profil di ponsel. */
@media (max-width: 699px) {
    .o-profil { margin-top: 18px; }
}

/* Tingkat ketiga di dalam menu jatuh. Berlekuk di daftar yang sama, bukan
   melayang lagi ke samping: menu melayang bertingkat menuntut arah tetikus yang
   tepat untuk tetap terbuka, dan pada layar sentuh ia praktis tidak dapat
   dibuka sama sekali. */
.o-nav-cucu {
    display: block;
    margin: 0 0 2px 10px;
    padding-left: 10px;
    border-left: 2px solid var(--garis);
}
.o-nav-cucu a {
    display: block;
    padding: 6px 10px;
    font-size: 12.5px;
    color: var(--teks-lembut);
    text-decoration: none;
    border-radius: 6px;
}
.o-nav-cucu a:hover { background: var(--latar-lembut); color: var(--utama-kuat); }

/* ===========================================================================
   Bentuk halaman: data statistik
   ---------------------------------------------------------------------------
   Angkanya dibuat besar dan labelnya kecil, bukan sebaliknya. Yang dicari
   pengunjung halaman statistik adalah angkanya; label yang lebih menonjol
   daripada angkanya memaksa mata mencari dua kali.
   =========================================================================== */

.s-tahun {
    margin: 0 0 14px;
    font-size: 11.5px;
    font-weight: 700;
    letter-spacing: 0.07em;
    text-transform: uppercase;
    color: var(--utama-kuat);
}

.s-petak { display: grid; gap: 12px; grid-template-columns: 1fr; }
@media (min-width: 480px) { .s-petak { grid-template-columns: 1fr 1fr; } }
@media (min-width: 820px) { .s-petak { grid-template-columns: repeat(3, 1fr); } }

.s-kartu {
    border: 1px solid var(--garis);
    border-radius: var(--lengkung);
    background: var(--latar-tinggi);
    padding: 15px 16px 16px;
    display: grid;
    gap: 4px;
}
.s-nilai {
    font-size: clamp(24px, 4vw, 31px);
    font-weight: 800;
    line-height: 1.05;
    letter-spacing: -0.02em;
    color: var(--utama-kuat);
    font-variant-numeric: tabular-nums;
}
.s-nilai small {
    font-size: 13px;
    font-weight: 600;
    letter-spacing: 0;
    color: var(--teks-lembut);
    margin-left: 3px;
}
.s-label { font-size: 13.5px; line-height: 1.4; color: var(--teks-lembut); }

.s-sumber {
    margin: 16px 0 0;
    font-size: 12.5px;
    color: var(--teks-lembut);
    padding-top: 12px;
    border-top: 1px solid var(--garis);
}

/* ===========================================================================
   Bentuk halaman: daftar layanan
   =========================================================================== */

.l-daftar { display: grid; gap: 12px; }
@media (min-width: 700px) { .l-daftar { grid-template-columns: 1fr 1fr; } }

.l-kartu {
    border: 1px solid var(--garis);
    border-radius: var(--lengkung);
    background: var(--latar-tinggi);
    padding: 15px 16px 16px;
    display: grid;
    gap: 7px;
    align-content: start;
}
.l-kartu h2 { margin: 0; font-size: 16px; line-height: 1.3; letter-spacing: -0.01em; }
.l-kartu p { margin: 0; font-size: 14px; line-height: 1.6; color: var(--teks-lembut); }

/* Tautannya didorong ke dasar kartu supaya deretan kartu yang tingginya
   disamakan tidak menyisakan lubang di bawah tautannya - cacat yang sama
   seperti pada kartu berita sebelum diperbaiki. */
.l-tautan {
    margin-top: auto;
    padding-top: 4px;
    font-size: 13.5px;
    font-weight: 600;
    display: inline-flex;
    gap: 5px;
    align-items: center;
}
