/* ==========================================================================
   LAPORAN HARIAN DATIN & HSI — sistem visual "espresso"
   ==========================================================================

   ARAH RANCANGAN

   Yang dibaca orang di halaman ini adalah TABEL ANGKA. Jadi seluruh sistem
   ini bekerja untuk satu hal: membuat angka jadi benda paling tenang dan
   paling jelas di layar, lalu membuat semua yang lain mundur tanpa hilang.

   Versi paling lama gagal justru karena berusaha terlalu keras — semuanya
   berkotak, berbayang, dan biru saturated dipakai untuk tujuh peran
   sekaligus. Akibatnya tidak ada yang menonjol karena semuanya menonjol.

   ENAM TEMA, SATU SISTEM. Espresso adalah bawaan, dan dia yang dipakai kalau
   tidak ada yang memilih apa pun. Lima tema lain (Bata, Senja, Hutan,
   Nokturn, Kertas) datang dari palet yang ditentukan mentor, dan semuanya
   hidup sebagai SATU blok token di bagian 1b — bukan sebagai salinan berkas.

   Yang membuat itu mungkin: TIDAK ADA SATU PUN ATURAN DI BAWAH BAGIAN 1 YANG
   MENYEBUT WARNA LANGSUNG. Semuanya lewat token. Aturan ini bukan kerapian —
   dia yang menentukan apakah tema ketujuh nanti butuh sepuluh baris atau
   seribu. Kalau ada warna mentah menyelip ke aturan biasa, gejalanya khas:
   satu benda tetap berwarna sama di enam tema.

   Lima dari enam tema gelap, satu terang (Kertas). Itu sebabnya token seperti
   `--cahaya`, `--noda`, dan `--gelap` ada: mereka menamai PERAN cahayanya
   (sorot spekular, bidang tipis, bayangan) alih-alih nilainya, jadi aturan
   yang sama tetap benar waktu arah cahayanya berbalik.

   ENAM ATURAN YANG DIPEGANG KONSISTEN

   1. GROUND-NYA KAYU BAKAR, BUKAN NAVY.
      Dasarnya espresso hangat (#17130f), bukan abu-biru gelap. Semua netral
      punya rona cokelat yang sama, jadi layar terasa seperti ruangan yang
      lampunya hangat — bukan panel LED. Abu-biru gelap (#0c0e12, versi paling
      lama) itu yang membuat halaman ini dulu terbaca "cyberpunk"; yang
      mengubahnya bukan tingkat gelapnya, tapi ronanya.

   2. TIDAK ADA WARNA UNTUK "PENTING". YANG ADA CUMA TERANG.
      `--sorot` bukan biru: dia krem (#f3ece1). Tombol utama, penanda tab
      terpilih, dan titik carousel aktif semuanya krem di atas espresso. Ini
      menghapus penyebab terbesar kesan "template admin": satu warna saturated
      yang diulang di mana-mana sampai tidak ada artinya lagi.

      SATU pengecualian, dan sengaja: baris jumlah tabel TIDAK memakai
      `--sorot`. Alasannya ada di bagian 9.

   3. SATU WARNA SINYAL, DIPAKAI HEMAT: TANAH LIAT (`--aksen`, #d99a63).
      Cuma untuk dua hal — garis pemantik di atas judul dan cincin fokus.
      Tidak pernah jadi latar blok besar.

      Sejak peta panas sel dilepas, ada satu warna sinyal KEDUA di tabel:
      `--usia-tua` untuk angka di kolom usia 61 hari ke atas. Dia berdiri
      sendiri dan tidak boleh dipakai untuk apa pun selain itu — begitu
      merah ini muncul di tempat lain, "merah = sudah terlalu lama" berhenti
      berlaku dan tabelnya kehilangan satu-satunya tanda cepatnya.

   4. MERAH TELKOM CUMA IDENTITAS, SEKALI PER LAYAR.
      Tanda merek di kiri atas. Titik. Tidak ada garis merah kedua.

   5. KACA ITU BAHAN, BUKAN HIASAN.
      Buram (`backdrop-filter`) cuma dipakai di benda yang MELAYANG di atas
      benda lain — bilah atas, strip KPI, panel tabel, dok carousel, kartu
      pendamping, lembar, obrolan, dan kepala tabel yang menempel. Benda yang
      duduk rata di ground tidak diberi kaca, karena tidak ada apa pun di
      bawahnya yang layak terlihat menembus.

      Tiga hal yang membuat kaca terbaca sebagai kaca, dan ketiganya harus ada
      bersamaan — ini yang paling sering setengah dikerjakan:
        a. ADA CAHAYA DI BELAKANGNYA. Empat noda hangat di `.latar-nyala`,
           salah satunya ditaruh persis di belakang tempat panggung berdiri.
           Tanpa itu, buramnya tidak mengaburkan apa pun.
        b. ADA TEPI SPEKULAR. Satu noda krem encer yang keluar dari pojok
           kiri ATAS tiap benda — dan arahnya SAMA untuk semua benda, karena
           cahaya yang datang dari arah berbeda-beda per benda langsung
           membongkar ilusinya. (Satu pengecualian: dok, yang cahayanya dari
           bawah karena dia sisi bawah satu benda bersama panggung.)
        c. ISIANNYA COKELAT YANG DIANGKAT, BUKAN PUTIH YANG DIENCERKAN.
           Di ground gelap, putih encer langsung jadi kabut abu — dan itu
           kesalahan yang paling sering membuat "glassmorphism" terlihat murah.

   6. HIERARKI DARI TIPOGRAFI, BUKAN DARI UKURAN KOTAK.
      Angka besar ditulis TIPIS (berat 320-340), label kecil ditulis TEBAL
      dengan tracking lebar. Ini kebalikan dari refleks biasa, dan justru
      inilah yang membuat angka besar terbaca mahal alih-alih berteriak. Di
      latar gelap berat tipis makin penting: huruf terang di atas gelap selalu
      terlihat lebih tebal daripada ukuran aslinya (iradiasi), jadi berat yang
      "pas" di kertas jadi gemuk di sini.

   TENTANG GERAK
   Hanya `transform` dan `opacity` yang dianimasikan pada benda yang bergerak,
   karena keduanya dikerjakan compositor tanpa menghitung ulang tata letak.
   Tidak ada animasi `width`/`height`/`top` di berkas ini.
   ========================================================================== */

@font-face {
  font-family: 'Plus Jakarta Sans';
  src: url('fonts/PlusJakartaSans-latin.woff2') format('woff2');
  font-weight: 200 800;
  font-display: swap;
}

/* ==========================================================================
   1. TOKEN
   ========================================================================== */

:root {
  /* --- netral espresso: SEMUANYA punya rona cokelat yang sama ---
     Ini bukan mode gelap hasil inversi, dan bukan setengah dari sepasang tema.
     Ini SATU-SATUNYA versi. Kanvasnya kayu bakar (#17130f), bukan navy dan
     bukan abu — dan itu yang membuatnya tetap masuk permintaan "warm, calm,
     premium" alih-alih jatuh ke cyberpunk. Abu-biru gelap (#0c0e12, versi
     paling lama) terasa seperti panel LED; cokelat gelap terasa seperti
     ruangan yang lampunya hangat.

     Satu versi itu keputusan, bukan pekerjaan yang belum selesai: setiap
     nilai di berkas ini jadi bisa disetel untuk SATU latar saja, dan tidak
     ada satu pun kompromi yang harus benar di dua tempat sekaligus. */
  --kanvas:        #17130f;
  --kanvas-dalam:  #100d0a;
  --permukaan:     #211b16;

  /* Kaca: isian setengah tembus untuk benda yang MELAYANG.
     Di atas ground gelap, kaca bekerja TERBALIK dari kaca di atas kertas —
     isiannya harus lebih terang daripada latarnya (cokelat yang diangkat),
     bukan lebih putih. Putih encer di atas espresso langsung terbaca sebagai
     kabut abu, dan itu kesalahan yang paling sering membuat "glassmorphism"
     terlihat murah.

     Tepi terangnya BUKAN token warna sendiri — dia `--kilau` di bawah, yang
     bentuknya `inset box-shadow` dan bukan border. Sempat ada `--kaca-tepi`
     di sini; dibuang setelah audit menunjukkan tidak ada satu pun `var()`
     yang menunjuknya. */
  --kaca:          rgba(52, 43, 35, .55);
  /* Kaca "padat" untuk benda yang harus DIBACA sambil melayang di atas tabel
     penuh angka — lembar dan panel obrolan. 92%, bukan 55%. */
  --kaca-padat:    rgba(43, 35, 28, .92);

  /* --- TIGA WARNA CAHAYA, DAN INI YANG MEMBUAT ENAM TEMA MUNGKIN ---
     Ketiganya menamai PERAN, bukan nilai:

       --cahaya  sorot spekular. Cahaya yang MENIMPA benda dari kiri atas:
                 tepi kaca, gradasi di puncak bilah atas, kilau. Di tema
                 gelap dia krem hangat; di Kertas dia putih.
       --noda    bidang tipis yang MENGANGKAT permukaan sedikit saja: zebra
                 tabel, jalur batang, garis, keping tombol hantu. Di tema
                 gelap arahnya ke terang (krem encer); di Kertas berbalik
                 jadi tinta encer.
       --gelap   bayangan. Nyaris hitam, tapi ikut rona temanya masing-masing
                 — bayangan netral di atas ground berona terbaca sebagai
                 kotor, bukan sebagai bayangan.

     Karena ketiganya token, aturan seperti "tepi atas panel = kilau" tetap
     satu aturan walau arah cahayanya berbalik total di tema Kertas. */
  --cahaya:        #fff0dc;
  --noda:          #f0dec4;
  --gelap:         #080503;
  /* Cahaya ambien di sekeliling benda kaca — madu, bukan hitam. Ini yang
     bekerja sebagai "bayangan" di ground gelap: benda kaca dipisahkan dari
     latarnya oleh cahaya yang bocor di sekitarnya, bukan oleh gelap. */
  --ambien:        #c8803a;

  /* Empat noda cahaya di latar. Ditaruh di token karena tiap tema memakai
     warna paletnya sendiri di sini — dan justru noda inilah yang membuat
     kacanya punya sesuatu untuk dikaburkan (lihat bagian 3). */
  --nyala-1:       rgba(198, 120, 58, .30);
  --nyala-2:       rgba(170, 72, 50, .22);
  --nyala-3:       rgba(152, 104, 56, .18);
  --nyala-4:       rgba(118, 94, 60, .24);

  /* Butiran latar. Di ground gelap butiran harus MENAMBAH cahaya (overlay);
     di kertas dia harus mengurangi (multiply). Dua-duanya di token supaya
     aturannya di bagian 3 tidak perlu tahu tema apa yang sedang jalan. */
  --butir-alpha:   .22;
  --butir-blend:   overlay;

  /* Garis: alpha `--noda`, bukan hex abu. Dengan alpha, garis selalu terbaca
     sebagai cahaya tipis di tepi bahan — jadi ikut hangat sendiri di atas
     kanvas maupun di atas kaca, dan ikut berbalik arah sendiri di Kertas. */
  --garis:         color-mix(in srgb, var(--noda) 11%, transparent);
  --garis-tegas:   color-mix(in srgb, var(--noda) 22%, transparent);

  /* Lima tingkat bidang tipis, dipakai di seluruh berkas alih-alih menulis
     alpha satu-satu di tiap aturan. Dulu tiap tempat menulis sendiri
     (.022, .035, .05, .07, .09, .1, .11) — tujuh nilai untuk lima peran,
     dan tidak ada satu pun yang bisa disetel ulang per tema. */
  --noda-1:        color-mix(in srgb, var(--noda) 2.5%, transparent);
  --noda-2:        color-mix(in srgb, var(--noda) 4%, transparent);
  --noda-3:        color-mix(in srgb, var(--noda) 5.5%, transparent);
  --noda-4:        color-mix(in srgb, var(--noda) 8%, transparent);
  --noda-5:        color-mix(in srgb, var(--noda) 12%, transparent);

  /* Keping beku: isian tombol hantu & tab. Sengaja BUKAN --noda-3: di Kertas
     keping harus lebih TERANG dari groundnya sementara zebra harus lebih
     gelap, jadi keduanya tidak bisa satu token walau di lima tema gelap
     arahnya kebetulan sama. */
  --keping:        color-mix(in srgb, var(--cahaya) 5%, transparent);
  --keping-kuat:   color-mix(in srgb, var(--cahaya) 12%, transparent);

  /* Tirai di belakang lembar, dan cekung di dalam bilah pindah halaman. */
  --tirai:         color-mix(in srgb, var(--gelap) 58%, transparent);
  --cekung:        inset 0 2px 5px color-mix(in srgb, var(--gelap) 30%, transparent);

  --tinta:         #f3ece1;
  --tinta-2:       #b8ab99;
  --tinta-3:       #8b7f6f;

  /* Merah Telkom — identitas, sekali per layar. Dinaikkan terangnya dari
     #c8102e: merah pekat di atas espresso jadi lumpur, bukan merah. */
  --merek:         #f4626f;
  --merek-lembut:  #2c1512;
  /* Ujung gelap gradasi tanda merek, dan tinta di ATAS keping merah (kabar
     galat). Keduanya dulu ditulis langsung di dalam aturannya. */
  --merek-dalam:   #4a0010;
  --di-merek:      #2a0d10;

  /* "Sorot" = KREM. Bukan warna, cuma terang. Tombol utama, penanda tab
     terpilih, dan titik carousel aktif semuanya krem di atas espresso — dan
     itu justru lebih tenang daripada warna saturated apa pun, sekaligus tetap
     jadi benda paling jelas di layar. Ini yang menghapus penyebab terbesar
     kesan "template admin": satu warna saturated yang diulang di mana-mana
     sampai tidak ada artinya lagi. */
  --sorot:         #f3ece1;
  --sorot-tekan:   #ffffff;
  --sorot-teks:    #1b1611;
  --sorot-lembut:  #2e2620;
  --sorot-tepi:    color-mix(in srgb, var(--noda) 20%, transparent);

  /* Satu-satunya warna sinyal: tanah liat, dinaikkan terangnya supaya tetap
     terbaca sebagai WARNA (bukan sekadar cokelat lain) di atas kanvas cokelat.
     Cuma untuk dua hal — garis pemantik di atas judul dan cincin fokus.
     Tidak pernah jadi latar blok besar. */
  --aksen:         #d99a63;
  --aksen-lembut:  #2b2017;
  /* Ujung terang gradasi batang. Satu warna, satu tugas — dulu ini `#e6c79a`
     yang ditulis langsung di dalam aturan `.batang-isi`, dan itu satu-satunya
     alasan batang perbandingan akan tetap cokelat di kelima tema lain. */
  --aksen-2:       #e6c79a;
  /* Semantik. "Naik" pada tumpukan order itu kabar buruk, jadi warnanya
     bukan hijau — hijau (lumut) dipakai untuk yang berkurang. */
  --naik:          #e08a5f;
  --naik-lembut:   #2a1a11;
  --turun:         #93b884;
  --turun-lembut:  #16210f;
  /* Tinta di ATAS keping hijau (kabar berhasil, ikon hasil unggah). Di tema
     gelap dia arang; di Kertas putih. */
  --di-turun:      #14210f;
  --awas:          #dfb45c;
  --awas-lembut:   #251d0c;

  /* Angka di kolom usia 61 hari ke atas. Menggantikan peta panas sel, yang
     dulu mewarnai SELURUH permukaan sel menurut besar angkanya.

     Sengaja bukan `--merek` walau merah Telkom juga merah dan sudah disetel
     untuk kedua ground: warna merek dipakai untuk menyebut Telkom, dan
     begitu dia juga berarti "order ini sudah terlalu lama", tidak ada lagi
     cara membedakan keduanya di halaman yang sama.

     Satu nilai untuk kelima tema gelap, satu lagi di Kertas — sama seperti
     `--naik`/`--turun`. Merah tidak perlu ikut berganti rona per tema; kalau
     ikut, dia berhenti terbaca sebagai satu sinyal yang selalu sama.
     Angkanya diverifikasi `npm run test:tema` terhadap keenam tema. */
  --usia-tua:      #f07a6e;

  /* Tiga bidang PADAT di tabel — padat, bukan alpha, karena ketiganya
     menempel (`position: sticky`) dan harus benar-benar menutupi angka yang
     lewat di bawahnya. */
  --kepala-tabel: #241d18;
  --kaki-tabel:   #322a22;
  --kaki-pojok:   #3c3229;

  /* --- ruang, jenjang 4px --- */
  --r1: 4px;  --r2: 8px;  --r3: 12px; --r4: 16px;
  --r5: 24px; --r6: 32px; --r7: 48px; --r8: 72px;

  --lengkung:    18px;
  --lengkung-s:  12px;
  --lengkung-l:  26px;

  /* --- bayang: pekat, berlapis, tidak pernah dianimasikan ---
     Di atas ground gelap, bayangan bekerja jauh lebih lemah daripada di atas
     kertas: yang memisahkan benda dari latarnya bukan bayangnya lagi, tapi
     tepi terangnya (`--kilau`) dan cahaya ambien hangat di sekelilingnya.
     Itu sebabnya setiap benda kaca di sini punya satu bayang tambahan yang
     warnanya madu, bukan hitam — itu cahaya, bukan bayangan. */
  --bayang-1: 0 1px 2px color-mix(in srgb, var(--gelap) 45%, transparent);
  --bayang-2: 0 1px 2px color-mix(in srgb, var(--gelap) 40%, transparent),
              0 14px 34px -14px color-mix(in srgb, var(--gelap) 62%, transparent);
  --bayang-3: 0 4px 14px color-mix(in srgb, var(--gelap) 50%, transparent),
              0 34px 74px -20px color-mix(in srgb, var(--gelap) 72%, transparent);
  --bayang-sorot: 0 6px 20px -8px color-mix(in srgb, var(--sorot) 26%, transparent);
  /* Sorot 1px di sisi atas benda kaca. Inset shadow, bukan border — border
     ikut menggeser tata letak, inset tidak. */
  --kilau: inset 0 1px 0 color-mix(in srgb, var(--cahaya) 13%, transparent);

  /* --- gerak: sengaja sedikit lebih lambat dari versi paling lama ---
     Yang diminta "calm". Transisi 120ms terbaca sebagai klik; 260ms terbaca
     sebagai gerakan. Bedanya tipis tapi terasa sepanjang hari. */
  --cepat:  140ms;
  --sedang: 260ms;
  --lambat: 460ms;
  --pegas:  cubic-bezier(.34, 1.28, .64, 1);
  --halus:  cubic-bezier(.22, .61, .36, 1);

  --lebar-isi: 1340px;
  --tinggi-atas: 70px;

  color-scheme: dark;
}

/* ==========================================================================
   1b. LIMA TEMA LAIN
   ==========================================================================
   Espresso di atas adalah bawaan, dan dia hidup di `:root` tanpa atribut.
   Lima blok di bawah menimpanya lewat `html[data-tema="…"]`, yang dipasang
   sebelum lukisan pertama oleh potongan skrip di `index.html`.

   ATURAN YANG MEMBUAT INI BISA DIKERJAKAN SEPENDEK INI
   Tidak ada satu pun aturan di bawah bagian 1 yang menyebut warna langsung.
   Semua lewat token. Jadi satu tema = satu blok token, bukan satu salinan
   berkas — dan menambah tema ketujuh nanti tidak menyentuh apa pun selain
   bagian ini. Kalau suatu saat ada warna mentah muncul di aturan biasa, dia
   akan tetap sama di enam tema dan itulah gejalanya.

   YANG SENGAJA TIDAK IKUT BERGANTI
   `--merek` (merah Telkom), `--naik`/`--turun`/`--awas` (semantik), dan
   `--sorot-tekan` tetap sama di lima tema gelap. Warna yang ARTINYA tetap
   tidak boleh ikut ganti rupa tiap tema — "naik" yang jadi hijau di satu tema
   dan jingga di tema lain berhenti berarti apa pun. Yang ikut berganti cuma
   bidang di BELAKANGnya (`--naik-lembut`), supaya keping semantiknya tetap
   duduk di ruangan yang sama.

   Tema terang (Kertas) adalah pengecualian di hampir semua hal, dan blok
   terakhir menjelaskan kenapa satu per satu.
   ========================================================================== */

/* --------------------------------------------------------------------------
   BATA
   Palet mentor #1: #60241E #95271D #B34A44 #E77B49 — semuanya satu keluarga
   merah-terakota, tidak ada warna dingin sama sekali. Jadi tema ini yang
   paling dekat ke espresso: bedanya ground-nya bata (rona 8°), bukan kayu
   bakar (rona 30°), dan sinyalnya jingga terang alih-alih tanah liat.

   Yang perlu diperhatikan: `--merek` (#f4626f) tetap merah Telkom di sini,
   dan di ground bata dia satu keluarga dengan seluruh palet. Tandanya masih
   kebaca sebagai tanda karena bentuknya keping bergradasi + bayang, bukan
   karena warnanya beda — dan itu memang cara kerjanya di lima tema lain.
   -------------------------------------------------------------------------- */
:root[data-tema='bata'] {
  --kanvas:        #1f110f;
  --kanvas-dalam:  #170c0b;
  --permukaan:     #291816;
  --kaca:          rgba(59, 39, 35, .55);
  --kaca-padat:    rgba(50, 31, 28, .92);

  --cahaya:        #ffe7db;
  --noda:          #edd1c4;
  --gelap:         #090504;
  --ambien:        #bf663d;

  --nyala-1:       rgba(179, 74, 68, .28);
  --nyala-2:       rgba(149, 39, 29, .22);
  --nyala-3:       rgba(231, 123, 73, .15);
  --nyala-4:       rgba(149, 39, 29, .22);

  --tinta:         #fae5db;
  --tinta-2:       #b8a59e;
  --tinta-3:       #82706b;

  --sorot:         #fae5db;
  --sorot-teks:    #221411;
  --sorot-lembut:  #36221f;

  --aksen:         #e77b49;
  --aksen-2:       #eea07c;
  --aksen-lembut:  #391f17;

  --merek-lembut:  #391b1b;
  --naik-lembut:   #362019;
  --turun-lembut:  #2d251d;
  --awas-lembut:   #362518;

  --kepala-tabel:  #2c1a18;
  --kaki-tabel:    #3a2522;
  --kaki-pojok:    #422d2a;
}

/* --------------------------------------------------------------------------
   SENJA
   Palet mentor #2: #0F3040 #464858 #A56F63 #D99B7F — dan ini palet paling
   menarik dari kelimanya, karena dia sepasang: dua dingin (petrol, slate)
   lawan dua hangat (tanah, persik). Jadi tema ini satu-satunya yang
   TINTANYA HANGAT DI ATAS GROUND DINGIN (#f7ebe5 di atas petrol) — persis
   pertukaran yang dimaksud paletnya, dan yang membuatnya terasa seperti
   ruangan sore alih-alih dashboard biru.
   -------------------------------------------------------------------------- */
:root[data-tema='senja'] {
  --kanvas:        #0e1920;
  --kanvas-dalam:  #0a1318;
  --permukaan:     #14222b;
  --kaca:          rgba(33, 51, 61, .55);
  --kaca-padat:    rgba(26, 43, 52, .92);

  --cahaya:        #ffe6db;
  --noda:          #edd1c4;
  --gelap:         #040709;
  --ambien:        #b3806a;

  --nyala-1:       rgba(165, 111, 99, .28);
  --nyala-2:       rgba(70, 72, 88, .22);
  --nyala-3:       rgba(217, 155, 127, .15);
  --nyala-4:       rgba(70, 72, 88, .22);

  --tinta:         #f7ebe5;
  --tinta-2:       #b1acaa;
  --tinta-3:       #777779;

  --sorot:         #f7ebe5;
  --sorot-teks:    #101c24;
  --sorot-lembut:  #1d2e38;

  --aksen:         #d99b7f;
  --aksen-2:       #e4b7a3;
  --aksen-lembut:  #282a2c;

  --merek-lembut:  #2a2229;
  --naik-lembut:   #272728;
  --turun-lembut:  #1e2c2c;
  --awas-lembut:   #272c27;

  --kepala-tabel:  #16252e;
  --kaki-tabel:    #20323c;
  --kaki-pojok:    #283a45;
}

/* --------------------------------------------------------------------------
   HUTAN
   Palet mentor #3: #092328 #12544F #2A835F #8BBB92 — pinus ke sage.

   Rona dasarnya SENGAJA digeser ke 164° (hijau), bukan ke 190° milik
   #092328. Alasannya praktis: rona 190° hampir sama dengan rona ground
   Senja (202°), jadi kalau diikuti apa adanya, dua tema berbeda akan
   terlihat sama di layar. Dengan 164°, groundnya jelas hijau pinus dan
   Senja jelas petrol — dua tema, dua ruangan.
   -------------------------------------------------------------------------- */
:root[data-tema='hutan'] {
  --kanvas:        #0e201b;
  --kanvas-dalam:  #0a1814;
  --permukaan:     #142b25;
  --kaca:          rgba(33, 61, 54, .55);
  --kaca-padat:    rgba(26, 52, 45, .92);

  --cahaya:        #dbffe1;
  --noda:          #c4edca;
  --gelap:         #040908;
  --ambien:        #739b79;

  --nyala-1:       rgba(42, 131, 95, .28);
  --nyala-2:       rgba(18, 84, 79, .22);
  --nyala-3:       rgba(139, 187, 146, .15);
  --nyala-4:       rgba(18, 84, 79, .22);

  --tinta:         #e8f1e9;
  --tinta-2:       #a7b2ab;
  --tinta-3:       #707e78;

  --sorot:         #e8f1e9;
  --sorot-teks:    #10241e;
  --sorot-lembut:  #1d3831;

  --aksen:         #8bbb92;
  --aksen-2:       #abceb1;
  --aksen-lembut:  #1e342a;
  --merek-lembut:  #2a2825;
  --naik-lembut:   #272d23;
  --turun-lembut:  #1e3228;
  --awas-lembut:   #273223;

  --kepala-tabel:  #162e27;
  --kaki-tabel:    #203c34;
  --kaki-pojok:    #28453d;
}

/* --------------------------------------------------------------------------
   NOKTURN
   Palet mentor #4: #091540 #1B2CC1 #7692FF #ABD2FA — biru malam ke es.

   Ini tema yang paling berisiko jatuh ke "cyberpunk", justru yang dihindari
   waktu sistem ini dibangun. Yang menahannya dua hal: #1B2CC1 (biru
   listrik) TIDAK PERNAH jadi bidang besar — dia cuma noda cahaya di latar
   dengan alpha .22; dan tangga terangnya sama dengan tema lain, jadi
   kontras teksnya tenang, bukan menyala. Sinyalnya #7692FF, dan biru es
   #ABD2FA cuma jadi ujung gradasi batang.
   -------------------------------------------------------------------------- */
:root[data-tema='nokturn'] {
  --kanvas:        #0d1121;
  --kanvas-dalam:  #090c19;
  --permukaan:     #13182c;
  --kaca:          rgba(32, 38, 62, .55);
  --kaca-padat:    rgba(25, 31, 53, .92);

  --cahaya:        #dbedff;
  --noda:          #c4d8ed;
  --gelap:         #040509;
  --ambien:        #6179d3;

  --nyala-1:       rgba(118, 146, 255, .28);
  --nyala-2:       rgba(27, 44, 193, .22);
  --nyala-3:       rgba(171, 210, 250, .15);
  --nyala-4:       rgba(27, 44, 193, .22);

  --tinta:         #eef6fe;
  --tinta-2:       #abb1bc;
  --tinta-3:       #727884;

  --sorot:         #eef6fe;
  --sorot-teks:    #0f1325;
  --sorot-lembut:  #1c223a;

  --aksen:         #7692ff;
  --aksen-2:       #abd2fa;
  --aksen-lembut:  #1b223e;

  --merek-lembut:  #291b2a;
  --naik-lembut:   #262028;
  --turun-lembut:  #1d252d;
  --awas-lembut:   #262528;

  --kepala-tabel:  #151a2f;
  --kaki-tabel:    #1f253d;
  --kaki-pojok:    #272d46;
}

/* --------------------------------------------------------------------------
   KERTAS — dan ini satu-satunya tema TERANG
   Palet mentor #5: #3368A0 #66A3BF #C8DFDB #F2EFE7. Palet ini beda jenis dari
   empat sebelumnya: warna paling gelapnya (#3368A0) masih terang sekali, dan
   warna paling terangnya (#F2EFE7) itu persis "warm off-white" yang jadi
   permintaan pertama sistem ini. Memaksanya jadi tema gelap berarti membuang
   tiga dari empat warnanya.

   KENAPA BLOKNYA PANJANG SEKALI
   Kaca di atas kertas bekerja TERBALIK dari kaca di atas ground gelap, dan
   hampir semua nilai yang di lima tema lain bisa diturunkan otomatis harus
   ditulis ulang di sini:
     - Isian kaca jadi PUTIH yang diencerkan, bukan cokelat yang diangkat.
     - `--noda` (bidang tipis: zebra, jalur batang, keping) jadi TINTA yang
       sangat encer, bukan krem — arahnya berbalik dari terang ke gelap.
     - Bayangan kembali jadi bayangan sungguhan: alphanya turun dari .45-.72
       ke .05-.30, karena di kertas yang memisahkan benda dari latarnya
       memang bayangnya, bukan tepi terangnya.
     - `--kilau` naik dari 13% ke 90%: sorot putih di tepi atas benda putih
       cuma terbaca kalau hampir pekat.
     - Peta panas turun jauh (.03-.33 dari .05-.38): tinta gelap di atas
       kertas tampak jauh lebih kuat daripada krem di atas espresso pada
       alpha yang sama.
     - Butiran latar berbalik dari `overlay` ke `multiply`. Di kertas,
       butiran harus MENGURANGI cahaya; overlay di sini tidak terlihat.
     - Merah Telkom balik ke #c8102e aslinya (di ground gelap dia jadi
       lumpur, jadi di sana dinaikkan ke #f4626f), dan tinta di atas keping
       merah/hijau jadi putih, bukan arang.
   -------------------------------------------------------------------------- */
:root[data-tema='kertas'] {
  --kanvas:        #f2efe7;
  --kanvas-dalam:  #e2e9e4;
  --permukaan:     #fdfcf8;
  --kaca:          rgba(253, 252, 248, .62);
  --kaca-padat:    rgba(253, 252, 248, .93);

  --cahaya:        #ffffff;
  --noda:          #17293a;
  --gelap:         #24404f;
  --ambien:        #66a3bf;

  /* Noda cahaya di latar: di kertas dia berperan sebagai WASH, bukan sebagai
     sumber cahaya — jadi alphanya jauh lebih tinggi (.16-.50 lawan .15-.28)
     tapi warnanya yang paling pucat dari paletnya. */
  --nyala-1:       rgba(102, 163, 191, .42);
  --nyala-2:       rgba(51, 104, 160, .20);
  --nyala-3:       rgba(200, 223, 219, .62);
  --nyala-4:       rgba(102, 163, 191, .34);

  --garis:         rgba(23, 41, 58, .14);
  --garis-tegas:   rgba(23, 41, 58, .26);

  --tinta:         #17293a;
  --tinta-2:       #4e6577;
  --tinta-3:       #6d8493;

  /* Di kertas, "yang paling jelas" bukan yang paling terang — dia yang paling
     GELAP. Jadi `--sorot` di sini biru-arang, bukan krem, dan seluruh aturan
     yang memakainya (tombol utama, penanda tab, titik carousel aktif) tetap
     benar tanpa satu pun perubahan. */
  --sorot:         #1e3a52;
  --sorot-tekan:   #12283a;
  --sorot-teks:    #f7faf9;
  --sorot-lembut:  #e7ede9;
  --sorot-tepi:    rgba(23, 41, 58, .2);

  --aksen:         #3368a0;
  --aksen-2:       #66a3bf;
  --aksen-lembut:  #e7eff5;

  --merek:         #c8102e;
  --merek-lembut:  #fbebe9;
  --di-merek:      #ffffff;

  --naik:          #a2452a;
  --naik-lembut:   #f7eae4;
  --turun:         #4d6b45;
  --turun-lembut:  #ebf1e9;
  --di-turun:      #ffffff;
  --awas:          #7f611b;
  --awas-lembut:   #f7f1de;

  --usia-tua:      #b3261e;

  --kepala-tabel:  #f8f6ef;
  --kaki-tabel:    #e4eae5;
  --kaki-pojok:    #d7e1dc;

  /* Keping beku (tombol hantu, tab): di kertas isiannya PUTIH yang diencerkan
     — lebih terang dari groundnya, bukan lebih gelap. Ini satu-satunya tempat
     arah `--noda` tidak cukup, jadi kedua nilainya ditulis sendiri. */
  --keping:        rgba(253, 252, 248, .55);
  --keping-kuat:   rgba(253, 252, 248, .92);

  --bayang-1: 0 1px 2px rgba(36, 64, 79, .06);
  --bayang-2: 0 1px 2px rgba(36, 64, 79, .05), 0 12px 30px -14px rgba(36, 64, 79, .2);
  --bayang-3: 0 4px 12px rgba(26, 50, 64, .1), 0 30px 68px -18px rgba(26, 50, 64, .3);
  --bayang-sorot: 0 6px 18px -6px rgba(30, 58, 82, .38);
  --cekung: inset 0 2px 5px rgba(36, 64, 79, .1);
  --kilau: inset 0 1px 0 rgba(255, 255, 255, .9);
  --tirai: rgba(30, 50, 64, .28);

  --butir-alpha: .15;
  --butir-blend: multiply;

  color-scheme: light;
}

/* ==========================================================================
   2. DASAR
   ========================================================================== */

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

/* ATURAN INI MEMPERBAIKI BUG, BUKAN GAYA — jangan dihapus.
   ------------------------------------------------------------------------
   `[hidden]` bekerja lewat gaya bawaan browser `[hidden] { display: none }`,
   dan gaya bawaan itu punya prioritas PALING RENDAH. Begitu ada satu aturan
   penulis yang menyetel `display` pada elemen yang sama, `hidden` berhenti
   berfungsi sama sekali — elemennya tetap ada di tata letak, cuma tidak
   terlihat.

   Di berkas ini ada tiga elemen seperti itu: `.obrol` (display: flex),
   `.lembar` (display: flex), dan turunannya. Ketiganya `position: fixed`
   dengan `opacity: 0`, jadi tidak terlihat — tapi mereka MENANGKAP KLIK dan
   MENELAN GULIRAN di seluruh kotaknya.

   Gejalanya persis yang dilaporkan: panah carousel di kanan bawah "tidak
   responsif" (tertutup panel obrolan 408x620px yang tak terlihat di pojok
   yang sama), dan halaman "susah digulir pakai touchpad" (`.obrol-alur` di
   dalamnya punya `overflow-y: auto` + `overscroll-behavior: contain`, jadi
   gulir di daerah itu masuk ke kotak obrolan yang kosong dan tidak diteruskan
   ke halaman).

   Dibuktikan lewat `document.elementFromPoint` di titik tengah kedua panah:
   yang terambil `obrol-alur`, bukan tombolnya.

   `!important` di sini disengaja: justru aturan penulis lain (`display: flex`
   itu) yang harus dikalahkan, dan menambah `:not([hidden])` di setiap
   selektor berarti menaruh jebakan yang sama untuk elemen berikutnya. */
[hidden] { display: none !important; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  min-height: 100vh;
  font-family: 'Plus Jakarta Sans', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
  font-size: 14.5px;
  line-height: 1.55;
  font-weight: 450;
  color: var(--tinta);
  background: var(--kanvas);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* Judul: berat 600, bukan 700 — dan di latar gelap itu lebih penting lagi.
   Huruf terang di atas espresso selalu terlihat lebih tebal daripada ukuran
   aslinya, jadi 700 terbaca sebagai tebal yang memaksa. */
h1, h2, h3, h4 { margin: 0; font-weight: 600; letter-spacing: -.022em; line-height: 1.22; }
p { margin: 0; }
button, input, select, textarea { font: inherit; color: inherit; }
button { cursor: pointer; border: none; background: none; }
svg { width: 1em; height: 1em; display: block; flex: none; }

/* Angka: SELALU tabular, di mana pun. Tanpa ini kolom angka bergoyang
   kiri-kanan antar baris dan mata kehilangan jejaknya. */
.angka, .tabel td, .tabel th, .kpi-nilai, .stat-nilai, .pil-angka {
  font-variant-numeric: tabular-nums;
  font-feature-settings: 'tnum' 1;
}

.lewati {
  position: fixed; top: var(--r2); left: var(--r2); z-index: 200;
  padding: var(--r2) var(--r4); border-radius: var(--lengkung-s);
  background: var(--sorot); color: var(--sorot-teks); font-weight: 600; text-decoration: none;
  transform: translateY(-200%);
  transition: transform var(--sedang) var(--halus);
}
.lewati:focus-visible { transform: translateY(0); }

/* Cincin fokus pakai tanah liat, bukan arang: di atas benda arang (tombol
   utama), cincin arang tidak akan terlihat sama sekali. */
:focus-visible {
  outline: 2px solid var(--aksen);
  outline-offset: 2px;
  border-radius: var(--r1);
}

/* Tiga detail yang TIDAK terlihat di potret tapi terasa dipakai sepanjang
   hari — dan justru yang begini yang membedakan halaman yang dirancang dari
   halaman yang cuma diwarnai:

   1. Bilah gulir. Bawaan Chrome abu-biru, dan di tabel yang digulir tiap hari
      dia jadi satu-satunya benda dingin di layar hangat.
   2. Warna seleksi teks. Bawaannya biru terang — merusak paletnya persis di
      saat orang menyalin angka untuk ditempel ke tempat lain.
   3. Kursor teks di kotak isian. Hitam bawaan, sementara semua penanda
      interaktif lain di sini tanah liat. */
* {
  scrollbar-width: thin;
  scrollbar-color: var(--garis-tegas) transparent;
}

::selection { background: color-mix(in srgb, var(--aksen) 24%, transparent); color: var(--tinta); }

input, textarea { caret-color: var(--aksen); }

/* ==========================================================================
   3. LATAR
   ==========================================================================
   Dua lapisan `position: fixed` di belakang segalanya, jadi menganimasikannya
   tidak pernah menyentuh tata letak halaman.

   Lapisan pertama: tiga noda cahaya hangat (pasir, terakota, madu) yang
   bergerak sangat lambat. Lapisan kedua: BUTIRAN. Versi lama memakai kisi
   garis 56px — dan kisi garis itu penanda paling khas "dashboard hasil
   generate". Butiran mengerjakan tugas yang sama (memberi tekstur supaya
   kanvasnya tidak terlihat seperti bidang kosong) tanpa membawa asosiasi itu,
   dan dia yang membuat ground-nya terbaca sebagai bahan, bukan sebagai
   kegelapan.                                                                */

.latar { position: fixed; inset: 0; z-index: 0; pointer-events: none; overflow: hidden; }

/* EMPAT noda, bukan tiga — dan yang keempat ada karena kaca.
   ------------------------------------------------------------------------
   Kaca cuma terlihat sebagai kaca kalau ada SESUATU di belakangnya yang
   berubah waktu ditembus. Di putaran-putaran awal, seluruh cahaya menumpuk di
   pojok kiri atas; akibatnya panel kaca yang duduk di tengah halaman melayang
   di atas kanvas rata, dan buramnya tidak mengaburkan apa pun — jadi dia
   terbaca sebagai bidang pucat, bukan sebagai kaca.

   Noda keempat (madu, kiri-tengah) ditaruh persis di belakang tempat panggung
   berdiri. Itu yang membuat tepi atas panel menangkap cahaya, dan yang
   membuat sisi bawahnya sedikit lebih redup daripada sisi atasnya. */
.latar-nyala {
  position: absolute; inset: -25%;
  background:
    radial-gradient(46% 38% at 12% 0%,   var(--nyala-1), transparent 64%),
    radial-gradient(40% 34% at 92% -4%,  var(--nyala-2), transparent 62%),
    radial-gradient(44% 40% at 26% 46%,  var(--nyala-3), transparent 68%),
    radial-gradient(60% 52% at 76% 98%,  var(--nyala-4), transparent 70%);
  transition: opacity var(--lambat) var(--halus);
  will-change: transform;
  animation: apung 34s ease-in-out infinite alternate;
}
@keyframes apung {
  from { transform: translate3d(0, 0, 0) scale(1); }
  to   { transform: translate3d(1.6%, -1.2%, 0) scale(1.05); }
}

.latar-kisi {
  position: absolute; inset: 0;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)' opacity='.55'/%3E%3C/svg%3E");
  background-size: 180px 180px;
  /* Di ground gelap butirannya harus MENAMBAH cahaya, bukan mengurangi — jadi
     blend-nya `overlay`. Dengan `multiply`, butiran di atas espresso cuma
     membuatnya makin pekat dan teksturnya hilang sama sekali. Di tema Kertas
     yang berlaku justru kebalikannya, jadi dua-duanya token. */
  opacity: var(--butir-alpha);
  mix-blend-mode: var(--butir-blend);
}
/* ==========================================================================
   4. BILAH ATAS
   ==========================================================================
   Satu-satunya benda yang menempel dan melayang di atas seluruh isi halaman,
   jadi satu-satunya yang wajib berkaca. Buramnya kuat (24px) dengan saturasi
   dinaikkan: tanpa saturasi, warna yang lewat di belakang kaca jadi pucat dan
   kacanya terbaca sebagai kabut abu.                                        */

.atas {
  position: sticky; top: 0; z-index: 60;
  /* Isiannya diturunkan ke 60% dan buramnya dinaikkan ke 30px. Pertukaran yang
     disengaja: makin tembus isiannya, makin terlihat apa yang lewat di
     belakang — dan makin kuat buramnya, makin tetap terbaca teks di atasnya.
     Yang salah adalah mengubah cuma salah satu dari keduanya. */
  background:
    linear-gradient(to bottom, color-mix(in srgb, var(--cahaya) 7%, transparent), transparent 62%),
    color-mix(in srgb, var(--kanvas) 62%, transparent);
  backdrop-filter: blur(30px) saturate(165%);
  -webkit-backdrop-filter: blur(30px) saturate(165%);
}

.atas-dalam {
  max-width: var(--lebar-isi); margin: 0 auto;
  min-height: var(--tinggi-atas);
  padding: var(--r2) var(--r6);
  display: flex; align-items: center; gap: var(--r5);
}

/* Garis bawah yang muncul saat digulir. Yang berubah cuma `transform: scaleX`
   dan `opacity` — bukan `height` atau `border-width`. */
.atas-garis {
  height: 1px; background: var(--garis);
  transform: scaleX(0); transform-origin: left;
  transition: transform var(--lambat) var(--halus);
}
.atas.tergulir .atas-garis { transform: scaleX(1); }

.merek { display: flex; align-items: center; gap: var(--r3); min-width: 0; }

.merek-tanda {
  width: 32px; height: 32px; flex: none;
  display: grid; place-items: center;
  border-radius: 10px;
  /* Satu-satunya merah di layar. */
  background: linear-gradient(150deg, var(--merek), color-mix(in srgb, var(--merek) 72%, var(--merek-dalam)));
  /* Putih di sini SENGAJA bukan token: apa pun temanya, tanda ini selalu
     keping merah bergradasi, jadi tintanya selalu putih. */
  color: #fff; font-size: 16px;
  box-shadow: 0 2px 12px -2px color-mix(in srgb, var(--merek) 55%, transparent), var(--kilau);
}

.merek-teks { display: flex; flex-direction: column; min-width: 0; }
.merek-judul { font-weight: 600; font-size: 14px; letter-spacing: -.02em; }
.merek-sub {
  font-size: 11px; color: var(--tinta-3); font-weight: 500;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* --- pindah halaman DATIN / HSI --- */

.pindah {
  position: relative; display: flex; gap: 2px; padding: 3px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--kanvas-dalam) 62%, transparent);
  box-shadow: var(--cekung), 0 0 0 1px var(--garis);
  margin-inline: auto;
}

/* Penanda yang meluncur: satu elemen digeser dengan `translate3d`, jadi
   perpindahannya mulus tanpa memaksa dua tombol menghitung ulang ukurannya. */
.pindah-geser {
  position: absolute; top: 3px; left: 3px; z-index: 0;
  height: calc(100% - 6px);
  border-radius: 999px;
  background: var(--sorot);
  box-shadow: var(--bayang-sorot);
  transition: transform var(--sedang) var(--pegas), width var(--sedang) var(--halus);
  will-change: transform;
}

.pindah-tombol {
  position: relative; z-index: 1;
  padding: 7px 22px; border-radius: 999px;
  font-weight: 600; font-size: 12.5px; letter-spacing: .04em;
  color: var(--tinta-2);
  transition: color var(--sedang) var(--halus);
}
.pindah-tombol:hover { color: var(--tinta); }
.pindah-tombol.aktif { color: var(--sorot-teks); }

.atas-alat { display: flex; align-items: center; gap: 6px; }

/* ==========================================================================
   5. TOMBOL
   ==========================================================================
   Tombol hantu SENGAJA tidak punya latar sendiri saat diam — cuma garis tipis.
   Di bilah atas yang berkaca, tombol berlatar putih penuh terlihat seperti
   tambalan yang menutupi kacanya.                                           */

.tombol {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  padding: 8px 14px; border-radius: 10px;
  font-weight: 600; font-size: 12.5px; white-space: nowrap;
  border: 1px solid transparent;
  transition: background var(--cepat) var(--halus), color var(--cepat) var(--halus),
              border-color var(--cepat) var(--halus), transform var(--cepat) var(--halus);
}
.tombol svg { font-size: 15px; }
.tombol:active { transform: scale(.975); }
.tombol[disabled] { opacity: .45; pointer-events: none; }

.tombol-utama {
  background: var(--sorot); color: var(--sorot-teks);
  box-shadow: var(--bayang-sorot), inset 0 -1px 0 rgba(0, 0, 0, .1);
}
.tombol-utama:hover { background: var(--sorot-tekan); }

/* Tombol hantu jadi keping BEKU, bukan garis kosong: isian sangat tipis
   (28%) plus buram 10px. Bedanya kecil di potret dan besar waktu digulir —
   kepingnya punya bahan, jadi dia ikut keluarga yang sama dengan panel dan
   lembar alih-alih terlihat seperti garis yang menempel di kaca bilah atas. */
.tombol-hantu {
  color: var(--tinta-2); border-color: var(--garis);
  background: var(--keping);
  backdrop-filter: blur(10px) saturate(130%);
  -webkit-backdrop-filter: blur(10px) saturate(130%);
}
.tombol-hantu:hover { color: var(--tinta); border-color: var(--garis-tegas); background: var(--keping-kuat); }

.tombol-sunyi { color: var(--tinta-2); }
.tombol-sunyi:hover { color: var(--tinta); background: var(--sorot-lembut); }

.tombol-bulat { width: 33px; height: 33px; padding: 0; border-radius: 50%; }
.tombol-lebar { width: 100%; padding: 11px; font-size: 14px; }
.tombol-kecil { padding: 5px 11px; font-size: 11.5px; border-radius: var(--r2); }

.tutup::before {
  content: ''; width: 13px; height: 13px;
  background: currentColor;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.2' stroke-linecap='round'%3E%3Cpath d='M6 6l12 12M18 6L6 18'/%3E%3C/svg%3E") center/contain no-repeat;
}

/* ==========================================================================
   5b. PEMILIH TEMA
   ==========================================================================
   Enam tema, dan pemilihnya harus mengambil ruang sekecil mungkin di bilah
   atas — dia perkakas yang dipakai sekali lalu dilupakan, bukan navigasi.

   Jadi tombolnya SATU KEPING 2x2 tanpa teks, dan kepingnya bukan gambar:
   keempat kotaknya memakai token tema yang sedang jalan (`--kanvas`,
   `--kaki-pojok`, `--aksen`, `--tinta`), jadi tombolnya selalu memperlihatkan
   tema yang sedang aktif tanpa satu pun label. Ikon palet bergambar akan
   menuntut orang menebak; keping ini tidak.

   Di dalam menunya kebalikannya: yang ditampilkan palet mentor APA ADANYA,
   bukan token turunannya. Alasannya di `tema.js` — singkatnya, kelima ground
   turunan nyaris hitam semua, jadi barisnya akan terlihat seragam justru di
   tempat orang harus membedakannya.                                        */

.tema-bungkus { position: relative; display: flex; }

/* (0,3,0) supaya tetap menang di atas `.atas-alat .tombol { padding: 8px 10px }`
   milik layar sempit — kepingnya persegi, dan padding asimetris membuatnya
   berhenti persegi. */
.atas-alat .tombol.tombol-tema { width: 33px; height: 33px; padding: 0; }

.tema-keping {
  display: grid;
  grid-template: repeat(2, 1fr) / repeat(2, 1fr);
  width: 17px; height: 17px;
  border-radius: 5px; overflow: hidden;
  box-shadow: 0 0 0 1px var(--garis-tegas), var(--kilau);
}
/* Aturan layar sempit menyembunyikan `span` di dalam tombol bilah atas
   (`.atas-alat .tombol span`) untuk membuang labelnya. Keping ini juga span,
   jadi tanpa pengecualian ini tombolnya jadi kotak kosong di ponsel. */
.atas-alat .tombol-tema .tema-keping { display: grid; }
.tema-keping i { display: block; }

.tombol-tema[aria-expanded='true'] {
  color: var(--tinta);
  border-color: var(--garis-tegas);
  background: var(--keping-kuat);
}

/* --- menunya --- */

.tema-menu {
  position: absolute; top: calc(100% + 10px); right: 0; z-index: 5;
  width: 268px; max-width: calc(100vw - 24px);
  padding: var(--r2);
  border-radius: var(--lengkung);
  /* ISIANNYA PADAT, DAN INI SATU-SATUNYA PANEL DI BERKAS INI YANG BEGITU.
     ------------------------------------------------------------------------
     Putaran pertama menu ini memakai `--kaca-padat` + `backdrop-filter:
     blur(26px)` seperti lembar dan panel obrolan. Hasilnya: teks di belakang
     menu tetap TERBACA — bukan samar, tapi terbaca — dan buramnya tidak
     mengerjakan apa pun.

     Sebabnya bukan alphanya. Menu ini anak dari `.atas`, dan `.atas` punya
     `backdrop-filter` sendiri. Elemen yang punya backdrop-filter membentuk
     BACKDROP ROOT: turunannya cuma bisa mengaburkan apa yang dilukis di dalam
     akar itu, dan di dalam bilah atas tidak ada apa-apa di bawah menu ini.
     Jadi buramnya mengaburkan bidang kosong, sementara isian .92-nya tetap
     melewatkan 8% halaman di belakangnya tanpa dikaburkan sedikit pun.

     Gejalanya khas dan mudah salah dibaca sebagai "alphanya kurang": makin
     dinaikkan alphanya makin bersih, dan buramnya tetap tidak pernah bekerja.
     Lembar dan panel obrolan tidak kena karena keduanya anak `<body>`.

     Jadi menu ini padat, dan kacanya datang dari yang lain: sorot spekular di
     pojok kiri atas, tepi rambut, kilau 1px, bayang berlapis, dan pendar
     ambien. Kelimanya tidak butuh backdrop sama sekali. */
  background:
    radial-gradient(120% 90% at 8% -10%, color-mix(in srgb, var(--cahaya) 11%, transparent), transparent 52%),
    var(--permukaan);
  box-shadow: var(--bayang-3), var(--kilau), 0 0 90px -30px color-mix(in srgb, var(--ambien) 26%, transparent);
  border: 1px solid var(--garis);
  animation: temaMenuMasuk var(--sedang) var(--halus) both;
}
@keyframes temaMenuMasuk {
  from { opacity: 0; transform: translate3d(0, -6px, 0) scale(.985); }
  to   { opacity: 1; transform: none; }
}

.tema-menu-kepala {
  padding: 6px 10px 8px;
  font-size: 9.5px; font-weight: 700; letter-spacing: .16em; text-transform: uppercase;
  color: var(--tinta-3);
}

.tema-baris {
  display: grid; grid-template-columns: 46px 1fr 14px; align-items: center; gap: var(--r3);
  width: 100%; padding: 7px 10px;
  border-radius: var(--lengkung-s);
  text-align: left;
  transition: background var(--cepat) var(--halus);
}
.tema-baris:hover { background: var(--sorot-lembut); }
.tema-baris[aria-checked='true'] { background: var(--sorot-lembut); }

/* Palet: empat pita, TANPA celah dan tanpa sudut membulat di dalamnya —
   satu bidang utuh yang terbagi empat. Dengan celah, keempatnya terbaca
   sebagai empat benda; tanpa celah, terbaca sebagai satu palet. */
.tema-palet {
  display: grid; grid-template-columns: repeat(4, 1fr);
  height: 18px; border-radius: 5px; overflow: hidden;
  box-shadow: 0 0 0 1px var(--garis), var(--kilau);
}
.tema-palet i { display: block; }

.tema-teks { display: flex; flex-direction: column; min-width: 0; }
.tema-nama { font-size: 12.5px; font-weight: 600; color: var(--tinta-2); letter-spacing: -.01em; }
.tema-catatan {
  font-size: 10.5px; font-weight: 500; color: var(--tinta-3);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.tema-baris:hover .tema-nama,
.tema-baris[aria-checked='true'] .tema-nama { color: var(--tinta); }

/* Centang cuma muncul di yang terpilih. Dia tanah liat, bukan krem: di baris
   yang latarnya sudah terangkat, krem di atas krem berhenti terbaca. */
.tema-tanda { width: 14px; height: 14px; }
.tema-baris[aria-checked='true'] .tema-tanda {
  background: var(--aksen);
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.6' stroke-linecap='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E") center/contain no-repeat;
}

.tema-menu-kaki {
  margin-top: 6px; padding: 8px 10px 4px;
  border-top: 1px solid var(--garis);
  font-size: 10.5px; color: var(--tinta-3);
}

/* --- pergantian temanya sendiri ---
   Enam puluhan warna berganti dalam satu frame terbaca sebagai KEDIPAN, jadi
   pergantiannya dilewatkan View Transitions: peramban memotret halaman lama
   dan baru, lalu menyilangkan keduanya di compositor.

   Yang perlu ditimpa di sini: perpindahan DATIN <-> HSI (bagian 6b) memakai
   pseudo-elemen yang sama, tapi dia MENGGESER halaman dan membekukan bilah
   atas. Untuk ganti tema keduanya salah — tidak ada yang berpindah tempat,
   dan bilah atas justru salah satu yang paling berubah warnanya. Jadi kelas
   `tema-pindah` (dipasang tepat sebelum transisi, dibuang setelahnya)
   mengembalikan keduanya jadi silang-pudar di tempat.

   Tidak dibungkus `prefers-reduced-motion` karena `tema.js` sudah memeriksa
   sendiri: yang tidak mau gerak tidak pernah memulai transisinya, jadi
   pseudo-elemen ini tidak pernah ada untuk mereka. */
html.tema-pindah .atas { view-transition-name: none; }
html.tema-pindah::view-transition-old(root) { animation: temaPudarKeluar 340ms var(--halus) both; }
html.tema-pindah::view-transition-new(root) { animation: temaPudarMasuk 420ms var(--halus) both; }
@keyframes temaPudarKeluar { to { opacity: 0; } }
@keyframes temaPudarMasuk { from { opacity: 0; } to { opacity: 1; } }

/* ==========================================================================
   6. HALAMAN
   ========================================================================== */

main { position: relative; z-index: 1; }

.halaman {
  max-width: var(--lebar-isi); margin: 0 auto;
  padding: var(--r7) var(--r6) var(--r8);
}

/* Masuknya isi halaman waktu berganti dataset. Sengaja pendek dan cuma naik
   10px: perpindahan tab itu tindakan yang sering diulang, dan animasi panjang
   di situ berubah dari "mulus" jadi "lambat". */
@keyframes masuk {
  from { opacity: 0; transform: translate3d(0, 10px, 0); }
  to   { opacity: 1; transform: none; }
}
.halaman > * { animation: masuk 300ms var(--halus) backwards; }

/* ==========================================================================
   6b. PERPINDAHAN DATIN <-> HSI
   ==========================================================================
   ARAHNYA MENGIKUTI LETAK TOMBOLNYA. Pindah ke tab kanan menggeser isi ke
   kiri, dan sebaliknya — `--arah` disetel `1` atau `-1` oleh app.js sebelum
   perpindahan dimulai. Arah yang searah dengan tempat yang diklik membuat
   perpindahannya terbaca sebagai "berpindah halaman"; arah yang selalu sama
   terbaca sebagai "layar berkedip".

   Dipakai lewat View Transitions API: browser mengambil potret halaman lama
   dan halaman baru, lalu menyilangkan keduanya di compositor. Karena yang
   dianimasikan potret (bukan elemen sungguhan), tidak ada satu pun
   perhitungan tata letak yang terjadi selama perpindahan.                   */

@media (prefers-reduced-motion: no-preference) {
  ::view-transition-old(root),
  ::view-transition-new(root) { animation: none; mix-blend-mode: normal; }

  ::view-transition-old(root) { animation: halamanKeluar 320ms var(--halus) both; }
  ::view-transition-new(root) { animation: halamanMasuk 420ms var(--halus) both; }

  /* Yang lama pergi lebih cepat daripada yang baru datang, dan jaraknya lebih
     pendek (3% vs 4%). Timpang begini disengaja: yang baru jadi terasa
     "mendorong masuk" alih-alih dua lapisan yang bertukar tempat. */
  @keyframes halamanKeluar {
    to { opacity: 0; transform: translate3d(calc(var(--arah, 1) * -3%), 0, 0); }
  }
  @keyframes halamanMasuk {
    from { opacity: 0; transform: translate3d(calc(var(--arah, 1) * 4%), 0, 0); }
    to   { opacity: 1; transform: none; }
  }

  /* Bilah atas tidak ikut bergeser — dia jangkar yang membuat isinya terasa
     berganti di dalam kerangka yang sama. */
  .atas { view-transition-name: bilah-atas; }
  ::view-transition-group(bilah-atas) { animation-duration: 0ms; }
  ::view-transition-old(bilah-atas),
  ::view-transition-new(bilah-atas) { animation: none; opacity: 1; }
}

/* --- judul halaman ---
   Versi lama memasang batang merah 3px di sisi kiri judul. Itu dibuang: garis
   berwarna di kiri judul adalah salah satu tanda template admin yang paling
   mudah dikenali, dan merahnya jadi merah KEDUA di layar.

   Penggantinya kerlingan mata (eyebrow) di ATAS judul — label mikro tanah
   liat dengan tracking lebar. Ini pola editorial: pembaca dapat konteks
   sebelum judulnya, bukan hiasan di sebelahnya.                             */

.judul-halaman {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: var(--r6); flex-wrap: wrap;
  margin-bottom: var(--r6);
}

.judul-kiri { min-width: 0; }

.judul-halaman h1 {
  font-size: clamp(2rem, 4.2vw, 3.05rem);
  font-weight: 380;
  letter-spacing: -.035em;
  line-height: 1.04;
}

/* Garis pemantik di ATAS judul, bukan di sebelahnya. Pendek (40px), tipis
   (2px), tanah liat. Tugasnya sama dengan batang merah lama — menandai awal
   halaman — tapi karena posisinya di atas dan bukan di samping, dia terbaca
   sebagai pembuka rubrik, bukan sebagai bingkai.

   Dibuat lewat ::before supaya tidak perlu menyentuh JS sama sekali. */
.judul-halaman h1::before {
  content: '';
  display: block;
  width: 34px; height: 2px;
  margin-bottom: var(--r4);
  border-radius: 2px;
  background: var(--aksen);
}

.judul-sub {
  margin-top: var(--r3);
  color: var(--tinta-2); font-size: 14px; max-width: 58ch;
  font-weight: 450;
}

/* --- catatan "terakhir diunggah" --- */

.cap-waktu {
  display: flex; flex-direction: column; align-items: flex-end; gap: 7px;
  font-size: 12px;
}
.cap-baris { display: flex; align-items: center; gap: 7px; color: var(--tinta-3); }
/* Yang dicari mata di blok ini cuma dua: kapan datanya, dan masih segar atau
   tidak. Jadi cuma dua bagian itu yang diberi tinta penuh; sisanya keterangan
   dan boleh tetap redup. */
.cap-baris b { color: var(--tinta); font-weight: 600; }

.cap-titik {
  width: 6px; height: 6px; border-radius: 50%; flex: none;
  background: var(--turun);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--turun) 18%, transparent);
}
.cap-titik.basi { background: var(--awas); box-shadow: 0 0 0 3px color-mix(in srgb, var(--awas) 18%, transparent); }
.cap-titik.lama { background: var(--tinta-3); box-shadow: 0 0 0 3px color-mix(in srgb, var(--tinta-3) 16%, transparent); }

.cap-sesi { display: flex; gap: 5px; }

/* Pil sesi. Sebagian dirender sebagai <button> (Pagi/Sore, bisa diklik) dan
   sebagian sebagai <span> (keterangan "Rekap: butuh dua sesi"), jadi gayanya
   harus benar untuk keduanya — itu sebabnya `padding` dan `font` disetel
   eksplisit dan tidak mengandalkan bawaan salah satu elemen. */
.pil-sesi {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 4px 12px; border-radius: 999px;
  font-size: 11px; font-weight: 600; letter-spacing: .04em;
  border: 1px solid var(--garis);
  background: var(--kaca); color: var(--tinta-3);
  transition: background var(--cepat) var(--halus), color var(--cepat) var(--halus),
              border-color var(--cepat) var(--halus), transform var(--cepat) var(--halus);
}
/* Ada datanya, tapi bukan yang sedang tampil. */
.pil-sesi.ada { border-color: var(--sorot-tepi); color: var(--tinta-2); }
button.pil-sesi.ada:hover { color: var(--tinta); background: var(--sorot-lembut); }

/* Yang SEDANG tampil. Dibedakan dengan isian krem penuh — sama seperti
   penanda tab DATIN/HSI di bilah atas, supaya "yang mana yang aktif" selalu
   punya rupa yang sama di seluruh halaman. */
.pil-sesi.terpilih {
  background: var(--sorot); border-color: var(--sorot); color: var(--sorot-teks);
}

/* Yang belum ada datanya tetap bisa diklik (dia yang memberi keterangan +
   tawaran), jadi dia TIDAK dibuat terlihat mati. Yang membedakannya cuma
   garis putus-putus: "tempatnya ada, isinya belum". */
button.pil-sesi.kosong { border-style: dashed; }
button.pil-sesi.kosong:hover { color: var(--tinta-2); border-color: var(--garis-tegas); }
button.pil-sesi:active { transform: scale(.96); }

/* Baris jawaban saat sesi kosong diklik. Rata kanan mengikuti seluruh blok
   cap-waktu, dan boleh membungkus kalau nama tanggalnya panjang. */
.cap-tawaran {
  display: flex; align-items: center; justify-content: flex-end;
  gap: var(--r2); flex-wrap: wrap;
  margin-top: 2px;
  animation: masuk 240ms var(--halus);
}
.cap-tawaran-teks { font-size: 11.5px; color: var(--tinta-3); }

/* ==========================================================================
   7. KPI — SATU STRIP BERSEKAT, BUKAN TUJUH KARTU
   ==========================================================================
   Ini perbaikan paling penting di seluruh berkas. Versi lama menaruh tujuh
   kartu kembar berjejer, masing-masing dengan border + bayang + lengkung
   sendiri — dan tujuh kartu KPI identik adalah penanda dashboard hasil
   generate yang paling khas.

   Sekarang: SATU benda kaca panjang, dibagi oleh garis rambut 1px. Yang
   dibaca mata jadi "satu baris ringkasan", bukan "tujuh benda yang harus
   diperiksa satu per satu". Sekatnya `inset box-shadow`, bukan border, supaya
   tidak ada 1px yang menambah lebar dan memecah kisinya.

   Angkanya ditulis BERAT 340. Berat tipis pada ukuran besar itu yang membuat
   angka terbaca mahal; berat 800 (versi lama) membuatnya berteriak.         */

/* ==========================================================================
   KERANGKA SELAGI MEMUAT
   ==========================================================================
   Pembukaan pertama hari ini butuh beberapa detik: Neon tidur sendiri sesudah
   lima menit sepi, dan permintaan pertama membangunkannya. Selama itu dulu
   yang terlihat halaman kosong di bawah bilah atas — dan halaman kosong tidak
   bisa dibedakan dari halaman rusak.

   Bentuknya meniru TATA LETAK yang akan datang (judul, strip KPI, satu kartu
   tabel), bukan lingkaran berputar di tengah. Lingkaran berputar cuma bilang
   "tunggu"; kerangka bilang "tunggu, dan beginilah nanti bentuknya" — dan
   waktu isinya datang, tidak ada yang melompat karena tempatnya sudah sama.  */

.rangka { animation: rangka-masuk var(--sedang) var(--halus); }
@keyframes rangka-masuk { from { opacity: 0; } to { opacity: 1; } }

.rangka-judul { display: flex; flex-direction: column; gap: var(--r3); margin-bottom: var(--r7); }

.rangka-kpi {
  display: grid; gap: 0;
  grid-template-columns: repeat(auto-fit, minmax(128px, 1fr));
  margin-bottom: var(--r7);
  border-radius: var(--lengkung);
  overflow: hidden;
  box-shadow: 0 0 0 1px var(--garis);
}
.rangka-kpi .rangka-bar { height: 92px; border-radius: 0; }
.rangka-kpi .rangka-bar + .rangka-bar { box-shadow: inset 1px 0 0 var(--garis); }

.rangka-tabel { height: 320px; border-radius: var(--lengkung-l); }

.rangka-bar, .rangka-tabel {
  display: block;
  background: var(--noda-1);
  border-radius: var(--lengkung-s);
  position: relative;
  overflow: hidden;
}
/* Kilau yang menyapu, bukan seluruh kotak yang berkedip. Kotak berkedip
   menarik mata ke dirinya sendiri; sapuan terbaca sebagai "sedang berjalan"
   di latar belakang, dan itu yang benar untuk sesuatu yang cuma penanda. */
.rangka-bar::after, .rangka-tabel::after {
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(90deg, transparent,
    color-mix(in srgb, var(--cahaya) 7%, transparent), transparent);
  transform: translateX(-100%);
  animation: rangka-sapu 1.6s var(--halus) infinite;
}
@keyframes rangka-sapu { to { transform: translateX(100%); } }

.rangka-lama {
  margin: var(--r5) 0 0; text-align: center;
  font-size: 12.5px; color: var(--tinta-3);
  opacity: 0;
  /* Tanpa JS: muncul sendiri sesudah 4 detik dan tetap tampil (`forwards`).
     Pemuatan yang normal sudah selesai sebelum itu, jadi pesan ini cuma
     terlihat oleh yang memang sedang menunggu lama. */
  animation: rangka-masuk var(--sedang) var(--halus) 4s forwards;
}

/* Gerakan dimatikan untuk yang memintanya. Kerangkanya tetap ada — yang
   hilang cuma sapuan dan pemunculannya, bukan penandanya. */
@media (prefers-reduced-motion: reduce) {
  .rangka, .rangka-bar::after, .rangka-tabel::after { animation: none; }
  .rangka-lama { animation: none; opacity: 1; }
}

.kpi-baris {
  display: grid; gap: 0;
  grid-template-columns: repeat(auto-fit, minmax(128px, 1fr));
  margin-bottom: var(--r7);
  border-radius: var(--lengkung);
  /* Sorot spekular: satu noda putih besar yang keluar dari pojok kiri ATAS
     benda, bukan gradien atas-ke-bawah. Gradien lurus terbaca sebagai warna;
     noda dari satu titik terbaca sebagai CAHAYA yang datang dari suatu arah —
     dan arahnya di sini sama untuk setiap benda kaca di halaman (kiri atas),
     karena cahaya yang datang dari arah berbeda-beda per benda langsung
     membongkar ilusinya. */
  background:
    radial-gradient(120% 150% at 1% -40%, color-mix(in srgb, var(--cahaya) 10%, transparent), transparent 48%),
    var(--kaca);
  backdrop-filter: blur(18px) saturate(150%);
  -webkit-backdrop-filter: blur(18px) saturate(150%);
  box-shadow: 0 0 0 1px var(--garis), var(--bayang-2), var(--kilau);
  overflow: hidden;
}

.kpi {
  position: relative;
  padding: var(--r4) var(--r5) var(--r6);
  background: transparent;
  transition: background var(--sedang) var(--halus);
}
/* Sekat antar ruas. `inset` supaya tidak menambah lebar. */
.kpi + .kpi { box-shadow: inset 1px 0 0 var(--garis); }
.kpi:hover { background: color-mix(in srgb, var(--permukaan) 55%, transparent); }

/* Kartu KPI yang bisa diklik dirender sebagai <button>, bukan <article>
   ber-`role`: dia benda mandiri di strip, bukan sel di dalam tata letak yang
   ketat seperti tabel, jadi tidak ada alasan menghindari elemen yang memang
   untuk diklik.

   Yang perlu dikembalikan cuma bawaan tombol yang tidak diminta — bingkai,
   font, dan perataan teks. Latar transparannya sudah datang dari `.kpi`. */
button.kpi {
  border: 0; font: inherit; color: inherit; text-align: left;
  width: 100%; display: block;
}
button.kpi.bisa-klik { cursor: pointer; }
/* `outline`, BUKAN `box-shadow`: sekat antar ruas (`.kpi + .kpi`) sudah
   memakai box-shadow, dan menimpanya akan menghapus sekatnya saat difokus. */
button.kpi:focus-visible { outline: 2px solid var(--aksen); outline-offset: -2px; }

.kpi-nama {
  font-size: 10px; font-weight: 700; letter-spacing: .15em; text-transform: uppercase;
  color: var(--tinta-3);
}
.kpi-nilai {
  margin-top: var(--r2);
  font-size: clamp(1.6rem, 2.5vw, 2.1rem);
  font-weight: 340; letter-spacing: -.035em; line-height: 1;
  color: var(--tinta);
}
.kpi-bagi { margin-top: 5px; font-size: 11px; color: var(--tinta-3); font-weight: 500; letter-spacing: .01em; }

/* Ruas pertama (total) tidak diberi warna blok — cuma diberi RUANG dan ukuran
   huruf yang lebih besar. Hierarki dari tipografi, bukan dari kotak berwarna. */
.kpi.utama {
  grid-column: span 2;
  background: linear-gradient(135deg, color-mix(in srgb, var(--aksen) 9%, transparent), transparent 78%);
}
.kpi.utama .kpi-nama { color: var(--aksen); }
.kpi.utama .kpi-nilai { font-size: clamp(2.2rem, 3.6vw, 3rem); font-weight: 320; }

/* Batang tipis di dasar tiap ruas: proporsi terhadap total. Lebarnya disetel
   sekali lewat `--isi` saat render, tidak pernah dianimasikan ulang. */
/* Batang disisipkan ke DALAM, sejajar dengan padding ruasnya — bukan
   menempel ke tepi strip. Dua sebabnya: ruas paling kiri dan paling kanan
   punya sudut membulat, jadi batang yang menyentuh tepi ikut terpotong dan
   terlihat rusak; dan sebagai garis pendek di bawah angkanya, dia terbaca
   sebagai bagian dari angka itu, bukan sebagai dasar strip. */
.kpi-batang {
  position: absolute; left: var(--r5); right: var(--r5); bottom: var(--r4); height: 2px;
  border-radius: 2px;
  background: var(--noda-4);
  overflow: hidden;
}
.kpi-batang::after {
  content: ''; position: absolute; inset: 0 auto 0 0;
  width: 100%;
  transform: scaleX(var(--isi, 0)); transform-origin: left;
  background: color-mix(in srgb, var(--aksen) 55%, transparent);
  transition: transform var(--lambat) var(--halus);
}
.kpi.utama .kpi-batang { display: none; }

/* ==========================================================================
   8. BINTANG UTAMA — panel tabel
   ==========================================================================
   Di HSI satu tabel ini pusat halaman; di DATIN delapan tabel bergiliran
   mengisi tempat yang sama lewat carousel.

   PERBAIKAN STRUKTURAL: versi lama bersarang tiga lapis —
   `.panggung` (border+bayang) > `.panggung-isi` (padding) > `.tabel-bungkus`
   (border+lengkung lagi). Tiga tepi untuk satu tabel. Sekarang tinggal SATU
   tepi: panelnya berkaca, dan tabelnya duduk langsung di dalamnya tanpa
   kotak sendiri.                                                            */

.panggung {
  position: relative;
  border-radius: var(--lengkung-l);
  /* Tiga lapis, dari atas ke bawah:
     1. sorot spekular dari pojok kiri atas — arah cahayanya sama dengan
        seluruh benda kaca lain di halaman;
     2. kilau lembut yang menyapu sisi atas, supaya tepi atasnya "basah";
     3. isian kaca yang menipis ke bawah, jadi dasarnya lebih redup daripada
        puncaknya — itu yang membuat benda ini punya KETEBALAN, bukan cuma
        permukaan. */
  background:
    radial-gradient(90% 120% at 2% -25%, color-mix(in srgb, var(--cahaya) 13%, transparent), transparent 46%),
    linear-gradient(to bottom, color-mix(in srgb, var(--cahaya) 7%, transparent), transparent 18%),
    linear-gradient(168deg, var(--kaca-padat), var(--kaca));
  backdrop-filter: blur(22px) saturate(150%);
  -webkit-backdrop-filter: blur(22px) saturate(150%);
  /* Bayang terakhir itu cahaya AMBIEN hangat, bukan bayangan: dia menyebar
     90px ke segala arah dengan warna madu, jadi panelnya terlihat duduk DI
     DALAM cahaya ruangan alih-alih ditempel di atas latar. */
  box-shadow:
    0 0 0 1px var(--garis),
    var(--bayang-2),
    var(--kilau),
    0 0 110px -28px color-mix(in srgb, var(--ambien) 30%, transparent);
  overflow: hidden;
}

.panggung-kepala {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: var(--r5); flex-wrap: wrap;
  padding: var(--r5) var(--r6) var(--r4);
  background: transparent;
  border-bottom: 1px solid var(--garis);
}

/* Kerlingan mata panel. Titik kecil di depannya adalah satu-satunya tempat
   tanah liat muncul sebagai bentuk, bukan sebagai teks. */
.panggung-tanda {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: 10px; font-weight: 700; letter-spacing: .16em; text-transform: uppercase;
  color: var(--aksen);
}
.panggung-tanda::before {
  content: ''; width: 4px; height: 4px; border-radius: 50%;
  background: currentColor;
}

.panggung-judul { font-size: 1.32rem; font-weight: 500; letter-spacing: -.028em; margin-top: var(--r2); }
.panggung-catatan {
  font-size: 10.5px; color: var(--tinta-3); margin-top: 6px;
  letter-spacing: .1em; text-transform: uppercase; font-weight: 600;
}

.panggung-angka { display: flex; align-items: baseline; gap: 8px; }
.panggung-angka b { font-size: 2.1rem; font-weight: 320; letter-spacing: -.04em; }
.panggung-angka span {
  font-size: 10px; font-weight: 700; letter-spacing: .16em; text-transform: uppercase;
  color: var(--tinta-3);
}

/* Panel ini memuat DUA macam isi: tabelnya, dan (di HSI) batang perbandingan
   di bawahnya. Jadi paddingnya dipasang di panel, lalu TABELNYA yang ditarik
   keluar sampai menyentuh tepi.

   Tabel yang menyentuh tepi panel itu keputusan, bukan kelalaian: dengan
   begitu baris jumlah yang gelap membentang penuh dari sisi ke sisi, dan dia
   berfungsi sebagai lantai panel — bukan sebagai kotak gelap yang mengapung
   di tengah bidang terang. */
.panggung-isi { padding: 0 var(--r6) var(--r6); }
.panggung-isi > .tabel-bungkus { margin-inline: calc(var(--r6) * -1); }
.panggung-isi > .bagian-kepala { margin-top: var(--r7); }

/* Panel harus MENGISI slide carousel, bukan mengapung di dalamnya. Tanpa ini,
   kedelapan slide saling meregangkan tinggi (flex row default `stretch`) dan
   slide yang tabelnya pendek meninggalkan bidang kanvas kosong sebesar ratusan
   piksel di bawah panelnya — cacat paling terlihat di putaran pertama. */
.karusel-slide > .panggung { height: 100%; display: flex; flex-direction: column; }
.karusel-slide > .panggung > .panggung-isi { flex: 1; }

/* ==========================================================================
   9. TABEL
   ==========================================================================
   Kepala baris & kolom melekat (`sticky`) supaya tabel lebar tetap terbaca
   saat digulir ke samping — pada tabel 12 kolom, kehilangan nama barisnya
   membuat seluruh angka jadi tak berarti.

   PERBAIKAN TERBESAR DI BAGIAN INI: kepala tabel tidak lagi blok biru solid.
   Blok warna penuh di baris kepala adalah hal yang membuat halaman ini
   terbaca seperti Excel 2013. Sekarang kepalanya dibedakan oleh TIGA hal yang
   semuanya tipografis — ukuran kecil, berat 700, tracking .14em — plus satu
   garis rambut tegas di bawahnya. Tidak ada warna yang dipakai sama sekali.  */

.tabel-bungkus {
  position: relative;
  overflow: auto;
  max-height: min(64vh, 640px);
  /* Tidak ada border dan tidak ada lengkung di sini. Tabelnya duduk langsung
     di dalam panel — inilah lapisan yang dihapus. */
  contain: paint;
  /* HANYA sumbu X yang ditahan. Sebelumnya `overscroll-behavior: contain`
     menahan KEDUA sumbu, dan itu bug yang terasa langsung dipakai: tabel ini
     benda paling besar di halaman, jadi kursor hampir selalu ada di atasnya.
     Begitu tabelnya bisa digulir (tabel 20+ baris), gulir dua-jari vertikal
     dimakan container tabel, dan waktu tabelnya habis gulirnya TIDAK
     diteruskan ke halaman — halamannya terasa macet.

     Sumbu X tetap ditahan, karena di situ containment-nya memang berguna:
     menggeser tabel lebar ke samping tidak boleh ikut menggeser carousel di
     belakangnya. */
  overscroll-behavior-x: contain;
  overscroll-behavior-y: auto;
}

.tabel {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  font-size: 13px;
}

.tabel th, .tabel td {
  padding: 11px 14px;
  text-align: center;
  white-space: nowrap;
  border-bottom: 1px solid var(--garis);
}
.tabel td { font-weight: 450; }

/* --- kepala kolom: aturan tipografi, bukan blok warna ---
   Kepalanya BEKU, bukan padat. Waktu tabel 25 baris digulir di dalam panel,
   baris-baris angka lewat DI BAWAH kepala kolom dan terlihat kabur menembusnya
   sebentar sebelum hilang. Ini satu-satunya tempat di halaman ini di mana
   kacanya bergerak, dan justru di situ dia paling terasa sebagai kaca.

   Isiannya tetap tinggi (82%): yang di belakang kepala kolom itu angka, dan
   angka yang setengah terbaca menembus kepala kolom bukan efek, itu kesalahan. */
.tabel thead th {
  position: sticky; top: 0; z-index: 3;
  background: color-mix(in srgb, var(--kepala-tabel) 82%, transparent);
  backdrop-filter: blur(12px) saturate(160%);
  -webkit-backdrop-filter: blur(12px) saturate(160%);
  color: var(--tinta-2);
  font-size: 9.5px; font-weight: 700; letter-spacing: .14em; text-transform: uppercase;
  padding-top: var(--r4); padding-bottom: var(--r3);
  /* Garis rambut tegas di bawah kepala, dipasang sebagai inset shadow supaya
     tidak ikut bergeser saat sticky (celah 1px yang terkenal). */
  border-bottom: none;
  box-shadow: inset 0 -1px 0 var(--garis-tegas);
}
.tabel thead th:first-child { text-align: left; z-index: 4; left: 0; }

/* --- kolom pertama (nama baris) --- */
.tabel tbody th {
  position: sticky; left: 0; z-index: 2;
  text-align: left; font-weight: 600; font-size: 12.5px;
  color: var(--tinta);
  background: var(--kepala-tabel);
  box-shadow: inset -1px 0 0 var(--garis);
}

/* Zebra sangat samar. Versi lama memakai `--permukaan-2` penuh, yang di atas
   panel kaca terlihat seperti dua bahan berbeda bergantian. */
.tabel tbody tr:nth-child(even) td,
.tabel tbody tr:nth-child(even) th { background-color: var(--noda-1); }
.tabel tbody tr { transition: background var(--cepat) linear; }
.tabel tbody tr:hover td,
.tabel tbody tr:hover th { background-color: var(--sorot-lembut); }

.tabel .kosong { color: var(--tinta-3); font-weight: 400; }

/* --- usia 61 hari ke atas: TULISANNYA saja yang merah ---
   Bukan latar selnya. Sel berwarna memakai seluruh permukaannya dan karena
   itu selalu menang melawan angka di dalamnya; di tabel 12 kolom, tiga kolom
   berlatar merah membuat sembilan kolom lain terbaca seperti tidak penting.
   Yang perlu menonjol angkanya, jadi angkanya yang diwarnai.

   Tebalnya dinaikkan sedikit karena merah di atas ground gelap kehilangan
   sebagian ketegasannya dibanding tinta biasa pada berat yang sama. */
.tabel td.usia-tua { color: var(--usia-tua); font-weight: 600; }
.tabel tfoot td.usia-tua { color: var(--usia-tua); }
/* Kepala kolomnya juga, supaya terlihat SAMPAI kolom mana merahnya berlaku.
   Beratnya tidak dinaikkan di sini — kepala tabel sudah 700. */
.tabel thead th.usia-tua { color: var(--usia-tua); }

/* --- kolom & baris total --- */
.tabel .total-kolom {
  font-weight: 700;
  background-color: var(--noda-3);
  box-shadow: inset 1px 0 0 var(--garis);
}
.tabel tbody tr:nth-child(even) .total-kolom { background-color: var(--noda-4); }
.tabel .tambahan { color: var(--tinta-2); background-color: var(--noda-2); }
/* Baris jumlah TIDAK memakai `--sorot`, walau `--sorot` adalah "yang paling
   jelas" di sistem ini. Bidang krem selebar tabel di atas kanvas espresso
   berhenti berfungsi sebagai lantai dan berubah jadi benda paling terang di
   layar — mata tertarik ke jumlahnya, padahal yang dibaca orang angka-angka di
   atasnya. Jadi dia bidang cokelat yang sedikit TERANGKAT, dibedakan oleh
   garis tegas di sisi atas: peran yang sama, cara yang berbeda. */
.tabel tfoot th, .tabel tfoot td {
  position: sticky; bottom: 0; z-index: 3;
  background: var(--kaki-tabel); color: var(--tinta);
  font-weight: 600; border-bottom: none;
  box-shadow: inset 0 1px 0 var(--garis-tegas);
}
.tabel tfoot th:first-child {
  text-align: left; left: 0; z-index: 4;
  font-size: 9.5px; letter-spacing: .14em; text-transform: uppercase; font-weight: 700;
}
.tabel tfoot .pojok { background: var(--kaki-pojok); }
.tabel .subtotal th, .tabel .subtotal td {
  font-weight: 700;
  background-color: var(--sorot-lembut);
  border-top: 1px solid var(--garis-tegas);
}

/* Petunjuk bahwa tabel masih bisa digulir ke samping.
   Pudarnya menuju `--kepala-tabel`, BUKAN `--permukaan` putih: kartu dan panel
   di sini berlatar kaca, jadi pudar ke satu warna asing meninggalkan pita
   yang terlihat seperti cacat render, bukan seperti tepi yang memudar.
   `--kepala-tabel` adalah rona yang memang sudah dipakai kolom nama baris,
   jadi pudarnya menyatu. */
.tabel-bungkus.bisa-geser::after {
  content: ''; position: sticky; right: 0; top: 0;
  display: block; width: 48px; height: 100%;
  margin-left: auto;
  background: linear-gradient(to left, var(--kepala-tabel) 30%, transparent);
  pointer-events: none;
}

.tabel-kaki {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--r4); flex-wrap: wrap;
  padding-top: var(--r3);
  font-size: 11px; color: var(--tinta-3);
  letter-spacing: .02em;
}

/* ==========================================================================
   10. CAROUSEL (DATIN)
   ==========================================================================
   Delapan tabel berbagi satu tempat. Dibuat dengan scroll-snap, BUKAN dengan
   menggeser `left` atau menyembunyikan slide: scroll-snap berjalan di thread
   compositor, jadi gesekan jari/trackpad-nya mulus dan gulirannya bisa
   dihentikan di tengah seperti carousel asli.                               */

.karusel { position: relative; }

.karusel-jalur {
  display: flex;
  gap: var(--r5);
  overflow-x: auto;
  /* `proximity`, BUKAN `mandatory`. Gulir dua-jari di touchpad hampir selalu
     punya komponen X kecil ikut serta; dengan snap `mandatory`, komponen
     sekecil apa pun langsung memicu animasi snap yang berkelahi dengan gulir
     vertikal yang sedang jalan — hasilnya halaman terasa berat dan kadang
     tersangkut. `proximity` cuma menarik ke slide terdekat kalau gerakannya
     memang sudah dekat, jadi gulir vertikal lewat tanpa diganggu.

     Yang hilang: geseran setengah slide tidak lagi dipaksa mendarat. Yang
     didapat: halamannya bisa digulir. Pertukaran yang jelas. */
  scroll-snap-type: x proximity;
  scroll-behavior: smooth;
  scrollbar-width: none;
  overscroll-behavior-x: contain;
  /* Gerakan vertikal di atas jalur ini milik halaman, bukan milik carousel. */
  overscroll-behavior-y: auto;
}
.karusel-jalur::-webkit-scrollbar { display: none; }

.karusel-slide {
  flex: 0 0 100%;
  scroll-snap-align: center;
  /* Slide di luar pandangan tidak perlu digambar. Ini yang menjaga carousel 8
     tabel tetap ringan — tanpa ini, delapan tabel penuh ikut dihitung tata
     letaknya sekaligus.

     ANGKA 420 ITU PENTING, BUKAN TEBAKAN BEBAS. Slide yang belum tergambar
     melaporkan tingginya sebesar angka ini, dan tinggi jalur flex = slide
     TERTINGGI. Waktu angkanya 560 (versi lama) sementara tabel sungguhan cuma
     ~400px, tujuh slide yang belum tergambar memaksa jalurnya 560px dan
     menyisakan ±160px bidang kosong di bawah tabel yang sedang tampil —
     terbaca sebagai halaman yang belum selesai. 420 mendekati tinggi
     sesungguhnya tabel pivot 5-6 baris, jadi kekosongannya tinggal sisa. */
  content-visibility: auto;
  contain-intrinsic-size: auto 420px;
}

/* DOK, bukan kemudi yang mengapung.
   ------------------------------------------------------------------------
   Sebelumnya titik, label, dan panah duduk begitu saja di bidang kosong 24px
   di bawah panggung — tiga benda kecil tanpa rumah, dan bidang kosong di
   antaranya membuat panggungnya terlihat seperti kartu yang hanyut.

   Sekarang dia bidang kaca yang MENEMPEL di dasar panggung: sudut bawah
   panggung dibuat kotak, sudut bawah dok dibulatkan, dan keduanya jadi satu
   benda — panggung dengan dasar. Kemudi jadi bagian dari alatnya, bukan
   kontrol yang tercecer di sekitarnya. */
.karusel-slide > .panggung { border-radius: var(--lengkung-l) var(--lengkung-l) 0 0; }

.karusel-kemudi {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--r4);
  padding: var(--r3) var(--r5) var(--r3) var(--r6);
  border-radius: 0 0 var(--lengkung-l) var(--lengkung-l);
  /* Dok itu DASAR panggung, jadi cahayanya datang dari BAWAH — bukan dari
     kiri atas seperti benda kaca lain. Dia menerima pantulan dari ground di
     bawahnya. Ini satu-satunya pengecualian arah cahaya di seluruh berkas,
     dan sengaja: itu yang membuatnya terbaca sebagai sisi bawah satu benda,
     bukan sebagai benda kedua yang ditempel di situ. */
  background:
    linear-gradient(to top, color-mix(in srgb, var(--cahaya) 6%, transparent), transparent 70%),
    var(--kaca);
  backdrop-filter: blur(18px) saturate(145%);
  -webkit-backdrop-filter: blur(18px) saturate(145%);
  /* Cincin 1px-nya sengaja TIDAK di sisi atas: kalau ada, akan muncul garis
     ganda dengan cincin panggung di perbatasan keduanya. */
  box-shadow: inset 1px 0 0 var(--garis), inset -1px 0 0 var(--garis),
              inset 0 -1px 0 var(--garis), var(--bayang-1);
}

.karusel-titik { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }

/* Titik navigasi. Yang aktif memanjang jadi kapsul — perubahan BENTUK yang
   bisa dilihat tanpa mengandalkan warna saja.

   TARGET KLIKNYA 26px, TITIKNYA 6px. Titik 6px itu ukuran yang benar secara
   visual dan salah secara pakai: sasaran sekecil itu menuntut ketepatan yang
   tidak masuk akal dengan touchpad, dan gagal-klik terbaca sebagai "tombolnya
   tidak responsif" — padahal kliknya memang tidak pernah kena.

   Jadi sasarannya diperbesar lewat ::after yang tak terlihat, bukan dengan
   membesarkan titiknya. Ini satu-satunya cara menaikkan keterpakaian tanpa
   mengubah rancangannya sama sekali. */
.titik {
  position: relative;
  width: 6px; height: 6px; border-radius: 999px; padding: 0;
  background: var(--garis-tegas);
  transition: background var(--sedang) var(--halus), width var(--sedang) var(--pegas);
}
.titik::after {
  content: ''; position: absolute;
  /* -10px vertikal & horizontal -> sasaran 26x26px di sekeliling titik 6px.
     Jarak antar titik dinaikkan ke 10px supaya sasaran tetangga tidak
     bertumpuk dan klik tidak pernah mendarat di titik yang salah. */
  inset: -10px;
  border-radius: 999px;
}
.titik:hover { background: var(--tinta-3); }
.titik.aktif { width: 28px; background: var(--sorot); }

.karusel-panah { display: flex; gap: 6px; }

/* Pemilih tabel. Dulu `.karusel-label`, sebuah tulisan mati — sekarang
   benda yang sama juga bisa dipakai melompat ke tabel mana pun.

   Dibuat setipis mungkin: TANPA bingkai, TANPA latar, dan mewarisi warna
   tulisan lama. Dok ini sudah penuh (titik, dua panah, kaca buram); satu
   kotak dropdown bergaris di tengahnya akan terbaca sebagai benda asing yang
   ditempel, bukan sebagai labelnya sendiri yang jadi bisa diklik. Bahwa dia
   bisa diklik disampaikan tanda panah bawaan peramban — itu isyarat yang
   sudah dikenali semua orang, dan tidak perlu digambar ulang. */
.karusel-pilih {
  font-size: 11px; font-weight: 600; color: var(--tinta-3);
  letter-spacing: .06em;
  min-width: 0; max-width: 320px; flex: 0 1 auto;
  /* Lebarnya ditentukan pilihan TERPANJANG, jadi ada sedikit jarak antara
     tulisan dan panahnya saat judul yang terpilih pendek. Itu dibiarkan:
     lebar yang menyesuaikan isi berarti dok ini melebar-menyempit sendiri
     tiap kali tabelnya berganti, dan titik serta panah di kiri-kanannya ikut
     bergeser. Kendali yang berpindah tempat jauh lebih mengganggu daripada
     jarak beberapa piksel yang tetap. */
  /* `select` bawaan memangkas sendiri teks yang kepanjangan, jadi
     `text-overflow` tidak diperlukan — yang diperlukan cuma `min-width: 0`
     supaya flex benar-benar mengizinkannya menyusut. */
  padding: 4px 2px;
  border: none; background: none; border-radius: var(--r2);
  cursor: pointer;
  transition: color var(--cepat) var(--halus);
}
.karusel-pilih:hover { color: var(--tinta); }
.karusel-pilih:focus-visible {
  outline: none; color: var(--tinta);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--aksen) 14%, transparent);
}
/* Daftar yang terbuka digambar sistem operasi, bukan halaman ini: di tema
   gelap, `option` tanpa warna sendiri bisa keluar sebagai tulisan gelap di
   atas latar gelap pada sebagian peramban. */
.karusel-pilih option { color: var(--tinta); background: var(--permukaan); }

/* ==========================================================================
   11. KISI TABEL PENDAMPING
   ==========================================================================
   Kepala bagian: versi lama memakai batang biru 3px di kiri. Sekarang garis
   rambut yang MEMANJANG ke seluruh lebar, dengan labelnya duduk di atas garis
   itu. Ini pola rubrik majalah — pemisah yang juga memberi nama.            */

.bagian { margin-top: var(--r8); }

.bagian-kepala {
  display: flex; align-items: baseline; gap: var(--r4);
  margin-bottom: var(--r5);
  padding-bottom: var(--r3);
  border-bottom: 1px solid var(--garis);
}
.bagian-kepala h2 {
  font-size: 10px; font-weight: 700; letter-spacing: .18em; text-transform: uppercase;
  color: var(--tinta-2);
  flex: none;
}
.bagian-kepala span { font-size: 11.5px; color: var(--tinta-3); letter-spacing: .02em; }

/* ================== KARTU BERSEBELAHAN SAMA TINGGI ==================
   Versi sebelumnya memakai `align-items: start`, dan komentarnya menyebut
   alasan yang memang benar: dengan diregangkan, kartu yang pendek dapat
   bidang kosong seratus piksel di bawah baris jumlahnya, dan itu terbaca
   sebagai kartu yang gagal memuat isinya.

   Tapi obatnya lebih buruk dari penyakitnya, dan itu kelihatan dari potret
   halaman HSI: keenam kartu punya jumlah baris yang sangat berbeda (4 error
   code vs 20+ status resume), jadi tepi bawahnya naik-turun dan barisan
   kartunya jadi tangga. Diminta langsung: "tinggi tiap tabel yang
   bersebelahan disamain aja, kalo ada yang butuh tinggi lebih, dibikin
   scrollable aja."

   Itu justru menjawab keberatan yang lama, dan tiga hal yang sudah ada di
   berkas ini yang membuatnya bekerja tanpa tambahan apa pun:

     - `.tabel-bungkus` memang sudah `overflow: auto`;
     - `.tabel thead th` sudah `position: sticky; top: 0`;
     - `.tabel tfoot th/td` sudah `position: sticky; bottom: 0`.

   Jadi tabel yang lebih tinggi dari kartunya digulir DI DALAM kartu dengan
   kepala kolom dan baris TOTAL tetap menempel — dan yang pendek tidak lagi
   punya bidang kosong, karena tabelnya diregangkan ikut kartunya (lihat
   `height: 100%` di bawah) sehingga baris TOTAL benar-benar jadi lantai kartu.

   Tingginya DIBATASI, bukan dibiarkan mengikuti kartu tertinggi: tanpa batas,
   satu tabel 30 baris membuat seluruh barisnya jadi 1.500 piksel dan kartu di
   sebelahnya ikut sepanjang itu. Dengan batas, yang panjang menggulir.
   ==================================================================== */
.kisi {
  display: grid; gap: var(--r5);
  grid-template-columns: repeat(auto-fit, minmax(430px, 1fr));
  /* `align-items` dibiarkan pada bawaannya (`stretch`) — itu yang
     menyamakan tinggi kartu dalam satu baris kisi. */
}

.kartu {
  display: flex; flex-direction: column;
  /* Batas tinggi kartu. `vh` supaya di layar pendek kartunya tidak lebih
     tinggi dari jendelanya, dan batas piksel supaya di layar sangat tinggi
     dia tidak melar tanpa alasan. */
  max-height: min(62vh, 580px);
  border-radius: var(--lengkung);
  background:
    radial-gradient(100% 130% at 2% -30%, color-mix(in srgb, var(--cahaya) 9%, transparent), transparent 44%),
    var(--kaca);
  backdrop-filter: blur(16px) saturate(145%);
  -webkit-backdrop-filter: blur(16px) saturate(145%);
  box-shadow: 0 0 0 1px var(--garis), var(--bayang-1), var(--kilau),
              0 0 70px -28px color-mix(in srgb, var(--ambien) 22%, transparent);
  overflow: hidden;
  transition: transform var(--sedang) var(--halus), box-shadow var(--sedang) var(--halus);
  content-visibility: auto;
  contain-intrinsic-size: auto 420px;
}
.kartu:hover {
  transform: translateY(-2px);
  box-shadow: 0 0 0 1px var(--garis-tegas), var(--bayang-2), var(--kilau);
}

.kartu-kepala { padding: var(--r5) var(--r5) var(--r4); }
.kartu-judul { font-size: 15px; font-weight: 550; letter-spacing: -.018em; }
.kartu-catatan {
  font-size: 10px; color: var(--tinta-3); margin-top: 5px;
  letter-spacing: .11em; text-transform: uppercase; font-weight: 600;
}
/* Sama seperti panggung: tabelnya menyentuh tepi kartu, supaya baris jumlah
   yang gelap jadi lantai kartu — bukan balok gelap yang mengapung dengan
   sisa 8px terang di bawahnya. */
.kartu-isi {
  padding: 0;
  /* `min-height: 0` WAJIB di anak flex yang isinya digulir. Tanpa itu,
     tinggi minimum anak flex adalah tinggi ISINYA (`min-height: auto`), jadi
     dia menolak menyusut, `max-height` kartunya terlampaui, dan tidak ada
     yang pernah menggulir. Ini kelas bug flexbox yang gejalanya "kok
     overflow-nya tidak jalan". */
  flex: 1; min-height: 0;
  display: flex; flex-direction: column;
}
.kartu-isi .tabel-bungkus {
  flex: 1; min-height: 0;
  /* Batas milik `.tabel-bungkus` sendiri (64vh/640px) dilepas di dalam kartu:
     yang menentukan tingginya sekarang kartunya, dan dua batas yang bersaing
     membuat salah satunya selalu jadi angka mati yang membingungkan. */
  max-height: none;
}
/* Tabel diregangkan mengisi kartu, jadi baris TOTAL mendarat di lantai kartu
   alih-alih mengapung dengan bidang kosong di bawahnya — itu keberatan
   terhadap `stretch` yang dulu, dan ini yang menghapusnya. Ruang lebihnya
   dibagi ke baris-barisnya oleh mesin tata letak tabel, jadi kartu yang
   isinya sedikit terbaca sebagai tabel berbaris lega, bukan tabel yang
   kekurangan isi. */
.kartu-isi .tabel { height: 100%; }
.kartu-isi .tabel-kaki { padding: var(--r3) var(--r5) var(--r4); flex: none; }

/* ==========================================================================
   12. BATANG PERBANDINGAN
   ==========================================================================
   Pendamping tabel utama: total per baris sebagai batang, supaya besar-kecil
   bisa dilihat tanpa membandingkan angka satu per satu.

   Gradien biru→ungu versi lama dibuang. Ungu tidak ada di paletnya dan tidak
   pernah punya arti — dia cuma "supaya batangnya ada gradiennya". Sekarang
   satu gradasi tanah liat → madu, dari keluarga warna yang sama dengan
   aksen tabel, jadi batang dan tabel terbaca sebagai satu bahan.  */

.batang-daftar { display: flex; flex-direction: column; gap: var(--r4); }

.batang-baris { display: grid; grid-template-columns: minmax(96px, 148px) 1fr auto; gap: var(--r4); align-items: center; }
.batang-nama {
  font-size: 10.5px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase;
  color: var(--tinta-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.batang-jalur { height: 6px; border-radius: 999px; background: var(--noda-5); overflow: hidden; }

.batang-isi {
  height: 100%; border-radius: 999px;
  background: linear-gradient(90deg, var(--aksen), color-mix(in srgb, var(--aksen) 55%, var(--aksen-2)));
  transform: scaleX(var(--isi, 0)); transform-origin: left;
  transition: transform 720ms var(--halus);
}
.batang-nilai { font-size: 14px; font-weight: 450; font-variant-numeric: tabular-nums; min-width: 56px; text-align: right; letter-spacing: -.02em; }

/* ==========================================================================
   13. LEMBAR & TIRAI
   ==========================================================================
   Lembar itu benda yang paling jelas MELAYANG, jadi kacanya paling padat
   (86%) — bukan paling tembus. Kaca tipis di atas tabel penuh angka membuat
   isi lembarnya tidak bisa dibaca, dan itu kegagalan yang tidak sepadan
   dengan efeknya.                                                           */

.tirai {
  position: fixed; inset: 0; z-index: 90;
  /* Scrim hangat, bukan hitam-biru — dan buramnya kuat (12px). Yang di bawah
     tirai ini tabel penuh angka; kalau angkanya masih bisa dibaca samar,
     mata terus mencoba membacanya alih-alih pindah ke lembar di depannya. */
  background: var(--tirai);
  backdrop-filter: blur(12px) saturate(120%);
  -webkit-backdrop-filter: blur(12px) saturate(120%);
  opacity: 0;
  transition: opacity var(--sedang) var(--halus);
}
.tirai.tampak { opacity: 1; }

.lembar {
  position: fixed; z-index: 100;
  top: 50%; left: 50%;
  width: min(560px, calc(100vw - 32px));
  max-height: min(86vh, 860px);
  display: flex; flex-direction: column;
  border-radius: var(--lengkung-l);
  background:
    radial-gradient(110% 80% at 12% -12%, color-mix(in srgb, var(--cahaya) 12%, transparent), transparent 50%),
    var(--kaca-padat);
  backdrop-filter: blur(32px) saturate(160%);
  -webkit-backdrop-filter: blur(32px) saturate(160%);
  box-shadow: 0 0 0 1px var(--garis), var(--bayang-3), var(--kilau),
              0 0 150px -36px color-mix(in srgb, var(--ambien) 34%, transparent);
  overflow: hidden;
  /* Titik awal & akhir animasi keduanya `transform` — tidak ada `top`/`left`
     yang berubah, jadi tidak ada perhitungan tata letak saat membuka. */
  transform: translate3d(-50%, -50%, 0) scale(.96);
  opacity: 0;
  transition: transform var(--sedang) var(--pegas), opacity var(--sedang) var(--halus);
}
.lembar.tampak { transform: translate3d(-50%, -50%, 0) scale(1); opacity: 1; }

/* --- sel tabel yang bisa ditelusuri --- */

/* Yang menandainya BUKAN warna, dan itu disengaja. Tabel ini sudah memakai
   merah untuk usia tua dan redup untuk nol; warna keempat akan membuat orang
   berhenti membaca angkanya dan mulai membaca warnanya.

   Jadi tandanya muncul saat disentuh saja: penunjuk berubah, latarnya naik
   tipis. Itu isyarat yang sama dengan yang dipakai seluruh web untuk "ini
   bisa diklik", dan tidak menambah apa pun ke keadaan diam tabelnya. */
.tabel td.bisa-klik { cursor: pointer; }

/* `--sorot` SELALU berpasangan dengan `--sorot-teks`, dan itu bukan hiasan.
   Versi pertama memasang latarnya saja; di tema Nokturn `--sorot` hampir
   putih sementara tinta tabelnya juga terang, jadi angka yang disentuh
   kursor MENGHILANG. Tiap tempat lain di berkas ini memasang keduanya
   (`.tab.aktif`, `.pilih-sesi`, tombol utama) — pasangan itu yang menjamin
   kontrasnya di keenam tema, bukan kebetulan warnanya cocok.

   Yang dipasang belakangan `color`, dan itu perlu: sel usia tua punya
   warnanya sendiri (`.tabel td.usia-tua`), dan tanpa baris ini dia tetap
   merah di atas latar terang saat disentuh. Kekhususan `:hover` di sini
   lebih tinggi, jadi merahnya mengalah — sengaja: yang sedang disentuh cuma
   satu sel, dan keterbacaannya menang atas penandaan usianya. */
.tabel td.bisa-klik:hover,
.tabel td.bisa-klik:focus-visible {
  background-color: var(--sorot);
  color: var(--sorot-teks);
}
.tabel td.bisa-klik:focus-visible {
  outline: none;
  box-shadow: inset 0 0 0 2px var(--aksen);
}

/* --- lembar rincian --- */

.lembar-jejak {
  margin: 2px 0 0; font-size: 12px; color: var(--tinta-3);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.lembar-jejak b { color: var(--tinta-2); font-weight: 600; }
.rincian-jejak-tanggal { color: var(--tinta-3); }

.rincian-ringkas {
  display: flex; align-items: baseline; gap: var(--r2);
  margin-bottom: var(--r4);
}
.rincian-ringkas b { font-size: 26px; font-weight: 700; }
.rincian-ringkas span { font-size: 12px; color: var(--tinta-3); }
.rincian-sebagian { margin-left: auto; }
/* Tombol unduh paling kanan. `margin-left: auto` dipindahkan ke sini kalau
   keterangan "200 ditampilkan" tidak ada — tanpa itu tombolnya menempel ke
   angka jumlahnya waktu seluruh barisnya sudah termuat. */
.rincian-ringkas .rincian-unduh { margin-left: auto; flex: none; }
.rincian-sebagian + .rincian-unduh { margin-left: var(--r3); }

@media (max-width: 520px) {
  .rincian-ringkas { flex-wrap: wrap; }
  .rincian-ringkas .rincian-unduh { margin-left: 0; width: 100%; margin-top: var(--r2); }
}

/* Tinggi tabelnya dibatasi supaya tombol "muat lagi" tetap terlihat tanpa
   menggulir seluruh lembar — dengan 200 baris, tombol yang ada di paling
   bawah sama saja dengan tombol yang tidak ada. */
.rincian-tabel { max-height: min(60vh, 560px); overflow: auto; }
.rincian-lagi { margin-top: var(--r4); width: 100%; }

.rincian-memuat, .rincian-galat {
  display: flex; flex-direction: column; align-items: center; gap: var(--r2);
  padding: var(--r8) var(--r4); text-align: center; color: var(--tinta-3);
  font-size: 13px;
}
.rincian-galat b { color: var(--tinta); font-size: 14px; }
.rincian-galat p { margin: 0; max-width: 46ch; line-height: 1.5; }
.rincian-galat-ikon { width: 34px; height: 34px; color: var(--tinta-3); opacity: .7; }
.rincian-galat-ikon svg { width: 100%; height: 100%; }

/* --- medan nama pengunggah & unduh berkas olahan --- */

.borang-medan { display: flex; flex-direction: column; gap: 6px; margin-bottom: var(--r5); }
.borang-medan label { font-size: 12px; font-weight: 700; color: var(--tinta-2); }
.borang-medan small { font-size: 11.5px; line-height: 1.5; }

/* --- salinan kolom penuh ke spreadsheet tim --- */

.kirim-tim {
  padding: var(--r4); border-radius: var(--lengkung-s);
  border: 1px solid var(--garis); background: var(--noda-1);
}
.kirim-tim-kepala { display: flex; align-items: baseline; gap: var(--r3); }
.kirim-tim-kepala b { font-size: 13px; flex: 1; min-width: 0; }
.kirim-tim-nilai { font-size: 11.5px; color: var(--tinta-3); flex: none; }
.kirim-tim-nilai.bagus { color: var(--turun); }
.kirim-tim-nilai.buruk { color: var(--merek); }

.kirim-tim-jalur {
  margin-top: var(--r3); height: 4px; border-radius: 999px;
  background: var(--noda-3); overflow: hidden;
}
.kirim-tim-isi {
  height: 100%; border-radius: 999px; background: var(--aksen);
  transition: width var(--sedang) var(--halus);
}
/* Peringatannya TIDAK diredupkan seperti petunjuk biasa. Dia satu-satunya hal
   yang bisa mencegah salinan berhenti di tengah, dan petunjuk abu-abu di
   bawah bilah kemajuan adalah hal pertama yang tidak dibaca orang. */
.kirim-tim-awas {
  margin: var(--r3) 0 0; font-size: 11.5px; line-height: 1.5;
  color: var(--awas);
}
.kirim-tim-galat {
  margin: var(--r2) 0 var(--r3); font-size: 11.5px; line-height: 1.5;
  color: var(--tinta-2);
}

.unduh-olahan {
  display: flex; align-items: center; gap: var(--r4);
  padding: var(--r4); border-radius: var(--lengkung-s);
  border: 1px solid var(--garis); background: var(--noda-1);
}
.unduh-olahan > div:first-child { flex: 1; min-width: 0; }
.unduh-olahan b { display: block; font-size: 13px; }
.unduh-olahan p { margin: 3px 0 0; font-size: 11.5px; color: var(--tinta-3); line-height: 1.5; }
/* Tombolnya tidak boleh menyusut waktu tulisannya berganti jadi
   "Menyusun... 40%" — kotak yang berdenyut tiap potongan selesai terbaca
   seperti halaman yang gemetar. */
.unduh-olahan .tombol { flex: none; min-width: 140px; justify-content: center; }

@media (max-width: 560px) {
  .unduh-olahan { flex-direction: column; align-items: stretch; }
  .unduh-olahan .tombol { width: 100%; }
}

.lembar-sempit { width: min(420px, calc(100vw - 32px)); }
.lembar-lebar { width: min(1080px, calc(100vw - 32px)); }

.lembar-kepala {
  display: flex; align-items: center; justify-content: space-between; gap: var(--r4);
  padding: var(--r5) var(--r5) var(--r4);
  border-bottom: 1px solid var(--garis);
  background: transparent;
}
.lembar-kepala h2 { font-size: 1.16rem; font-weight: 500; letter-spacing: -.026em; }

.lembar-isi { padding: var(--r5); overflow-y: auto; overscroll-behavior: contain; }

.petunjuk { font-size: 13px; color: var(--tinta-2); margin-bottom: var(--r5); max-width: 56ch; }

/* ================== GERBANG: PENUH LAYAR, TIDAK BISA DITUTUP ==================
   Beda dari .lembar/.tirai di atas (yang MELAYANG di atas dashboard yang
   sudah tergambar, dan bisa ditutup): gerbang ini terbuka SEBELUM dashboard
   mana pun tergambar, dan sengaja tidak punya tombol tutup sama sekali.
   Latarnya kanvas padat, bukan kaca tembus — tidak ada apa pun di baliknya
   yang perlu diredam, karena memang belum ada yang digambar. */
.gerbang {
  position: fixed; inset: 0; z-index: 200;
  display: grid; place-items: center;
  padding: var(--r5);
  background: var(--kanvas);
}
.gerbang-kartu {
  width: min(380px, 100%);
  border-radius: var(--lengkung-l);
  padding: var(--r6) var(--r5);
  background:
    radial-gradient(110% 80% at 12% -12%, color-mix(in srgb, var(--cahaya) 12%, transparent), transparent 50%),
    var(--kaca-padat);
  box-shadow: 0 0 0 1px var(--garis), var(--bayang-3), var(--kilau);
}
.gerbang-kartu h1 {
  font-size: 1.28rem; font-weight: 500; letter-spacing: -.024em; margin-bottom: var(--r3);
}
.gerbang-kartu .petunjuk { margin-bottom: var(--r5); max-width: none; }

/* Keping dataset di lembar unggah: "DATIN — halaman yang sedang kamu buka". */
.unggah-konteks {
  display: flex; align-items: center; gap: var(--r3);
  margin-bottom: var(--r4);
}
.unggah-konteks-teks { font-size: 11.5px; color: var(--tinta-3); }

/* ==========================================================================
   14. BORANG
   ========================================================================== */

.borang { display: flex; flex-direction: column; gap: var(--r4); }
.borang-baris { display: flex; flex-direction: column; gap: 7px; }
.borang-baris > span {
  font-size: 10px; font-weight: 700; letter-spacing: .13em; text-transform: uppercase;
  color: var(--tinta-3);
}

input[type='text'], input[type='password'], input[type='date'], select {
  padding: 11px 14px;
  border-radius: var(--lengkung-s);
  border: 1px solid var(--garis-tegas);
  background: color-mix(in srgb, var(--permukaan) 70%, transparent);
  transition: border-color var(--cepat) var(--halus), box-shadow var(--cepat) var(--halus);
}
input:focus, select:focus {
  outline: none;
  border-color: var(--aksen);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--aksen) 14%, transparent);
}

.borang-galat {
  font-size: 12.5px; color: var(--merek); font-weight: 600;
  padding: var(--r2) var(--r3); border-radius: var(--r2);
  background: var(--merek-lembut);
}

/* --- pilihan sesi --- */

.pilih-sesi { display: grid; grid-template-columns: 1fr 1fr; gap: var(--r2); }

.pilih-sesi label {
  display: flex; flex-direction: column; align-items: center; gap: 3px;
  padding: var(--r4); border-radius: var(--lengkung-s);
  border: 1px solid var(--garis); background: color-mix(in srgb, var(--permukaan) 60%, transparent);
  font-weight: 600; font-size: 13px; cursor: pointer;
  transition: border-color var(--cepat) var(--halus), background var(--cepat) var(--halus), transform var(--cepat) var(--halus);
}
.pilih-sesi label:active { transform: scale(.985); }
.pilih-sesi input { position: absolute; opacity: 0; pointer-events: none; }
.pilih-sesi label:has(input:checked) { border-color: var(--sorot); background: var(--sorot-lembut); color: var(--tinta); }
.pilih-sesi small { font-weight: 500; font-size: 11px; color: var(--tinta-3); }

/* ==========================================================================
   15. JATUHAN BERKAS
   ==========================================================================
   Sasarannya besar dan satu-satunya hal di lembar itu. Yang mengunggah tiap
   hari bukan orang IT — jadi tidak ada pilihan yang harus diputuskan dulu
   sebelum bisa menaruh berkas: dataset dan sesi ditebak, lalu tebakannya
   ditampilkan supaya bisa dibetulkan kalau salah.                           */

.jatuhan {
  position: relative;
  display: flex; flex-direction: column; align-items: center; gap: var(--r4);
  padding: var(--r8) var(--r5);
  border-radius: var(--lengkung);
  /* Garisnya diberi warna tanah liat encer, bukan netral. Dengan `--garis-tegas`
     (alpha .24) garis putus-putusnya nyaris tak terlihat di atas kaca, dan
     sasaran jatuhan berkas adalah satu-satunya benda di lembar ini — dia harus
     terbaca sebagai sasaran, bukan sebagai bidang kosong. */
  border: 1.5px dashed color-mix(in srgb, var(--aksen) 34%, transparent);
  background: color-mix(in srgb, var(--permukaan) 45%, transparent);
  text-align: center; cursor: pointer;
  transition: border-color var(--sedang) var(--halus), background var(--sedang) var(--halus), transform var(--sedang) var(--pegas);
}
.jatuhan:hover { border-color: var(--aksen); background: var(--aksen-lembut); }
.jatuhan.dekat { border-color: var(--aksen); background: var(--aksen-lembut); transform: scale(1.01); }

.jatuhan-ikon {
  width: 54px; height: 54px; border-radius: 50%;
  display: grid; place-items: center; font-size: 22px;
  background: var(--aksen-lembut); color: var(--aksen);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--aksen) 18%, transparent);
  transition: transform var(--sedang) var(--pegas);
}
.jatuhan:hover .jatuhan-ikon, .jatuhan.dekat .jatuhan-ikon { transform: translateY(-3px) scale(1.05); }

.jatuhan-judul { font-weight: 550; font-size: 16px; letter-spacing: -.02em; }
.jatuhan-sub { font-size: 12.5px; color: var(--tinta-3); max-width: 42ch; }
/* Input berkasnya menutupi seluruh area jatuhan supaya seluruh kotak itu bisa
   diklik — bukan cuma tombolnya.

   `opacity: 0` saja TIDAK CUKUP: sebagian browser tetap menggambar teks
   bawaannya ("No file selected.") beserta cincin fokusnya, dan hasilnya teks
   Inggris nyasar di tengah lembar. `font-size: 0` menghapus ukuran teks itu,
   jadi tidak ada lagi yang bisa digambar sekalipun browsernya memaksa. */
.jatuhan input[type='file'] {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  opacity: 0; cursor: pointer;
  font-size: 0; color: transparent;
}

/* --- kemajuan --- */

.maju { display: flex; flex-direction: column; gap: var(--r3); align-items: center; padding: var(--r7) var(--r4); text-align: center; }
.maju-judul { font-weight: 550; }
.maju-sub { font-size: 12.5px; color: var(--tinta-3); }

.maju-jalur { width: 100%; height: 4px; border-radius: 999px; background: var(--noda-5); overflow: hidden; }
.maju-isi {
  height: 100%; width: 40%; border-radius: 999px;
  background: linear-gradient(90deg, transparent, var(--aksen), transparent);
  animation: geser 1.3s linear infinite;
}
@keyframes geser {
  from { transform: translate3d(-100%, 0, 0); }
  to   { transform: translate3d(350%, 0, 0); }
}

/* ==========================================================================
   16. HASIL UNGGAH
   ========================================================================== */

.hasil { display: flex; flex-direction: column; gap: var(--r5); }

.hasil-kepala {
  display: flex; align-items: center; gap: var(--r4);
  padding: var(--r4) var(--r5); border-radius: var(--lengkung-s);
  background: var(--turun-lembut);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--turun) 20%, transparent);
}
.hasil-tanda {
  width: 34px; height: 34px; flex: none; border-radius: 50%;
  display: grid; place-items: center;
  /* Sama seperti kabar: `--turun` di palet ini warna TERANG, jadi centangnya
     gelap. */
  background: var(--turun); color: var(--di-turun); font-size: 16px;
  animation: pop 460ms var(--pegas);
}
@keyframes pop {
  from { transform: scale(0); }
  to   { transform: scale(1); }
}
.hasil-teks b { display: block; font-size: 14px; font-weight: 600; }
.hasil-teks span { font-size: 12px; color: var(--tinta-2); }

.rinci { display: grid; grid-template-columns: repeat(auto-fit, minmax(128px, 1fr)); gap: 0;
  border-radius: var(--lengkung-s); overflow: hidden;
  box-shadow: 0 0 0 1px var(--garis);
}
.rinci-sel { padding: var(--r4); background: color-mix(in srgb, var(--permukaan) 50%, transparent); }
.rinci-sel + .rinci-sel { box-shadow: inset 1px 0 0 var(--garis); }
.rinci-nama { font-size: 9.5px; font-weight: 700; letter-spacing: .13em; text-transform: uppercase; color: var(--tinta-3); }
.rinci-nilai { font-size: 18px; font-weight: 400; font-variant-numeric: tabular-nums; margin-top: 4px; letter-spacing: -.028em; }

/* ==========================================================================
   17. REKAP
   ==========================================================================
   Sama seperti KPI: satu strip bersekat, bukan empat kartu terpisah. Yang
   berbeda cuma bahwa di sini sebagian ruas memang PERLU warna, karena
   naik/turun adalah arti, bukan hiasan.                                     */

.rekap-atas {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(148px, 1fr)); gap: 0;
  margin-bottom: var(--r6);
  border-radius: var(--lengkung-s); overflow: hidden;
  box-shadow: 0 0 0 1px var(--garis);
}

.stat { padding: var(--r4) var(--r5); background: color-mix(in srgb, var(--permukaan) 50%, transparent); }
.stat + .stat { box-shadow: inset 1px 0 0 var(--garis); }
.stat-nama { font-size: 9.5px; font-weight: 700; letter-spacing: .13em; text-transform: uppercase; color: var(--tinta-3); }
.stat-nilai { font-size: 1.7rem; font-weight: 340; letter-spacing: -.035em; margin-top: 4px; line-height: 1.05; }
.stat.naik { background: var(--naik-lembut); }
.stat.naik .stat-nama { color: color-mix(in srgb, var(--naik) 78%, var(--tinta-3)); }
.stat.naik .stat-nilai { color: var(--naik); }
.stat.turun { background: var(--turun-lembut); }
.stat.turun .stat-nama { color: color-mix(in srgb, var(--turun) 78%, var(--tinta-3)); }
.stat.turun .stat-nilai { color: var(--turun); }

/* Tab dimensi rekap */
.tab-baris { display: flex; gap: 4px; flex-wrap: wrap; margin-bottom: var(--r5); padding-bottom: var(--r3); border-bottom: 1px solid var(--garis); }
.tab {
  padding: 6px 14px; border-radius: 999px;
  font-size: 12px; font-weight: 600; color: var(--tinta-3);
  border: 1px solid transparent;
  background: var(--keping);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  transition: background var(--cepat) var(--halus), color var(--cepat) var(--halus), border-color var(--cepat) var(--halus);
}
.tab:hover { color: var(--tinta); background: var(--sorot-lembut); }
.tab.aktif { background: var(--sorot); border-color: var(--sorot); color: var(--sorot-teks); }

/* Delta di dalam tabel rekap */
.delta { font-weight: 700; }
.delta.plus { color: var(--naik); }
.delta.minus { color: var(--turun); }
.delta.nol { color: var(--tinta-3); font-weight: 400; }

/* ==========================================================================
   18. OBROLAN
   ========================================================================== */

.obrol {
  position: fixed; z-index: 100;
  right: var(--r5); bottom: var(--r5);
  width: min(408px, calc(100vw - 32px));
  height: min(620px, calc(100vh - 130px));
  display: flex; flex-direction: column;
  border-radius: var(--lengkung-l);
  background:
    radial-gradient(110% 70% at 14% -8%, color-mix(in srgb, var(--cahaya) 11%, transparent), transparent 48%),
    var(--kaca-padat);
  backdrop-filter: blur(32px) saturate(160%);
  -webkit-backdrop-filter: blur(32px) saturate(160%);
  box-shadow: 0 0 0 1px var(--garis), var(--bayang-3), var(--kilau),
              0 0 130px -34px color-mix(in srgb, var(--ambien) 30%, transparent);
  overflow: hidden;
  transform: translate3d(0, 18px, 0) scale(.98);
  opacity: 0;
  transition: transform var(--sedang) var(--pegas), opacity var(--sedang) var(--halus);
}
.obrol.tampak { transform: none; opacity: 1; }

.obrol-kepala {
  display: flex; align-items: flex-start; justify-content: space-between; gap: var(--r3);
  padding: var(--r5) var(--r5) var(--r4); border-bottom: 1px solid var(--garis); background: transparent;
}
.obrol-kepala-teks { min-width: 0; }
.obrol-kepala h2 { font-size: 15px; font-weight: 550; }
/* Barisnya bisa berubah panjang (nama dataset + tanggal + jumlah pesan), dan
   panelnya cuma 408px. Dibiarkan memotong dengan elipsis, bukan membungkus:
   kepala panel yang tiba-tiba jadi dua baris menggeser seluruh alur pesan di
   bawahnya tiap kali angkanya berubah. */
.obrol-sub {
  font-size: 11px; color: var(--tinta-3); margin-top: 2px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.obrol-alat { display: flex; align-items: center; gap: 6px; flex: none; }

.obrol-alur {
  flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain;
  padding: var(--r5); display: flex; flex-direction: column; gap: var(--r4);
}

.gelembung {
  max-width: 86%; padding: 11px 14px;
  border-radius: var(--lengkung);
  font-size: 13px; line-height: 1.6;
  white-space: pre-wrap; word-break: break-word;
  animation: masuk 240ms var(--halus);
}
.gelembung.dari-orang {
  align-self: flex-end;
  background: var(--sorot); color: var(--sorot-teks);
  border-bottom-right-radius: var(--r1);
}
.gelembung.dari-mesin {
  align-self: flex-start;
  background: color-mix(in srgb, var(--permukaan) 62%, transparent);
  box-shadow: inset 0 0 0 1px var(--garis);
  border-bottom-left-radius: var(--r1);
}
.gelembung.galat { background: var(--merek-lembut); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--merek) 22%, transparent); color: var(--merek); }

.obrol-usul { display: flex; flex-wrap: wrap; gap: 6px; }
.usul {
  padding: 6px 12px; border-radius: 999px;
  font-size: 12px; font-weight: 550; text-align: left;
  border: 1px solid color-mix(in srgb, var(--aksen) 22%, transparent);
  background: var(--aksen-lembut); color: var(--aksen);
  transition: background var(--cepat) var(--halus), transform var(--cepat) var(--halus);
}
.usul:hover { background: color-mix(in srgb, var(--aksen) 14%, transparent); }
.usul:active { transform: scale(.975); }

.obrol-kirim { display: flex; gap: var(--r2); padding: var(--r3); border-top: 1px solid var(--garis); background: transparent; }
.obrol-kirim input { flex: 1; min-width: 0; }

/* Tiga titik "sedang berpikir". Animasinya `transform` saja. */
.mikir { display: inline-flex; gap: 4px; align-items: center; padding: 4px 0; }
.mikir i { width: 5px; height: 5px; border-radius: 50%; background: var(--tinta-3); animation: pantul 1.25s ease-in-out infinite; }
.mikir i:nth-child(2) { animation-delay: .14s; }
.mikir i:nth-child(3) { animation-delay: .28s; }
@keyframes pantul {
  0%, 60%, 100% { transform: translateY(0); opacity: .4; }
  30%           { transform: translateY(-5px); opacity: 1; }
}

/* ==========================================================================
   19. KABAR SINGKAT
   ========================================================================== */

.kabar-tumpuk {
  position: fixed; z-index: 150;
  bottom: var(--r5); left: 50%;
  transform: translateX(-50%);
  display: flex; flex-direction: column; gap: var(--r2);
  align-items: center; pointer-events: none;
}

.kabar {
  display: flex; align-items: center; gap: var(--r2);
  padding: 11px 20px; border-radius: 999px;
  background: var(--sorot); color: var(--sorot-teks);
  font-size: 13px; font-weight: 550;
  box-shadow: var(--bayang-3);
  max-width: min(560px, calc(100vw - 32px));
  animation: kabarMasuk 300ms var(--pegas);
}
.kabar.pergi { animation: kabarPergi 220ms var(--halus) forwards; }
/* TEKSNYA GELAP, bukan putih. Di palet espresso, `--merek` dan `--turun`
   dinaikkan terangnya supaya terbaca sebagai warna di atas kanvas cokelat —
   dan begitu keduanya jadi warna terang, teks putih di atasnya hilang. Ini
   jebakan yang khas waktu satu palet dibalik dari terang ke gelap: yang
   berubah bukan cuma latarnya, tapi juga siapa yang jadi "terang". */
.kabar.buruk { background: var(--merek); color: var(--di-merek); }
.kabar.bagus { background: var(--turun); color: var(--di-turun); }

@keyframes kabarMasuk {
  from { opacity: 0; transform: translate3d(0, 14px, 0) scale(.96); }
  to   { opacity: 1; transform: none; }
}
@keyframes kabarPergi {
  to { opacity: 0; transform: translate3d(0, 10px, 0) scale(.97); }
}

/* ==========================================================================
   20. KOSONG & GALAT
   ========================================================================== */

.kosongan {
  display: flex; flex-direction: column; align-items: center; gap: var(--r4);
  padding: var(--r8) var(--r5); text-align: center;
  border-radius: var(--lengkung-l);
  background: var(--kaca);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  box-shadow: 0 0 0 1px var(--garis), var(--kilau);
}
.kosongan-ikon {
  width: 58px; height: 58px; border-radius: 50%;
  display: grid; place-items: center; font-size: 24px;
  background: var(--aksen-lembut); color: var(--aksen);
}
.kosongan h2 { font-size: 1.3rem; font-weight: 500; }
.kosongan p { font-size: 13.5px; color: var(--tinta-2); max-width: 46ch; }

.peringatan {
  display: flex; gap: var(--r3); align-items: flex-start;
  padding: var(--r3) var(--r4); border-radius: var(--lengkung-s);
  background: var(--awas-lembut);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--awas) 22%, transparent);
  font-size: 12.5px; color: var(--tinta);
  margin-bottom: var(--r5);
}
.peringatan b { color: var(--awas); }

/* --- riwayat --- */

.riwayat-baris {
  display: flex; align-items: center; justify-content: space-between; gap: var(--r3);
  padding: var(--r4); border-radius: var(--lengkung-s);
  background: color-mix(in srgb, var(--permukaan) 50%, transparent);
  box-shadow: inset 0 0 0 1px var(--garis);
  margin-bottom: 6px;
  transition: box-shadow var(--cepat) var(--halus), transform var(--cepat) var(--halus);
}
.riwayat-baris:hover { box-shadow: inset 0 0 0 1px var(--garis-tegas); transform: translateX(2px); }
.riwayat-tgl { font-weight: 600; font-size: 13.5px; }
.riwayat-sub { font-size: 11.5px; color: var(--tinta-3); }
.riwayat-kanan { display: flex; align-items: center; gap: var(--r2); }

/* ==========================================================================
   21. LAYAR SEMPIT
   ========================================================================== */

@media (max-width: 1080px) {
  .kisi { grid-template-columns: 1fr; }
}

@media (max-width: 860px) {
  .atas-dalam { flex-wrap: wrap; gap: var(--r3); padding: var(--r3) var(--r4); }
  .pindah { order: 3; width: 100%; margin: 0; }
  .pindah-tombol { flex: 1; }
  .atas-alat { margin-left: auto; }
  .atas-alat .tombol span { display: none; }
  .atas-alat .tombol { padding: 8px 10px; }
  .atas-alat #btnAkun span { display: inline; }

  .halaman { padding: var(--r6) var(--r4) var(--r7); }
  .judul-halaman { flex-direction: column; align-items: flex-start; gap: var(--r4); }
  .cap-waktu { align-items: flex-start; }

  /* Di layar sempit, strip KPI berubah jadi dua kolom — sekatnya harus ikut
     berubah dari garis kiri jadi kisi penuh, kalau tidak baris kedua kehilangan
     garis atasnya dan stripnya terlihat bocor. */
  .kpi-baris { grid-template-columns: repeat(2, 1fr); }
  .kpi { box-shadow: inset 1px 0 0 var(--garis), inset 0 1px 0 var(--garis); }
  .kpi:nth-child(odd) { box-shadow: inset 0 1px 0 var(--garis); }
  .kpi.utama, .kpi:first-child { box-shadow: none; }
  .kpi.utama { grid-column: span 2; }

  /* Batang proporsi dimatikan di layar sempit. Waktu strip KPI jadi empat
     baris, batang yang menempel di dasar tiap ruas berhenti terbaca sebagai
     "dasar strip" dan berubah jadi coretan klei pendek di tengah bidang —
     informasinya tidak sepadan dengan kekacauannya, dan persentasenya sudah
     tertulis dengan huruf tepat di atasnya. */
  .kpi-batang { display: none; }

  .panggung-kepala { padding: var(--r5) var(--r4) var(--r4); }
  .tabel-kaki { padding: var(--r3) var(--r4) var(--r4); }

  .obrol { right: 0; left: 0; bottom: 0; width: 100%; height: 82vh; border-radius: var(--lengkung-l) var(--lengkung-l) 0 0; }
  .lembar { width: calc(100vw - 16px); }
}

@media (max-width: 520px) {
  .rinci { grid-template-columns: 1fr 1fr; }
  .judul-halaman h1 { font-size: 2rem; }
}


/* ==========================================================================
   22. BILAH ALAT — FILTER + SIMPAN GAMBAR
   ==========================================================================
   Dua benda dengan sifat berlawanan dalam satu baris, dan itu yang menentukan
   tata letaknya: filter dipakai berulang-ulang sambil melihat tabelnya, sedang
   "simpan gambar" dipakai SEKALI di akhir. Jadi filter mengambil ruang di kiri
   dan boleh melimpah ke baris berikutnya; tombol gambar dipatok di kanan dan
   tidak pernah ikut melimpah.

   Bilahnya duduk RATA di ground, tanpa kotak dan tanpa kaca. Alasannya aturan
   5 di kepala berkas ini: kaca cuma untuk benda yang melayang di atas benda
   lain. Bilah ini tidak melayang — dia label untuk tabel di bawahnya. Yang
   memberinya batas cuma satu garis tipis di bawah.                          */

.alat-baris {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: var(--r4); flex-wrap: wrap;
  margin: var(--r5) 0 var(--r3);
  padding-bottom: var(--r3);
  border-bottom: 1px solid var(--garis);
}

.filter-bilah { flex: 1 1 420px; min-width: 0; }

.filter-kepala {
  display: flex; align-items: center; gap: var(--r3);
  margin-bottom: var(--r2);
}

.filter-tanda {
  font-size: 10.5px; font-weight: 700; letter-spacing: .14em;
  text-transform: uppercase; color: var(--tinta-3);
}

.filter-reset { color: var(--aksen); }

.filter-daftar { display: flex; flex-wrap: wrap; gap: var(--r2); }

.filter-memuat, .filter-kosong {
  font-size: 12px; color: var(--tinta-3); margin: 0;
}

.filter-mati {
  display: flex; gap: var(--r3); align-items: flex-start;
  font-size: 12.5px; line-height: 1.5;
}
.filter-mati b { display: block; color: var(--tinta); margin-bottom: 2px; }
.filter-mati span { color: var(--tinta-3); }
.filter-mati-ikon { width: 18px; flex: none; color: var(--awas); }
.filter-mati-ikon svg { width: 18px; height: 18px; }

/* --- satu filter: tombol + menu --- */

.filter-bungkus { position: relative; }

.filter-tombol {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 6px 9px 6px 11px;
  font: inherit; font-size: 12px;
  color: var(--tinta-2);
  background: var(--keping);
  border: 1px solid var(--garis);
  border-radius: 999px;
  cursor: pointer;
  transition: background var(--cepat), border-color var(--cepat), color var(--cepat);
}
.filter-tombol:hover { background: var(--keping-kuat); color: var(--tinta); }

/* FILTER YANG AKTIF DITANDAI WARNA SINYAL, DAN INI PEMAKAIAN KEEMPAT `--aksen`.
   ---------------------------------------------------------------------------
   Aturan 3 di kepala berkas bilang `--aksen` cuma untuk tiga hal. Ini yang
   keempat, dan penambahannya disengaja: angka yang sudah disaring tapi dibaca
   sebagai angka penuh adalah kesalahan yang bisa dibawa ke rapat, dan itu
   justru kelas bahaya yang paling pantas dapat satu-satunya warna sinyal di
   sistem ini. Yang dijaga: dia tetap HEMAT — cuma tepi dan teks, tidak pernah
   jadi latar blok penuh. */
.filter-tombol.disaring {
  color: var(--aksen);
  border-color: color-mix(in srgb, var(--aksen) 45%, transparent);
  background: var(--aksen-lembut);
}

.filter-tombol-nama { font-weight: 600; }
.filter-tombol-nilai {
  color: var(--tinta-3);
  font-variant-numeric: tabular-nums;
}
.filter-tombol.disaring .filter-tombol-nilai { color: inherit; }

.filter-tombol-panah { width: 12px; height: 12px; opacity: .55; }
.filter-tombol-panah svg { width: 12px; height: 12px; display: block; transform: rotate(90deg); }
.filter-tombol[aria-expanded='true'] .filter-tombol-panah svg { transform: rotate(-90deg); }

.filter-menu {
  position: absolute; top: calc(100% + 8px); left: 0; z-index: 6;
  width: 262px; max-width: calc(100vw - 24px);
  padding: var(--r2);
  border-radius: var(--lengkung-s);
  /* Isian padat, bukan kaca — alasannya sama dengan menu tema (bagian 5b):
     menu yang menumpuk di atas tabel angka harus benar-benar menutupinya,
     kalau tidak angka di belakang tetap terbaca dan bersaing dengan
     daftar centangnya. */
  background: var(--kaca-padat);
  border: 1px solid var(--garis-tegas);
  box-shadow: var(--bayang-3);
}

.filter-menu-alat {
  display: flex; flex-wrap: wrap; gap: 2px;
  padding-bottom: var(--r2);
  margin-bottom: var(--r2);
  border-bottom: 1px solid var(--garis);
}

.filter-aksi {
  padding: 4px 8px; font-size: 11px; font-weight: 600;
  color: var(--tinta-3); border-radius: var(--r1);
  cursor: pointer;
}
.filter-aksi:hover { color: var(--tinta); background: var(--keping); }
.filter-aksi-cepat { margin-left: auto; color: var(--aksen); }

.filter-cari {
  width: 100%; margin-bottom: var(--r2);
  padding: 6px 9px; font: inherit; font-size: 12px;
  color: var(--tinta);
  background: var(--kanvas-dalam);
  border: 1px solid var(--garis);
  border-radius: var(--r2);
}

.filter-kelompok {
  display: block; width: 100%; text-align: left;
  padding: 5px 8px; margin-bottom: 2px;
  font-size: 11.5px; font-weight: 600;
  color: var(--aksen); border-radius: var(--r1);
  cursor: pointer;
}
.filter-kelompok:hover { background: var(--keping); }

/* Daftar centang dibatasi tingginya lalu digulir sendiri. Provider HSI punya
   20 nilai; tanpa batas ini menunya lebih tinggi dari layar dan tombol
   "Semua" di atasnya jadi tidak terjangkau. */
.filter-pilihan { max-height: 264px; overflow-y: auto; margin: 0 calc(var(--r1) * -1); }

.filter-baris {
  display: flex; align-items: center; gap: var(--r2);
  padding: 5px var(--r1); border-radius: var(--r1);
  font-size: 12.5px; cursor: pointer;
}
.filter-baris:hover { background: var(--keping); }
.filter-baris input { flex: none; accent-color: var(--aksen); cursor: pointer; }

.filter-nilai {
  flex: 1; min-width: 0; color: var(--tinta-2);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.filter-jumlah {
  flex: none; font-size: 11px; color: var(--tinta-3);
  font-variant-numeric: tabular-nums;
}

/* --- keping "Tersaring" di kepala tabel --- */

.keping-saring {
  display: inline-block; vertical-align: middle;
  margin-left: var(--r2);
  padding: 2px 8px;
  font-size: 10px; font-weight: 700; letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--aksen);
  background: var(--aksen-lembut);
  border: 1px solid color-mix(in srgb, var(--aksen) 40%, transparent);
  border-radius: 999px;
  /* Sejajar dengan huruf besar judulnya, bukan dengan garis dasarnya —
     keping sekecil ini yang duduk di baseline terlihat seperti jatuh. */
  transform: translateY(-2px);
}

/* KPI yang tersaring: angkanya tetap tenang, cuma namanya yang diberi tanda.
   Memberi warna pada ANGKANYA akan membuat tujuh KPI berwarna sekaligus
   begitu satu filter aktif — dan tujuh benda bertanda sama dengan nol benda
   bertanda. */
.kpi.tersaring .kpi-nama { color: var(--aksen); }

/* --- tombol simpan gambar --- */

.alat-gambar { display: flex; gap: var(--r2); flex: none; }
.alat-gambar .tombol svg { width: 14px; height: 14px; }

/* ==========================================================================
   23. TABEL YANG TERSARING HABIS
   ==========================================================================
   Nol baris cuma bisa terjadi karena filter (`computeCrosstab` tidak pernah
   mengembalikan tabel tanpa baris). Jadi yang tampil di sini bukan "tidak ada
   data" — melainkan "filternya terlalu ketat", yang langkah berikutnya jelas
   dan harus disebutkan.                                                     */

.tabel-hampa {
  display: flex; flex-direction: column; align-items: center;
  gap: var(--r2); text-align: center;
  padding: var(--r7) var(--r4);
  color: var(--tinta-3);
}
.tabel-hampa-ikon { width: 32px; height: 32px; color: var(--aksen); opacity: .8; }
.tabel-hampa-ikon svg { width: 32px; height: 32px; }
.tabel-hampa b { color: var(--tinta); font-size: 15px; }
.tabel-hampa span { font-size: 12.5px; max-width: 40ch; line-height: 1.55; }

/* ==========================================================================
   24. PEMILIH BANDING (data awal / data akhir)
   ==========================================================================
   Dua `<select>` dengan satu tombol tukar di tengah. Bentuk ini dipilih karena
   dia menjelaskan arahnya sendiri: kiri lebih dulu, kanan sesudahnya, dan
   panah di tengah menunjuk dari yang satu ke yang lain. Dua dropdown
   bertumpuk vertikal kehilangan keterangan arah itu seluruhnya.             */

.banding-kepala {
  display: flex; align-items: flex-end; gap: var(--r3); flex-wrap: wrap;
  padding-bottom: var(--r4); margin-bottom: var(--r4);
  border-bottom: 1px solid var(--garis);
}

.banding-medan { flex: 1 1 190px; min-width: 0; display: block; }
.banding-medan > span {
  display: block; margin-bottom: 5px;
  font-size: 10.5px; font-weight: 700; letter-spacing: .12em;
  text-transform: uppercase; color: var(--tinta-3);
}

.banding-pilih {
  width: 100%; padding: 8px 10px;
  font: inherit; font-size: 13px; font-weight: 600;
  color: var(--tinta);
  background: var(--kanvas-dalam);
  border: 1px solid var(--garis-tegas);
  border-radius: var(--r2);
  cursor: pointer;
}
.banding-pilih:focus-visible { outline: 2px solid var(--aksen); outline-offset: 1px; }

/* Tombol tukar dipatok sejajar dengan kotak pilihannya, bukan dengan labelnya
   — jadi ada `margin-bottom` nol dan tidak ada `align-self: center` yang akan
   menaikkannya ke tengah termasuk tinggi labelnya. */
.banding-tukar { flex: none; margin-bottom: 1px; }
.banding-tukar svg { width: 16px; height: 16px; }


/* --- sakelar "ikuti filter dashboard" + penanda tersaring ---------------
   Sakelarnya mengambil SATU BARIS PENUH di atas kedua pemilih, bukan menyelip
   di sampingnya. Alasannya bukan ruang: dia mengubah arti seluruh angka di
   panel ini, jadi dia harus terbaca sebelum pemilih tanggalnya — bukan
   sesudah, dan bukan di sebelah sesuatu yang lain.                        */

.banding-ikut {
  flex: 1 0 100%;
  display: flex; align-items: flex-start; gap: var(--r2);
  padding: 9px 11px;
  border: 1px solid var(--garis);
  border-radius: var(--r2);
  background: var(--keping);
  cursor: pointer;
  transition: background var(--cepat), border-color var(--cepat);
}
.banding-ikut:hover { background: var(--keping-kuat); }
.banding-ikut.nyala {
  border-color: color-mix(in srgb, var(--aksen) 42%, transparent);
  background: var(--aksen-lembut);
}
.banding-ikut input { flex: none; margin-top: 2px; accent-color: var(--aksen); cursor: pointer; }

.banding-ikut-teks { min-width: 0; font-size: 12.5px; line-height: 1.45; }
.banding-ikut-teks b { display: block; color: var(--tinta); font-size: 12px; }
.banding-ikut.nyala .banding-ikut-teks b { color: var(--aksen); }
.banding-ikut-rinci {
  color: var(--tinta-3); font-size: 11.5px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* --- bilah filter DI DALAM panel banding ---------------------------------
   Sama alasannya dengan sakelar di atas: mengambil satu baris penuh, dan di
   ATAS pemilih tanggal, karena dia mengubah arti seluruh angka di bawahnya.
   Isinya `.filter-bilah` yang SAMA PERSIS (kelas & komponen) dengan bilah di
   dashboard utama — lihat kepala `rekap.js` kenapa itu bukan kebetulan. */
.banding-filter { flex: 1 0 100%; }
.banding-filter-label {
  margin-bottom: 7px;
  font-size: 10.5px; font-weight: 700; letter-spacing: .12em;
  text-transform: uppercase; color: var(--tinta-3);
}
.banding-abaikan {
  display: flex; align-items: center; gap: 7px;
  margin-top: var(--r3);
  font-size: 12px; color: var(--tinta-2);
  cursor: pointer;
}
.banding-abaikan input { accent-color: var(--aksen); cursor: pointer; }

.banding-saring {
  display: flex; gap: var(--r3); align-items: flex-start;
  padding: var(--r3);
  margin-bottom: var(--r4);
  border-radius: var(--r2);
  border: 1px solid color-mix(in srgb, var(--aksen) 34%, transparent);
  background: var(--aksen-lembut);
  font-size: 12.5px; line-height: 1.5;
}
.banding-saring b { color: var(--aksen); font-size: 11.5px; letter-spacing: .04em; }
.banding-saring-ikon { width: 17px; flex: none; color: var(--aksen); margin-top: 1px; }
.banding-saring-ikon svg { width: 17px; height: 17px; display: block; }
.banding-saring-rinci { color: var(--tinta-2); margin-top: 2px; }

/* ==========================================================================
   25. PEMILIH BAHASA
   ==========================================================================
   Memakai `.tema-menu` dan `.tema-baris` apa adanya (bagian 5b) — dua kendali
   sejenis yang berdampingan sebaiknya juga terlihat sejenis. Yang ditambahkan
   di sini cuma bagian yang memang berbeda: bahasa tidak punya palet untuk
   dipratinjau, jadi tempat kepingan warna diisi kode dua huruf.             */

.tombol-bahasa { gap: 6px; padding-left: 9px; padding-right: 10px; }
.bahasa-bola { width: 15px; height: 15px; flex: none; opacity: .75; }
.bahasa-bola svg { width: 15px; height: 15px; display: block; }

.bahasa-kode {
  font-size: 11px; font-weight: 800; letter-spacing: .08em;
  font-variant-numeric: tabular-nums;
}

.bahasa-menu { width: 210px; }

.bahasa-baris-kode {
  flex: none;
  width: 30px; height: 22px;
  display: grid; place-items: center;
  font-size: 10.5px; font-weight: 800; letter-spacing: .06em;
  color: var(--tinta-3);
  background: var(--keping);
  border: 1px solid var(--garis);
  border-radius: var(--r1);
}
.bahasa-baris[aria-checked='true'] .bahasa-baris-kode {
  color: var(--aksen);
  border-color: color-mix(in srgb, var(--aksen) 40%, transparent);
}

/* ==========================================================================
   26. LAYAR SEMPIT — bilah alat & filter
   ==========================================================================   */

@media (max-width: 720px) {
  .alat-baris { align-items: stretch; }
  .alat-gambar { width: 100%; }
  .alat-gambar .tombol { flex: 1; justify-content: center; }
  /* Menu filter di layar sempit dipatok ke tepi kiri wadahnya, bukan ke
     tombolnya: tombol yang letaknya di kanan akan menjulurkan menu 262px
     keluar layar. */
  .filter-menu { left: auto; right: 0; }
  .banding-tukar { order: 3; margin: 0 auto; transform: rotate(90deg); }
}

@media print {
  .alat-baris, .filter-menu { display: none !important; }
  /* Keping "Tersaring" JUSTRU harus ikut tercetak — cetakan yang beredar tanpa
     penandanya bisa dibaca sebagai angka penuh, kesalahan yang persis sama
     dengan gambar yang dikirim ke WA tanpa keterangan filter. */
  .keping-saring {
    display: inline-block !important;
    color: #7a4a1c !important; background: #f6ecdf !important;
    border-color: #c99a63 !important;
  }
}

/* ==========================================================================
   27. GERAK DIKURANGI & CETAK
   ==========================================================================
   Bukan sekadar mematikan animasi: `animation: none` pada elemen yang animasi
   masuknya memakai `backwards` akan meninggalkannya tak terlihat. Jadi
   durasinya dipangkas jadi hampir nol, bukan dihapus.                       */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
  .karusel-jalur { scroll-behavior: auto; }
}

@media print {
  .latar, .atas, .obrol, .tirai, .kabar-tumpuk, .karusel-kemudi { display: none !important; }
  body { background: #fff; }

  /* `content-visibility: auto` melewatkan penggambaran apa pun yang di luar
     pandangan — hemat sekali saat digulir, dan MEMATIKAN saat dicetak: kartu
     dan slide yang belum pernah tergambar keluar sebagai kotak kosong. Sama
     jadinya di potret satu-halaman-penuh. Jadi di cetakan dia dipaksa gambar. */
  .kartu, .karusel-slide { content-visibility: visible !important; }
  .halaman { padding: 0; max-width: none; }
  .panggung, .kartu, .kpi-baris {
    box-shadow: none !important; backdrop-filter: none !important;
    border: 1px solid #d8cfc0; break-inside: avoid;
  }
  .tabel-bungkus { max-height: none; overflow: visible; }
  .karusel-jalur { display: block; overflow: visible; }
  .karusel-slide { break-inside: avoid; margin-bottom: var(--r5); }
  /* Cetakan itu KERTAS. Espresso yang dicetak jadi ember tinta dan tetap tidak
     terbaca, jadi di sini seluruh paletnya dibalik sekali lagi — satu-satunya
     tempat di berkas ini yang masih punya dua rupa, dan alasannya bukan selera
     tapi bahan. */
  body { color: #1b1611 !important; }
  .tabel th, .tabel td,
  .judul-halaman h1, .judul-sub, .kpi-nilai, .kpi-nama,
  .panggung-judul, .kartu-judul, .batang-nilai { color: #1b1611 !important; }
  .tabel thead th { background: #f2ece2 !important; color: #1b1611 !important; }
  .tabel tbody th { background: #faf7f2 !important; }
  .tabel tfoot th, .tabel tfoot td { background: #2f2822 !important; color: #fff !important; }
}
