/* ===========================================================================
   Portal Pemerintah Kabupaten Hulu Sungai Selatan
   ---------------------------------------------------------------------------
   Ditulis tangan, tanpa kerangka kerja dan tanpa langkah build.
   Warna merek dipertahankan dari desain lama: biru #1B558A, aksen #1ACC8D.

   Susunan berkas:
     1. Token warna & tema
     2. Dasar dan utilitas
     3. Kepala
     4. Sorot, pencarian & pita komitmen
     5. Bilah kategori
     6. Bagian & pintasan
     7. Petak kartu
     8. Daftar teks berkolom
     9. Register inovasi
    10. Kaki
    11. Gerak
    12. Penyesuaian gerak & cetak
   =========================================================================== */

/* --- 1. Token warna & tema ------------------------------------------------ */

/* Mode terang adalah dasarnya: setiap warna didefinisikan di sini lebih dulu,
   blok tema di bawah hanya menimpa nilainya. */
:root {
    --biru-900 : #0d2c48;
    --biru-700 : #14406b;
    --biru-600 : #1b558a;
    --biru-500 : #2a71b4;
    --biru-300 : #7fb2e0;
    --hijau    : #12b47c;

    --latar        : #f4f7fb;
    --latar-tinggi : #ffffff;
    --latar-lembut : #e9eff7;
    --garis        : #d5e0ed;
    --garis-tegas  : #b9cadd;

    /* Tepi kartu. Lebih lembut daripada --garis, yang dipakai untuk garis
       PEMISAH — dan pemisah memang boleh terlihat, sedangkan tepi kartu
       tugasnya hanya menutup bidangnya. Bayangannya yang membentuk kartu;
       tepinya cukup menahan bidang putih agar tidak lumer ke latar. */
    --garis-lembut : #e4ecf5;

    --teks        : #17293a;
    --teks-lembut : #536b81;
    --teks-balik  : #ffffff;

    --utama       : var(--biru-600);
    --utama-kuat  : var(--biru-700);
    --sorot-awal  : var(--biru-700);
    /* Sengaja lebih gelap daripada --biru-500 (#2a71b4), meski hanya inilah
       tempat ia dipakai. Dengan #2a71b4, sub judul putih 94% hanya mencapai
       4.71:1 — lulus tipis — dan begitu kilau menyapu di atasnya (putih 14.4%
       efektif) latarnya memutih dan rasionya jatuh ke 3.63:1, di bawah AA.
       Nilai ini memberi 6.98:1 tanpa kilau dan 4.95:1 saat kilau lewat. */
    --sorot-akhir : #1f5688;

    --fokus  : #f0a500;
    --bahaya : #a3341f;
    --bahaya-latar : #fdecea;

    /* Batas antara area biru dan latar halaman. --sorot-kaki menuakan warna
       biru di kakinya, --sorot-bayang jatuh ke sisi putih di bawah lengkung
       sehingga panel biru terbaca sedikit terangkat. */
    --sorot-kaki   : rgb(6 20 32 / 26%);
    --sorot-bayang : rgb(6 20 32 / 34%);

    /* Warna penanda jenis tautan pada register inovasi. Dipilih agar
       kontrasnya lolos 4.5:1 di atas latar kartu masing-masing tema. */
    --lencana-sosial   : #8d3f79;
    --lencana-dokumen  : #8a5e10;
    --lencana-aplikasi : #1f6f4a;

    /* Keping kecil tempat ikon register duduk. Warnanya dipatok terang di
       kedua tema: 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. */
    --ikon-kartu       : #ffffff;
    --ikon-kartu-garis : var(--garis);
    --ikon-kartu-teks  : var(--biru-600);

    --bayang-1 : 0 1px 2px rgb(13 44 72 / 6%), 0 2px 8px rgb(13 44 72 / 6%);
    --bayang-2 : 0 4px 10px rgb(13 44 72 / 10%), 0 12px 28px rgb(13 44 72 / 12%);

    --lengkung   : 14px;

    /* Lama peralihan. Satu tempat untuk seluruh tanggapan sentuhan tetikus,
       supaya kartu di beranda, kartu berita, kartu galeri satuan kerja, dan
       judul di dalamnya menanggapi dengan irama yang sama.

       Sebelum token ini ada, angkanya tersebar dan tidak satu pun sama: kartu
       berita 180ms, berita utama 200ms, tombol dan pil 140ms, kotak cari 150ms.
       Bedanya kecil satu per satu, tetapi pengunjung yang berpindah dari
       beranda ke halaman berita merasakannya sebagai halaman yang "beratnya"
       berbeda — tanpa pernah bisa menunjuk apa yang berbeda.

       Angkanya diambil dari kartu beranda, sebab ke sanalah yang lain
       diseragamkan. Perlu dicari dua kali: .kartu punya DUA deklarasi
       transition — satu di bagian kartu, satu lagi di bagian "Tanggapan
       tetikus" — dan yang belakangan itulah yang selama ini berlaku. Yang di
       depan sudah dilepas; nilai yang ditulis di sini nilai yang benar-benar
       terpakai, yaitu 200ms.

       Tiga nilai, masing-masing dengan tugas yang jelas berbeda — bukan tiga
       rasa dari hal yang sama. Lengkung transform-nya --lentur, sama dengan
       kartu beranda; warna dan bayangan tetap `ease`, juga sama. */
    --gerak-cepat  : 150ms;   /* kendali kecil: tombol, pil, kotak isian   */
    --gerak-kartu  : 200ms;   /* kartu dan judul di dalamnya               */
    --gerak-lambat : 320ms;   /* gambar membesar di dalam bingkainya       */

    /* Tinggi kepala yang menempel: min-height .kepala-isi (68px) ditambah
       garis bawahnya. Dijadikan token karena angkanya dibutuhkan setiap elemen
       lain yang ikut menempel — bilah kategori beranda, dan bilah sisi halaman
       berita — dan salinan angka yang tersebar akan melenceng satu demi satu
       begitu tinggi kepalanya berubah sekali saja.

       Aman sebagai angka tetap meski --skala-teks memperbesar seluruh huruf:
       lambang di kepala 44px tetap, dan tulisan mereknya pada skala terbesar
       (1,35) mencapai sekitar 50px — masih di dalam min-height 68px, jadi
       kepalanya tidak pernah tumbuh melewatinya. */
    --tinggi-kepala : 69px;
    /* Dinaikkan dari 1180px agar seluruh halaman selebar halaman berita.
       1180 cocok untuk daftar tautan, tetapi kartu berisi gambar berdesakan di
       dalamnya sementara ratusan piksel di kiri dan kanan menganggur.

       Berhenti di 1440, bukan selebar layar: mata harus melintas dari kartu
       paling kiri ke paling kanan, dan petak selebar layar penuh membuat
       perjalanan itu melelahkan alih-alih efisien.

       Prosa TIDAK ikut melebar - .a-teks dibatasi --ukur-prosa (600px) dan
       ditengahkan di dalam kolomnya. Batas ini mengatur lebar halaman, bukan
       lebar baris bacaan. */
    --lebar-maks : 1440px;

    /* Plus Jakarta Sans, disinggahkan sendiri di assets/font/ — lihat
       huruf.css untuk alasan huruf ini dipilih dan mengapa ia TIDAK boleh
       ditarik dari fonts.googleapis.com.

       Tumpukan huruf sistem tetap berdiri di belakangnya, dan itu bukan
       kebiasaan menyalin: selama berkas hurufnya belum tiba — atau tidak
       pernah tiba, di jaringan yang memutus unduhan besar — seluruh portal
       tetap terbaca dengan huruf bawaan perangkatnya. Yang berganti hanya
       rupanya, tidak satu pun tata letaknya, sebab tidak ada satu ukuran pun
       di berkas ini yang dihitung dari lebar huruf. */
    --huruf : "Plus Jakarta Sans", system-ui, -apple-system, "Segoe UI", Roboto,
              "Helvetica Neue", Arial, "Noto Sans", sans-serif;
}

/* Tema baku portal adalah terang. Mode gelap tidak lagi ikut setelan
   sistem pengunjung — ia hanya menyala kalau dipilih sendiri lewat tombol
   tema, yang ditangani :root[data-tema="gelap"] di bawah. */

/* Pilihan sadar pengguna selalu menang, ke arah mana pun. */
:root[data-tema="gelap"] {
    --latar        : #0a1410;
    --latar-tinggi : #121e28;
    --latar-lembut : #18262f;
    --garis        : #24363f;
    --garis-tegas  : #354b57;
    --garis-lembut : #1d2d35;

    --teks        : #e6eef5;
    --teks-lembut : #9db0c0;

    --utama       : var(--biru-300);
    --utama-kuat  : #a8cbec;
    --sorot-awal  : #0d2c48;
    --sorot-akhir : #14406b;

    --bahaya       : #ff9d8a;
    --bahaya-latar : #3a1a14;

    /* Latar gelap membuat bayangan hitam nyaris tak terlihat;
       versinya dipekatkan supaya batasnya tetap terbaca. */
    --sorot-kaki   : rgb(4 12 18 / 52%);
    --sorot-bayang : rgb(0 0 0 / 62%);

    --lencana-sosial   : #e8a6d6;
    --lencana-dokumen  : #e2b75f;
    --lencana-aplikasi : #6fd6a5;

    --ikon-kartu       : #e7eef6;
    --ikon-kartu-garis : #33495a;

    --bayang-1 : 0 1px 2px rgb(0 0 0 / 40%), 0 2px 8px rgb(0 0 0 / 30%);
    --bayang-2 : 0 4px 10px rgb(0 0 0 / 45%), 0 12px 28px rgb(0 0 0 / 40%);
}


/* --- 2. Dasar dan utilitas ------------------------------------------------ */

*, *::before, *::after { box-sizing: border-box; }

/* Seluruh ukuran huruf bertumpu pada nilai ini. Panel aksesibilitas mengubah
   --skala-teks, dan karena hampir semua font-size di berkas ini memakai rem,
   satu perubahan di sini ikut membesarkan seluruh halaman. Lihat bagian 13. */
html {
    -webkit-text-size-adjust: 100%;
    font-size: calc(16px * var(--skala-teks, 1));
}

body {
    margin      : 0;
    background  : var(--latar);
    color       : var(--teks);
    font-family : var(--huruf);
    /* 1rem, bukan 16px: nilai tetap di sini akan memutus penskalaan bagi
       setiap elemen yang mewarisi ukuran huruf dari body. */
    font-size   : 1rem;
    line-height : 1.6;
    /* Halaman tidak pernah menggulir mendatar, seberapa pun panjang judulnya. */
    overflow-x  : hidden;

    /* Menyaring ke kategori kecil membuat isi halaman lebih pendek daripada
       layar. Tanpa ini kaki halaman menggantung di tengah dengan ruang
       kosong di bawahnya. */
    display       : flex;
    flex-direction: column;
    min-height    : 100vh;
    min-height    : 100dvh;
}

body > main { flex: 1 0 auto; }

h1, h2, h3 { line-height: 1.25; margin: 0; text-wrap: balance; }

img { max-width: 100%; height: auto; }

svg {
    fill           : none;
    stroke         : currentColor;
    stroke-width   : 2;
    stroke-linecap : round;
    stroke-linejoin: round;
}

.bungkus {
    width       : 100%;
    max-width   : var(--lebar-maks);
    margin-inline: auto;
    padding-inline: clamp(16px, 4vw, 32px);
}

/* Terlihat oleh pembaca layar, tersembunyi secara visual. */
.sr-only {
    position: absolute;
    width: 1px; height: 1px;
    padding: 0; margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
}

/* Cincin fokus tunggal dipakai konsisten di seluruh halaman. */
:where(a, button, input, [tabindex]):focus-visible {
    outline        : 3px solid var(--fokus);
    outline-offset : 3px;
    border-radius  : 6px;
}

/* Tautan lewati: tersembunyi sampai pengguna keyboard menekan Tab. */
.lewati {
    position   : absolute;
    inset-inline-start: 12px;
    inset-block-start : -100px;
    z-index    : 100;
    padding    : 12px 20px;
    background : var(--utama-kuat);
    color      : #fff;
    border-radius: 0 0 10px 10px;
    font-weight: 600;
    text-decoration: none;
    transition : inset-block-start 150ms ease;
}
.lewati:focus { inset-block-start: 0; }


/* --- 3. Kepala ------------------------------------------------------------ */

.kepala {
    position   : sticky;
    top        : 0;
    z-index    : 40;
    background : color-mix(in srgb, var(--latar-tinggi) 88%, transparent);
    backdrop-filter: blur(10px);
    border-bottom  : 1px solid var(--garis);
}

.kepala-isi {
    display        : flex;
    align-items    : center;
    justify-content: space-between;
    gap            : 16px;
    min-height     : 68px;
}

.merek {
    display        : flex;
    align-items    : center;
    gap            : 12px;
    color          : inherit;
    text-decoration: none;
}

.merek img { width: 44px; height: 44px; object-fit: contain; flex: none; }

.merek-teks { display: flex; flex-direction: column; line-height: 1.3; }
/* rem, bukan px, supaya nama daerah di kepala halaman ikut membesar bersama
   pengaturan ukuran teks. */
.merek-teks strong { font-size: 0.94rem; letter-spacing: -0.01em; }
.merek-teks span   { font-size: 0.78rem; color: var(--teks-lembut); }

/* Kedua tombol kepala dikelompokkan supaya .kepala-isi tetap punya dua anak.
   Tanpa pembungkus ini, space-between menyebar ketiganya dan tombol tema
   berhenti di tengah bilah. */
.kepala-aksi {
    display    : flex;
    align-items: center;
    gap        : 8px;
    flex       : none;
}

/*
   Pintu masuk pengelola. Sengaja setenang tombol tema — bukan tombol utama:
   yang datang ke portal ini hampir seluruhnya warga, dan tombol mencolok
   bertuliskan "Masuk" mengundang orang mencoba masuk ke tempat yang memang
   bukan untuknya.

   Warnanya diambil dari peubah tema yang sama, jadi ia ikut terang, gelap,
   maupun kontras tinggi tanpa satu pun aturan tambahan.
*/
.tombol-masuk {
    display        : inline-flex;
    align-items    : center;
    gap            : 7px;
    height         : 42px;
    padding        : 0 14px;
    flex           : none;
    border         : 1px solid var(--garis);
    border-radius  : 10px;
    background     : var(--latar-tinggi);
    color          : var(--teks);
    font-size      : 0.86rem;
    font-weight    : 600;
    text-decoration: none;
    white-space    : nowrap;
    transition     : background 150ms ease, border-color 150ms ease;
}
.tombol-masuk:hover { background: var(--latar-lembut); border-color: var(--garis-tegas); }
.tombol-masuk svg {
    width : 18px;
    height: 18px;
    flex  : none;
    fill  : none;
    stroke: var(--utama);
    stroke-width: 1.9;
    stroke-linecap: round;
    stroke-linejoin: round;
}

/*
   Pintasan layanan pegawai: surel, penyimpanan berkas, AI. Hanya ikon.

   Warnanya berbeda per layanan dan itu bukan hiasan: tombol tanpa tulisan
   dibedakan dari bentuk DAN warna sekaligus. Tiga kotak abu berjajar menuntut
   orang memelototi gambarnya satu per satu setiap kali.

   Nilainya ditulis tetap, bukan diambil dari peubah tema, karena warna sebuah
   layanan tidak berubah hanya karena portalnya sedang gelap. Ketiganya dipilih
   di rentang tengah supaya tetap terbaca di atas latar terang maupun gelap.
*/
.tombol-alat {
    display        : grid;
    place-items    : center;
    width          : 42px;
    height         : 42px;
    flex           : none;
    border         : 1px solid var(--garis);
    border-radius  : 10px;
    background     : var(--latar-tinggi);
    transition     : background 150ms ease, border-color 150ms ease;
}
.tombol-alat:hover { background: var(--latar-lembut); border-color: var(--garis-tegas); }
.tombol-alat svg {
    width : 20px;
    height: 20px;
    fill  : none;
    stroke: var(--warna-alat);
    stroke-width: 1.8;
    stroke-linecap: round;
    stroke-linejoin: round;
}
.tombol-alat.surel       { --warna-alat: #2563eb; }
.tombol-alat.awan        { --warna-alat: #0891b2; }
.tombol-alat.kecerdasan  { --warna-alat: #7c3aed; }

/* Bintang AI diisi penuh: bentuknya terlalu tipis untuk terbaca sebagai
   percikan bila hanya digariskan. */
.tombol-alat.kecerdasan svg { fill: var(--warna-alat); stroke-width: 1.2; }

/* Kontras tinggi meniadakan warna layanan: di mode itu yang diutamakan
   keterbacaan, bukan pengenalan cepat. */
:root[data-kontras="tinggi"] .tombol-alat svg { stroke: currentColor; }
:root[data-kontras="tinggi"] .tombol-alat.kecerdasan svg { fill: currentColor; }
:root[data-kontras="tinggi"] .tombol-alat { color: var(--teks); }

/* Di layar sempit tinggal ikonnya. Dengan lima tombol di kanan (surel, awan,
   AI, masuk, tema), kepala halaman pada ponsel 360px tidak lagi menyisakan
   ruang untuk nama kabupaten sama sekali — bahkan terpotong berelipsis pun
   ia masih mendesak tombol-tombol itu.

   Tulisannya karena itu disembunyikan SECARA VISUAL saja (teknik .sr-only),
   bukan display:none: logo tanpa nama di sampingnya tetap harus terbaca
   sebagai "Kabupaten Hulu Sungai Selatan" bagi pembaca layar, sebab alt pada
   logonya sendiri sengaja kosong. */
@media (max-width: 560px) {
    .tombol-masuk { padding: 0; width: 42px; justify-content: center; }
    .tombol-masuk span { display: none; }

    .kepala-aksi { gap: 6px; }
    .tombol-masuk, .tombol-alat, .tombol-tema { width: 38px; height: 38px; }
    .tombol-alat svg, .tombol-tema svg { width: 18px; height: 18px; }

    .merek-teks {
        position : absolute;
        width    : 1px;
        height   : 1px;
        padding  : 0;
        margin   : -1px;
        overflow : hidden;
        clip-path: inset(50%);
        white-space: nowrap;
    }
}

.tombol-tema {
    display        : grid;
    place-items    : center;
    width          : 42px;
    height         : 42px;
    flex           : none;
    border         : 1px solid var(--garis);
    border-radius  : 10px;
    background     : var(--latar-tinggi);
    color          : var(--teks);
    cursor         : pointer;
    transition     : background 150ms ease, border-color 150ms ease;
}
.tombol-tema:hover { background: var(--latar-lembut); border-color: var(--garis-tegas); }
.tombol-tema svg   { width: 20px; height: 20px; grid-area: 1 / 1; }

/* Hanya satu ikon yang tampak, mengikuti tema yang sedang aktif. */
.ikon-gelap { display: none; }
:root[data-tema="gelap"] .ikon-terang { display: none; }
:root[data-tema="gelap"] .ikon-gelap  { display: block; }
:root[data-tema="terang"] .ikon-terang { display: block; }
:root[data-tema="terang"] .ikon-gelap  { display: none; }


/* --- 4. Sorot, pencarian & pita komitmen ---------------------------------- */

.sorot {
    position   : relative;
    /* Bantalan bawah tidak boleh kurang dari tinggi lengkung (44px), kalau
       tidak teks bantuan yang berwarna putih jatuh di atas lengkung putih
       dan lenyap — terlihat di layar sempit. */
    padding    : clamp(40px, 7vw, 76px) 0 clamp(56px, 6vw, 64px);
    background : linear-gradient(135deg, var(--sorot-awal) 0%, var(--sorot-akhir) 100%);
    color      : #fff;
    text-align : center;
    isolation  : isolate;
    /* Kilau menyapu ke kanan sampai ke luar panel dan membuat SELURUH halaman
       bisa digulir mendatar (2185px pada viewport 1732px). Sengaja 'clip'
       pada sumbu x saja, bukan 'hidden': overflow-y tetap visible sehingga
       lengkung .sorot::after yang menjorok 1px ke bawah tidak ikut terpotong
       dan garis rambut putih di sambungannya tidak muncul kembali. */
    overflow-x : clip;
}

/* Gradasi di kaki area biru: warnanya menua perlahan sepanjang 130px
   terakhir, sehingga perpindahan ke latar halaman tidak terbaca sebagai
   garis potong yang mendadak.

   Diletakkan di lapisan paling bawah (z-index -2) supaya hanya menggelapkan
   birunya — foto Bupati dan Wakil Bupati di lapisan -1 tetap bersih. */
.sorot::before {
    content     : "";
    position    : absolute;
    inset-inline: 0;
    bottom      : 0;
    height      : 130px;
    z-index     : -2;
    background  : linear-gradient(to bottom, transparent, var(--sorot-kaki));
    pointer-events: none;
}

/* Lengkung lembut di kaki sorot, pengganti SVG gelombang lama.
   Sengaja dikurung di dalam lebar sorot (inset-inline: 0): versi yang
   melebar ke luar tepi membuat dokumen menggulir mendatar di ponsel.

   Bayangan inset menempel di bibir atas lengkung dan jatuh ke sisi putih,
   mengikuti lengkungnya. Inilah yang membuat panel biru terbaca mengambang
   sedikit di atas halaman, bukan sekadar bersambung dengannya. */
.sorot::after {
    content    : "";
    position   : absolute;
    inset-inline: 0;
    bottom     : -1px;
    height     : 44px;
    background : var(--latar);
    border-radius: 50% 50% 0 0 / 100% 100% 0 0;
    box-shadow : inset 0 13px 16px -11px var(--sorot-bayang);
    z-index    : -1;
}

/* Kilau yang sama dengan pil register inovasi, dipinjam untuk panel biru:
   seberkas cahaya lebar menyapu pelan dari kiri ke kanan, lalu diam lama.

   Lapisannya sama dengan foto (z-index -1), tetapi ia tergambar lebih dulu
   karena berada paling awal di markup — jadi cahaya menyapu latar birunya,
   bukan wajah Bupati dan Wakil Bupati. Lengkung putih di kaki (.sorot::after)
   juga tergambar setelahnya, sehingga kilau tidak tumpah ke halaman. */
.sorot-kilau {
    position   : absolute;
    inset-block: 0;
    inset-inline-start: 0;
    width      : 34%;
    z-index    : -1;
    /* Kepekatannya dibatasi: keyframes kilau memuncak di opacity 0.45, jadi
       puncak nyatanya 14.4% putih (0.32 x 0.45).
       Angka itu saja TIDAK cukup menjaga kontras. Diukur ulang: dengan ujung
       gradien yang lama (#2a71b4), sub judul putih 94% jatuh ke 3.63:1 saat
       tersapu kilau — gagal AA meski hanya sekejap, dan WCAG tidak mengenal
       pengecualian untuk keadaan sesaat. Yang menyelesaikannya adalah
       --sorot-akhir yang digelapkan; lihat catatan pada token itu. */
    background : linear-gradient(90deg, transparent, rgb(255 255 255 / 32%), transparent);
    pointer-events: none;
    animation  : kilau 11s 1.2s infinite ease-out;
}

/* Foto Bupati dan Wakil Bupati mengapit judul, seolah berdiri menempel pada
   tepi bawah area biru. Berkasnya sudah dipotong sampai pinggang oleh
   tools/siapkan-foto.py, jadi di sini tinggal ditempatkan.

   Disembunyikan secara baku dan baru muncul di layar lebar. Ambang 1280px
   dipilih setelah diukur: judul "Kabupaten Hulu Sungai Selatan" pada ukuran
   terbesarnya selebar ~750px, dan di bawah 1280px sisa ruang di kiri-kanan
   tidak cukup menampung foto tanpa berhimpitan dengan judul. */
.tokoh { display: none; }

/* Jarak foto dari tepi layar. Bukan nilai tetap: makin lebar layar, makin
   banyak ruang bebas di samping judul, dan foto ikut bergeser ke tengah.
   Pengurang 70px adalah jarak aman yang disisakan terhadap judul terpanjang
   ("Kabupaten Hulu Sungai Selatan" pada ukuran font terbesarnya). */
.sorot { --tokoh-tepi: clamp(8px, calc((100vw - 1180px) / 2 - 70px), 220px); }

@media (min-width: 1280px) {
    .tokoh {
        display : block;
        position: absolute;
        bottom  : 0;
        /* Negatif supaya berada di atas gradien biru tetapi di belakang
           judul dan kotak pencarian. .sorot sudah punya isolation: isolate,
           jadi foto tidak pernah menembus ke belakang seluruh halaman. */
        z-index : -1;
        height  : clamp(290px, 20vw + 48px, 440px);
        /* Tinggi di atas bisa melebihi panel birunya sendiri — pada layar
           1920px foto setinggi 432px sedangkan panel hanya 406px, sehingga
           26px teratas (bagian peci) menyembul ke area kepala yang sticky
           dan tampak terpotong garis navbar. Pagar ini menahannya, dengan
           12px sisa supaya kepala tidak menyentuh tepi panel. */
        max-height: calc(100% - 12px);
        width   : auto;
        /* Murni hiasan: jangan sampai menghalangi klik atau seleksi teks. */
        pointer-events: none;
        user-select   : none;
    }

    /* Seragam putih bertemu lengkung putih di kaki area biru, sehingga
       tepinya lebur. drop-shadow mengikuti siluet transparan foto —
       berbeda dari box-shadow yang hanya membayangi kotak pembungkusnya. */
    .tokoh img {
        display: block;
        height : 100%;
        width  : auto;
        filter : drop-shadow(0 6px 16px rgb(6 20 32 / 38%));
    }

    .tokoh-kiri  { inset-inline-start: var(--tokoh-tepi); }
    .tokoh-kanan { inset-inline-end  : var(--tokoh-tepi); }
}

/* Judul sorot disusun bertingkat, bukan dua baris tebal sama besar: penanda
   resmi berhuruf kapital berjarak lebar di atas, nama daerah sebagai baris
   utama di bawahnya. Susunannya seperti kepala surat resmi — dan karena
   tingkat atasnya mengecil, nama kabupaten dapat tampil lebih besar tanpa
   menambah tinggi panel biru. */
.sorot h1 {
    display      : grid;
    justify-items: center;
    gap          : clamp(9px, 1.2vw, 15px);
    font-size    : clamp(1.7rem, 1.1rem + 2.6vw, 2.9rem);
    font-weight  : 800;
    letter-spacing: -0.02em;
}

/* Garis emas tipis menutup blok judul — warna lambang daerah, menegaskan
   tanpa menambah satu kata pun. Ikut dipakai judul halaman register. */
.sorot h1::after {
    content      : "";
    width        : clamp(84px, 12vw, 132px);
    height       : 2px;
    border-radius: 2px;
    background   : linear-gradient(90deg, transparent, #e8bd5a, transparent);
}

.judul-atas {
    display    : flex;
    align-items: center;
    gap        : clamp(10px, 1.6vw, 18px);
    color      : #fff;
    font-size  : clamp(0.66rem, 0.58rem + 0.3vw, 0.82rem);
    font-weight: 600;
    letter-spacing: 0.3em;
    text-indent: 0.3em;             /* mengimbangi jarak di belakang huruf terakhir */
    text-transform: uppercase;
}

/* Garis pengapit kiri-kanan, seperti pada kepala surat. Murni hiasan. */
.judul-atas::before,
.judul-atas::after {
    content   : "";
    width     : clamp(22px, 5vw, 54px);
    height    : 1px;
    background: rgb(255 255 255 / 55%);
}

.judul-nama {
    font-size  : clamp(1.75rem, 1.05rem + 2.9vw, 3.1rem);
    line-height: 1.14;
    /* Bayangan tipis: nama daerah tetap tegas ketika kilau menyapu di
       belakangnya, tanpa terbaca sebagai teks bercahaya. */
    text-shadow: 0 2px 14px rgb(6 20 32 / 38%);
}

.sorot-sub {
    max-width : 60ch;
    margin    : 16px auto 0;
    color     : rgb(255 255 255 / 94%);
    font-size : clamp(0.95rem, 0.9rem + 0.3vw, 1.08rem);
}

.cari-kotak {
    position     : relative;
    display      : flex;
    align-items  : center;
    max-width    : 620px;
    margin       : 28px auto 0;
    background   : var(--latar-tinggi);
    border-radius: 999px;
    box-shadow   : var(--bayang-2);
}

.cari-ikon {
    position: absolute;
    inset-inline-start: 20px;
    width: 20px; height: 20px;
    color: var(--teks-lembut);
    pointer-events: none;
}

#cari {
    width        : 100%;
    padding      : 16px 52px;
    border       : 2px solid transparent;
    border-radius: 999px;
    background   : transparent;
    color        : var(--teks);
    font         : inherit;
    font-size    : 1rem;
}
#cari::placeholder { color: var(--teks-lembut); }
#cari:focus-visible { outline-offset: 0; border-color: var(--fokus); outline: none; }
/* Tombol silang bawaan peramban disembunyikan; kita pakai tombol sendiri. */
#cari::-webkit-search-cancel-button { display: none; }

.cari-hapus {
    position     : absolute;
    inset-inline-end: 12px;
    display      : grid;
    place-items  : center;
    width        : 32px; height: 32px;
    border       : 0;
    border-radius: 50%;
    background   : var(--latar-lembut);
    color        : var(--teks-lembut);
    cursor       : pointer;
}
.cari-hapus:hover { background: var(--garis); color: var(--teks); }
.cari-hapus svg   { width: 15px; height: 15px; }

/* display:grid di atas mengalahkan [hidden] bawaan peramban, sehingga tombol
   silang tetap terlihat walau kotak pencarian masih kosong. */
.cari-hapus[hidden] { display: none; }

.cari-bantuan {
    margin    : 12px 0 0;
    color     : rgb(255 255 255 / 78%);
    font-size : 0.86rem;
}



/* --- Pita komitmen antigratifikasi ---------------------------------------- */

/* Satu kalimat komitmen yang berjalan mendatar di bawah sorot, di atas bilah
   kategori. Alasan ia berjalan dan tidak dibungkus menjadi paragraf biasa:
   kalimatnya panjang dan harus terbaca sebagai satu pernyataan utuh,
   sementara membungkusnya menjadi tiga baris di ponsel mendorong bilah
   kategori keluar dari layar pertama.

   Latarnya --latar-lembut, bukan putih: lengkung kaki sorot tepat di atasnya
   berwarna --latar, jadi putih di bawahnya akan terbaca sebagai dua bidang
   terang yang bertumpuk tanpa batas. Diukur: --teks #17293a di atas #e9eff7
   = 12.4:1; mode gelap #e6eef5 di atas #18262f = 12.6:1; kontras tinggi
   hitam di atas #f0f0f0 = 18.9:1. Ketiganya jauh di atas AA.

   Tinggi pita TIDAK bergantung pada panjang teks (nowrap), jadi menyunting
   kalimatnya tidak menggeser tata letak satu piksel pun. */
.pita {
    background   : var(--latar-lembut);
    border-bottom: 1px solid var(--garis);
    color        : var(--teks);
}

/* Jendela tempat jalur bergerak.

   Bantalan samping disamakan dengan .bungkus, dan saat berjalan ia TIDAK
   menyempitkan pitanya: overflow memotong di kotak bantalan, bukan di kotak
   isi, jadi teks yang lewat tetap terlihat sampai tepi elemen. Yang
   merasakannya hanya keadaan diam, tempat paragrafnya tersusun di kotak isi
   dan karena itu tidak menempel ke tepi layar. */
.pita-lintas {
    overflow-x    : hidden;
    padding-block : 9px;
    padding-inline: clamp(16px, 4vw, 32px);
}

/* Dua salinan berjejer, jalur digeser -50% — tepat selebar SATU salinan,
   sehingga sambungannya tidak terlihat. Karena itu jarak antar salinan wajib
   ikut di dalam salinan (padding-inline-end) dan BUKAN lewat gap: gap hanya
   ada di antara keduanya, sehingga -50% tidak lagi jatuh di batas salinan dan
   teksnya tersentak sekali setiap putaran. */
.pita-jalur {
    display  : flex;
    width    : max-content;
    animation: pita-jalan 40s linear infinite;
}

.pita-teks {
    display     : flex;
    align-items : center;
    gap         : 9px;
    flex        : none;
    margin      : 0;
    padding-inline-end: clamp(48px, 12vw, 160px);
    font-size   : 0.86rem;
    font-weight : 600;
    line-height : 1.5;
    white-space : nowrap;
}

/* Warna garis ikon dipatok --utama, bukan currentColor seperti ikon lain di
   berkas ini: tanpa itu perisainya seberat teksnya dan pita terbaca sebagai
   satu blok tebal. */
.pita-ikon {
    width       : 17px;
    height      : 17px;
    flex        : none;
    stroke      : var(--utama);
    stroke-width: 1.7;
}

@keyframes pita-jalan {
    from { transform: translateX(0); }
    to   { transform: translateX(-50%); }
}

/* Berhenti selagi dibaca — tetikus di atasnya atau fokus papan tuts masuk ke
   dalamnya. Tanpa ini kalimat sepanjang ini mustahil dibaca sampai habis. */
.pita:hover .pita-jalur,
.pita:focus-within .pita-jalur { animation-play-state: paused; }


/* --- 5. Bilah kategori ---------------------------------------------------- */

/* Menempel di bawah kepala, sehingga pengunjung bisa berpindah kategori dari
   posisi gulir mana pun tanpa kembali ke atas. */
.rel {
    position  : sticky;
    top       : var(--tinggi-kepala);
    z-index   : 30;
    background: color-mix(in srgb, var(--latar) 94%, transparent);
    backdrop-filter: blur(8px);
    border-bottom  : 1px solid var(--garis);
}

/* Jarak antarpil dan bantalan di dalamnya dipangkas beberapa piksel dari
   ukuran nyaman biasa. Alasannya satu: keenam pil — termasuk pil inovasi yang
   lebih lebar karena berpiala — harus muat dalam satu baris pada lebar penuh
   1180px. Tinggi sentuh 44px tidak ikut dikurangi.

   align-items rata atas, bukan tengah: bila pil penyaring di dalam .rel-kat
   sampai membungkus menjadi dua baris, pil inovasi harus tetap sejajar dengan
   baris pertama — rata tengah akan menaruhnya di antara kedua baris. */
.rel-isi {
    display      : flex;
    align-items  : flex-start;
    gap          : 7px;
    padding-block: 10px;
    overflow-x   : auto;
    scrollbar-width: thin;
    scroll-padding-inline: 16px;
}

/* Kelompok pil penyaring. Bakunya ia menolak menyusut: tanpa JavaScript,
   bilah di ponsel kembali menjadi baris yang digulir mendatar, dan kelompok
   yang bisa menyusut akan memampatkan dirinya sampai pil di dalamnya menindih
   pil inovasi. Keleluasaan menyusut baru diberikan di layar lebar, di bawah,
   karena di sanalah ia dibutuhkan untuk membungkus. */
.rel-kat {
    display: flex;
    gap    : 7px;
    flex   : none;
}

/* Salinan pil "Berita" dan "Inovasi Daerah" KHUSUS untuk panel kategori di
   ponsel — lihat markah di index.php. Pil aslinya, di luar .rel-kat, tetap
   satu-satunya yang tampil di layar lebar maupun pada mode tanpa JavaScript,
   sehingga jaminan "Inovasi tidak pernah membungkus ke baris kedua" (lihat
   .rel-isi .pil-inovasi di bawah) tidak ikut berubah.

   Baku tersembunyi: hanya dimunculkan di dalam panel terlipat, pada
   @media (max-width: 699.98px) di bawah. */
.rel-kat-salinan {
    display: none;
}

/* Di ponsel bilah digulir mendatar. Begitu ruangnya cukup untuk dua baris,
   pil dibiarkan membungkus — menggulir mendatar di layar lebar membuat pil
   terakhir tersembunyi tanpa petunjuk apa pun.

   Yang membungkus adalah .rel-kat, bukan .rel-isi. Bedanya menentukan:
   flexbox memutus baris lebih dulu, baru menyusutkan isinya. Selama .rel-isi
   yang membungkus, pil inovasi diputus ke baris kedua sebelum kelompok pil di
   kirinya sempat mengalah — persis keluhan yang hendak diperbaiki. Karena itu
   kedua bilah memakai .rel-kat, termasuk bilah di halaman register inovasi
   yang tidak berpil inovasi. */
@media (min-width: 700px) {
    .rel-isi {
        overflow-x: visible;
    }

    /* min-width: 0 wajib menyertai flex-shrink di sini: tanpa itu kelompok ini
       tidak akan menyusut di bawah lebar isinya, jadi ia tidak pernah
       membungkus dan justru mendorong pil inovasi keluar. */
    .rel-kat {
        flex     : 0 1 auto;
        min-width: 0;
        flex-wrap: wrap;
    }
}

/* Pil inovasi didorong ke ujung dan dilarang menyusut: apa pun yang terjadi
   pada pil penyaring di kirinya, ia tetap tinggal di baris utama. */
.rel-isi .pil-inovasi {
    flex        : none;
    margin-inline-start: auto;
}

/* 5a. Pelipat kategori di ponsel ------------------------------------------- */

/* Baku tersembunyi: di layar lebar pil penyaring tampil sendiri-sendiri, dan
   tanpa JavaScript atribut hidden membuatnya tak pernah muncul sama sekali. */
.rel-lipat {
    display: none;
}

.rel-lipat[hidden] {
    display: none;
}

/* Di bawah 700px seluruh pil — keempat kategori, juga Berita dan Inovasi
   Daerah — dilipat ke dalam panel, menyisakan satu tombol pelipat sendirian
   di baris utama. Sebelumnya keenamnya berjejer dalam baris yang digulir
   mendatar, dan pil inovasi — yang paling akhir — praktis selalu berada di
   luar layar.

   699.98px, bukan 699px: pada layar berskala (Windows 125%, misalnya) lebar
   jendela bisa jatuh di angka pecahan. Dengan batas bulat, lebar 699,2px tidak
   ditangkap oleh max-width: 699px maupun min-width: 700px — pelipatnya hilang
   dan kelima pil kembali berjejal dalam satu baris. */
@media (max-width: 699.98px) {

    /* Hanya berlaku setelah portal.js menyalakannya. Tanpa JavaScript panel
       tidak bisa dibuka, jadi bilah dibiarkan seperti semula.

       Tombol ini sendirian di baris utama — Berita dan Inovasi disembunyikan
       dari sana di bawah — jadi ia melebar penuh alih-alih menyusut berbagi
       ruang. Isinya dibelah dua kelompok (lihat markah di index.php):
       ikon+nama rata kiri lewat .rel-lipat-label, angka+panah rata kanan
       lewat .rel-lipat-hitung. space-between di antara keduanya membuat
       lebar penuh ini terbaca simetris, bukan sekadar pil yang direntangkan. */
    .rel[data-lipat="siap"] .rel-lipat {
        display        : flex;
        align-items    : center;
        justify-content: space-between;
        gap            : 10px;
        width          : 100%;
        min-height     : 44px;
        padding        : 0 14px;
        border         : 1px solid var(--garis-tegas);
        border-radius  : 999px;
        background     : var(--latar-tinggi);
        color          : var(--teks);
        font           : inherit;
        font-size      : 0.85rem;
        font-weight    : 600;
        white-space    : nowrap;
        cursor         : pointer;
    }

    .rel[data-lipat="siap"] .rel-lipat-label,
    .rel[data-lipat="siap"] .rel-lipat-hitung {
        display    : flex;
        align-items: center;
        gap        : 7px;
        min-width  : 0;
    }

    /* Gulir mendatar dimatikan: selain tidak lagi diperlukan, overflow yang
       tidak visible akan memangkas panel yang menggantung di bawahnya. */
    .rel[data-lipat="siap"] .rel-isi {
        align-items: center;
        overflow-x : visible;
    }

    .rel[data-lipat="siap"] .rel-lipat-ikon,
    .rel[data-lipat="siap"] .rel-lipat-panah {
        width: 16px; height: 16px; flex: none;
    }

    /* Nama kategori yang panjang dipotong, bukan mendesak angka dan panah
       keluar dari tombol. Keduanya tetap utuh karena .rel-lipat-hitung
       memakai flex: none secara tidak langsung (anak-anaknya tak pernah
       menyusut, lihat svg dan .pil-n). */
    .rel[data-lipat="siap"] .rel-lipat-nama {
        overflow     : hidden;
        text-overflow: ellipsis;
        min-width    : 0;
    }

    /* Pil "Berita" dan "Inovasi Daerah" ASLI (anak langsung .rel-isi, dipakai
       di layar lebar dan pada mode tanpa JavaScript) disembunyikan dari baris
       utama begitu panel terlipat aktif. Salinannya sudah ada di dalam panel
       (.rel-kat-salinan) — tanpa baris ini keduanya tampil dua kali: sekali
       berjejer dengan tombol pelipat, sekali lagi di dalam panel saat dibuka. */
    .rel[data-lipat="siap"] .rel-isi > .pil-pergi {
        display: none;
    }

    .rel[data-lipat="siap"] .rel-lipat[aria-expanded="true"] {
        border-color: var(--utama);
        color       : var(--utama-kuat);
    }

    .rel[data-lipat="siap"] .rel-lipat[aria-expanded="true"] .rel-lipat-panah {
        transform: rotate(180deg);
    }

    /* Panel digantung pada .rel — yang position: sticky, jadi ia memang
       menjadi acuan bagi keturunan absolut — supaya lebarnya mengikuti bilah
       dan tidak terikat lebar tombol pelipatnya. */
    .rel[data-lipat="siap"] .rel-kat {
        display       : none;
        position      : absolute;
        z-index       : 40;
        top           : calc(100% - 4px);
        inset-inline  : clamp(16px, 4vw, 32px);
        flex-direction: column;
        gap           : 4px;
        padding       : 8px;
        border        : 1px solid var(--garis);
        border-radius : 16px;
        background    : var(--latar-tinggi);
        box-shadow    : var(--bayang-2);
    }

    .rel[data-lipat="siap"][data-buka="ya"] .rel-kat {
        display: flex;
    }

    /* Di dalam panel pil menjadi baris penuh: angka rata kanan supaya keempat
       jumlah bisa dibandingkan sekilas. */
    .rel[data-lipat="siap"] .rel-kat .pil {
        justify-content: space-between;
        width          : 100%;
        border-color   : transparent;
        background     : transparent;
    }

    .rel[data-lipat="siap"] .rel-kat .pil:hover {
        background: var(--latar-lembut);
    }

    .rel[data-lipat="siap"] .rel-kat .pil[aria-current="true"] {
        background  : var(--utama);
        border-color: var(--utama);
        color       : var(--latar-tinggi);
    }

    /* Garis pemisah menandai Berita & Inovasi sebagai tujuan ke halaman lain,
       bukan penyaring, meski keduanya terlihat seperti baris daftar yang sama
       dengan pil kategori di atasnya. */
    .rel[data-lipat="siap"] .rel-kat-salinan {
        display       : flex;
        flex-direction: column;
        gap           : 4px;
        margin-top    : 4px;
        padding-top   : 8px;
        border-top    : 1px solid var(--garis);
    }

    /* Spesifisitas sengaja disamakan dengan aturan ".rel-kat .pil" di atas
       (empat kelas/atribut) supaya urutan tulisan yang menentukan — dan
       aturan ini ditulis sesudahnya — bukan rata kiri transparan yang
       menang. Inovasi mempertahankan gradasi dan warnanya sendiri di dalam
       panel: penegasannya tidak boleh luruh hanya karena berpindah ke dalam
       daftar. */
    .rel[data-lipat="siap"] .rel-kat-salinan .pil-inovasi {
        margin-inline-start: 0;
        border-color: transparent;
        background  : linear-gradient(115deg, #14406b 0%, #146b8f 48%, #0f6d4e 100%);
        color       : #fff;
    }

    .rel[data-lipat="siap"] .rel-kat-salinan .pil-inovasi .pil-n {
        background: rgb(255 255 255 / 16%);
        color     : #fff;
    }
}

.pil {
    display      : inline-flex;
    align-items  : center;
    gap          : 7px;
    flex         : none;
    min-height   : 44px;            /* target sentuh WCAG */
    padding      : 0 13px;
    border       : 1px solid var(--garis);
    border-radius: 999px;
    background   : var(--latar-tinggi);
    color        : var(--teks);
    font         : inherit;
    font-size    : 0.85rem;
    font-weight  : 600;
    white-space  : nowrap;
    text-decoration: none;
    cursor       : pointer;
    transition   : background 150ms ease, border-color 150ms ease, color 150ms ease;
}

.pil:hover { background: var(--latar-lembut); border-color: var(--garis-tegas); }

/* --latar-tinggi ikut berbalik bersama tema, jadi teks pil aktif tetap
   kontras di atas --utama pada tema terang maupun gelap. */
.pil[aria-current="true"] {
    background  : var(--utama);
    border-color: var(--utama);
    color       : var(--latar-tinggi);
}

.pil-n {
    padding      : 1px 6px;
    border-radius: 999px;
    background   : var(--latar-lembut);
    color        : var(--teks-lembut);
    font-size    : 0.7rem;
    font-weight  : 700;
    font-variant-numeric: tabular-nums;
}

.pil[aria-current="true"] .pil-n {
    background: rgb(255 255 255 / 22%);
    color     : inherit;
}

/* Pil penuntun ke halaman lain, bukan penyaring. Panah dan warna berbeda
   supaya pengunjung tahu ini berpindah halaman. */
.pil-pergi {
    border-color: color-mix(in srgb, var(--utama) 45%, var(--garis));
    color       : var(--utama-kuat);
}
.pil-pergi:hover { border-color: var(--utama); }
.pil-pergi svg   { width: 15px; height: 15px; flex: none; }
.pil-pergi .pil-n {
    background: color-mix(in srgb, var(--utama) 16%, transparent);
    color     : var(--utama-kuat);
}

/* Pil register inovasi: satu-satunya yang berisi penuh di bilah ini. Warnanya
   dipatok — tidak ikut token tema — supaya sama tegasnya di terang maupun
   gelap, dan hijaunya cukup tua agar teks putih tetap lolos 4.5:1. */
.pil-inovasi {
    position     : relative;
    overflow     : hidden;              /* menahan kilau di dalam lengkungnya */
    padding      : 0 15px;              /* sedikit lebih lapang dari pil lain */
    border-color : transparent;
    background   : linear-gradient(115deg, #14406b 0%, #146b8f 48%, #0f6d4e 100%);
    color        : #fff;
    font-weight  : 700;
    box-shadow   : 0 2px 12px rgb(15 109 78 / 34%), var(--bayang-1);
}

.pil-inovasi:hover,
.pil-inovasi:focus-visible {
    border-color: transparent;
    background  : linear-gradient(115deg, #17497a 0%, #16789f 48%, #12805c 100%);
    box-shadow  : 0 5px 18px rgb(15 109 78 / 42%), var(--bayang-1);
}

/* Selubung putihnya ditahan di 16%: lebih terang dari itu, angka putih di
   atasnya jatuh di bawah 4.5:1 terhadap hijau di ujung gradien. */
.pil-inovasi .pil-n {
    background: rgb(255 255 255 / 16%);
    color     : #fff;
}

/* Piala sedikit lebih besar dari panah: ia yang menarik mata, panah hanya
   memberi tahu bahwa pil ini berpindah halaman. */
.pil-inovasi .pil-lencana { width: 18px; height: 18px; }
.pil-inovasi .pil-panah   { opacity: 0.85; }

/* --- 6. Bagian & pintasan ------------------------------------------------- */

.bagian {
    padding-block   : clamp(30px, 4.5vw, 52px) 0;
    /* Judul bagian tidak boleh tersembunyi di balik kepala + bilah kategori
       saat pengunjung membuka tautan anchor. */
    scroll-margin-top: 140px;
}

.bagian[hidden] { display: none; }

.bagian-kepala {
    display    : flex;
    align-items: baseline;
    flex-wrap  : wrap;
    gap        : 8px 12px;
    margin-bottom: 6px;
}

.bagian-kepala h2 {
    font-size     : clamp(1.1rem, 1rem + 0.6vw, 1.42rem);
    letter-spacing: -0.01em;
}

.jumlah {
    padding      : 2px 9px;
    border-radius: 999px;
    background   : var(--latar-lembut);
    color        : var(--teks-lembut);
    font-size    : 0.74rem;
    font-weight  : 700;
    font-variant-numeric: tabular-nums;
}

.bagian-ket {
    max-width: 68ch;
    margin   : 0 0 20px;
    color    : var(--teks-lembut);
    font-size: 0.9rem;
}

.pintasan { padding-block: clamp(26px, 4vw, 44px) 0; }
.pintasan[hidden] { display: none; }

/* Kendali baris pintasan: tombol jeda dan titik penanda kelompok. Ditaruh di
   bawah barisnya dan dibuat kecil — ia pelayan baris kartu, bukan pesaingnya.
   Baru ditampilkan JavaScript, karena tanpa JavaScript tidak ada yang
   berganti dan tidak ada pula yang perlu dihentikan. */
.pintasan-kendali {
    display        : flex;
    align-items    : center;
    justify-content: center;
    gap            : 14px;
    margin-top     : 16px;
}

.pintasan-kendali[hidden] { display: none; }

.pintasan-jeda {
    display      : grid;
    place-items  : center;
    width        : 34px;
    height       : 34px;
    padding      : 0;
    border       : 1px solid var(--garis);
    border-radius: 999px;
    background   : var(--latar-tinggi);
    color        : var(--teks-lembut);
    cursor       : pointer;
    transition   : color 150ms ease, border-color 150ms ease;
}

.pintasan-jeda:hover { color: var(--utama-kuat); border-color: var(--garis-tegas); }
.pintasan-jeda svg   { width: 13px; height: 13px; }

/* Ikon jeda berubah jadi ikon putar ketika pergantian dihentikan. */
.pintasan-jeda .ikon-putar { display: none; }
.pintasan-jeda[aria-pressed="true"] .ikon-jeda  { display: none; }
.pintasan-jeda[aria-pressed="true"] .ikon-putar { display: block; fill: currentColor; }

.pintasan-titik-baris { display: flex; gap: 2px; }

/* Titiknya kecil, tetapi tombolnya 24x24 — batas terkecil yang masih nyaman
   disentuh menurut WCAG 2.5.8. Titik digambar oleh ::before di dalamnya. */
.pintasan-titik {
    display      : grid;
    place-items  : center;
    width        : 24px;
    height       : 24px;
    padding      : 0;
    border       : 0;
    background   : none;
    cursor       : pointer;
}

.pintasan-titik::before {
    content      : "";
    width        : 8px;
    height       : 8px;
    border-radius: 999px;
    background   : var(--garis-tegas);
    transition   : width 220ms var(--lentur), background 180ms ease;
}

.pintasan-titik:hover::before { background: var(--teks-lembut); }

.pintasan-titik[aria-current="true"]::before {
    width     : 20px;
    background: var(--utama);
}


/* --- 7. Petak kartu ------------------------------------------------------- */

.petak {
    display              : grid;
    /* 140px menjaga ponsel sempit (360px) tetap mendapat dua kolom;
       di bawah itu kartu jadi terlalu tinggi dan daftar terasa panjang. */
    grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
    gap                  : clamp(12px, 1.6vw, 18px);
    margin               : 0;
    padding              : 0;
    list-style           : none;
}

/* Pintasan memakai jumlah kolom tetap, bukan auto-fill: baris berisi empat
   entri yang diisi auto-fill menyisakan separuh lebar kosong di layar lebar. */
.petak-pintasan { grid-template-columns: repeat(2, minmax(0, 1fr)); }

@media (min-width: 620px) {
    .petak-pintasan { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

.petak-pintasan .kartu      { padding: 24px 14px 18px; }
.petak-pintasan .kartu-ikon { width: 84px; height: 84px; }
.petak-pintasan .mono       { width: 74px; height: 74px; font-size: 1.55rem; }
.petak-pintasan .kartu-judul{ font-size: 0.9rem; }

.petak-sel { display: flex; }
.petak-sel[hidden] { display: none; }

/* Satu gaya kartu dipakai oleh <a> maupun <button> supaya keduanya identik. */
.kartu {
    position       : relative;
    display        : flex;
    flex-direction : column;
    align-items    : center;
    gap            : 12px;
    width          : 100%;
    padding        : 22px 14px 18px;
    border         : 1px solid var(--garis-lembut);
    border-radius  : var(--lengkung);
    background     : var(--latar-tinggi);
    box-shadow     : var(--bayang-1);
    color          : inherit;
    font           : inherit;
    text-align     : center;
    text-decoration: none;
    cursor         : pointer;

    /* Peralihannya TIDAK di sini. Ia hidup di bagian 11c bersama tanggapan
       tetikus lainnya, dan dulu ditulis di kedua tempat — yang di sini tidak
       pernah berlaku sebab yang di sana datang belakangan. */
}

.kartu:hover {
    transform    : translateY(-3px);
    box-shadow   : var(--bayang-2);
}

.kartu:active { transform: translateY(-1px); }

.kartu-ikon {
    display     : grid;
    place-items : center;
    width       : 76px;
    height      : 76px;
}

.kartu-ikon img {
    max-width  : 100%;
    max-height : 100%;
    object-fit : contain;
}

/* Monogram pengganti saat berkas ikon belum tersedia. Portal tidak pernah
   tampil bolong, dan ikon bisa ditambahkan bertahap tanpa menyentuh kode. */
.mono {
    display      : grid;
    place-items  : center;
    width        : 66px;
    height       : 66px;
    border-radius: 16px;
    background   : var(--latar-lembut);
    color        : var(--utama);
    font-size    : 1.35rem;
    font-weight  : 800;
    letter-spacing: -0.02em;
}

.kartu-judul {
    font-size     : 0.84rem;
    font-weight   : 700;
    line-height   : 1.35;
    letter-spacing: 0.01em;
    text-wrap     : balance;
}

.kartu-ket {
    margin-top : -3px;
    color      : var(--teks-lembut);
    font-size  : 0.74rem;
    line-height: 1.45;
    /* Keterangan dibatasi tiga baris supaya tinggi kartu tetap seragam. */
    display           : -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 3;
    overflow          : hidden;
}

/* Lencana "Khusus ASN": menempel di belakang judul, bukan baris sendiri,
   supaya tidak menambah tinggi kartu. */
.lencana {
    display      : inline-block;
    vertical-align: 1px;
    margin-inline-start: 6px;
    padding      : 1px 7px;
    border-radius: 999px;
    background   : var(--latar-lembut);
    color        : var(--teks-lembut);
    font-size    : 0.62rem;
    font-weight  : 800;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    white-space  : nowrap;
}

.kartu-luar {
    position : absolute;
    top      : 10px;
    inset-inline-end: 10px;
    color    : var(--teks-lembut);
    opacity  : 0;
    transition: opacity 160ms ease;
}
.kartu-luar svg { width: 14px; height: 14px; }
.kartu:hover .kartu-luar,
.kartu:focus-visible .kartu-luar { opacity: 1; }

.tanpa-hasil,
.kosong {
    margin    : 8px 0 60px;
    padding   : 40px 20px;
    border    : 1px dashed var(--garis-tegas);
    border-radius: var(--lengkung);
    color     : var(--teks-lembut);
    text-align: center;
}


/* --- 8. Daftar teks berkolom ---------------------------------------------- */

/* Bentuk baris dipakai dua keadaan, jadi ditulis sekali untuk keduanya:

     .baris                      kategori berjudul panjang — perangkat daerah,
                                 kecamatan, aplikasi. Dua puluh nama dinas
                                 sepanjang "BADAN PERENCANAAN PEMBANGUNAN,
                                 PENELITIAN DAN PENGEMBANGAN DAERAH" jauh lebih
                                 cepat dipindai berderet ke bawah daripada
                                 berjajar dalam kartu yang judulnya dipotong.

     [data-hasil="cari"] .kartu  seluruh hasil pencarian. Pencarian menjangkau
                                 kelima kategori sekaligus, sehingga hasilnya
                                 mencampur kartu berikon dengan baris teks —
                                 dua bentuk berbeda untuk hal yang setara.
                                 Selama mencari, kartu ikut memakai bentuk
                                 baris dan ikonnya disembunyikan.

   Penanda data-hasil dipasang JavaScript pada elemen <html>. Tanpa JavaScript
   pencarian memang tidak berjalan, jadi keadaan ini tidak pernah muncul. */

.daftar,
:root[data-hasil="cari"] .petak {
    /* .petak aslinya grid; kolom teks memerlukan aliran block. */
    display    : block;
    columns    : 3;
    column-gap : 30px;
    margin     : 0;
    padding    : 0;
    list-style : none;
}

@media (max-width: 900px) {
    .daftar,
    :root[data-hasil="cari"] .petak { columns: 2; }
}

@media (max-width: 600px) {
    .daftar,
    :root[data-hasil="cari"] .petak { columns: 1; }
}

/* Tanpa break-inside satu entri bisa terpotong di batas kolom. */
.daftar > li,
:root[data-hasil="cari"] .petak-sel {
    display      : block;
    break-inside : avoid;
    margin-bottom: 2px;
}

/* Harus lebih kuat daripada aturan display:block di atas, kalau tidak entri
   yang tersaring keluar justru ikut tampil. */
.daftar > li[hidden],
:root[data-hasil="cari"] .petak-sel[hidden] { display: none; }

:root[data-hasil="cari"] .kartu-ikon { display: none; }

.baris,
:root[data-hasil="cari"] .kartu {
    position       : relative;
    display        : block;
    width          : 100%;
    padding        : 9px 26px 9px 12px;
    border         : 0;
    border-radius  : 10px;
    background     : transparent;
    box-shadow     : none;
    color          : inherit;
    text-align     : start;
    text-decoration: none;
    transform      : none;
    transition     : background 130ms ease;
}

.baris:hover,
:root[data-hasil="cari"] .kartu:hover {
    background  : var(--latar-tinggi);
    box-shadow  : var(--bayang-1);
    border-color: transparent;
    transform   : none;
}

.baris-judul,
:root[data-hasil="cari"] .kartu-judul {
    display    : block;
    font-size  : 0.87rem;
    font-weight: 650;
    line-height: 1.35;
    transition : color 130ms ease;
}

.baris:hover .baris-judul,
:root[data-hasil="cari"] .kartu:hover .kartu-judul { color: var(--utama-kuat); }

/* display:block sekaligus melepas pemotongan tiga baris pada .kartu-ket:
   di dalam daftar, keterangan tidak perlu dipangkas. */
.baris-ket,
:root[data-hasil="cari"] .kartu-ket {
    display    : block;
    margin-top : 0;
    color      : var(--teks-lembut);
    font-size  : 0.76rem;
    line-height: 1.4;
    overflow   : visible;
}

.baris-panah,
:root[data-hasil="cari"] .kartu-luar {
    position : absolute;
    top      : 12px;
    inset-inline-end: 8px;
    color    : var(--teks-lembut);
    opacity  : 0;
    transition: opacity 130ms ease;
}

.baris-panah svg,
:root[data-hasil="cari"] .kartu-luar svg { width: 13px; height: 13px; display: block; }

.baris:hover .baris-panah,
.baris:focus-visible .baris-panah,
:root[data-hasil="cari"] .kartu:hover .kartu-luar,
:root[data-hasil="cari"] .kartu:focus-visible .kartu-luar { opacity: 1; }

/* --- 9. Register inovasi -------------------------------------------------- */

/* Halaman inovasi.php memakai berkas gaya yang sama. Sorotnya diringkas:
   tanpa foto pimpinan dan dengan bantalan lebih tipis, karena halaman ini
   dibaca sebagai daftar kerja, bukan halaman muka. */
.sorot-ringkas { padding-block: clamp(26px, 4vw, 48px) clamp(52px, 5vw, 60px); }
.sorot-ringkas h1 { font-size: clamp(1.5rem, 1.1rem + 1.8vw, 2.2rem); }

/* Sorot di sini lebih pendek, jadi foto pimpinan ikut diperpendek. Tetapi
   judulnya jauh lebih ringkas daripada di portal utama, sehingga fotonya
   justru bisa digeser lebih ke tengah — yang membatasi di sini kotak
   pencarian selebar 620px, bukan judulnya. */
.sorot-ringkas { --tokoh-tepi: clamp(8px, calc((100vw - 1180px) / 2 - 20px), 265px); }

@media (min-width: 1280px) {
    .sorot-ringkas .tokoh { height: clamp(230px, 15vw + 40px, 330px); }
}

/* Register berbentuk tabel: satu tabel per jenjang, satu baris per inovasi.
   Bentuk ini menyejajarkan jenis tautan dan alamat antarbaris sehingga
   kelengkapan tiap satuan kerja terbaca sekali lihat. Ikon tetap dipakai di
   kolom pertama — banyak inovasi lebih dikenali lewat logonya. */
.tabel-bingkai {
    margin-top   : 18px;
    border       : 1px solid var(--garis);
    border-radius: var(--lengkung);
    background   : var(--latar-tinggi);
    /* Layar sempit menggulir tabel ke samping, bukan memampatkan kolomnya. */
    overflow-x   : auto;
}

.inov-tabel {
    width          : 100%;
    min-width      : 560px;
    border-collapse: collapse;
    font-size      : 0.85rem;
}

.inov-tabel thead th {
    padding      : 10px 16px;
    border-bottom: 1px solid var(--garis);
    color        : var(--teks-lembut);
    font-size    : 0.66rem;
    font-weight  : 800;
    letter-spacing: 0.07em;
    text-transform: uppercase;
    text-align   : start;
    white-space  : nowrap;
}

/* Lebar kolom dipatok supaya ketiga tabel jenjang tampak satu bentuk. */
.inov-tabel thead th:nth-child(2) { width: 9.5rem; }

/* Cukup lebar untuk subdomain terpanjang di register — nama inang yang
   terpotong ke baris kedua justru lebih sulit dibaca daripada satu baris. */
.inov-tabel thead th:nth-child(3) { width: 17.5rem; }

.inov-tabel tbody th,
.inov-tabel tbody td {
    padding      : 10px 16px;
    border-top   : 1px solid var(--garis);
    vertical-align: middle;
    text-align   : start;
    font-weight  : 400;
}

/* Satu satuan kerja: kelompok baris dengan judulnya sendiri di dalam tabel. */
.unit { scroll-margin-top: 140px; }

.inov-tabel .unit-baris th {
    padding     : 13px 16px 11px;
    border-block: 1px solid var(--garis);
    background  : var(--latar-lembut);
    font-size   : 0.87rem;
    font-weight : 700;
}

.inov-tabel tbody:first-of-type .unit-baris th { border-top: 0; }

.inov-tabel tbody tr:not(.unit-baris):hover { background: var(--latar-lembut); }

/* Baris yang punya alamat bisa diklik seluruhnya; lihat portal.js. */
.inov-tabel tbody tr[data-url] { cursor: pointer; }

.inov-tabel tbody[hidden],
.inov-tabel tr[hidden] { display: none; }

.sel-inov {
    display    : flex;
    align-items: center;
    gap        : 13px;
}

/* Ikon duduk di keping bersudut tumpul. Logo satuan kerja berbeda-beda ukuran,
   rasio, dan latarnya; keping ini menyamakan bentuknya sehingga kolom pertama
   terbaca rapi sepanjang tabel. */
.inov-logo {
    display    : grid;
    place-items: center;
    width      : 52px;
    height     : 52px;
    padding    : 6px;
    flex       : none;
    border       : 1px solid var(--ikon-kartu-garis);
    border-radius: 13px;
    background   : var(--ikon-kartu);
    overflow     : hidden;
}

.inov-logo img { max-width: 100%; max-height: 100%; object-fit: contain; }

/* Monogram mengisi keping itu sendiri, bukan menjadi kotak kedua di dalamnya. */
.mono-kecil {
    width     : 100%;
    height    : 100%;
    border-radius: 8px;
    background: transparent;
    color     : var(--ikon-kartu-teks);
    font-size : 0.95rem;
}

.inov-nama {
    font-size  : 0.87rem;
    font-weight: 650;
    line-height: 1.3;
    color      : inherit;
    text-decoration: none;
    transition : color 130ms ease;
}

a.inov-nama:hover,
a.inov-nama:focus-visible { color: var(--utama-kuat); text-decoration: underline; }

/* Alamat cukup sampai nama inang: sudah menjawab "ke mana tautan ini". */
.inov-alamat {
    color    : var(--teks-lembut);
    font-size: 0.76rem;
    word-break: break-word;
}

/* Inovasi tanpa alamat tetap tercatat, kolomnya sekadar diberi tanda. */
.inov-kosong { color: var(--teks-lembut); }

/* Di layar telepon kolom alamat dilepas, bukan digulir ke samping: nama
   inovasi sudah menjadi tautannya, dan yang belum punya alamat sudah ditandai
   lencana "Tanpa tautan". Dua kolom sisanya muat tanpa digulir. */
@media (max-width: 620px) {
    .inov-tabel { min-width: 0; font-size: 0.82rem; }

    .inov-tabel thead th:nth-child(3),
    .sel-alamat { display: none; }

    .inov-tabel thead th:nth-child(2) { width: 8rem; }

    .inov-tabel thead th,
    .inov-tabel tbody th,
    .inov-tabel tbody td { padding-inline: 12px; }

    /* Keping ikon ikut mengecil supaya nama inovasi tetap kebagian lebar. */
    .sel-inov  { gap: 10px; }
    .inov-logo { width: 44px; height: 44px; padding: 5px; border-radius: 11px; }
}

/* Penanda jenis tautan. Warnanya membedakan tanpa mengandalkan warna saja —
   labelnya tetap tertulis penuh. */
.lencana-resmi {
    background: color-mix(in srgb, var(--utama) 16%, transparent);
    color     : var(--utama-kuat);
}
.lencana-aplikasi {
    background: color-mix(in srgb, var(--lencana-aplikasi) 16%, transparent);
    color     : var(--lencana-aplikasi);
}
.lencana-sosial {
    background: color-mix(in srgb, var(--lencana-sosial) 16%, transparent);
    color     : var(--lencana-sosial);
}
.lencana-dokumen {
    background: color-mix(in srgb, var(--lencana-dokumen) 18%, transparent);
    color     : var(--lencana-dokumen);
}
.lencana-pihak-ketiga {
    background: var(--latar-lembut);
    color     : var(--teks-lembut);
}
.lencana-takada {
    background: var(--bahaya-latar);
    color     : var(--bahaya);
}

.sumber {
    max-width: 78ch;
    margin   : clamp(36px, 5vw, 56px) 0 0;
    padding-top: 18px;
    border-top : 1px solid var(--garis);
    color    : var(--teks-lembut);
    font-size: 0.8rem;
}

.inov-tabel .lencana { margin-inline-start: 0; vertical-align: baseline; }

/* --- 10. Kaki -------------------------------------------------------------- */

.kaki {
    border-top : 1px solid var(--garis);
    background : var(--latar-tinggi);
}

.kaki-isi {
    display        : flex;
    flex-wrap      : wrap;
    align-items    : center;
    justify-content: space-between;
    gap            : 12px;
    padding-block  : 28px;
    font-size      : 0.87rem;
}

.kaki-isi p { margin: 0; }
.kaki-hak   { color: var(--teks-lembut); }

.peringatan {
    margin       : 24px 0 0;
    padding      : 16px 20px;
    border       : 1px solid currentColor;
    border-radius: var(--lengkung);
    background   : var(--bahaya-latar);
    color        : var(--bahaya);
    font-size    : 0.88rem;
}
.peringatan ul { margin: 8px 0 0; padding-inline-start: 20px; }


/* --- 11. Gerak ------------------------------------------------------------- */

/* Tiga lapis gerak, semuanya CSS — tidak ada satu baris JavaScript pun yang
   ditambahkan untuk ini:

     1. Masuk halaman   isi sorot naik berurutan saat halaman pertama dibuka
     2. Muncul digulir  tiap bagian naik lembut ketika memasuki layar
     3. Tanggapan       kartu, baris, dan pil menanggapi tetikus dan papan ketik

   Lapisan kedua memakai animation-timeline, yang belum ada di semua peramban.
   Karena itu dibungkus @supports: peramban yang belum mendukungnya cukup
   menampilkan isinya langsung — tidak ada yang hilang, hanya tanpa gerak. */

/* Lengkung perlambatan yang dipakai seragam: cepat di awal, mengendap di
   akhir. Terasa seperti benda yang berhenti sendiri, bukan dipotong. */
:root { --lentur: cubic-bezier(0.22, 0.61, 0.36, 1); }

html { scroll-behavior: smooth; }

@keyframes naik {
    from { opacity: 0; transform: translateY(16px); }
    to   { opacity: 1; transform: none; }
}

@keyframes masuk-kiri {
    from { opacity: 0; transform: translateX(-34px); }
    to   { opacity: 1; transform: none; }
}

@keyframes masuk-kanan {
    from { opacity: 0; transform: translateX(34px); }
    to   { opacity: 1; transform: none; }
}

/* Kilau yang menyapu pil register inovasi dan panel biru sorot. Menyala
   sebentar lalu diam lama: cukup untuk menarik mata yang sedang menelusuri
   halaman, tidak sampai berkedip terus-menerus di sudut pandang orang yang
   sedang membaca. Keduanya memakai gerak yang sama tetapi periodenya berbeda
   (7 detik dan 11 detik) supaya tidak pernah menyala serentak. */
@keyframes kilau {
    0%        { opacity: 0;    transform: translateX(-160%) skewX(-18deg); }
    10%       { opacity: 0.45; }
    32%       { opacity: 0;    transform: translateX(260%)  skewX(-18deg); }
    100%      { opacity: 0;    transform: translateX(260%)  skewX(-18deg); }
}


/* --- 11a. Masuk halaman --------------------------------------------------- */

/* Berurutan dari atas ke bawah, jeda 90 milidetik antarunsur. Seluruh
   rangkaian selesai di bawah satu detik supaya kotak pencarian tidak terasa
   lambat bagi yang langsung ingin mengetik. */
.sorot h1     { animation: naik 620ms  60ms both var(--lentur); }
.sorot-sub    { animation: naik 620ms 150ms both var(--lentur); }
.cari-kotak   { animation: naik 620ms 240ms both var(--lentur); }
.cari-bantuan { animation: naik 620ms 330ms both var(--lentur); }
.rel-isi      { animation: naik 620ms 400ms both var(--lentur); }

/* Kartu pintasan menyusul satu per satu setelah bilah kategori tampil. Hanya
   empat yang perlu diberi jeda: sisanya menunggu giliran dalam keadaan
   tersembunyi, dan masuk lewat animasi .masuk di bawah. */
.petak-pintasan > li { animation: naik 520ms both var(--lentur); }
.petak-pintasan > li:nth-child(1) { animation-delay: 470ms; }
.petak-pintasan > li:nth-child(2) { animation-delay: 530ms; }
.petak-pintasan > li:nth-child(3) { animation-delay: 590ms; }
.petak-pintasan > li:nth-child(4) { animation-delay: 650ms; }

/* Kelompok berikutnya turun dari atas, satu demi satu berjarak 70 milidetik
   (jeda itu dipasang JavaScript). Arahnya sengaja berlawanan dengan animasi
   masuk halaman: yang ini pergantian, bukan kedatangan pertama. */
@keyframes turun {
    from { opacity: 0; transform: translateY(-24px); }
    to   { opacity: 1; transform: none; }
}

.petak-pintasan > li.masuk { animation: turun 520ms both var(--lentur); }


/* --- 11b. Muncul saat digulir --------------------------------------------- */

@supports (animation-timeline: view()) {
    /* Digerakkan posisi gulir, bukan waktu: maju-mundur mengikuti gerak
       pengguna, dan tidak ada yang tertinggal separuh tampil. Tabel register
       ikut sebagai satu bingkai — barisnya tidak dianimasikan sendiri-sendiri
       karena transform pada baris tabel tidak seragam antarperamban. */
    .bagian-kepala,
    .tabel-bingkai {
        animation: naik 1ms both linear;
        animation-timeline: view();
        animation-range: entry 0% entry 38%;
    }

    /* Kartu ikon dan baris teks ikut, dengan jarak tempuh lebih pendek supaya
       daftar panjang tidak terasa bergelombang. */
    .petak:not(.petak-pintasan) > li,
    .daftar > li {
        animation: naik 1ms both linear;
        animation-timeline: view();
        animation-range: entry 0% entry 22%;
    }
}

@supports (animation-timeline: scroll()) {
    /* Kepala halaman menegas begitu halaman digulir, sehingga batas dengan
       isi di bawahnya tetap terbaca saat menempel. */
    .kepala {
        animation: kepala-menempel 1ms both linear;
        animation-timeline: scroll();
        animation-range: 0 90px;
    }

    @keyframes kepala-menempel {
        to { box-shadow: 0 3px 18px rgb(13 44 72 / 9%); }
    }
}


/* --- 11c. Tanggapan tetikus dan papan ketik ------------------------------- */

.kartu-ikon img,
.mono {
    transition: transform var(--gerak-lambat) var(--lentur);
}

.kartu:hover .kartu-ikon img,
.kartu:focus-visible .kartu-ikon img,
.kartu:hover .mono,
.kartu:focus-visible .mono { transform: scale(1.07); }

.kartu { transition: transform var(--gerak-kartu) var(--lentur), box-shadow var(--gerak-kartu) ease; }

/* Baris teks bergeser sedikit ke dalam — cukup untuk menandai baris yang
   sedang disorot tanpa menggeser baris di sekitarnya. */
.baris,
:root[data-hasil="cari"] .kartu { transition: background 160ms ease, padding-inline-start 160ms var(--lentur); }

.baris:hover,
.baris:focus-visible,
:root[data-hasil="cari"] .kartu:hover { padding-inline-start: 16px; }

/* Baris tabel tidak bergeser — kolomnya harus tetap sejajar — jadi penanda
   sorotnya hanya latar baris dan ikonnya yang sedikit membesar. */
.inov-tabel tbody tr { transition: background 160ms ease; }

.inov-logo img { transition: transform 220ms var(--lentur); }
.inov-tabel tbody tr:hover .inov-logo img,
.inov-tabel tbody tr:focus-within .inov-logo img { transform: scale(1.08); }

.pil { transition: background 160ms ease, border-color 160ms ease, color 160ms ease, transform 160ms var(--lentur); }
.pil:hover { transform: translateY(-1px); }

/* Di dalam panel pelipat pil menjadi baris; mengangkatnya saat disentuh
   membuat baris di bawahnya seolah bergeser. Di layar lebar .rel-kat hanyalah
   pengelompok biasa, jadi di sana pil tetap boleh terangkat. */
@media (max-width: 699.98px) {
    .rel[data-lipat="siap"] .rel-kat .pil:hover { transform: none; }
}

.rel-lipat { transition: border-color 160ms ease, color 160ms ease; }
.rel-lipat-panah { transition: transform 200ms var(--lentur); }

/* Pil inovasi terangkat sedikit lebih tinggi daripada pil biasa, dan
   kilaunya menyapu tiap 7 detik. */
.pil-inovasi { transition: background 160ms ease, box-shadow 200ms ease, transform 160ms var(--lentur); }
.pil-inovasi:hover { transform: translateY(-2px); }

.pil-inovasi::after {
    content    : '';
    position   : absolute;
    inset-block : -50%;
    inset-inline-start: 0;
    width      : 34%;
    background : linear-gradient(90deg, transparent, rgb(255 255 255 / 85%), transparent);
    pointer-events: none;
    animation  : kilau 7s 1.6s infinite ease-out;
}

.pil-inovasi .pil-lencana { transition: transform 260ms var(--lentur); }
.pil-inovasi:hover .pil-lencana { transform: rotate(-8deg) scale(1.08); }

/* Kotak pencarian melebar sedikit saat difokuskan. */
.cari-kotak { transition: box-shadow 220ms ease, transform 220ms var(--lentur); }
.cari-kotak:focus-within { transform: translateY(-2px); }

.tombol-tema svg { transition: transform 320ms var(--lentur); }
.tombol-tema:hover svg { transform: rotate(18deg); }

/* --- 12. Penyesuaian gerak & cetak ----------------------------------------- */

/* Pengguna yang meminta gerak dikurangi mendapat halaman yang sama persis,
   hanya tanpa perpindahan. Animasi berbasis gulir perlu dilepas terpisah:
   animation-duration tidak berlaku padanya, sehingga tanpa animation-timeline
   dikembalikan ke auto, isinya justru tertahan di keadaan awal — tidak
   terlihat sama sekali. */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration  : 0.01ms !important;
        animation-delay     : 0ms !important;
        animation-iteration-count: 1 !important;
        animation-timeline  : auto !important;
        transition-duration : 0.01ms !important;
        scroll-behavior     : auto !important;
    }

    html { scroll-behavior: auto; }

    .kartu:hover,
    .pil:hover,
    .pil-inovasi:hover,
    .cari-kotak:focus-within { transform: none; }

    /* Kilau dilepas seluruhnya, bukan dipercepat: gerak berulang justru yang
       paling mengganggu bagi yang meminta gerak dikurangi. */
    .pil-inovasi::after,
    .sorot-kilau { display: none; }

    .pil-inovasi:hover .pil-lencana { transform: none; }

    .kartu:hover .kartu-ikon img,
    .kartu:hover .mono,
    .inov-tabel tbody tr:hover .inov-logo img,
    .tombol-tema:hover svg { transform: none; }

    .baris:hover,
    :root[data-hasil="cari"] .kartu:hover { padding-inline-start: 12px; }

    /* Pita komitmen berhenti dan kalimatnya dibungkus jadi paragraf biasa.
       Menghentikan animasinya saja TIDAK cukup: teksnya nowrap di dalam
       jendela yang overflow-hidden, jadi separuh kalimat akan terpotong.
       Salinan kedua dilepas — ia cuma penambal sambungan animasi.

       display: block pada jalurnya WAJIB, dan inilah bagian yang mudah
       terlewat: .pita-teks memakai flex: none supaya tiap salinan selebar
       isinya saat berjalan, dan flex-shrink 0 di dalamnya tetap berlaku
       setelah animasi mati — salinan yang tersisa tinggal selebar max-content
       lalu dipotong .pita-lintas, bukan membungkus. Melepas tata letak flex
       pada jalurnya menyelesaikannya tanpa menyentuh aturan saat berjalan. */
    .pita-jalur { animation: none; display: block; width: auto; }
    .pita-teks  { white-space: normal; padding-inline-end: 0; align-items: flex-start; }
    .pita-ikon  { margin-block-start: 3px; }
    .pita-teks[aria-hidden="true"] { display: none; }
}

/* Beberapa peramban lama tidak mengenal color-mix; beri warna padat. */
@supports not (background: color-mix(in srgb, red 50%, blue)) {
    .kepala { background: var(--latar-tinggi); }
}

/* Versi cetak berguna sebagai daftar tautan pegangan meja: seluruh 62 entri
   ikut tercetak karena tidak ada lagi yang disembunyikan di balik dialog. */
@media print {
    .kepala, .sorot, .rel, .tombol-tema, .lewati,
    .cari-kotak, .cari-bantuan { display: none; }

    /* Pita komitmen ikut tercetak, utuh dan diam (alasannya di bagian 4). */
    .pita       { background: none; border-bottom: 0; }
    .pita-jalur { animation: none; display: block; width: auto; }
    .pita-teks  { white-space: normal; padding-inline-end: 0; align-items: flex-start; }
    .pita-ikon  { margin-block-start: 3px; }
    .pita-teks[aria-hidden="true"] { display: none; }

    .kartu, .baris    { break-inside: avoid; box-shadow: none; }
    .bagian           { break-before: auto; }
    .bagian-kepala h2 { break-after: avoid; }
    .daftar           { columns: 2; }

    /* Tabel register dicetak utuh: tanpa gulir samping, dan tiap barisnya
       tidak terpotong pindah halaman. */
    .tabel-bingkai    { overflow: visible; }
    .inov-tabel       { min-width: 0; }
    .inov-tabel tr    { break-inside: avoid; }
    .unit-baris th    { break-after: avoid; }

    body { background: #fff; color: #000; display: block; min-height: 0; }
}


/* --- 13. Aksesibilitas ----------------------------------------------------- */

/* Seluruh pengaturan di bagian ini dikendalikan atribut data-* pada <html>,
   dipasang oleh lib/aksesibilitas.php sebelum halaman tergambar. Tidak ada
   gaya yang ditulis dari JavaScript: mematikan JavaScript hanya berarti
   panelnya tidak muncul, bukan tampilan yang rusak. */

/* 13a. Ukuran teks -------------------------------------------------------- */

/* Kelipatannya sengaja tidak terlalu jauh. Melewati 1.35 membuat judul
   terpanjang ("BADAN KEPEGAWAIAN DAN PENGEMBANGAN SUMBER DAYA MANUSIA")
   memaksa kartu jadi sangat tinggi, dan bilah kategori pecah jadi tiga baris. */
:root[data-teks="kecil"]        { --skala-teks: 0.9; }
:root[data-teks="besar"]        { --skala-teks: 1.15; }
:root[data-teks="sangat-besar"] { --skala-teks: 1.35; }

/* Pada teks yang diperbesar, pemotongan judul kartu dilepas: memperbesar
   huruf lalu memotongnya di baris ketiga tidak menolong siapa pun. */
:root[data-teks="besar"] .kartu-judul,
:root[data-teks="sangat-besar"] .kartu-judul {
    -webkit-line-clamp: unset;
    overflow          : visible;
}

/* 13b. Kontras tinggi ----------------------------------------------------- */

/* Hitam-putih murni dengan tepi tegas. Warna merek dipertahankan hanya pada
   unsur yang tetap lolos 4.5:1, sisanya diturunkan ke hitam atau putih. */
:root[data-kontras="tinggi"] {
    --latar        : #ffffff;
    --latar-tinggi : #ffffff;
    --latar-lembut : #f0f0f0;
    --garis        : #000000;
    --garis-tegas  : #000000;

    /* TIDAK dilunakkan di sini. Tepi yang samar adalah kebalikan dari yang
       diminta mode ini, dan yang membutuhkannya tidak dapat memberi tahu kita
       bahwa kartunya tidak lagi terlihat berbatas. */
    --garis-lembut : #000000;

    --teks        : #000000;
    --teks-lembut : #000000;

    --utama       : #00335f;
    --utama-kuat  : #00243f;
    --sorot-awal  : #00243f;
    --sorot-akhir : #00243f;

    --fokus        : #000000;
    --bahaya       : #8a0000;
    --bahaya-latar : #ffffff;

    /* Bayangan tidak menyampaikan apa pun bagi mata yang butuh kontras
       tinggi, dan justru mengaburkan tepi. Digantikan garis. */
    --bayang-1 : none;
    --bayang-2 : none;
}

:root[data-kontras="tinggi"][data-tema="gelap"] {
    --latar        : #000000;
    --latar-tinggi : #000000;
    --latar-lembut : #1a1a1a;
    --garis        : #ffffff;
    --garis-tegas  : #ffffff;
    --garis-lembut : #ffffff;

    --teks        : #ffffff;
    --teks-lembut : #ffffff;

    --utama       : #9ccdf5;
    --utama-kuat  : #c9e4fb;
    --sorot-awal  : #000000;
    --sorot-akhir : #000000;

    --fokus        : #ffd24a;
    --bahaya       : #ff9a9a;
    --bahaya-latar : #000000;
}

/* Tepi dipertegas dan seluruh gaya yang mengandalkan kelembutan dimatikan. */
:root[data-kontras="tinggi"] .kartu,
:root[data-kontras="tinggi"] .pil,
:root[data-kontras="tinggi"] .rel-lipat,
:root[data-kontras="tinggi"] .baris,
:root[data-kontras="tinggi"] .a11y-panel,
:root[data-kontras="tinggi"] .a11y-picu,
:root[data-kontras="tinggi"] .tombol-tema {
    border-width: 2px;
}

/* Panel sorot rata, bukan gradien: gradien membuat rasio kontras teks putih
   berubah-ubah sepanjang lebarnya. */
:root[data-kontras="tinggi"] .sorot { background: var(--sorot-awal); }

/* Kilau dan foto pimpinan bersifat hiasan, dan keduanya menurunkan kontras
   teks yang tersapu di atasnya. */
:root[data-kontras="tinggi"] .sorot-kilau,
:root[data-kontras="tinggi"] .tokoh { display: none; }

/* Pil register inovasi memakai gradien hijau-biru; diratakan agar teks
   putihnya punya satu rasio yang bisa dipastikan. */
:root[data-kontras="tinggi"] .pil-inovasi {
    background  : var(--sorot-awal);
    border-color: var(--garis);
    box-shadow  : none;
}

:root[data-kontras="tinggi"] .pil[aria-current="true"] {
    background: var(--utama-kuat);
    color     : var(--latar);
}

/* Pil di dalam panel pelipat sengaja bertepi bening supaya panelnya tidak
   terbaca sebagai tumpukan kotak; di mode ini tepi itu justru diperlukan
   sebagai pemisah antarbaris. */
@media (max-width: 699.98px) {
    :root[data-kontras="tinggi"] .rel[data-lipat="siap"] .rel-kat .pil {
        border-color: var(--garis);
        background  : var(--latar-tinggi);
    }

    :root[data-kontras="tinggi"] .rel[data-lipat="siap"] .rel-kat .pil[aria-current="true"] {
        background: var(--utama-kuat);
        color     : var(--latar);
    }
}

/* Tautan wajib bergaris di mode ini: warna saja bukan penanda yang cukup. */
:root[data-kontras="tinggi"] a { text-decoration: underline; }

/* Pita komitmen didiamkan juga di sini: yang membutuhkan kontras tinggi
   umumnya membaca lebih lambat, dan teks berjalan menghapus keuntungan itu. */
:root[data-kontras="tinggi"] .pita-jalur { animation: none; display: block; width: auto; }
:root[data-kontras="tinggi"] .pita-teks  { white-space: normal; padding-inline-end: 0; align-items: flex-start; }
:root[data-kontras="tinggi"] .pita-ikon  { margin-block-start: 3px; }
:root[data-kontras="tinggi"] .pita-teks[aria-hidden="true"] { display: none; }

/* 13c. Mode abu-abu ------------------------------------------------------- */

/* Diterapkan pada <html>, bukan body: filter pada body menjadikannya
   containing block bagi elemen position:fixed, sehingga panel aksesibilitas
   dan garis panduan baca ikut bergeser. Tidak ada isi di top layer pada
   portal ini (tidak ada <dialog>), jadi tidak ada yang lolos dari filter. */
:root[data-abu="ya"] { filter: grayscale(1); }

/* 13d. Garis bawah tautan ------------------------------------------------- */

:root[data-garis="ya"] a {
    text-decoration          : underline;
    text-underline-offset    : 3px;
    text-decoration-thickness: 1px;
}

/* Kartu dan baris daftar seluruhnya berupa tautan; menggarisbawahi seluruh
   isinya membuat ikon dan lencana ikut tergaris. Cukup judulnya. */
:root[data-garis="ya"] .kartu,
:root[data-garis="ya"] .baris { text-decoration: none; }

:root[data-garis="ya"] .kartu-judul,
:root[data-garis="ya"] .baris-judul { text-decoration: underline; }

/* 13e. Garis panduan baca ------------------------------------------------- */

.a11y-garis-baca { display: none; }

:root[data-panduan="ya"] .a11y-garis-baca {
    display       : block;
    position      : fixed;
    inset-inline  : 0;
    top           : 0;
    height        : 2.6em;
    z-index       : 60;
    pointer-events: none;
    border-block  : 2px solid var(--utama);
    background    : color-mix(in srgb, var(--utama) 10%, transparent);
    /* Posisi tegaknya disetel JavaScript lewat translateY. */
    transform     : translateY(-100%);
    will-change   : transform;
}

@supports not (background: color-mix(in srgb, red 50%, blue)) {
    :root[data-panduan="ya"] .a11y-garis-baca { background: rgb(27 85 138 / 10%); }
}

/* 13f. Panel -------------------------------------------------------------- */

.a11y {
    position        : fixed;
    inset-inline-end: clamp(12px, 2vw, 22px);
    bottom          : clamp(12px, 2vw, 22px);
    z-index         : 70;
}

.a11y-picu {
    display      : grid;
    place-items  : center;
    width        : 52px;
    height       : 52px;
    border       : 1px solid var(--garis);
    border-radius: 50%;
    background   : var(--utama-kuat);
    color        : #fff;
    cursor       : pointer;
    box-shadow   : var(--bayang-2);
    transition   : transform 160ms ease, background 160ms ease;
}

.a11y-picu svg   { width: 28px; height: 28px; }
.a11y-picu:hover { transform: scale(1.06); }
.a11y-picu[aria-expanded="true"] { background: var(--biru-600); }

/* Pada tema gelap --utama-kuat berupa biru muda, jadi ikon putih di atasnya
   tidak terbaca. Warnanya dibalik. */
:root[data-tema="gelap"] .a11y-picu { color: #06121c; }

.a11y-panel {
    position        : absolute;
    inset-inline-end: 0;
    bottom          : 64px;
    width           : min(310px, calc(100vw - 32px));
    max-height      : min(70vh, 560px);
    overflow-y      : auto;
    border          : 1px solid var(--garis);
    border-radius   : var(--lengkung);
    background      : var(--latar-tinggi);
    color           : var(--teks);
    box-shadow      : var(--bayang-2);
}

.a11y-panel[hidden] { display: none; }

.a11y-kepala {
    display        : flex;
    align-items    : center;
    justify-content: space-between;
    gap            : 12px;
    padding        : 13px 15px;
    border-bottom  : 1px solid var(--garis);
}

.a11y-kepala h2 { font-size: 0.95rem; margin: 0; }

.a11y-tutup {
    display      : grid;
    place-items  : center;
    width        : 32px;
    height       : 32px;
    flex         : none;
    border       : 1px solid var(--garis);
    border-radius: 8px;
    background   : var(--latar-tinggi);
    color        : var(--teks-lembut);
    cursor       : pointer;
}

.a11y-tutup:hover { background: var(--latar-lembut); color: var(--teks); }
.a11y-tutup svg   { width: 15px; height: 15px; }

.a11y-isi  { padding: 14px 15px 16px; }
.a11y-grup { margin-bottom: 16px; }

.a11y-label {
    display       : block;
    margin-bottom : 7px;
    color         : var(--teks-lembut);
    font-size     : 0.72rem;
    font-weight   : 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
}

.a11y-ukuran { display: flex; gap: 6px; }

.a11y-ukuran button {
    flex         : 1;
    min-height   : 44px;              /* target sentuh WCAG */
    border       : 1px solid var(--garis);
    border-radius: 9px;
    background   : var(--latar-tinggi);
    color        : var(--teks);
    font         : inherit;
    font-weight  : 700;
    cursor       : pointer;
}

.a11y-ukuran button:nth-child(1) { font-size: 0.78rem; }
.a11y-ukuran button:nth-child(2) { font-size: 0.92rem; }
.a11y-ukuran button:nth-child(3) { font-size: 1.06rem; }
.a11y-ukuran button:nth-child(4) { font-size: 1.2rem; }
.a11y-ukuran button:hover        { background: var(--latar-lembut); }

.a11y-ukuran button[aria-pressed="true"] {
    background  : var(--utama);
    border-color: var(--utama);
    color       : var(--latar-tinggi);
}

.a11y-alih {
    display        : flex;
    align-items    : center;
    justify-content: space-between;
    gap            : 10px;
    width          : 100%;
    min-height     : 44px;
    margin-bottom  : 6px;
    padding        : 8px 11px;
    border         : 1px solid var(--garis);
    border-radius  : 9px;
    background     : var(--latar-tinggi);
    color          : var(--teks);
    font           : inherit;
    text-align     : start;
    cursor         : pointer;
}

.a11y-alih:hover { background: var(--latar-lembut); }

.a11y-alih-teks        { display: flex; flex-direction: column; line-height: 1.3; }
.a11y-alih-teks strong { font-size: 0.83rem; font-weight: 600; }
.a11y-alih-teks small  { font-size: 0.71rem; color: var(--teks-lembut); }

/* Suis: penanda visual saja. Keadaan sesungguhnya ada pada aria-pressed,
   itulah yang dibaca teknologi bantu. */
.a11y-suis {
    position     : relative;
    flex         : none;
    width        : 38px;
    height       : 22px;
    border       : 1px solid var(--garis-tegas);
    border-radius: 999px;
    background   : var(--latar-lembut);
    transition   : background 160ms ease, border-color 160ms ease;
}

.a11y-suis::after {
    content           : "";
    position          : absolute;
    top               : 2px;
    inset-inline-start: 2px;
    width             : 16px;
    height            : 16px;
    border-radius     : 50%;
    background        : var(--teks-lembut);
    transition        : transform 160ms ease, background 160ms ease;
}

.a11y-alih[aria-pressed="true"] .a11y-suis {
    background  : var(--utama);
    border-color: var(--utama);
}

.a11y-alih[aria-pressed="true"] .a11y-suis::after {
    background: var(--latar-tinggi);
    transform : translateX(16px);
}

.a11y-reset {
    width        : 100%;
    min-height   : 44px;
    border       : 1px solid var(--garis-tegas);
    border-radius: 9px;
    background   : var(--latar-lembut);
    color        : var(--teks);
    font         : inherit;
    font-size    : 0.83rem;
    font-weight  : 600;
    cursor       : pointer;
}

.a11y-reset:hover { background: var(--garis); }

/* Panel tidak berguna di atas kertas. */
@media print {
    .a11y, .a11y-garis-baca { display: none; }
}

/* Yang meminta gerak dikurangi tidak perlu suis yang meluncur maupun tombol
   yang membesar. */
@media (prefers-reduced-motion: reduce) {
    .a11y-picu:hover              { transform: none; }
    .a11y-suis, .a11y-suis::after { transition: none; }
}

/* Catatan kecil di bawah sakelar suara. Dipakai untuk hal yang harus
   diketahui pengunjung sebelum menyalakannya — terutama bahwa suara Bahasa
   Indonesia di Windows umumnya milik layanan daring, sehingga teks yang
   dibacakan meninggalkan komputernya. Portal ini tidak melakukan satu pun
   permintaan ke pihak ketiga, jadi pengecualian itu perlu disebut. */
.a11y-catatan {
    margin       : 8px 0 0;
    padding      : 8px 10px;
    border       : 1px solid var(--garis);
    border-radius: 8px;
    background   : var(--latar-lembut);
    color        : var(--teks-lembut);
    font-size    : 0.7rem;
    line-height  : 1.45;
}

.a11y-catatan[hidden] { display: none; }

/* Penanda pada tombol picu selagi ada yang dibacakan, supaya keadaan itu
   terlihat dan bukan hanya terdengar. */
:root[data-suara="ya"] .a11y-picu::after {
    content      : "";
    position     : absolute;
    top          : 2px;
    inset-inline-end: 2px;
    width        : 11px;
    height       : 11px;
    border       : 2px solid var(--latar-tinggi);
    border-radius: 50%;
    background   : #12b47c;
}

.a11y-picu { position: relative; }
