Bikin Hidup Lebih Santai: Menguasai Otomasi Python untuk Bot & Web Scraping

PintarApp Juli 20, 2026
Bikin Hidup Lebih Santai: Menguasai Otomasi Python untuk Bot & Web Scraping

Selamat Datang di Dunia Bebas Tugas Monoton!

Dulu, saya sering merasa seperti seorang koki di dapur yang harus memotong ribuan bawang merah setiap hari. Rasanya jari sudah kram, mata perih, tapi tugas harus tetap selesai. Begitu juga di dunia digital; kadang kita terjebak dalam pekerjaan yang repetitif, seperti mengumpulkan data dari website satu per satu, mengisi formulir yang sama berulang kali, atau memantau harga produk secara manual. Jujur saja, waktu itu saya pernah ngalamin error aneh di Excel waktu mencoba otomatisasi pake VBA, terus mikir, "Pasti ada cara yang lebih elegan dan universal dari ini!" Nah, disitulah Python masuk dan mengubah segalanya.

Pekerjaan monoton itu, kawan, bisa membuat kita bosan, lelah, dan bahkan kehilangan fokus untuk hal-hal yang lebih penting. Tapi untungnya, kita hidup di era di mana mesin bisa kita perintahkan untuk melakukan tugas-tugas itu. Dan siapa 'dalang' di balik layar yang paling lihai untuk urusan ini? Tentu saja, Python!

Artikel ini akan jadi panduan santai kita untuk mulai menyelami dunia otomatisasi dengan Python, khususnya untuk membangun bot dan melakukan web scraping. Anggap saja kita sedang merakit robot pribadi di bengkel, dari nol sampai bisa berjalan sendiri!

Kenapa Python Jadi Pilihan Utama untuk Otomasi?

Kalau kita bicara soal merakit sesuatu di bengkel, kita pasti butuh perkakas yang multifungsi, mudah dipakai, dan tersedia banyak suku cadangnya. Nah, Python itu persis seperti multi-tool andalan di dunia pemrograman. Kenapa?

  • Sintaks yang Jelas dan Mudah Dibaca: Ibarat panduan perakitan yang ditulis dengan bahasa sehari-hari, bukan kode morse. Ini bikin kita cepat belajar dan gampang banget memahami kode orang lain.
  • Ekosistem Pustaka yang Melimpah: Ini seperti bengkel yang punya semua jenis kunci pas, obeng, dan alat khusus yang kamu butuhkan. Untuk web scraping dan bot, ada pustaka seperti Requests, BeautifulSoup, dan Selenium yang siap pakai.
  • Komunitas yang Besar: Kalau ada masalah, nggak perlu khawatir sendirian. Ada jutaan programmer Python lain yang siap bantu (atau sudah punya solusi dari masalah yang sama!).

Dengan Python, kamu bisa mengubah jam-jam kerja manual jadi hitungan menit. Bayangkan, pekerjaan yang biasanya bikin pundak pegal, sekarang cukup kamu pantau sambil ngopi santai!

Mengintip Dunia Web Scraping: Si "Pustakawan Digital" Andalan

Apa Itu Web Scraping?

Web scraping itu seperti punya pustakawan super cerdas dan super cepat. Kamu minta dia masuk ke sebuah perpustakaan raksasa (internet), mencari buku-buku tertentu (data dari website), dan menyalin informasi spesifik dari buku-buku itu ke dalam catatanmu (file Excel, database, dsb.). Semua dilakukan secara otomatis dan terorganisir.

Contoh nyata? Mengumpulkan harga produk dari beberapa e-commerce, memantau berita terbaru dari portal-portal, atau bahkan mengumpulkan ulasan pelanggan untuk analisis sentimen. Ini semua adalah pekerjaan yang sempurna untuk web scraping.

Alat Perang untuk Web Scraping: Requests & BeautifulSoup

Untuk tugas ini, kita punya dua alat utama:

  • Requests: Ini adalah "kaki" si pustakawan kita yang bertugas pergi ke website. Dia mengirim permintaan ke server dan mengambil seluruh isi halaman web (HTML).
  • BeautifulSoup: Ini adalah "otak" si pustakawan kita. Setelah Requests mengambil halaman, BeautifulSoup akan membantu kita memilah-milah struktur HTML tersebut, mencari elemen-elemen spesifik seperti judul, harga, atau paragraf tertentu.

Mari kita coba dengan contoh sederhana. Kita akan mencoba mengambil judul dari sebuah halaman web fiktif.


import requests
from bs4 import BeautifulSoup
# URL website target
url = "https://www.example.com" # Ganti dengan URL yang valid jika ingin mencoba
try:
# Mengirim permintaan GET ke URL
response = requests.get(url)
response.raise_for_status() # Cek jika ada error HTTP
# Membuat objek BeautifulSoup untuk mem-parsing HTML
soup = BeautifulSoup(response.text, 'html.parser')
# Mencari judul halaman (biasanya di tag )
title = soup.title.string
print(f"Judul Halaman: {title}")
# Contoh lain: mencari semua paragraf
paragraphs = soup.find_all('p')
print("\nBeberapa Paragraf Pertama:")
for i, p in enumerate(paragraphs[:3]): # Ambil 3 paragraf pertama
print(f"- {p.get_text()}")
except requests.exceptions.RequestException as e:
print(f"Terjadi error saat mengambil data: {e}")
except Exception as e:
print(f"Terjadi error lain: {e}")
</code></pre>
<p>Kode di atas adalah pondasi awal untuk web scraping. Kita mengirimkan permintaan ke server, mendapatkan respons HTML, lalu menggunakan BeautifulSoup untuk "membedah" respons tersebut dan mengekstrak informasi yang kita inginkan.</p>
<h2>Membangun Bot Otomasi Sederhana: Si "Koki Digital" yang Teliti</h2>
<h3>Apa Itu Bot Otomasi?</h3>
<p>Jika web scraping itu tentang membaca, maka bot otomasi itu tentang berinteraksi. Bayangkan kamu punya koki pribadi yang sudah terlatih. Kamu beri dia resep (script), dia akan dengan teliti mengikuti setiap langkah: mengambil bahan, memotong, mencampur, dan menyajikan. Nah, bot otomasi melakukan hal yang sama di dunia digital.</p>
<p>Bot bisa digunakan untuk login ke sebuah website, mengisi formulir, mengklik tombol, mengunggah file, atau bahkan berinteraksi dengan elemen JavaScript yang dinamis. Ini adalah alat yang sangat ampuh untuk tugas-tugas yang melibatkan interaksi langsung dengan antarmuka web.</p>
<h3>Alat Perang untuk Bot Otomasi: Selenium</h3>
<p>Untuk pekerjaan "interaktif" ini, kita punya <strong>Selenium</strong>. Selenium itu seperti pengemudi mobil balap yang sangat terampil. Dia bisa mengontrol browser web (Chrome, Firefox, dll.) seolah-olah ada manusia yang mengoperasikannya. Jadi, apa yang bisa kamu lakukan secara manual di browser, Selenium bisa melakukannya secara otomatis!</p>
<p>Sebelum mulai, kamu perlu menginstal Selenium dan juga WebDriver (misalnya ChromeDriver untuk Google Chrome) yang sesuai dengan browser yang kamu gunakan. Anggap saja WebDriver itu "mesin" yang bikin Selenium bisa ngegas browsernya.</p>
<pre><code>
# Instalasi Selenium (jalankan di terminal)
# pip install selenium
# pip install webdriver_manager
</code></pre>
<p>Berikut contoh sederhana untuk membuka Google, mengetik sesuatu di kolom pencarian, dan menekan tombol enter:</p>
<pre><code>
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service as ChromeService
from webdriver_manager.chrome import ChromeDriverManager
import time
try:
# Menginisialisasi WebDriver untuk Chrome
# Dengan webdriver_manager, kita tidak perlu download chromedriver manual
service = ChromeService(ChromeDriverManager().install())
driver = webdriver.Chrome(service=service)
# Membuka halaman Google
driver.get("https://www.google.com")
time.sleep(2) # Beri waktu browser untuk memuat halaman
# Mencari elemen input pencarian berdasarkan nama 'q'
search_box = driver.find_element(By.NAME, "q")
# Mengetikkan query pencarian
search_box.send_keys("Python automation tutorial")
# Menekan tombol ENTER
search_box.send_keys(Keys.ENTER)
time.sleep(5) # Beri waktu untuk melihat hasil
print("Pencarian berhasil dilakukan!")
except Exception as e:
print(f"Terjadi error saat mengoperasikan bot: {e}")
finally:
# Tutup browser setelah selesai
if 'driver' in locals() and driver:
driver.quit()
</code></pre>
<div style="text-align:center;margin:30px 0;"><script>atOptions={'key':'7d25a94073d391d12386aaa75b909463','format':'iframe','height':90,'width':728,'params':{}};</script><script src="https://www.highperformanceformat.com/7d25a94073d391d12386aaa75b909463/invoke.js"></script></div>
<p>Nah, dari kode di atas, kamu bisa lihat bagaimana Selenium membuka browser, "mengetik" di kolom pencarian, dan bahkan "menekan" tombol enter. Ini cuma permulaan, imajinasimu adalah batasnya!</p>
<h2>Etika dan Tanggung Jawab: Jangan Sampai Jadi "Preman Digital"!</h2>
<p>Kekuatan besar datang dengan tanggung jawab besar, bukan? Otomasi dan web scraping memang powerful, tapi kita harus menggunakannya dengan bijak. Ibarat memancing, kita tidak boleh memancing di kolam orang tanpa izin, apalagi menggunakan bom ikan.</p>
<ul>
<li><strong>Cek robots.txt:</strong> Sebelum scraping, selalu cek file <code>robots.txt</code> di website target (misalnya: <code>www.example.com/robots.txt</code>). File ini adalah "rambu-rambu" yang memberitahu bagian mana dari website yang boleh dan tidak boleh di-crawl.</li>
<li><strong>Jangan Membebani Server:</strong> Beri jeda waktu (<code>time.sleep()</code>) antar permintaan. Jangan mengirim ribuan permintaan dalam sedetik. Kamu bisa membuat server website down, dan itu adalah perbuatan yang tidak etis (dan bisa diblokir!).</li>
<li><strong>Baca Terms of Service (ToS):</strong> Beberapa website melarang scraping dalam ToS mereka. Hormati aturan ini.</li>
<li><strong>Gunakan Data dengan Bijak:</strong> Jangan menyalahgunakan data yang kamu kumpulkan. Jaga privasi dan patuhi hukum yang berlaku.</li>
</ul>
<h2>Tips Jitu Anti-Blokir dan Anti-Pusing</h2>
<p>Terkadang, website target tidak suka kita "mengunjungi" mereka secara otomatis. Mereka bisa memblokir IP kita atau mengidentifikasi kita sebagai bot. Ini beberapa triknya:</p>
<ul>
<li><strong>Ganti User-Agent:</strong> Website sering mengecek 'User-Agent' untuk mengetahui jenis browser atau OS yang kamu gunakan. Buat script-mu terlihat seperti browser biasa.</li>
<li><strong>Gunakan Proxy:</strong> Jika IP-mu terblokir, coba gunakan proxy untuk merotasi alamat IP. Ini seperti kamu menyamar dengan ganti-ganti identitas.</li>
<li><strong>Tambahkan Jeda Acak:</strong> Daripada jeda <code>time.sleep(2)</code> yang konstan, gunakan <code>time.sleep(random.uniform(1, 5))</code> untuk jeda yang lebih acak dan menyerupai perilaku manusia.</li>
<li><strong>Tangani Error dengan Baik:</strong> Gunakan blok <code>try-except</code> untuk mengantisipasi jika ada elemen tidak ditemukan atau koneksi terputus. Script-mu tidak akan langsung crash.</li>
</ul>
<h2>Kesimpulan: Jadikan Python Asisten Pribadimu!</h2>
<p>Selamat! Kamu sudah mengintip potensi luar biasa Python dalam otomatisasi, baik untuk web scraping maupun membangun bot. Ini bukan lagi sekadar bahasa pemrograman, ini adalah kunci untuk membuka gerbang efisiensi dan kebebasan dari tugas-tugas yang membosankan.</p>
<p>Ingat, setiap baris kode yang kamu tulis adalah instruksi yang akan dikerjakan oleh 'asisten digital' pribadi kamu. Jadi, mari kita mulai bereksperimen, berkreasi, dan ubah hidup kita menjadi lebih santai dengan bantuan Python. Selamat ngoding, para calon master otomatisasi!</p>
</div>
<div class='mt-8 pt-4 border-t border-gray-200 dark:border-dark-border flex flex-wrap gap-2'>
<a class='px-2.5 py-1 bg-gray-50 dark:bg-dark-700 border border-gray-200 dark:border-dark-border text-blue-600 dark:text-dark-link text-xs font-medium rounded-full hover:bg-gray-100 dark:hover:bg-dark-border transition-colors' href='https://script.pintarapp.com/search/label/Bot'>Bot</a>
<a class='px-2.5 py-1 bg-gray-50 dark:bg-dark-700 border border-gray-200 dark:border-dark-border text-blue-600 dark:text-dark-link text-xs font-medium rounded-full hover:bg-gray-100 dark:hover:bg-dark-border transition-colors' href='https://script.pintarapp.com/search/label/Python'>Python</a>
<a class='px-2.5 py-1 bg-gray-50 dark:bg-dark-700 border border-gray-200 dark:border-dark-border text-blue-600 dark:text-dark-link text-xs font-medium rounded-full hover:bg-gray-100 dark:hover:bg-dark-border transition-colors' href='https://script.pintarapp.com/search/label/Web%20Scraping'>Web Scraping</a>
</div>
<div class='mt-8 pt-4 border-t border-gray-200 dark:border-dark-border flex justify-center w-full'>
<script async='async' data-cfasync='false' src='https://pl28962147.profitablecpmratenetwork.com/7797da862e5153c59970a9d83ab07d97/invoke.js'></script>
<div id='container-7797da862e5153c59970a9d83ab07d97'></div>
</div>
</div>
</div></div>
</main>
<!-- KOLOM 3: SIDEBAR KANAN (Tetap 3 Kolom / 25%) -->
<aside class='lg:col-span-3 w-full order-3 sticky top-20'>
<!-- Slot Iklan Atas Sidebar Kanan -->
<div class='w-full mb-4 flex justify-center items-center overflow-hidden adsterra-slot' data-h='250' data-key='017ff5a2024d32a8d605ed757a4d6002' data-w='300'>
<div class='no-items section' id='ad-sidebar-right'></div>
</div>
<div class='sidebar-right section' id='sidebar-right'><div class='widget PopularPosts' data-version='2' id='PopularPosts1'>
<div class='widget bg-white dark:bg-dark-800 border border-gray-200 dark:border-dark-border p-4 rounded-md shadow-sm'>
<h2>Trending</h2>
<div class='space-y-3'>
<a class='group flex gap-3 items-start' href='https://script.pintarapp.com/2026/03/otomatisasi-kompresi-gambar-massal-ke.html'>
<div class='w-10 h-10 flex-shrink-0 bg-gray-50 dark:bg-dark-900 border border-gray-200 dark:border-dark-border rounded-md overflow-hidden'>
<img class='w-full h-full object-cover transition-transform duration-500 group-hover:scale-110' loading='lazy' src='https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiYDgcW77dIwQ7Fn8qRlFuAhiTxJ0mIpi2gvJ1ZAZhhjppBXp9F0yF6zzOIyOJqoiyWqubxaQhI6HJwoeyhsG8XDBRZhpsZ7NBTltmGv8sibMyKJgGnj9l7fkrTlqSHueUoNOcU7NLJOQbdx5vJPj4_DHrWxmlVtsdjaKsT0pC63WM8UJtLtJQpFtprsls/s400/compress%20massal%20webp.jpg'/>
</div>
<div class='flex-1'>
<h4 class='text-xs font-semibold text-gray-800 dark:text-dark-text group-hover:text-blue-600 dark:group-hover:text-dark-link line-clamp-2 leading-snug'>Otomatisasi Kompresi Gambar Massal ke format WebP</h4>
</div>
</a>
<a class='group flex gap-3 items-start' href='https://script.pintarapp.com/2026/03/dari-nol-jadi-pro-bangun-dapps-smart.html'>
<div class='w-10 h-10 flex-shrink-0 bg-gray-50 dark:bg-dark-900 border border-gray-200 dark:border-dark-border rounded-md overflow-hidden'>
<img class='w-full h-full object-cover transition-transform duration-500 group-hover:scale-110' loading='lazy' src='https://lh3.googleusercontent.com/blogger_img_proxy/AEn0k_sRctWA2BY7_wwlYXPLFauPpZPwhtGJ9rFNBGQNKY6TaxiOGyzNyAafAfTaPv3NjbbeLpQe29A_P_rAKK9UMilD_4AmWZg1R7cE_3s'/>
</div>
<div class='flex-1'>
<h4 class='text-xs font-semibold text-gray-800 dark:text-dark-text group-hover:text-blue-600 dark:group-hover:text-dark-link line-clamp-2 leading-snug'>Dari Nol Jadi Pro: Bangun dApps & Smart Contract di Solana yang Ngebut Abis!</h4>
</div>
</a>
<a class='group flex gap-3 items-start' href='https://script.pintarapp.com/2026/03/rahasia-bikin-hidup-lebih-mudah-python.html'>
<div class='w-10 h-10 flex-shrink-0 bg-gray-50 dark:bg-dark-900 border border-gray-200 dark:border-dark-border rounded-md overflow-hidden'>
<img class='w-full h-full object-cover transition-transform duration-500 group-hover:scale-110' loading='lazy' src='https://lh3.googleusercontent.com/blogger_img_proxy/AEn0k_tjqREQ9LyGe8kkh6ZYH2mXh-m052qvwjokhuhzZI5r63a8qiZFvrLr5kmE_oLgyMziLA7GcV992wNqZKShm8g9zr1ZQ9dGZdjt0fg'/>
</div>
<div class='flex-1'>
<h4 class='text-xs font-semibold text-gray-800 dark:text-dark-text group-hover:text-blue-600 dark:group-hover:text-dark-link line-clamp-2 leading-snug'>Rahasia Bikin Hidup Lebih Mudah: Python untuk Bot & Web Scraping Otomatis!</h4>
</div>
</a>
<a class='group flex gap-3 items-start' href='https://script.pintarapp.com/2026/03/python-jadi-kuncian-bikin-bot-otomasi.html'>
<div class='w-10 h-10 flex-shrink-0 bg-gray-50 dark:bg-dark-900 border border-gray-200 dark:border-dark-border rounded-md overflow-hidden'>
<img class='w-full h-full object-cover transition-transform duration-500 group-hover:scale-110' loading='lazy' src='https://lh3.googleusercontent.com/blogger_img_proxy/AEn0k_vbyPqLM2pm7cBVV3nVifpGrIn5h9Oq9wG19B92arJTbloJSqTZ4Pzm6ndv_IOrQ0YV5he2DNACjStD6CC9VlUOSLgCf_ScYSroPGZjRhYGQaUM01T1'/>
</div>
<div class='flex-1'>
<h4 class='text-xs font-semibold text-gray-800 dark:text-dark-text group-hover:text-blue-600 dark:group-hover:text-dark-link line-clamp-2 leading-snug'>Python Jadi Kuncian! Bikin Bot Otomasi & Web Scraping Anti Ribet (Panduan Lengkap)</h4>
</div>
</a>
<a class='group flex gap-3 items-start' href='https://script.pintarapp.com/2026/03/dari-nol-sampai-pro-panduan-lengkap.html'>
<div class='w-10 h-10 flex-shrink-0 bg-gray-50 dark:bg-dark-900 border border-gray-200 dark:border-dark-border rounded-md overflow-hidden'>
<img class='w-full h-full object-cover transition-transform duration-500 group-hover:scale-110' loading='lazy' src='https://lh3.googleusercontent.com/blogger_img_proxy/AEn0k_sxFAsniLDUPqkc_rs_IeVFK_9hzMbn9yjTZzaik_OgAWnH-c0KYYKdMWPdykLpY29C7JijxJOOdJrtAaw6_gyftafeunuuk129JZRSdDypW_aEww'/>
</div>
<div class='flex-1'>
<h4 class='text-xs font-semibold text-gray-800 dark:text-dark-text group-hover:text-blue-600 dark:group-hover:text-dark-link line-clamp-2 leading-snug'>Dari Nol Sampai Pro: Panduan Lengkap Simulasi Jaringan Pakai GNS3 dan Packet Tracer</h4>
</div>
</a>
<a class='group flex gap-3 items-start' href='https://script.pintarapp.com/2026/03/memaksimalkan-mikrotik-chr-panduan.html'>
<div class='w-10 h-10 flex-shrink-0 bg-gray-50 dark:bg-dark-900 border border-gray-200 dark:border-dark-border rounded-md overflow-hidden'>
<img class='w-full h-full object-cover transition-transform duration-500 group-hover:scale-110' loading='lazy' src='https://lh3.googleusercontent.com/blogger_img_proxy/AEn0k_uU3smnzWakBiUOA9NsK-WXiReDPZMTQwpeF9LFAiNEdsQXH-ngPIEvbNRPy-GS7Fb2O1Jq5R-QLAr23ZCfcCHJ61nEAMR8U3FBbgHm4Wup1RLe'/>
</div>
<div class='flex-1'>
<h4 class='text-xs font-semibold text-gray-800 dark:text-dark-text group-hover:text-blue-600 dark:group-hover:text-dark-link line-clamp-2 leading-snug'>Memaksimalkan MikroTik CHR: Panduan Lengkap Manajemen Bandwidth dan Server Impianmu</h4>
</div>
</a>
<a class='group flex gap-3 items-start' href='https://script.pintarapp.com/2026/03/jago-jaringan-tanpa-nombok-hardware.html'>
<div class='w-10 h-10 flex-shrink-0 bg-gray-50 dark:bg-dark-900 border border-gray-200 dark:border-dark-border rounded-md overflow-hidden'>
<img class='w-full h-full object-cover transition-transform duration-500 group-hover:scale-110' loading='lazy' src='https://lh3.googleusercontent.com/blogger_img_proxy/AEn0k_v0V_4UZgcAkg8lvrsxZasry8AeA8uZYaaOuWaed0cLfgWJHZQVehvcqG4DN4w0MwAn6QNrf6N1I2SqRJxQ1B7xNrs2pjy9kYrT6V-ryQmkWCVCLA'/>
</div>
<div class='flex-1'>
<h4 class='text-xs font-semibold text-gray-800 dark:text-dark-text group-hover:text-blue-600 dark:group-hover:text-dark-link line-clamp-2 leading-snug'>Jago Jaringan Tanpa Nombok Hardware: Panduan Lengkap Simulasi dengan GNS3 dan Cisco Packet Tracer</h4>
</div>
</a>
<a class='group flex gap-3 items-start' href='https://script.pintarapp.com/2026/03/dari-nol-sampai-pro-bikin-kalkulator.html'>
<div class='w-10 h-10 flex-shrink-0 bg-gray-50 dark:bg-dark-900 border border-gray-200 dark:border-dark-border rounded-md overflow-hidden'>
<img class='w-full h-full object-cover transition-transform duration-500 group-hover:scale-110' loading='lazy' src='https://lh3.googleusercontent.com/blogger_img_proxy/AEn0k_tGfGAE5wzOJDHO5AqanshJBPf_ky-_hStPXwYV--gQNY5kaqE9k7DHCGw82jo-SnGegIT_ieknasCoSn69O9RMiLT_0VCddMwkBO2weVSzKgY-dQ'/>
</div>
<div class='flex-1'>
<h4 class='text-xs font-semibold text-gray-800 dark:text-dark-text group-hover:text-blue-600 dark:group-hover:text-dark-link line-clamp-2 leading-snug'>Dari Nol Sampai Pro: Bikin Kalkulator dan Page Builder Interaktif Pakai HTML, CSS, JS!</h4>
</div>
</a>
<a class='group flex gap-3 items-start' href='https://script.pintarapp.com/2026/03/membangun-kalkulator-dan-page-builder.html'>
<div class='w-10 h-10 flex-shrink-0 bg-gray-50 dark:bg-dark-900 border border-gray-200 dark:border-dark-border rounded-md overflow-hidden'>
<img class='w-full h-full object-cover transition-transform duration-500 group-hover:scale-110' loading='lazy' src='https://lh3.googleusercontent.com/blogger_img_proxy/AEn0k_tNo3HaVyFB82HDmevkJYIFXhrCqCyCs9xKVcVLJ6J0SIWoZxJlzlGEpiZlPimH27waM967t4Ofz3n-1alk1jx7-GTXh3uNgjU4g94jpw'/>
</div>
<div class='flex-1'>
<h4 class='text-xs font-semibold text-gray-800 dark:text-dark-text group-hover:text-blue-600 dark:group-hover:text-dark-link line-clamp-2 leading-snug'>Membangun Kalkulator dan Page Builder Interaktif dengan HTML, CSS, dan JavaScript Murni</h4>
</div>
</a>
<a class='group flex gap-3 items-start' href='https://script.pintarapp.com/2026/03/bedah-solana-web3-panduan-lengkap.html'>
<div class='w-10 h-10 flex-shrink-0 bg-gray-50 dark:bg-dark-900 border border-gray-200 dark:border-dark-border rounded-md overflow-hidden'>
<img class='w-full h-full object-cover transition-transform duration-500 group-hover:scale-110' loading='lazy' src='https://lh3.googleusercontent.com/blogger_img_proxy/AEn0k_s3tC7DGgr9Z2sVkXkKIWuw8ZejoT4v3ElEWH6xY6VTuRIMAVANhDjquajx8maUYHie3tkORn8VRulI21gCwN_3IjxHSGXHBlt8Oc5ufZyhQg-s'/>
</div>
<div class='flex-1'>
<h4 class='text-xs font-semibold text-gray-800 dark:text-dark-text group-hover:text-blue-600 dark:group-hover:text-dark-link line-clamp-2 leading-snug'>Bedah Solana Web3: Panduan Lengkap Ngoding dApps dan Smart Contract dari Nol (Pakai Anchor, Bro!)</h4>
</div>
</a>
</div>
</div>
</div></div>
</aside>
</div>
</div>
<!-- FOOTER -->
<footer class='w-full border-t border-gray-200 dark:border-dark-border bg-gray-50 dark:bg-dark-900 mt-auto'>
<div class='max-w-[1200px] mx-auto px-4 py-6 flex flex-col md:flex-row justify-between items-center gap-4 text-xs text-gray-500 dark:text-dark-muted'>
<div class='flex items-center gap-2'>
<svg class='w-5 h-5 text-gray-400 dark:text-dark-muted' fill='currentColor' viewBox='0 0 24 24'><path clip-rule='evenodd' d='M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z' fill-rule='evenodd'></path></svg>
<span>© 2026 PintarApp Script. All rights reserved.</span>
</div>
<div class='flex space-x-4'>
<a class='hover:text-blue-600 dark:hover:text-dark-link transition-colors' href='/p/about.html#tentang'>About</a>
<a class='hover:text-blue-600 dark:hover:text-dark-link transition-colors' href='/p/about.html#privasi'>Privacy Policy</a>
<a class='hover:text-blue-600 dark:hover:text-dark-link transition-colors' href='/p/about.html#syarat'>Terms of Service</a>
</div>
</div>
</footer>
<!-- FLOATING SHARE (BOTTOM LEFT) -->
<div class='fixed bottom-20 md:bottom-6 left-4 md:left-6 z-50 flex flex-col items-center gap-3' id='floating-share'>
<div class='flex flex-col gap-3 opacity-0 invisible translate-y-4 transition-all duration-300' id='share-icons'>
<a class='w-10 h-10 rounded-full bg-white dark:bg-dark-800 border border-gray-200 dark:border-dark-border text-gray-700 dark:text-dark-text flex items-center justify-center hover:text-white hover:bg-[#1877F2] transition-colors shadow-lg' href='#' onclick='window.open("https://www.facebook.com/sharer.php?u="+encodeURIComponent(window.location.href), "_blank"); return false;'>
<svg class='w-5 h-5' fill='currentColor' viewBox='0 0 24 24'><path d='M24 12.073c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.99 4.388 10.954 10.125 11.854v-8.385H7.078v-3.469h3.047V9.43c0-3.007 1.792-4.669 4.533-4.669 1.312 0 2.686.235 2.686.235v2.953H15.83c-1.491 0-1.956.925-1.956 1.874v2.25h3.328l-.532 3.469h-2.796v8.385C19.612 23.027 24 18.062 24 12.073z'></path></svg>
</a>
<a class='w-10 h-10 rounded-full bg-white dark:bg-dark-800 border border-gray-200 dark:border-dark-border text-gray-700 dark:text-dark-text flex items-center justify-center hover:text-white hover:bg-[#25D366] transition-colors shadow-lg' href='#' onclick='window.open("https://api.whatsapp.com/send?text="+encodeURIComponent(document.title + " " + window.location.href), "_blank"); return false;'>
<svg class='w-5 h-5' fill='currentColor' viewBox='0 0 24 24'><path d='M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51a12.8 12.8 0 00-.57-.01c-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347m-5.421 7.403h-.004a9.87 9.87 0 01-5.031-1.378l-.361-.214-3.741.982.998-3.648-.235-.374a9.86 9.86 0 01-1.51-5.26c.001-5.45 4.436-9.884 9.888-9.884 2.64 0 5.122 1.03 6.988 2.898a9.825 9.825 0 012.893 6.994c-.003 5.45-4.437 9.884-9.885 9.884m8.413-18.297A11.815 11.815 0 0012.05 0C5.495 0 .16 5.335.157 11.892c0 2.096.547 4.142 1.588 5.945L.057 24l6.305-1.654a11.882 11.882 0 005.683 1.448h.005c6.554 0 11.89-5.335 11.893-11.893a11.821 11.821 0 00-3.48-8.413Z'></path></svg>
</a>
</div>
<button aria-label='Share' class='w-12 h-12 rounded-full bg-hacker-500 border border-transparent text-white flex items-center justify-center shadow-[0_4px_10px_rgba(35,134,54,0.4)] hover:bg-hacker-600 transition-colors' id='share-toggle-btn'>
<svg class='w-5 h-5 ml-[-2px]' fill='none' stroke='currentColor' viewBox='0 0 24 24'><path d='M8.684 13.342C8.886 12.938 9 12.482 9 12c0-.482-.114-.938-.316-1.342m0 2.684a3 3 0 110-2.684m0 2.684l6.632 3.316m-6.632-6l6.632-3.316m0 0a3 3 0 105.367-2.684 3 3 0 00-5.367 2.684zm0 9.316a3 3 0 105.368 2.684 3 3 0 00-5.368-2.684z' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'></path></svg>
</button>
</div>
<!-- HIGHLIGHT.JS SCRIPT -->
<script src='https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.8.0/highlight.min.js'></script>
<script>hljs.highlightAll();</script>
<!-- CUSTOM LOGIC (SEARCH, SHARE, ADS, FETCHERS) -->
<script>
    //<![CDATA[
        document.addEventListener('DOMContentLoaded', () => {

            // Dark Mode Toggle Logic
            const themeToggleBtn = document.getElementById('theme-toggle');
            const darkIcon = document.getElementById('theme-toggle-dark-icon');
            const lightIcon = document.getElementById('theme-toggle-light-icon');

            if (darkIcon && lightIcon) {
                if (document.documentElement.classList.contains('dark')) {
                    lightIcon.classList.remove('hidden');
                } else {
                    darkIcon.classList.remove('hidden');
                }
            }

            function toggleTheme() {
                if (darkIcon) darkIcon.classList.toggle('hidden');
                if (lightIcon) lightIcon.classList.toggle('hidden');

                if (localStorage.getItem('color-theme')) {
                    if (localStorage.getItem('color-theme') === 'light') {
                        document.documentElement.classList.add('dark');
                        localStorage.setItem('color-theme', 'dark');
                    } else {
                        document.documentElement.classList.remove('dark');
                        localStorage.setItem('color-theme', 'light');
                    }
                } else {
                    if (document.documentElement.classList.contains('dark')) {
                        document.documentElement.classList.remove('dark');
                        localStorage.setItem('color-theme', 'light');
                    } else {
                        document.documentElement.classList.add('dark');
                        localStorage.setItem('color-theme', 'dark');
                    }
                }
            }

            if (themeToggleBtn) themeToggleBtn.addEventListener('click', toggleTheme);

            // Hamburger Mobile Menu Logic
            const mobileMenuBtn = document.getElementById('mobile-menu-btn');
            const mobileNavMenu = document.getElementById('mobile-nav-menu');
            if (mobileMenuBtn && mobileNavMenu) {
                mobileMenuBtn.addEventListener('click', (e) => {
                    e.stopPropagation();
                    mobileNavMenu.classList.toggle('hidden');
                });
                document.addEventListener('click', (e) => {
                    if (!mobileNavMenu.contains(e.target) && !mobileMenuBtn.contains(e.target)) {
                        mobileNavMenu.classList.add('hidden');
                    }
                });
            }

            // 1. SEARCH TOGGLE LOGIC
            const searchBtn = document.getElementById('search-toggle');
            const searchBox = document.getElementById('search-box');
            if (searchBtn && searchBox) {
                searchBtn.addEventListener('click', (e) => {
                    e.stopPropagation();
                    if (searchBox.classList.contains('opacity-0')) {
                        searchBox.classList.remove('opacity-0', 'invisible', 'translate-y-1');
                        searchBox.querySelector('input').focus();
                    } else {
                        searchBox.classList.add('opacity-0', 'invisible', 'translate-y-1');
                    }
                });
                document.addEventListener('click', (e) => {
                    if (!searchBox.contains(e.target) && !searchBtn.contains(e.target)) {
                        searchBox.classList.add('opacity-0', 'invisible', 'translate-y-1');
                    }
                });
            }

            // 2. FLOATING SHARE TOGGLE
            const shareBtn = document.getElementById('share-toggle-btn');
            const shareIcons = document.getElementById('share-icons');
            if (shareBtn && shareIcons) {
                shareBtn.addEventListener('click', () => {
                    shareIcons.classList.toggle('opacity-0');
                    shareIcons.classList.toggle('invisible');
                    shareIcons.classList.toggle('translate-y-4');
                });
            }

            // 3. AUTO INJECT COPY BUTTON TO PRE CODE
            document.querySelectorAll('pre').forEach(pre => {
                const btn = document.createElement('button');
                btn.className = 'copy-btn';
                btn.innerHTML = '<svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z"></path></svg> Copy';
                btn.onclick = () => {
                    const code = pre.querySelector('code');
                    if (code) {
                        navigator.clipboard.writeText(code.innerText).then(() => {
                            btn.innerHTML = '<svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path></svg> Copied!';
                            btn.classList.add('copied');
                            setTimeout(() => {
                                btn.innerHTML = '<svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z"></path></svg> Copy';
                                btn.classList.remove('copied');
                            }, 2000);
                        });
                    }
                };
                pre.appendChild(btn);
            });

            // 4. PARALLAX AD & IMAGE PROXY (Inside Post)
            const postBodies = document.querySelectorAll('.post-body');
            postBodies.forEach(body => {
                // Auto Photon Proxy for ibb
                const imgs = body.querySelectorAll('img');
                imgs.forEach(img => {
                    if (img.src && img.src.includes('ibb.co')) {
                        let cleanUrl = img.src.replace(/^https?:\/\//, '');
                        img.src = 'https://i0.wp.com/' + cleanUrl + '?quality=80&strip=all';
                    }
                });

                // Inject Parallax Ad at middle of post
                let pTags = body.querySelectorAll('br, p');
                if (pTags.length > 0) {
                    let mid = Math.floor(pTags.length / 2);
                    let target = pTags[mid];
                    if (target) {
                        const adHtml = '<div class="scriptParallax"><div class="ptx1"><div class="ptx2"><div class="flex justify-center items-center adsterra-slot w-[300px] h-[250px] lg:mr-[350px]" data-w="300" data-h="250" data-key="017ff5a2024d32a8d605ed757a4d6002"></div></div></div></div></div>';
                        target.insertAdjacentHTML('afterend', adHtml);
                    }
                }
            });

            // 5. FETCH DATA FOR HOMEPAGE MODULES
            if (document.getElementById('home-modules')) {
                fetchHomeModules();
            }

            // 6. ADSTERRA OBSERVER LAZY LOAD
            if ('IntersectionObserver' in window) {
                const adObserver = new IntersectionObserver((entries, observer) => {
                    entries.forEach(entry => {
                        if (entry.isIntersecting) {
                            const el = entry.target;
                            const k = el.getAttribute('data-key');
                            const w = el.getAttribute('data-w');
                            const h = el.getAttribute('data-h');
                            if (k && !el.hasAttribute('data-loaded')) {
                                el.setAttribute('data-loaded', 'true');
                                const iframe = document.createElement('iframe');
                                iframe.width = w; iframe.height = h; iframe.frameBorder = '0'; iframe.scrolling = 'no';
                                iframe.style.border = 'none'; iframe.style.overflow = 'hidden'; iframe.style.background = 'transparent';
                                iframe.style.margin = 'auto'; // Menggantikan absolute inset-0 agar tidak keluar jalur
                                el.appendChild(iframe);
                                const doc = iframe.contentWindow.document;
                                doc.open();
                                doc.write('<!DOCTYPE html><html><head><style>body{margin:0;padding:0;overflow:hidden;background:transparent;display:flex;justify-content:center;align-items:center;}</style></head><body>');
                                doc.write('<scr'+'ipt type="text/javascript">atOptions={"key":"'+k+'","format":"iframe","height":'+h+',"width":'+w+',"params":{}};</scr'+'ipt>');
                                doc.write('<scr'+'ipt type="text/javascript" src="https://www.highperformanceformat.com/'+k+'/invoke.js"></scr'+'ipt>');
                                doc.write('</body></html>');
                                doc.close();
                            }
                            observer.unobserve(el);
                        }
                    });
                }, { rootMargin: '200px' });

                document.querySelectorAll('.adsterra-slot').forEach(slot => adObserver.observe(slot));
            }
        });

        // === MOBILE TOP AD FUNCTIONS ===
        function minimizeMobileTopAd() {
            const ad = document.getElementById('mobile-top-ad');
            const btn = document.getElementById('show-mobile-top-ad-btn');
            if(ad && btn) {
                ad.style.transform = 'translateY(-100%)';
                setTimeout(() => { btn.classList.remove('hidden'); }, 300);
            }
        }
        function maximizeMobileTopAd() {
            const ad = document.getElementById('mobile-top-ad');
            const btn = document.getElementById('show-mobile-top-ad-btn');
            if(ad && btn) {
                ad.style.transform = 'translateY(0)';
                btn.classList.add('hidden');
            }
        }

        // === MOBILE BOTTOM STICKY AD FUNCTIONS ===
        function toggleMobileBottomAd() {
            const wrapper = document.getElementById('mobile-bottom-ad-wrapper');
            const icon = document.getElementById('bottom-ad-icon');
            // Jika posisinya di 0 (tampil), kita dorong ke bawah sejauh tingginya content (50px) + border (1px) = 51px
            if(wrapper.style.transform === 'translateY(0px)' || wrapper.style.transform === '') {
                wrapper.style.transform = 'translateY(51px)';
                icon.style.transform = 'rotate(180deg)'; // Panah naik
            } else {
                wrapper.style.transform = 'translateY(0px)';
                icon.style.transform = 'rotate(0deg)'; // Panah turun
            }
        }

        // === HOMEPAGE FETCHERS ===
        function fetchHomeModules() {
            // Fetch Sub Category 1 (List Style - Ex: Blogger)
            fetch('/feeds/posts/default/-/Blogger?alt=json&max-results=3')
            .then(res => res.json())
            .then(data => {
                let html = '';
                if(data.feed && data.feed.entry) {
                    data.feed.entry.forEach(post => {
                        const title = post.title.$t;
                        let link = post.link.find(l => l.rel === 'alternate')?.href || '#';
                        html += `<a href="${link}" class="flex gap-2 items-center group py-1">
                            <svg class="w-4 h-4 text-gray-400 dark:text-dark-muted group-hover:text-blue-600 dark:group-hover:text-dark-link transition-colors flex-shrink-0" fill="currentColor" viewBox="0 0 16 16"><path d="M2 2.5A2.5 2.5 0 0 1 4.5 0h8.75a.75.75 0 0 1 .75.75v12.5a.75.75 0 0 1-.75.75h-2.5a.75.75 0 0 1 0-1.5h1.75v-2h-8a1 1 0 0 0-.714 1.7.75.75 0 1 1-1.072 1.05A2.495 2.495 0 0 1 2 11.5Zm10.5-1h-8a1 1 0 0 0-1 1v6.708A2.486 2.486 0 0 1 4.5 9h8ZM5 12.25a.25.25 0 0 1 .25-.25h3.5a.25.25 0 0 1 .25.25v3.25a.25.25 0 0 1-.4.2l-1.45-1.087a.249.249 0 0 0-.3 0L5.4 15.7a.25.25 0 0 1-.4-.2Z"></path></svg>
                            <span class="text-blue-600 dark:text-dark-link group-hover:underline truncate">${title}</span>
                        </a>`;
                    });
                } else { html = '<span class="text-gray-500 dark:text-dark-muted">No scripts found.</span>'; }
                let container = document.getElementById('cat-blogger');
                if(container) container.innerHTML = html;
            }).catch(() => {});

            // Fetch Sub Category 2 (Grid Box Style - Ex: Tools)
            fetch('/feeds/posts/default/-/Tools?alt=json&max-results=4') 
            .then(res => res.json())
            .then(data => {
                let html = '';
                if(data.feed && data.feed.entry) {
                    data.feed.entry.forEach(post => {
                        const title = post.title.$t;
                        let link = post.link.find(l => l.rel === 'alternate')?.href || '#';
                        let snip = post.summary ? post.summary.$t : (post.content ? post.content.$t.replace(/<[^>]+>/g, '').substring(0, 60) + '...' : '');
                        html += `<a href="${link}" class="block bg-gray-50 dark:bg-dark-900 border border-gray-200 dark:border-dark-border p-4 rounded-md hover:border-gray-400 dark:hover:border-dark-muted transition-colors group">
                            <h3 class="text-blue-600 dark:text-dark-link font-semibold mb-1 group-hover:underline line-clamp-1">${title}</h3>
                            <p class="text-xs text-gray-500 dark:text-dark-muted line-clamp-2">${snip}</p>
                        </a>`;
                    });
                } else { html = '<span class="text-gray-500 dark:text-dark-muted">No data found.</span>'; }
                let container = document.getElementById('cat-tools');
                if(container) container.innerHTML = html;
            }).catch(() => {});
        }

        // Utility to extract images (incl. ImgBB to Photon)
        function extractThumb(post, w, h) {
            let thumbUrl = `https://via.placeholder.com/${w}x${h}/f3f4f6/9ca3af?text=[code]`;
            if (document.documentElement.classList.contains('dark')) {
                thumbUrl = `https://via.placeholder.com/${w}x${h}/161b22/30363d?text=[code]`;
            }
            if (post.media$thumbnail && post.media$thumbnail.url) {
                thumbUrl = post.media$thumbnail.url.replace(/\/s[0-9]+(\-c)?/, `/w${w}-h${h}-c`);
            } else if (post.content && post.content.$t) {
                const imgMatch = post.content.$t.match(/<img[^>]+src=['"]([^'"]+)['"]/i);
                if (imgMatch && imgMatch[1]) {
                    thumbUrl = imgMatch[1];
                    if (thumbUrl.includes('ibb.co')) {
                        let cleanUrl = thumbUrl.replace(/^https?:\/\//, '');
                        thumbUrl = `https://i0.wp.com/${cleanUrl}?resize=${w},${h}&quality=80&strip=all`;
                    }
                }
            }
            return thumbUrl;
        }
    //]]>
    </script>
<style>
    /* CSS Scoped khusus untuk Chatbot agar tidak merusak template Blogger */
    #bc-wrapper {
        font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif !important;
        position: fixed !important;
        bottom: 20px !important;
        right: 20px !important;
        z-index: 2147483647 !important; /* Nilai maksimum absolut z-index */
        display: block !important;
        visibility: visible !important;
        opacity: 1 !important;
        pointer-events: auto !important;
        margin: 0 !important;
        padding: 0 !important;
    }

    /* Tombol Toggle (Bulat di pojok) */
    #bc-toggle-btn {
        width: 60px !important;
        height: 60px !important;
        background: linear-gradient(135deg, #2563eb, #1d4ed8) !important;
        color: white !important;
        border: none !important;
        border-radius: 50% !important;
        cursor: pointer !important;
        box-shadow: 0 4px 12px rgba(37, 99, 235, 0.4) !important;
        display: flex !important;
        align-items: center !important;
        justify-content: center !important;
        transition: transform 0.3s ease, box-shadow 0.3s ease !important;
        float: right !important;
        visibility: visible !important;
        opacity: 1 !important;
        pointer-events: auto !important;
        margin: 0 !important;
        padding: 0 !important;
    }

    #bc-toggle-btn:hover {
        transform: scale(1.05) !important;
        box-shadow: 0 6px 16px rgba(37, 99, 235, 0.6) !important;
    }

    #bc-toggle-btn svg {
        width: 28px !important;
        height: 28px !important;
    }

    /* Kontainer Chat Utama */
    #bc-container {
        position: absolute !important;
        bottom: 80px !important;
        right: 0 !important;
        width: 350px !important;
        height: 500px !important;
        max-height: 80vh !important;
        max-width: 90vw !important;
        background-color: #ffffff !important;
        border-radius: 16px !important;
        box-shadow: 0 10px 25px rgba(0, 0, 0, 0.15) !important;
        display: flex !important;
        flex-direction: column !important;
        overflow: hidden !important;
        transition: opacity 0.3s ease, transform 0.3s ease !important;
        transform-origin: bottom right !important;
    }

    #bc-container.closed {
        opacity: 0 !important;
        transform: scale(0.8) !important;
        pointer-events: none !important;
    }

    /* Header Chat */
    .bc-header {
        background: linear-gradient(135deg, #2563eb, #1d4ed8) !important;
        color: white !important;
        padding: 16px !important;
        display: flex !important;
        align-items: center !important;
        justify-content: space-between !important;
    }

    .bc-header-info {
        display: flex !important;
        align-items: center !important;
        gap: 12px !important;
    }

    .bc-avatar {
        width: 36px !important;
        height: 36px !important;
        background-color: white !important;
        color: #2563eb !important;
        border-radius: 50% !important;
        display: flex !important;
        align-items: center !important;
        justify-content: center !important;
    }

    .bc-title {
        font-weight: 600 !important;
        font-size: 16px !important;
        margin: 0 !important;
        line-height: 1.2 !important;
    }

    .bc-subtitle {
        font-size: 12px !important;
        color: #bfdbfe !important;
        margin: 0 !important;
    }

    .bc-close-btn {
        background: none !important;
        border: none !important;
        color: white !important;
        cursor: pointer !important;
        opacity: 0.8 !important;
        padding: 4px !important;
    }

    .bc-close-btn:hover {
        opacity: 1 !important;
    }

    /* Area Pesan */
    #bc-messages {
        flex: 1 !important;
        padding: 16px !important;
        overflow-y: auto !important;
        background-color: #f8fafc !important;
        display: flex !important;
        flex-direction: column !important;
        gap: 12px !important;
    }

    .bc-message {
        max-width: 80% !important;
        padding: 10px 14px !important;
        border-radius: 12px !important;
        font-size: 14px !important;
        line-height: 1.5 !important;
        word-wrap: break-word !important;
    }

    .bc-message.bot {
        background-color: #ffffff !important;
        color: #334155 !important;
        align-self: flex-start !important;
        border: 1px solid #e2e8f0 !important;
        border-bottom-left-radius: 2px !important;
    }

    .bc-message.user {
        background-color: #2563eb !important;
        color: #ffffff !important;
        align-self: flex-end !important;
        border-bottom-right-radius: 2px !important;
    }

    .bc-message a {
        color: #2563eb !important;
        text-decoration: underline !important;
        font-weight: 500 !important;
    }

    .bc-message.user a {
        color: #bfdbfe !important;
    }

    /* Area Input */
    .bc-input-area {
        padding: 12px 16px !important;
        background-color: #ffffff !important;
        border-top: 1px solid #e2e8f0 !important;
        display: flex !important;
        gap: 8px !important;
    }

    #bc-input {
        flex: 1 !important;
        padding: 10px 14px !important;
        border: 1px solid #cbd5e1 !important;
        border-radius: 20px !important;
        outline: none !important;
        font-size: 14px !important;
        transition: border-color 0.2s !important;
        color: #0f172a !important;
    }

    #bc-input:focus {
        border-color: #2563eb !important;
    }

    #bc-send-btn {
        background-color: #2563eb !important;
        color: white !important;
        border: none !important;
        width: 40px !important;
        height: 40px !important;
        border-radius: 50% !important;
        cursor: pointer !important;
        display: flex !important;
        align-items: center !important;
        justify-content: center !important;
        transition: background-color 0.2s !important;
    }

    #bc-send-btn:hover {
        background-color: #1d4ed8 !important;
    }

    #bc-send-btn svg {
        width: 18px !important;
        height: 18px !important;
        transform: translateX(-1px) !important;
    }

    /* Animasi Mengetik */
    .bc-typing-indicator {
        display: inline-flex !important;
        gap: 4px !important;
        padding: 4px 8px !important;
    }

    .bc-dot {
        width: 6px !important;
        height: 6px !important;
        background-color: #94a3b8 !important;
        border-radius: 50% !important;
        animation: bc-bounce 1.4s infinite ease-in-out both !important;
    }

    .bc-dot:nth-child(1) {
        animation-delay: -0.32s !important;
    }

    .bc-dot:nth-child(2) {
        animation-delay: -0.16s !important;
    }

    @keyframes bc-bounce {

        0%,
        80%,
        100% {
            transform: scale(0) !important;
        }

        40% {
            transform: scale(1) !important;
        }
    }

    /* Notifikasi Tooltip */
    #bc-notification {
        position: absolute !important;
        bottom: 75px !important;
        right: 0 !important;
        background-color: #ffffff !important;
        color: #334155 !important;
        padding: 12px 28px 12px 16px !important;
        border-radius: 12px !important;
        box-shadow: 0 4px 15px rgba(0, 0, 0, 0.15) !important;
        font-size: 13px !important;
        width: max-content !important;
        max-width: 220px !important;
        opacity: 0 !important;
        transform: translateY(15px) scale(0.9) !important;
        transition: all 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275) !important;
        pointer-events: none !important;
        border: 1px solid #e2e8f0 !important;
        cursor: pointer !important;
        z-index: 999999 !important;
    }

    #bc-notification.show {
        opacity: 1 !important;
        transform: translateY(0) scale(1) !important;
        pointer-events: auto !important;
    }

    #bc-notification::after {
        content: '' !important;
        position: absolute !important;
        bottom: -6px !important;
        right: 20px !important;
        width: 12px !important;
        height: 12px !important;
        background-color: #ffffff !important;
        transform: rotate(45deg) !important;
        border-right: 1px solid #e2e8f0 !important;
        border-bottom: 1px solid #e2e8f0 !important;
    }

    .bc-tooltip-close {
        position: absolute !important;
        top: 2px !important;
        right: 8px !important;
        font-size: 18px !important;
        color: #94a3b8 !important;
        cursor: pointer !important;
    }

    .bc-tooltip-close:hover {
        color: #ef4444 !important;
    }
</style>
<div id='bc-wrapper'>
<!-- Template Kontainer Chat (Diload malas / lazy-load saat diklik) -->
<template id='bc-chat-template'>
<div class='closed' id='bc-container'>
<!-- Header -->
<div class='bc-header'>
<div class='bc-header-info'>
<div class='bc-avatar'>
<!-- SVG Robot Icon -->
<svg fill='none' height='20' stroke='currentColor' viewBox='0 0 24 24' width='20'>
<path d='M9.75 17L9 20l-1 1h8l-1-1-.75-3M3 13h18M5 17h14a2 2 0 002-2V5a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'>
</path>
</svg>
</div>
<div>
<p class='bc-title'>Asisten Blog</p>
<p class='bc-subtitle'>Online</p>
</div>
</div>
<button class='bc-close-btn' onclick='toggleBCChat()' title='Tutup Chat'>
<!-- SVG Close Icon -->
<svg fill='none' height='20' stroke='currentColor' viewBox='0 0 24 24' width='20'>
<path d='M6 18L18 6M6 6l12 12' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'>
</path>
</svg>
</button>
</div>
<!-- Area Pesan -->
<div id='bc-messages'>
<div class='bc-message bot'>
                    Halo! Saya asisten virtual blog ini. Ada yang bisa saya bantu temukan hari ini?
                </div>
</div>
<!-- Area Input -->
<div class='bc-input-area'>
<input id='bc-input' onkeypress='handleBCKeyPress(event)' placeholder='Tanya sesuatu...' type='text'/>
<button id='bc-send-btn' onclick='sendBCMessage()' title='Kirim'>
<!-- SVG Send Icon -->
<svg fill='none' stroke='currentColor' viewBox='0 0 24 24'>
<path d='M12 19l9 2-9-18-9 18 9-2zm0 0v-8' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'></path>
</svg>
</button>
</div>
</div>
</template>
<!-- Notifikasi Ajakan Chat -->
<div id='bc-notification' onclick='toggleBCChat()'>
        šŸ‘‹ Punya pertanyaan? <b>Tanya AI</b> di sini...
        <span class='bc-tooltip-close' onclick='closeBCNotification(event)'>×</span>
</div>
<!-- Tombol Toggle Chat (Melayang) -->
<button id='bc-toggle-btn' onclick='toggleBCChat()' title='Buka Chat'>
<!-- SVG Chat Bubble Icon -->
<svg fill='none' id='bc-icon-chat' stroke='currentColor' viewBox='0 0 24 24'>
<path d='M8 10h.01M12 10h.01M16 10h.01M9 16H5a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v8a2 2 0 01-2 2h-5l-5 5v-5z' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'>
</path>
</svg>
<!-- SVG Close Icon (Hidden by default) -->
<svg fill='none' id='bc-icon-close' stroke='currentColor' style='display: none;' viewBox='0 0 24 24'>
<path d='M6 18L18 6M6 6l12 12' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'></path>
</svg>
</button>
</div>
<script>
    //<![CDATA[
    // URL blog Anda (otomatis mendeteksi domain tempat script ini dipasang)
    const BC_BLOG_URL = window.location.origin;

    // Element Referensi (Variabel disiapkan untuk Lazy Loading)
    let bcContainer, bcMessages, bcInput;
    const bcWrapper = document.getElementById('bc-wrapper');
    const bcIconChat = document.getElementById('bc-icon-chat');
    const bcIconClose = document.getElementById('bc-icon-close');
    let isBCChatLoaded = false;

    // --- KNOWLEDGE BASE (KECERDASAN BUATAN MULTI-DOMAIN) ---
    const bcDomains = {
        app: "https://app.pintarapp.com",
        main: "https://pintarapp.com",
        news: "https://news.pintarapp.com",
        crypto: "https://crypto.pintarapp.com",
        store: "https://store.pintarapp.com",
        wedding: "https://wedding.pintarapp.com",
        catatan: "https://catatan-ku.pintarapp.com",
        script: "https://script.pintarapp.com"
    };

    const bcDomainNames = {
        app: "Alat PintarApp",
        main: "PintarApp Utama",
        news: "Berita PintarApp",
        crypto: "Kripto PintarApp",
        store: "Toko PintarApp",
        wedding: "Wedding PintarApp",
        catatan: "Catatan PintarApp",
        script: "Script PintarApp"
    };

    // Database Kategori & Kata Kunci (Didesain untuk menjawab 1000+ variasi pertanyaan)
    const bcIntents = [
        // --- SAPAAN & BANTUAN ---
        {
            category: "sapaan",
            keywords: ["halo", "hai", "hey", "hello", "hi", "pagi", "siang", "sore", "malam", "selamat", "assalamualaikum"],
            response: "Halo! Selamat datang di jaringan PintarApp. Ada yang bisa saya bantu hari ini?",
            domain: null
        },
        {
            category: "terima_kasih",
            keywords: ["terima kasih", "makasih", "thanks", "thank you", "tq", "suwun"],
            response: "Sama-sama! Jangan ragu untuk bertanya lagi jika Anda membutuhkan bantuan.",
            domain: null
        },
        {
            category: "generative_ai_decline",
            keywords: ["buatkan", "bikinkan", "tuliskan", "gambarkan", "lukiskan", "buat cerita", "buat naskah", "buat puisi", "bikin cerita", "bikin puisi", "tolong buatkan", "buatkan saya"],
            response: "Maaf, saya didesain secara khusus sebagai **Asisten Pencari Informasi (Research AI)** untuk menyajikan referensi dari jaringan PintarApp dan Ensiklopedia.\n\nSaya tidak memiliki kemampuan *Generative AI* untuk menulis cerita fiksi, menggambar, atau merangkai naskah secara mandiri dari nol. Namun, jika Anda membutuhkan *referensi* atau *artikel* tentang cara membuat hal-hal tersebut, saya dengan senang hati akan mencarikannya untuk Anda!",
            domain: null
        },
        {
            category: "bantuan",
            keywords: ["bantu", "tolong", "help", "bingung", "cara menggunakan", "panduan", "bisa apa", "fungsi"],
            response: "Tentu, saya bisa membantu! PintarApp memiliki banyak layanan: alat PDF & Gambar, artikel teknologi, berita, kripto, toko online, pernikahan, dan catatan harian. Apa yang sedang Anda cari?",
            domain: null
        },

        // --- APP.PINTARAPP.COM (TOOLS) ---
        {
            category: "tool_hapus_bg",
            keywords: ["hapus bg", "hapus background", "hapus latar", "remove bg", "background transparan", "menghapus background", "ilangin background", "background remover", "hapus background ai"],
            response: "Anda bisa menghapus background foto secara otomatis menggunakan AI di alat 'Hapus BG (AI)' kami. Prosesnya cepat, rapi, dan 100% gratis!",
            domain: "app",
            linkPath: "/search?q=hapus+bg"
        },
        {
            category: "tool_canvas",
            keywords: ["canvas pro", "menggambar", "lukis", "gambar html5", "paint", "corat coret", "aplikasi menggambar", "draw"],
            response: "Ingin menggambar secara digital? Gunakan 'Canvas Pro' di PintarApp! Aplikasi menggambar HTML5 dengan fitur lengkap dan dukungan latar transparan.",
            domain: "app",
            linkPath: "/search?q=canvas+pro"
        },
        {
            category: "tool_favicon",
            keywords: ["favicon", "buat favicon", "bikin favicon", "icon website", "favicon maker", "ico", "ikon web"],
            response: "Buat ikon website Anda dengan mudah! Gunakan alat 'Favicon Maker' kami untuk mengubah teks atau gambar menjadi paket favicon (ICO & PNG) siap pakai.",
            domain: "app",
            linkPath: "/search?q=favicon+maker"
        },
        {
            category: "tool_kompres_jpg",
            keywords: ["kompres jpg", "perkecil jpg", "ukuran jpg", "compress jpg", "kecilin jpg", "kurangi ukuran jpg", "kompress jpg"],
            response: "Ukuran file JPG Anda terlalu besar? Gunakan alat 'Kompres JPG' kami untuk memperkecil ukurannya secara ekstrem tanpa mengurangi ketajaman visual.",
            domain: "app",
            linkPath: "/search?q=kompres+jpg"
        },
        {
            category: "tool_kompres_png",
            keywords: ["kompres png", "perkecil png", "ukuran png", "compress png", "kecilin png", "kurangi ukuran png", "kompress png"],
            response: "Perkecil ukuran file PNG Anda dengan alat 'Kompres PNG' kami. Transparansi background dan kualitas warna akan tetap terjaga dengan baik!",
            domain: "app",
            linkPath: "/search?q=kompres+png"
        },
        {
            category: "tool_pipet_warna",
            keywords: ["pipet warna", "ambil warna", "color picker", "kode warna", "hex", "rgb", "ekstrak warna", "cek warna", "cari warna"],
            response: "Butuh kode warna dari sebuah gambar? Gunakan 'Pipet Warna' untuk mengekstrak kode warna Hex dan RGB dari gambar apa pun secara instan.",
            domain: "app",
            linkPath: "/search?q=pipet+warna"
        },
        {
            category: "tool_pas_foto",
            keywords: ["pas foto", "pasfoto", "foto 3x4", "foto 4x6", "buat pas foto", "crop wajah", "bikin pas foto", "pas foto maker", "foto ktp", "foto ijazah"],
            response: "Mau buat pas foto untuk dokumen penting? Gunakan 'Pas Foto Maker' untuk memotong (crop) wajah ke ukuran standar 3x4 atau 4x6 dan atur warna latar belakangnya dengan mudah.",
            domain: "app",
            linkPath: "/search?q=pas+foto"
        },
        {
            category: "tool_hapus_exif",
            keywords: ["hapus exif", "exif", "metadata foto", "hapus metadata", "lokasi gps foto", "privasi foto", "remove exif"],
            response: "Jaga privasi Anda! Gunakan alat 'Hapus EXIF' untuk menghapus data rahasia seperti metadata kamera dan lokasi GPS dari foto Anda sebelum dibagikan ke internet.",
            domain: "app",
            linkPath: "/search?q=hapus+exif"
        },
        {
            category: "tool_kalkulator_bmi",
            keywords: ["bmi", "kalkulator bmi", "berat badan ideal", "indeks massa tubuh", "imt", "cek berat badan", "kalkulator berat badan", "gemuk", "kurus"],
            response: "Ingin tahu apakah berat badan Anda ideal? Hitung Indeks Massa Tubuh (IMT) Anda secara akurat menggunakan 'Kalkulator BMI' kami.",
            domain: "app",
            linkPath: "/search?q=kalkulator+bmi"
        },
        {
            category: "tool_kalkulator_persen",
            keywords: ["persen", "persentase", "kalkulator persen", "hitung diskon", "diskon", "persenan", "hitung keuntungan", "kalkulator diskon"],
            response: "Pusing berhitung? Hitung nilai persentase, potongan harga (diskon), atau margin keuntungan secara instan dengan 'Kalkulator Persen' PintarApp.",
            domain: "app",
            linkPath: "/search?q=kalkulator+persen"
        },
        {
            category: "tool_kalkulator_umur",
            keywords: ["umur", "kalkulator umur", "hitung umur", "usia", "usia tepat", "hitung usia", "berapa umur saya", "tanggal lahir"],
            response: "Ketahui usia pasti Anda hingga hitungan hari, bulan, dan tahun secara presisi menggunakan 'Kalkulator Umur' kami.",
            domain: "app",
            linkPath: "/search?q=kalkulator+umur"
        },
        {
            category: "tool_konversi_satuan",
            keywords: ["konversi satuan", "ubah satuan", "konverter", "satuan panjang", "satuan berat", "satuan suhu", "satuan kecepatan", "konversi berat", "konversi panjang"],
            response: "Ubah berbagai macam satuan pengukuran (panjang, berat, suhu, kecepatan, dll) dengan cepat melalui alat 'Konversi Satuan' kami.",
            domain: "app",
            linkPath: "/search?q=konversi+satuan"
        },
        {
            category: "tool_pdf",
            keywords: ["pdf", "gabung pdf", "kompres pdf", "edit pdf", "alat pdf", "pdf tool", "pisah pdf", "ubah pdf", "pdf ke word", "word ke pdf", "baca pdf", "semua alat pdf"],
            response: "PintarApp menyediakan berbagai alat PDF 100% GRATIS dan diproses aman secara lokal di perangkat Anda. Anda bisa menggabungkan, mengompres, dan memanipulasi dokumen PDF.",
            domain: "app",
            linkPath: "/search?q=pdf"
        },

        // --- PINTARAPP.COM (Tech, SEO, Adsense, Coding, Umum) ---
        {
            category: "tech_seo",
            keywords: ["seo", "search engine optimization", "page 1 google", "trafik blog", "pengunjung blog", "optimasi seo", "backlink", "keyword", "kata kunci", "indeks google"],
            response: "SEO sangat penting untuk meningkatkan trafik organik blog Anda. Kami punya banyak panduan SEO, riset keyword, dan tips mendapatkan backlink yang terbukti ampuh.",
            domain: "main",
            linkPath: "/search?q=seo"
        },
        {
            category: "tech_adsense",
            keywords: ["adsense", "google adsense", "iklan", "monetisasi", "dapat uang dari blog", "penghasilan blog", "cpc", "ctr", "iklan adsense", "daftar adsense"],
            response: "Google AdSense adalah cara populer menghasilkan uang dari blog. Pelajari cara daftar AdSense, mengoptimalkan penempatan iklan, dan meningkatkan nilai klik (CPC) di blog kami.",
            domain: "main",
            linkPath: "/search?q=adsense"
        },
        {
            category: "tech_blogger_template",
            keywords: ["template", "tema", "template blogger", "tema blog", "template responsif", "template seo", "ganti template", "template gratis", "template premium", "blogspot"],
            response: "Memilih template yang responsif, loading cepat, dan SEO-friendly sangat disarankan untuk performa blog. Temukan berbagai rekomendasi dan tutorial edit template di blog kami.",
            domain: "main",
            linkPath: "/search?q=template"
        },
        {
            category: "tech_coding",
            keywords: ["html", "css", "javascript", "js", "coding", "pemrograman", "belajar coding", "bikin web", "buat website", "php", "kode", "script", "frontend", "backend"],
            response: "Belajar coding itu menyenangkan! Kami menyediakan berbagai tutorial HTML, CSS, JavaScript dasar hingga lanjut, serta trik membuat tampilan website yang interaktif dan menarik.",
            domain: "main",
            linkPath: "/search?q=coding"
        },
        {
            category: "tech_blogging",
            keywords: ["blogging", "cara buat blog", "menulis artikel", "blogger", "wordpress", "artikel seo", "ngeblog", "buat blog", "domain", "hosting"],
            response: "Dunia blogging penuh dengan peluang. Pelajari panduan cara membuat blog dari nol, tips menulis artikel SEO yang disukai mesin pencari, dan cara mengelola website dengan profesional.",
            domain: "main",
            linkPath: "/search?q=blogging"
        },

        // --- NEWS.PINTARAPP.COM (Berita, Viral, Update) ---
        {
            category: "news_umum",
            keywords: ["berita", "berita hari ini", "berita terbaru", "news", "viral", "trending", "info terbaru", "kabar terbaru", "berita terkini", "kejadian", "update", "peristiwa"],
            response: "Dapatkan berita terbaru, isu-isu yang sedang viral, dan informasi terkini dari berbagai penjuru. Tetap up-to-date dan jangan kudet bersama portal berita kami!",
            domain: "news",
            linkPath: "/"
        },
        {
            category: "news_tekno",
            keywords: ["berita teknologi", "gadget terbaru", "smartphone", "hp baru", "berita tekno", "teknologi", "inovasi", "review hp", "laptop terbaru", "spesifikasi hp"],
            response: "Ingin tahu perkembangan teknologi dan gadget terbaru? Kunjungi portal berita teknologi kami untuk membaca review, update spesifikasi smartphone, dan inovasi terkini di dunia tekno.",
            domain: "news",
            linkPath: "/search?q=teknologi"
        },

        // --- CRYPTO.PINTARAPP.COM (Kripto, Bitcoin, Trading) ---
        {
            category: "crypto_bitcoin",
            keywords: ["kripto", "crypto", "cryptocurrency", "bitcoin", "btc", "ethereum", "eth", "altcoin", "koin micin", "blockchain", "mining", "wallet kripto"],
            response: "Tertarik dengan dunia Cryptocurrency? Temukan analisa mendalam tentang pergerakan harga Bitcoin, prediksi koin potensial (altcoin), dan edukasi teknologi blockchain di blog kripto kami.",
            domain: "crypto",
            linkPath: "/"
        },
        {
            category: "crypto_trading",
            keywords: ["trading", "investasi", "saham", "forex", "binance", "indodax", "tokocrypto", "cara trading", "analisa teknikal", "cuan", "investasi kripto", "indikator trading", "stop loss"],
            response: "Pelajari strategi trading, cara investasi aset digital yang benar, pemahaman analisa teknikal (charting), dan tips aman bertransaksi di bursa (exchange) agar portofolio Anda tetap cuan.",
            domain: "crypto",
            linkPath: "/search?q=trading"
        },

        // --- STORE.PINTARAPP.COM (Toko, Belanja, Produk) ---
        {
            category: "store_belanja",
            keywords: ["belanja", "toko", "store", "beli", "jual", "produk", "harga", "promo", "diskon", "murah", "marketplace", "jualan", "beli online", "checkout", "keranjang"],
            response: "Sedang mencari produk menarik dengan harga terbaik? Kunjungi toko online resmi kami untuk melihat berbagai penawaran spesial, diskon menarik, dan produk-produk pilihan berkualitas.",
            domain: "store",
            linkPath: "/"
        },

        // --- WEDDING.PINTARAPP.COM (Pernikahan, Undangan) ---
        {
            category: "wedding_umum",
            keywords: ["pernikahan", "wedding", "nikah", "undangan", "undangan digital", "undangan online", "vendor pernikahan", "souvenir", "gaun pengantin", "katering", "dekorasi pernikahan", "akad nikah"],
            response: "Sedang merencanakan hari bahagia Anda? Temukan berbagai inspirasi vendor pernikahan, panduan pembuatan undangan digital yang cantik dan elegan, serta berbagai tips persiapan pernikahan impian di portal wedding kami.",
            domain: "wedding",
            linkPath: "/"
        },

        // --- SCRIPT.PINTARAPP.COM (Script, Source Code, Plugin) ---
        {
            category: "script_umum",
            keywords: ["script", "source code", "plugin", "tema premium", "download script", "kode php", "bot", "script web", "template web"],
            response: "Mencari source code, plugin, atau script website siap pakai? Kami menyediakan koleksi script berkualitas untuk berbagai kebutuhan di portal Script PintarApp.",
            domain: "script",
            linkPath: "/"
        },

        // --- CATATAN-KU.PINTARAPP.COM (Catatan, Jurnal, Opini, Motivasi) ---
        {
            category: "catatan_umum",
            keywords: ["catatan", "jurnal", "opini", "diary", "motivasi", "inspirasi", "pengalaman", "cerita", "curhat", "quotes", "kata bijak", "puisi", "keseharian"],
            response: "Mencari bahan bacaan yang menyentuh hati, inspiratif, atau sekadar cerita pengalaman sehari-hari? Kunjungi blog catatan harian kami yang merangkum berbagai opini, jurnal kehidupan, dan motivasi.",
            domain: "catatan",
            linkPath: "/"
        }
    ];

    // Notifikasi Tooltip Logic
    function closeBCNotification(e) {
        if (e) e.stopPropagation();
        const notif = document.getElementById('bc-notification');
        if (notif) notif.classList.remove('show');
        sessionStorage.setItem('bc_chat_notified', 'true');
    }

    // Tampilkan notifikasi setelah 3 detik jika chat belum dibuka
    setTimeout(() => {
        if (!sessionStorage.getItem('bc_chat_notified') && !isBCChatLoaded) {
            const notif = document.getElementById('bc-notification');
            if (notif) notif.classList.add('show');
        }
    }, 3000);

    // Buka/Tutup Chatbot & Lazy Load DOM
    function toggleBCChat() {
        closeBCNotification(); // Tutup notifikasi saat chat dibuka
        if (!isBCChatLoaded) {
            // Render DOM hanya ketika ikon diklik untuk pertama kali (Lazy Load)
            const template = document.getElementById('bc-chat-template');
            bcWrapper.insertBefore(template.content.cloneNode(true), document.getElementById('bc-toggle-btn'));

            bcContainer = document.getElementById('bc-container');
            bcMessages = document.getElementById('bc-messages');
            bcInput = document.getElementById('bc-input');

            // Deteksi nama blog saat ini untuk judul Header
            let currentDomainName = "Blog";
            const currentHost = window.location.hostname;
            for (const key in bcDomains) {
                if (currentHost === new URL(bcDomains[key]).hostname) {
                    currentDomainName = bcDomainNames[key];
                    break;
                }
            }
            const titleEl = bcContainer.querySelector('.bc-title');
            if (titleEl) {
                titleEl.textContent = "Asisten " + currentDomainName;
            }

            // Muat Riwayat Chat dari SessionStorage
            const savedHistory = sessionStorage.getItem('bc_chat_history');
            if (savedHistory) {
                try {
                    const historyArray = JSON.parse(savedHistory);
                    if (historyArray.length > 0) {
                        bcMessages.innerHTML = ''; // Hapus pesan default
                        historyArray.forEach(msg => {
                            appendBCMessage(msg.sender, msg.text, msg.isHTML, false, true);
                        });
                    }
                } catch (e) {
                    console.error("Gagal memuat histori chat:", e);
                }
            }

            isBCChatLoaded = true;
        }

        bcContainer.classList.toggle('closed');

        // Ubah ikon tombol toggle
        if (bcContainer.classList.contains('closed')) {
            bcIconChat.style.display = 'block';
            bcIconClose.style.display = 'none';
        } else {
            bcIconChat.style.display = 'none';
            bcIconClose.style.display = 'block';
            // Fokus input setelah animasi transisi selesai
            setTimeout(() => { if (bcInput) bcInput.focus(); }, 300);
        }
    }

    // Deteksi tombol Enter
    function handleBCKeyPress(event) {
        if (event.key === 'Enter') {
            sendBCMessage();
        }
    }

    // Algoritma Pencarian Jawaban
    function getBCLocalResponse(message) {
        const lowerMessage = message.toLowerCase();
        let bestMatch = null;
        let maxMatchCount = 0;

        // Tokenisasi input user menjadi kata-kata unik (membuang tanda baca)
        const userWords = lowerMessage.replace(/[^\w\s]/gi, '').split(/\s+/).filter(word => word.length > 0);

        for (const intent of bcIntents) {
            let matchCount = 0;

            for (const keyword of intent.keywords) {
                const lowerKeyword = keyword.toLowerCase();

                // Jika kata kunci mengandung spasi (berupa frasa)
                if (lowerKeyword.includes(' ')) {
                    if (lowerMessage.includes(lowerKeyword)) {
                        matchCount += 3; // Bobot tinggi untuk pencocokan frasa
                    }
                } else {
                    // Pencocokan per kata
                    if (userWords.includes(lowerKeyword)) {
                        matchCount += 1.5;
                    } else if (lowerKeyword.length > 4 && lowerMessage.includes(lowerKeyword)) {
                        // Pencocokan parsial (menangkap kata berimbuhan, misal "menggambar" -> "gambar")
                        matchCount += 0.5;
                    }
                }
            }

            if (matchCount > maxMatchCount) {
                maxMatchCount = matchCount;
                bestMatch = intent;
            }
        }

        let responseText = "";
        let domainId = null;
        let isFallback = false;
        let bestMatchObj = null;

        if (bestMatch && maxMatchCount > 0) {
            responseText = bestMatch.response;
            domainId = bestMatch.domain;
            bestMatchObj = bestMatch;
        } else {
            isFallback = true;
            // Fallback: Jika pertanyaan tidak dikenali di satu kategori spesifik
            // Beri rujukan pencarian lintas-blog (Cross-blog search referral)
            responseText = `Maaf, saya tidak menemukan jawaban instan untuk "${message}". Tapi Anda bisa menjelajahi jaringan blog PintarApp kami:\n\n` +
                `šŸ” [Cari di Alat PintarApp](${bcDomains.app}/search?q=${encodeURIComponent(message)})\n` +
                `šŸ“° [Cari di Artikel Utama](${bcDomains.main}/search?q=${encodeURIComponent(message)})\n` +
                `šŸ’” Atau coba gunakan kata kunci yang lebih spesifik (misal: "kompres jpg", "seo", "bitcoin").`;
        }

        return { text: responseText, domainId: domainId, isFallback: isFallback, bestMatch: bestMatchObj };
    }

    // Utilitas untuk mengambil data feed Blogger lintas domain (Bypass CORS via JSONP)
    function fetchBloggerJSONP(url) {
        return new Promise((resolve, reject) => {
            const callbackName = 'bc_jsonp_' + Math.round(100000 * Math.random());
            const script = document.createElement('script');
            const jsonpUrl = url + (url.includes('?') ? '&' : '?') + 'alt=json-in-script&callback=' + callbackName;

            const timeoutId = setTimeout(() => {
                cleanup();
                reject(new Error('JSONP Timeout'));
            }, 5000);

            function cleanup() {
                delete window[callbackName];
                if (script.parentNode) script.parentNode.removeChild(script);
                clearTimeout(timeoutId);
            }

            window[callbackName] = function (data) {
                cleanup();
                resolve(data);
            };

            script.onerror = function () {
                cleanup();
                reject(new Error('JSONP Failed'));
            };

            script.src = jsonpUrl;
            document.body.appendChild(script);
        });
    }

    // Eksekusi Kirim Pesan (Diperbarui dengan Fitur Cross-Domain Live Post Reading)
    async function sendBCMessage() {
        const messageText = bcInput.value.trim();
        if (!messageText) return;

        // Tampilkan pesan pengunjung
        appendBCMessage('user', messageText);
        bcInput.value = '';

        // Tampilkan animasi mengetik
        const typingId = showBCTyping();

        // 0. Deteksi Permintaan Generate Gambar yang Jauh Lebih Pintar
        const isImageRequest = /gambar|lukis|foto|ilustrasi|potret/i.test(messageText);
        const isGenerateVerb = /buat|bikin|lukis|generate|minta/i.test(messageText);

        if (isImageRequest && isGenerateVerb) {
            // Bersihkan kata-kata perintah di awal untuk mengekstrak murni objek yang ingin digambar
            let prompt = messageText.replace(/^(?:tolong\s+|coba\s+|bantu\s+)?(?:buatkan|bikinkan|buat|bikin|gambarkan|lukiskan|generate|minta)(?:\s+(?:aku|saya|kami|dong|coba|tolong))?(?:\s+(?:sebuah|satu|suatu))?(?:\s+(?:gambar|foto|lukisan|ilustrasi|potret|desain))?\s+/i, '').trim();

            // Jika regex di atas gagal memotong dengan bersih, kita bersihkan kata kerjanya secara manual
            if (!prompt || prompt === messageText) {
                prompt = messageText.replace(/buatkan|bikinkan|buat|bikin|gambarkan|lukiskan|gambar|foto|tolong|saya/gi, '').trim();
            }

            if (prompt) {
                const encodedPrompt = encodeURIComponent(prompt);
                const imgUrl = `https://image.pollinations.ai/prompt/${encodedPrompt}?width=1024&height=1024&model=flux&nologo=true`;
                const responseHtml = `šŸŽØ Tentu! Berikut adalah gambar **${prompt}** hasil karya saya:\n\n<img src="${imgUrl}" style="max-width: 100%; border-radius: 8px; box-shadow: 0 4px 6px rgba(0,0,0,0.1); margin-top: 8px;" alt="${prompt}" />`;

                setTimeout(() => {
                    removeBCElement(typingId);
                    const formattedText = formatBCResponse(responseHtml);
                    appendBCMessage('bot', formattedText, true, true);
                }, 1000);
                return;
            }
        }

        // 0.5 Deteksi Permintaan Matematika yang Lebih Pintar
        // Menerjemahkan kata-kata matematika bahasa Indonesia ke dalam simbol angka (contoh: "dua tambah dua" -> "2 + 2")
        const normalizedMath = messageText.toLowerCase()
            .replace(/\b(?:nol|kosong)\b/g, '0')
            .replace(/\b(?:satu)\b/g, '1')
            .replace(/\b(?:dua)\b/g, '2')
            .replace(/\b(?:tiga)\b/g, '3')
            .replace(/\b(?:empat)\b/g, '4')
            .replace(/\b(?:lima)\b/g, '5')
            .replace(/\b(?:enam)\b/g, '6')
            .replace(/\b(?:tujuh)\b/g, '7')
            .replace(/\b(?:delapan)\b/g, '8')
            .replace(/\b(?:sembilan)\b/g, '9')
            .replace(/\b(?:sepuluh)\b/g, '10')
            .replace(/\b(?:sebelas)\b/g, '11')
            .replace(/\b(?:seratus)\b/g, '100')
            .replace(/\b(?:seribu)\b/g, '1000')
            .replace(/\b(?:tambah|ditambah|plus|diberi|dapat|mendapat|beli lagi|tambahan)\b/g, '+')
            .replace(/\b(?:kurang|dikurang|minus|dikurangi|kurangi|kasih|dikasih|diberikan|diambil|hilang|buang|pecah|dimakan|terjual|bayar|minta)\b/g, '-')
            .replace(/\b(?:kali|dikali)\b/g, '*')
            .replace(/\b(?:bagi|dibagi)\b/g, '/');

        // Mengekstrak murni karakter matematika dari pesan yang sudah diterjemahkan
        const mathClean = normalizedMath.replace(/[^0-9\+\-\*\/\(\)\.\s]/g, '').trim();
        // Cek apakah pesan asli mengandung niat matematika atau sepenuhnya berupa hitungan
        const isMathQuery = /berapa|hitung|hasil|jumlah|tambah|kurang|kali|bagi|sisa|=|\?/i.test(messageText) || /^[0-9\+\-\*\/\(\)\.\s]+$/.test(normalizedMath);

        // Pastikan ada angka, ada operator, dan ekspresi cukup panjang untuk dievaluasi
        if (isMathQuery && /[0-9]/.test(mathClean) && /[\+\-\*\/]/.test(mathClean) && mathClean.length >= 3) {
            try {
                const result = new Function('return ' + mathClean)();
                if (isFinite(result)) {
                    const formattedResult = Number.isInteger(result) ?
                        result.toLocaleString('id-ID') :
                        result.toLocaleString('id-ID', { maximumFractionDigits: 4 });

                    const responseHtml = `🧮 Hasil dari **${mathClean}** adalah **${formattedResult}**`;

                    setTimeout(() => {
                        removeBCElement(typingId);
                        const formattedText = formatBCResponse(responseHtml);
                        appendBCMessage('bot', formattedText, true, true);
                    }, 800);
                    return;
                }
            } catch (e) {
                // Abaikan jika bukan ekspresi yang valid (lanjut pencarian blog)
            }
        }

        // 1. Dapatkan jawaban awal dari Intent Mapping (Kecerdasan Buatan)
        const matchResult = getBCLocalResponse(messageText);
        let responseText = matchResult.text;

        // 2. Tentukan domain target pencarian Blogger Feed API
        // Jika ada domain rujukan, gunakan domain rujukan tersebut. Jika tidak (fallback), gunakan blog saat ini.
        let searchDomainUrl = null;
        if (matchResult.domainId && bcDomains[matchResult.domainId]) {
            searchDomainUrl = bcDomains[matchResult.domainId];
        } else if (matchResult.isFallback) {
            searchDomainUrl = window.location.origin;
        }

        // Peta nama portal untuk tampilan user
        const domainNameDisplay = matchResult.domainId ? bcDomainNames[matchResult.domainId] : "blog ini";

        // 3. FITUR BACA POSTINGAN LINTAS DOMAIN (FEDERATED SEARCH): 
        let fetchedArticles = false;

        if (!matchResult.isFallback && searchDomainUrl) {
            let isFallbackToLatest = false;

            try {
                // Percobaan 1: Cari artikel berdasarkan kata kunci di domain spesifik
                let searchUrl = `${searchDomainUrl}/feeds/posts/summary?q=${encodeURIComponent(messageText)}&max-results=3`;
                let data = await fetchBloggerJSONP(searchUrl);

                // Percobaan 2: Jika kata kunci tidak ditemukan satupun, ambil postingan terbaru secara umum
                if (!data.feed || !data.feed.entry || data.feed.entry.length === 0) {
                    searchUrl = `${searchDomainUrl}/feeds/posts/summary?max-results=3`;
                    data = await fetchBloggerJSONP(searchUrl);
                    isFallbackToLatest = true;
                }

                // Jika artikel ditemukan (entah spesifik atau terbaru)
                if (data.feed && data.feed.entry && data.feed.entry.length > 0) {
                    fetchedArticles = true;

                    if (isFallbackToLatest) {
                        responseText += `\n\nSaya tidak menemukan postingan spesifik untuk kata kunci tersebut, tapi berikut beberapa artikel terbaru dari **${domainNameDisplay}**:\n\n`;
                    } else {
                        responseText += `\n\nBerikut rekomendasi artikel yang cocok dari **${domainNameDisplay}**:\n\n`;
                    }

                    data.feed.entry.forEach(entry => {
                        const title = entry.title.$t;
                        let link = "";
                        for (let i = 0; i < entry.link.length; i++) {
                            if (entry.link[i].rel === "alternate") {
                                link = entry.link[i].href;
                                break;
                            }
                        }
                        responseText += `šŸ‘‰ [${title}](${link})\n`;
                    });
                }
            } catch (error) {
                // Abaikan jika API tidak tersedia
            }

            // Selalu tampilkan link menuju portal terkait jika pencarian terikat domain
            const targetUrl = matchResult.bestMatch.linkPath ? (searchDomainUrl + matchResult.bestMatch.linkPath) : (searchDomainUrl + "/search?q=" + encodeURIComponent(messageText));
            if (!fetchedArticles) {
                responseText += `\n\nMaaf, saya gagal memuat daftar artikel saat ini.`;
            }
            responseText += `\n\n🌐 **Kunjungi Portal ${domainNameDisplay}:**\nšŸ‘‰ [Klik di sini untuk mencari selengkapnya](${targetUrl})`;

        } else if (matchResult.isFallback) {
            // JIKA FALLBACK: Integrasi Jawaban Wikipedia + Federated Search
            try {
                // 1. Wikipedia API untuk menjawab pertanyaan umum ("apa itu python")
                const wikiFetchUrl = `https://id.wikipedia.org/w/api.php?action=query&list=search&srsearch=${encodeURIComponent(messageText)}&utf8=&format=json&origin=*`;
                // Panggil fetch biasa untuk Wikipedia karena mereka mendukung CORS secara publik
                const wikiPromise = fetch(wikiFetchUrl).then(res => res.json()).catch(() => null);

                // 2. Federated Search: Cari di SEMUA blog secara bersamaan via JSONP
                const searchPromises = Object.keys(bcDomains).map(async (key) => {
                    const url = bcDomains[key];
                    const fetchUrl = `${url}/feeds/posts/summary?q=${encodeURIComponent(messageText)}&max-results=2`;
                    const json = await fetchBloggerJSONP(fetchUrl);
                    return { key, json };
                });

                // Tunggu Wikipedia dan Blogger selesai bersamaan (paralel)
                const [wikiData, results] = await Promise.all([wikiPromise, Promise.allSettled(searchPromises)]);

                // Proses jawaban cerdas dari Wikipedia
                let wikiAnswer = "";
                if (wikiData && wikiData.query && wikiData.query.search && wikiData.query.search.length > 0) {
                    const topResult = wikiData.query.search[0];
                    // Bersihkan tag HTML dari snippet Wikipedia
                    const cleanSnippet = topResult.snippet.replace(/<\/?[^>]+(>|$)/g, "");
                    wikiAnswer = `*${cleanSnippet}...*\n\n`;
                }

                // Proses hasil pencarian artikel dari semua blog
                let foundArticles = [];
                for (const result of results) {
                    if (result.status === 'fulfilled' && result.value.json.feed && result.value.json.feed.entry) {
                        const key = result.value.key;
                        result.value.json.feed.entry.forEach(entry => {
                            const title = entry.title.$t;
                            let snippet = "";
                            if (entry.summary && entry.summary.$t) snippet = entry.summary.$t;
                            else if (entry.content && entry.content.$t) snippet = entry.content.$t;

                            let link = "";
                            for (let i = 0; i < entry.link.length; i++) {
                                if (entry.link[i].rel === "alternate") { link = entry.link[i].href; break; }
                            }
                            foundArticles.push({ title, link, snippet, domainName: bcDomainNames[key] });
                        });
                    }
                }

                // Ekstrak snippet dari blog (RAG / Retreival-Augmented Generation)
                let blogAnswer = "";
                if (foundArticles.length > 0) {
                    // Coba cari artikel pertama yang memiliki snippet teks
                    const bestArticle = foundArticles.find(art => art.snippet && art.snippet.length > 10);
                    if (bestArticle) {
                        const cleanSnippet = bestArticle.snippet.replace(/<\/?[^>]+(>|$)/g, "").trim().substring(0, 250);
                        blogAnswer = `šŸ’” **Menurut ${bestArticle.domainName}:**\n*"${cleanSnippet}..."*\n\n`;
                    }
                }

                // Gabungkan jawaban
                if (foundArticles.length > 0 || wikiAnswer) {
                    fetchedArticles = true;
                    responseText = "";

                    if (wikiAnswer) responseText += wikiAnswer;
                    if (blogAnswer) responseText += blogAnswer;

                    if (foundArticles.length > 0) {
                        if (wikiAnswer || blogAnswer) {
                            responseText += `šŸ“š **Selengkapnya dari Jaringan PintarApp:**\n`;
                        } else {
                            responseText = `Saya telah memindai seluruh jaringan blog PintarApp dan menemukan artikel ini untuk Anda:\n\n`;
                        }

                        const limitedArticles = foundArticles.slice(0, 5);
                        limitedArticles.forEach(art => {
                            responseText += `šŸ‘‰ [${art.title}](${art.link}) *(di ${art.domainName})*\n`;
                        });
                    }
                } else {
                    // Jika tidak ada di seluruh jaringan dan wikipedia kosong, ambil postingan terbaru blog ini
                    let searchUrl = `${window.location.origin}/feeds/posts/summary?max-results=3`;
                    let data = await fetchBloggerJSONP(searchUrl);
                    if (data.feed && data.feed.entry && data.feed.entry.length > 0) {
                        responseText += `\n\nSebagai gantinya, ini beberapa artikel terbaru kami:\n\n`;
                        data.feed.entry.forEach(entry => {
                            const title = entry.title.$t;
                            let link = "";
                            for (let i = 0; i < entry.link.length; i++) {
                                if (entry.link[i].rel === "alternate") { link = entry.link[i].href; break; }
                            }
                            responseText += `šŸ‘‰ [${title}](${link})\n`;
                        });
                    }
                }
            } catch (e) {
                // Abaikan jika error
            }
        }

        // Jeda seolah bot sedang "berpikir" dan membaca
        setTimeout(() => {
            // Hapus animasi mengetik
            removeBCElement(typingId);

            // Format teks (Ubah markdown ke link HTML)
            const formattedText = formatBCResponse(responseText);

            // Tampilkan pesan bot dengan efek mengetik
            appendBCMessage('bot', formattedText, true, true);

        }, 1000);
    }

    // --- UTILITAS DOM ---
    function typeHTMLEffect(element, htmlString, speed = 15) {
        let i = 0;
        let isTag = false;
        let currentTag = "";
        let tokens = [];

        for (let char of htmlString) {
            if (char === '<') { isTag = true; currentTag = char; }
            else if (char === '>') { isTag = false; currentTag += char; tokens.push(currentTag); currentTag = ""; }
            else if (isTag) { currentTag += char; }
            else { tokens.push(char); }
        }

        element.innerHTML = "";
        let currentHTML = "";

        function typeWriter() {
            if (i < tokens.length) {
                currentHTML += tokens[i];
                element.innerHTML = currentHTML;
                scrollBCBottom();
                i++;
                if (tokens[i - 1] && tokens[i - 1].startsWith('<')) {
                    typeWriter(); // Skip delay for HTML tags
                } else {
                    setTimeout(typeWriter, speed);
                }
            }
        }
        typeWriter();
    }

    function appendBCMessage(sender, text, isHTML = false, typeEffect = false, skipSave = false) {
        const msgDiv = document.createElement('div');
        msgDiv.classList.add('bc-message', sender);
        bcMessages.appendChild(msgDiv);

        if (isHTML && typeEffect) {
            typeHTMLEffect(msgDiv, text, 15);
        } else if (isHTML) {
            msgDiv.innerHTML = text;
            scrollBCBottom();
        } else {
            msgDiv.textContent = text;
            scrollBCBottom();
        }

        // Simpan ke history jika bukan sedang memuat ulang history
        if (!skipSave) {
            try {
                let historyArray = JSON.parse(sessionStorage.getItem('bc_chat_history') || '[]');
                historyArray.push({ sender, text, isHTML });
                // Batasi history maksimal 50 pesan terakhir agar memori browser tidak penuh
                if (historyArray.length > 50) historyArray = historyArray.slice(historyArray.length - 50);
                sessionStorage.setItem('bc_chat_history', JSON.stringify(historyArray));
            } catch (e) {
                console.error("Gagal menyimpan histori chat:", e);
            }
        }
    }

    function formatBCResponse(text) {
        let htmlText = text.replace(/\n/g, '<br>'); // Enter ke <br>
        // Bold: **teks**
        htmlText = htmlText.replace(/\*\*([^*]+)\*\*/g, '<strong>$1</strong>');
        // Italic: *teks*
        htmlText = htmlText.replace(/\*([^*]+)\*/g, '<em>$1</em>');
        // Link: [Teks](URL)
        const linkRegex = /\[([^\]]+)\]\(([^)]+)\)/g;
        htmlText = htmlText.replace(linkRegex, '<a href="$2" target="_blank">$1</a>');
        return htmlText;
    }

    function showBCTyping() {
        const id = 'bc-typing-' + Date.now();
        const msgDiv = document.createElement('div');
        msgDiv.id = id;
        msgDiv.classList.add('bc-message', 'bot', 'bc-typing-indicator');
        msgDiv.innerHTML = `
            <div class="bc-dot"></div>
            <div class="bc-dot"></div>
            <div class="bc-dot"></div>
        `;
        bcMessages.appendChild(msgDiv);
        scrollBCBottom();
        return id;
    }

    function removeBCElement(id) {
        const el = document.getElementById(id);
        if (el) el.remove();
    }

    function scrollBCBottom() {
        bcMessages.scrollTop = bcMessages.scrollHeight;
    }
    //]]>
</script>

</body>
</html>