<?xml version="1.0" encoding="UTF-8" standalone="no"?><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:blogger="http://schemas.google.com/blogger/2008" xmlns:gd="http://schemas.google.com/g/2005" xmlns:georss="http://www.georss.org/georss" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/" xmlns:thr="http://purl.org/syndication/thread/1.0" version="2.0"><channel><atom:id>tag:blogger.com,1999:blog-9000860041661554971</atom:id><lastBuildDate>Fri, 16 Oct 2026 02:16:55 +0000</lastBuildDate><category>herbal</category><category>download</category><category>ebook</category><category>islami</category><category>Forex</category><category>Marketiva</category><category>converter</category><category>Cinta</category><category>El-shirazy</category><category>Habiburahman</category><category>Investasi Menurut Hukum Islam</category><category>Kang Abik</category><category>Novel</category><category>Online</category><category>Trading</category><category>VALUTA</category><category>doa</category><category>#pemimpinmerdekabelajar #refleksimerdekabelajar</category><category>18 Cara Merawat Komputer/Laptop Agar Tetap Awet Dan Tidak Rusak</category><category>ASING</category><category>Apa</category><category>Ayat</category><category>BATASAN RIBA DALAM SYARIAH</category><category>Bank konvensional vs Bank Syariah</category><category>Basic</category><category>Batasan Mengambil Keuntungan dalam Islam</category><category>Bertasbih</category><category>Bertasbih II</category><category>CARI</category><category>COMMODITIES</category><category>Cara</category><category>Cara Daftar Google Adsense Indonesia untuk menghasilkan uang dari internet</category><category>Cara Download Video Di YouTube Tanpa Software</category><category>Cara Investasi yang benar dan aman</category><category>Cara Memasang Iklan Adsense di Tengah Posting Secara Otomatis</category><category>Cara Memperbaiki Harddisk Tidak Terbaca Komputer</category><category>Cara Mendapatkan Uang dari Internet  seo</category><category>Cara Mendapatkan Uang dari Internet Bagi Anda yang Suka Bermain Game</category><category>Cara Mendapatkan Uang dari Internet Jika Anda Memahami Teknik SEO</category><category>Cara Mendapatkan Uang dari Internet Jika Anda Memiliki Modal Memadai</category><category>Cara Mendapatkan Uang dari Internet Jika Anda Punya Waktu Memadai</category><category>Cara Mendapatkan Uang dari Internet dengan Membuat Program/Software</category><category>Cara Mendapatkan Uang dari Internet dengan Toko Online</category><category>Cara Meningkatkan lalu lintas Pengunjung Blog / Website Dengan Cepat</category><category>Cara Mudah Membuat Akun PayPal Tanpa Kartu Kredit</category><category>Cara atasi Bluetooth Laptop tidak bekerja</category><category>Cara mengetahui spesifikasi komputer di linux</category><category>Cara mudah Download Video Di YouTube</category><category>DI INTERNET</category><category>DOWNLOAD SOAL-SOAL LATIHAN PRAKTEK EXCEL</category><category>Deposit</category><category>Deposito Syariah</category><category>Download ebook islami bagian 5</category><category>Download internet download accelator IrfanView</category><category>Dunia</category><category>Edensor</category><category>FUND</category><category>Forex dalam hukum Islam</category><category>HOBI YANG MENGHASILKAN UANG</category><category>Hukum Investasi  Menurut Syariat Islam</category><category>Hukum Tansaksi Valas dan Spekulasi Kurs Mata Uang</category><category>INDEXES</category><category>INVESTASI SYARIAH MENGUNTUNGKAN DUNIA DAN AKHIRAT</category><category>Instrumen Pasar Modal Syariah</category><category>Investasi dalam pandangan islam (syariah)</category><category>Jenis Investasi Berdasarkan Syariah</category><category>Join</category><category>Jual Beli dalam Syariah</category><category>KAMUS ISTILAH FOREX</category><category>Kenapa Kamu Harus Punya PayPal</category><category>Kumpulan Perintah Linux di Terminal Lengkap</category><category>MARKETIVA AGEA MUDAHNYA BERTRANSAKSI FOREX</category><category>MATA UANG</category><category>MENGENAL SAHAM (1)</category><category>MENGENAL SAHAM (2)</category><category>MENGUMPULKAM MODAL</category><category>MENYIAPKAN DANA HAJI</category><category>MONEY GAME</category><category>Materi</category><category>Membuat blog jadi 3 kolom</category><category>Mengetahui Kapasitas Memory</category><category>Menghasilkan Uang dari Internet dengan ClixSense</category><category>Menghasilkan Uang dari Internet dengan WHAFF!</category><category>Modul penyelesain masalah akuntansi dengan excel</category><category>Musik Klasik Bagi Bayi 1</category><category>Musik Klasik Bagi Bayi 2</category><category>Musik Klasik Bagi Bayi 3</category><category>Nama</category><category>Novel Ayat-Ayat Cinta</category><category>PELATIHAN PEMANFAATAN TIK DAN LITERASASI DIGITAL DI SMK N 8 SOLO KERJASAMA PUSTEKOM KEMDIKBUD DAN KOGTIK</category><category>PRODUK SIMPANAN DI BANK</category><category>Pasar Modal Syariah</category><category>Penyebab Blue Screen Windows dan Solusi Cara Mengatasinya</category><category>Processor</category><category>REKSA DANA (1)</category><category>REKSA DANA (2)</category><category>Resiko dalam Investasi</category><category>SAW</category><category>SENI BACA ALQURAN</category><category>SIKLUS FINANSIAL ANDA</category><category>STRATEGI FOREX</category><category>Secara</category><category>Singkat</category><category>Soal</category><category>Spekulasi di Pasar Modal</category><category>Strategy</category><category>TEMPAT</category><category>Tantangan Investasi Syariah di Pasar Modal</category><category>Tata Cara Jual Beli dalam Islam</category><category>Tinjauan Syariat Terhadap Jual-Beli Kredit</category><category>Tips Jitu Trading</category><category>Tips Memperbaiki Komputer Yang Macet Hang</category><category>Tradding</category><category>Transaksi</category><category>Tutorial</category><category>Tutorial Cara</category><category>UANG</category><category>Witdrawl</category><category>ahmed</category><category>aisyah</category><category>akm</category><category>alam</category><category>alquran</category><category>andrea</category><category>andrea hirata</category><category>ansav</category><category>antivirus</category><category>aqiqah</category><category>audio</category><category>avi</category><category>bagian</category><category>bepergian</category><category>berhijab</category><category>berjilbab</category><category>dan</category><category>dan Hardisk pada PC</category><category>dan Hardisk pada PC Mengetahui Kapasitas Memory</category><category>dan Referensi Jawaban</category><category>deedat</category><category>dogma</category><category>download converter</category><category>download lagu Letto - Lethologica (2009)</category><category>download laskar pelangi karya andrea hirata</category><category>download modul praktek SPSS</category><category>download setup alqur'an in word</category><category>download soal-soal pilihan Ganda TKJ (teknik Jaringan dan Komputer)</category><category>engkau</category><category>fiqih</category><category>flv</category><category>hamil</category><category>hirata</category><category>ilmu</category><category>iman</category><category>injil</category><category>islam</category><category>jual beli kredit dalam islam</category><category>karpov</category><category>karya andrea hirata</category><category>keajaiban</category><category>kristen</category><category>kristus</category><category>laskar pelangi 3</category><category>laut</category><category>lintas</category><category>maryamah</category><category>matematika</category><category>mati</category><category>menghalangi</category><category>menghasilkan uang dari internet dengan ProBux</category><category>misteri</category><category>mpeg</category><category>muallaf</category><category>muhammmad</category><category>nabawiyah</category><category>naskah</category><category>nusantar</category><category>orientasi</category><category>pcmav</category><category>pemuda</category><category>pendeta</category><category>penduduk</category><category>perdebatan</category><category>perjalanan</category><category>quran</category><category>rahasia</category><category>sang pemimpi</category><category>sedang</category><category>sejarah</category><category>semesta</category><category>sirah</category><category>smadav</category><category>surga</category><category>swaramuslim</category><category>tawakal</category><category>wanita</category><category>wav</category><category>wma</category><title>INVESTASI DEMI HIDUP YANG LEBIH BAIK</title><description>"Berbuat BAIK adalah investasi"-
"Kesehatan adalah investasi"-
"Ilmu adalah investasi"--

"BerInvestasilah yang bisa Menjamin Kebahagian Kehidupan Dunia Akhirat"</description><link>http://kitab-investasi.blogspot.com/</link><managingEditor>noreply@blogger.com (Unknown)</managingEditor><generator>Blogger</generator><openSearch:totalResults>763</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><language>en-us</language><itunes:explicit>yes</itunes:explicit><copyright>Bussines for you</copyright><itunes:keywords>reksadana,saham,forex,Bank,Tabungan,Forex,Pulsa,Elektronik,HP,Bisnis,Bussine</itunes:keywords><itunes:summary>Islamic canon law investment for calm old age, happy, Very Rich, Barokah if died entered heaven Reksadana , Saham, Bank, Tabungan, Forex, Pulsa Elektronik</itunes:summary><itunes:subtitle>Investasi syariah</itunes:subtitle><itunes:category text="Business"><itunes:category text="Investing"/></itunes:category><itunes:author>abang_cool</itunes:author><itunes:owner><itunes:email>nof_rizal07@yahoo.co.id</itunes:email><itunes:name>abang_cool</itunes:name></itunes:owner><item><guid isPermaLink="false">tag:blogger.com,1999:blog-9000860041661554971.post-6933410701014625663</guid><pubDate>Fri, 16 Oct 2026 02:16:55 +0000</pubDate><atom:updated>2026-10-16T09:16:55.634+07:00</atom:updated><title>Latihan Soal Tipe AKM: Pokok Bahasan Teks Ceramah</title><description>&lt;style&gt;
.kq{--ink:#14213d;--mut:#4a5568;--pri:#1d4ed8;--pri2:#1e3a8a;--ok:#047857;--bad:#b91c1c;--bg:#f1f5f9;--card:#ffffff;--line:#cbd5e1;font-family:Segoe UI,Roboto,Arial,sans-serif;color:var(--ink);line-height:1.6;max-width:880px;margin:0 auto}
.kq *{box-sizing:border-box}
.kq .hero{background:linear-gradient(135deg,#1e3a8a,#1d4ed8 60%,#0ea5e9);color:#fff;border-radius:18px;padding:26px 22px;margin-bottom:16px}
.kq .hero h2{margin:0 0 6px;font-size:1.55em;color:#fff;border:0}
.kq .hero p{margin:0;color:#e0f2fe}
.kq .grid{display:grid;grid-template-columns:repeat(4,1fr);gap:10px;margin-bottom:16px}
.kq .stat{background:var(--card);border:2px solid var(--line);border-radius:14px;padding:12px;text-align:center}
.kq .stat b{display:block;font-size:1.6em;color:var(--pri2)}
.kq .stat span{font-size:.85em;color:var(--mut)}
.kq .card{background:var(--card);border:2px solid var(--line);border-radius:14px;padding:16px 18px;margin-bottom:16px}
.kq .card h3{margin:0 0 8px;font-size:1.1em;color:var(--pri2)}
.kq .card ul{margin:0;padding-left:20px}
.kq .card li{margin:4px 0}
.kq .warn{background:#fff7ed;border-color:#fb923c}
.kq label.f{display:block;font-weight:700;margin:10px 0 4px}
.kq input.t{width:100%;padding:11px 12px;border:2px solid #94a3b8;border-radius:10px;font-size:1em;color:var(--ink);background:#fff}
.kq input.t:focus{outline:3px solid #93c5fd;border-color:var(--pri)}
.kq .row{display:grid;grid-template-columns:2fr 1fr 1fr;gap:10px}
.kq button.b{background:var(--pri);color:#fff;border:0;border-radius:12px;padding:13px 20px;font-size:1em;font-weight:700;cursor:pointer;margin-top:14px}
.kq button.b:hover{background:var(--pri2)}
.kq button.g{background:#fff;color:var(--pri2);border:2px solid var(--pri)}
.kq .msg{margin-top:12px;font-weight:600}
.kq .msg.e{color:var(--bad)}
.kq .done{background:#ecfdf5;border-color:#34d399}
@media(max-width:640px){.kq .grid{grid-template-columns:repeat(2,1fr)}.kq .row{grid-template-columns:1fr}}

#kqStage{position:fixed;left:0;top:0;right:0;bottom:0;z-index:2147483647;background:#f1f5f9;overflow:auto;font-family:Segoe UI,Roboto,Arial,sans-serif;color:#14213d;line-height:1.6;-webkit-user-select:none;user-select:none}
#kqStage *{box-sizing:border-box}
#kqStage .top{position:sticky;top:0;z-index:5;background:#1e3a8a;color:#fff;padding:10px 14px;display:flex;flex-wrap:wrap;gap:8px 18px;align-items:center;justify-content:space-between}
#kqStage .top b{font-size:1.02em}
#kqStage .pill{background:#fff;color:#1e3a8a;border-radius:999px;padding:3px 12px;font-weight:700;font-size:.9em}
#kqStage .pill.v{background:#fee2e2;color:#991b1b}
#kqStage .bar{height:6px;background:#93c5fd}
#kqStage .bar i{display:block;height:6px;background:#22c55e;width:0}
#kqStage .wrap{max-width:860px;margin:0 auto;padding:16px 14px 60px}
#kqStage .stim{background:#fffbeb;border:2px solid #f59e0b;border-radius:14px;padding:14px 16px;margin:18px 0 10px}
#kqStage .stim h4{margin:0 0 8px;color:#92400e;font-size:1.05em}
#kqStage .stim p{margin:0 0 8px}
#kqStage .q{background:#fff;border:2px solid #cbd5e1;border-radius:14px;padding:14px 16px;margin:10px 0}
#kqStage .q .qt{font-weight:700;margin-bottom:8px}
#kqStage .o{display:flex;gap:10px;align-items:flex-start;padding:9px 10px;border:2px solid #e2e8f0;border-radius:10px;margin:6px 0;cursor:pointer;background:#f8fafc}
#kqStage .o:hover{border-color:#60a5fa;background:#eff6ff}
#kqStage .o input{margin-top:5px;width:18px;height:18px;flex:none}
#kqStage .o.sel{border-color:#1d4ed8;background:#dbeafe}
#kqStage .o b{flex:none;color:#1e3a8a}
#kqStage button.b{background:#1d4ed8;color:#fff;border:0;border-radius:12px;padding:13px 22px;font-size:1em;font-weight:700;cursor:pointer;margin:8px 8px 0 0}
#kqStage button.g{background:#fff;color:#1e3a8a;border:2px solid #1d4ed8}
#kqStage .res{background:#fff;border:2px solid #cbd5e1;border-radius:18px;padding:24px;text-align:center;margin-top:20px}
#kqStage .big{font-size:3.4em;font-weight:800;line-height:1.1}
#kqStage .ok{color:#047857}#kqStage .no{color:#b91c1c}
#kqStage .rv{text-align:left;margin-top:14px;font-size:.92em}
#kqStage .rv div{padding:4px 0;border-bottom:1px solid #e2e8f0}
#kqModal{position:fixed;left:0;top:0;right:0;bottom:0;z-index:2147483647;background:rgba(15,23,42,.88);display:flex;align-items:center;justify-content:center;padding:18px}
#kqModal div{background:#fff;color:#14213d;border-radius:16px;padding:22px;max-width:440px;border:4px solid #dc2626;font-family:Segoe UI,Roboto,Arial,sans-serif}
#kqModal h3{margin:0 0 8px;color:#b91c1c}
#kqModal button{background:#dc2626;color:#fff;border:0;border-radius:10px;padding:11px 20px;font-weight:700;cursor:pointer;margin-top:10px}
#kqPrint{display:none;font-family:Arial,sans-serif;color:#000;font-size:11pt}
#kqPrint h1{font-size:15pt;margin:0 0 4px;text-align:center}
#kqPrint h2{font-size:11pt;margin:10px 0 4px}
#kqPrint table{border-collapse:collapse;width:100%;margin-bottom:6px}
#kqPrint td,#kqPrint th{border:1px solid #000;padding:3px 6px;font-size:10pt;text-align:left}
#kqPrint .sub{text-align:center;margin:0 0 8px}
#kqPrint .two{display:flex;gap:10px}
#kqPrint .two table{width:50%}
#kqPrint .sig{display:flex;justify-content:space-between;margin-top:18px;page-break-inside:avoid}
@media print{@page{size:215mm 330mm;margin:12mm}body.kq-printing&gt;*:not(#kqPrint){display:none!important}body.kq-printing #kqPrint{display:block!important}}
&lt;/style&gt;

&lt;div class="kq" id="kq"&gt;
  &lt;div class="hero"&gt;
    &lt;h2&gt;Latihan Soal Tipe AKM: Pokok Bahasan Teks Ceramah&lt;/h2&gt;
    &lt;p&gt;Bahasa Indonesia Kelas XI SMK. Evaluasi informasi, perbandingan teks, dan kaidah kebahasaan ceramah.&lt;/p&gt;
  &lt;/div&gt;
  &lt;div class="grid"&gt;
    &lt;div class="stat"&gt;&lt;b&gt;50&lt;/b&gt;&lt;span&gt;Soal AKM&lt;/span&gt;&lt;/div&gt;
    &lt;div class="stat"&gt;&lt;b&gt;5&lt;/b&gt;&lt;span&gt;Pilihan jawaban (A-E)&lt;/span&gt;&lt;/div&gt;
    &lt;div class="stat"&gt;&lt;b&gt;75&lt;/b&gt;&lt;span&gt;KKM&lt;/span&gt;&lt;/div&gt;
    &lt;div class="stat"&gt;&lt;b&gt;3x&lt;/b&gt;&lt;span&gt;Kesempatan&lt;/span&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="card"&gt;
    &lt;h3&gt;Cakupan materi&lt;/h3&gt;
    &lt;ul&gt;
      &lt;li&gt;Evaluasi informasi dalam teks ceramah (gagasan pokok, gagasan pendukung, enam kriteria evaluasi)&lt;/li&gt;
      &lt;li&gt;Membandingkan isi teks ceramah dengan teks artikel opini&lt;/li&gt;
      &lt;li&gt;Kaidah kebahasaan teks ceramah bagian 1 (kata ganti, kata teknis, kata persuasif)&lt;/li&gt;
      &lt;li&gt;Kaidah kebahasaan teks ceramah bagian 2 (sapaan, kalimat retoris, konjungsi, majas, kalimat efektif, dan lainnya)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/div&gt;
  &lt;div class="card"&gt;
    &lt;h3&gt;Aturan nilai&lt;/h3&gt;
    &lt;ul&gt;
      &lt;li&gt;Setiap soal bernilai 2 poin (skor maksimal 100). Urutan teks, soal, dan pilihan jawaban diacak untuk setiap siswa dan setiap percobaan.&lt;/li&gt;
      &lt;li&gt;Jika nilai suatu percobaan sudah 75 atau lebih, nilai itu langsung dikirim dan disimpan sebagai nilai akhir.&lt;/li&gt;
      &lt;li&gt;Jika dalam 3 percobaan belum mencapai 75, nilai tertinggi dari ketiga percobaan yang dikirim dan disimpan.&lt;/li&gt;
      &lt;li&gt;Gunakan Nama, Kelas, dan No. Absen yang sama pada setiap percobaan.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/div&gt;
  &lt;div class="card warn"&gt;
    &lt;h3&gt;Aturan keamanan&lt;/h3&gt;
    &lt;ul&gt;
      &lt;li&gt;Soal tampil satu layar penuh. Dilarang berpindah tab, membuka aplikasi lain, atau menekan tombol kembali selama mengerjakan.&lt;/li&gt;
      &lt;li&gt;Setiap pindah tab/aplikasi dicatat sebagai pelanggaran dan dilaporkan ke guru. Pada pelanggaran ke-3, jawaban otomatis dikirim.&lt;/li&gt;
      &lt;li&gt;Salin (copy), klik kanan, dan tombol pintas tertentu dinonaktifkan.&lt;/li&gt;
      &lt;li&gt;Setelah selesai, unduh/cetak bukti pengerjaan (PDF) dan serahkan ke guru.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/div&gt;
  &lt;div class="card"&gt;
    &lt;h3&gt;Identitas siswa&lt;/h3&gt;
    &lt;div class="row"&gt;
      &lt;div&gt;&lt;label class="f" for="kqNama"&gt;Nama lengkap&lt;/label&gt;&lt;input class="t" id="kqNama" type="text" autocomplete="off" placeholder="Nama lengkap"&gt;&lt;/div&gt;
      &lt;div&gt;&lt;label class="f" for="kqKelas"&gt;Kelas&lt;/label&gt;&lt;input class="t" id="kqKelas" type="text" autocomplete="off" placeholder="XI TKJ 1"&gt;&lt;/div&gt;
      &lt;div&gt;&lt;label class="f" for="kqAbsen"&gt;No. Absen&lt;/label&gt;&lt;input class="t" id="kqAbsen" type="number" min="1" max="99" placeholder="Contoh: 12"&gt;&lt;/div&gt;
    &lt;/div&gt;
    &lt;button class="b" id="kqStart" type="button"&gt;Mulai Mengerjakan&lt;/button&gt;
    &lt;div class="msg" id="kqMsg"&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div id="kqStatus"&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;script&gt;
(function(){
var GAS_URL="https://script.google.com/macros/s/AKfycbzM7t2qgAENzxQJXzSYJYL28R6nb3TxJVELLL3CopyEXb51t_gRtrkPOxTpI5mq6VCEKw/exec";
var MATERI="Latihan Soal Tipe AKM - Teks Ceramah";
var KKM=75, MAXA=3, MAXV=3, LET=["A","B","C","D","E"];

/* Format soal: [tingkat, soal, jawaban benar, salah1, salah2, salah3, salah4]  (e=mudah, m=sedang, h=sulit; tidak ditampilkan) */
var G=[
{t:"Teks 1: Ceramah Keselamatan Kerja",p:[
"(1) Assalamualaikum warahmatullahi wabarakatuh. Bapak Kepala Sekolah, Bapak dan Ibu guru, serta teman-teman siswa kelas XI yang saya hormati. Puji syukur marilah kita panjatkan kepada Tuhan Yang Maha Esa atas kesehatan pagi ini. Izinkan saya menyampaikan renungan singkat tentang keselamatan kerja di bengkel.",
"(2) Hadirin sekalian, keselamatan kerja adalah syarat utama sebelum kita berbicara tentang keterampilan. Sebab, tangan yang terampil tidak ada gunanya jika terluka karena kelalaian. Sebagian besar kecelakaan kerja disebabkan oleh kelalaian manusia, bukan oleh kerusakan mesin.",
"(3) Mengapa kita perlu memakai alat pelindung diri? Karena kacamata pelindung menjaga mata dari percikan logam, sarung tangan menjaga tangan dari panas, dan sepatu kerja menjaga kaki dari benda jatuh. Selain itu, perusahaan besar biasanya menolak lulusan yang tidak terbiasa dengan aturan keselamatan.",
"(4) Saya sendiri pernah bekerja sebagai teknisi selama dua belas tahun di sebuah pabrik komponen otomotif. Dari pengalaman itu saya meyakini bahwa kebiasaan kecil, seperti merapikan alat setelah dipakai, mencegah kecelakaan besar. Semua pekerja yang rajin menaati aturan pasti tidak pernah mengalami kecelakaan.",
"(5) Oleh karena itu, marilah kita mulai dari diri sendiri. Hendaknya kita memakai alat pelindung diri setiap kali memasuki bengkel. Mari kita jadikan keselamatan sebagai budaya, bukan sekadar kewajiban. Demikian yang dapat saya sampaikan. Wassalamualaikum warahmatullahi wabarakatuh."],
q:[
["e","Bagian pembukaan pada teks ceramah di atas ditandai oleh ...","salam, sapaan kepada hadirin, ucapan syukur, dan pengantar topik","penjelasan tentang kelalaian manusia","ajakan memakai alat pelindung diri","simpulan dan harapan penceramah","pengalaman penceramah bekerja di pabrik"],
["e","Gagasan pokok paragraf (2) adalah ...","keselamatan kerja merupakan syarat utama sebelum keterampilan","kecelakaan kerja hanya terjadi di pabrik","tangan yang terampil selalu mengalami luka","mesin bengkel sering mengalami kerusakan","keterampilan tidak penting bagi pekerja"],
["m","Pernyataan berikut yang merupakan contoh (gagasan pendukung) bagi alasan perlunya alat pelindung diri adalah ...","kacamata pelindung menjaga mata dari percikan logam","keselamatan dijadikan budaya","penceramah bekerja selama dua belas tahun","semua pekerja yang taat tidak pernah celaka","marilah kita mulai dari diri sendiri"],
["m","Kredibilitas penceramah pada teks tersebut diperkuat oleh ...","pengalamannya selama dua belas tahun sebagai teknisi pabrik komponen otomotif","ajakan memakai alat pelindung diri","salam dan sapaan di awal ceramah","penggunaan kata ganti kita","penggunaan kalimat tanya pada paragraf (3)"],
["h","Pernyataan 'Semua pekerja yang rajin menaati aturan pasti tidak pernah mengalami kecelakaan' paling lemah jika dinilai dari kriteria ...","kelogisan, karena menggeneralisasi secara berlebihan","kredibilitas, karena penceramah tidak berpengalaman","kesesuaian tujuan, karena tidak membahas keselamatan","kelengkapan, karena tidak ada salam penutup","keakuratan, karena menyebut data yang salah"]]},

{t:"Teks 2: Ceramah Pengurus OSIS tentang Berita Bohong",p:[
"(1) Selamat pagi, hadirin yang saya hormati. Pada kesempatan ini kami dari pengurus OSIS ingin mengajak kita semua membahas bahaya berita bohong di media sosial.",
"(2) Berita bohong menyebar lebih cepat daripada klarifikasi. Banyak orang membagikan kabar tanpa membacanya sampai selesai. Akibatnya, pesan yang belum tentu benar dapat diterima sebagai kenyataan oleh ratusan orang dalam hitungan menit.",
"(3) Lalu, apa yang harus kita lakukan? Pertama, periksa sumbernya. Kedua, bandingkan dengan media lain. Ketiga, tahan jari kita sebelum membagikan. Menurut saya, kebiasaan tiga langkah itu dapat mengurangi penyebaran hoaks secara signifikan.",
"(4) Beberapa teman mengatakan bahwa media sosial itu sumber kebohongan terbesar, sehingga sebaiknya semua siswa dilarang memakainya. Padahal, media sosial juga dipakai untuk belajar, berjualan, dan berkarya.",
"(5) Dengan demikian, yang perlu kita perbaiki adalah cara kita menyikapi informasi, bukan menghapus media sosialnya. Marilah kita menjadi pembaca yang cerdas."],
q:[
["e","Kata 'kami' pada paragraf (1) merujuk pada ...","penceramah dan kelompoknya (pengurus OSIS) tanpa melibatkan pendengar","penceramah dan seluruh pendengar","pendengar saja","penceramah seorang diri","seluruh pengguna media sosial"],
["e","Ungkapan yang menandai opini penceramah pada paragraf (3) adalah ...","Menurut saya","Pertama, periksa sumbernya","Kedua, bandingkan dengan media lain","Lalu, apa yang harus kita lakukan","Ketiga, tahan jari kita"],
["m","Kalimat 'Lalu, apa yang harus kita lakukan?' termasuk ...","kalimat retoris yang dipakai untuk menarik perhatian dan mengantar penjelasan","kalimat tanya yang menuntut jawaban tertulis dari pendengar","kalimat perintah yang bersifat larangan","kalimat berita yang berisi fakta","kalimat seru yang mengungkapkan kemarahan"],
["m","Fungsi konjungsi 'Dengan demikian' pada paragraf (5) adalah ...","menyimpulkan uraian sebelumnya","menyatakan pertentangan","menyatakan syarat","menambahkan keterangan","menyatakan urutan waktu"],
["h","Klaim sebagian teman bahwa 'media sosial itu sumber kebohongan terbesar' paling tepat dinilai ...","tidak objektif dan tidak didukung data, karena hanya melihat sisi negatif","sangat akurat, karena sesuai dengan fakta penyebaran berita bohong","sangat kredibel, karena disampaikan oleh banyak orang","lengkap, karena membahas semua manfaat media sosial","sesuai tujuan, karena mengajak siswa berhenti membaca berita"]]},

{t:"Teks 3: Dua Teks tentang Membaca Buku",p:[
"Teks A (ceramah): Hadirin yang berbahagia, marilah kita bertanya pada diri sendiri: kapan terakhir kali kita menamatkan sebuah buku? Saya yakin, buku yang kita baca hari ini akan menentukan siapa kita lima tahun lagi. Oleh karena itu, ayo kita sisihkan lima belas menit setiap hari untuk membaca.",
"Teks B (artikel opini): Rendahnya minat baca remaja Indonesia tercermin dalam laporan PISA yang menempatkan kemampuan membaca siswa di bawah rata-rata negara OECD. Fakta ini menunjukkan bahwa budaya baca belum menjadi kebiasaan. Karena itu, sekolah perlu menyediakan waktu membaca rutin dan perpustakaan yang menarik."],
q:[
["e","Persamaan Teks A dan Teks B adalah ...","sama-sama bersifat persuasif karena mengajak agar gemar membaca","sama-sama disampaikan secara lisan","sama-sama menyapa langsung pendengar","sama-sama memakai data resmi","sama-sama ditulis tanpa struktur"],
["e","Ciri yang hanya tampak pada Teks A adalah ...","sapaan 'hadirin' dan kata ganti 'kita'","rujukan pada laporan PISA","kalimat argumentatif berbasis data","penyebutan tokoh ahli","paparan kebijakan sekolah"],
["m","Kelebihan Teks B dibandingkan Teks A dalam hal kualitas informasi adalah ...","memuat rujukan data yang dapat diverifikasi","menyentuh emosi melalui intonasi","memungkinkan tanya jawab langsung","memakai sapaan yang akrab","menggunakan kalimat ajakan yang kuat"],
["m","Kekurangan Teks A bila dijadikan rujukan informasi adalah ...","keyakinan penceramah tidak disertai data atau sumber yang jelas","tidak memiliki ajakan kepada pendengar","tidak membahas topik membaca","terlalu banyak memakai istilah teknis","strukturnya tidak memiliki pembuka"],
["h","Seorang siswa akan menyusun pidato yang menyentuh emosi sekaligus meyakinkan dengan bukti. Strategi yang paling tepat adalah ...","menggabungkan sapaan dan ajakan seperti Teks A dengan data bersumber seperti Teks B","memakai sapaan saja tanpa data agar singkat","memakai data saja tanpa sapaan agar terkesan resmi","menyalin Teks B secara utuh","menambahkan keyakinan pribadi sebanyak mungkin"]]},

{t:"Teks 4: Ceramah Palang Merah Remaja",p:[
"(1) Hadirin yang saya hormati, izinkan saya memperkenalkan diri. Saya Dina, perwakilan Palang Merah Remaja.",
"(2) Pada musim pancaroba, daya tahan tubuh atau imunitas kita mudah menurun. Oleh sebab itu, kita perlu mengonsumsi gizi seimbang dan cukup tidur.",
"(3) Marilah kita membiasakan mencuci tangan. Hendaknya setiap kelas menyediakan sabun. Mari kita jaga kesehatan bersama-sama agar kegiatan belajar tidak terganggu."],
q:[
["e","Kata 'hadirin' pada paragraf (1) termasuk ...","sapaan kepada pendengar (orang kedua)","kata ganti orang pertama tunggal","kata ganti orang pertama jamak","kata teknis kesehatan","kata persuasif berupa anjuran"],
["e","Kata teknis bertema kesehatan dalam teks adalah ...","imunitas dan gizi seimbang","pancaroba dan sabun","hadirin dan saya","marilah dan hendaknya","kelas dan belajar"],
["e","Kata persuasif berupa ajakan pada paragraf (3) adalah ...","marilah dan mari kita","hadirin dan saya","imunitas dan gizi","pancaroba dan kegiatan","terganggu dan sabun"],
["m","Kata 'kita' pada 'daya tahan tubuh atau imunitas kita' mencakup ...","penceramah dan seluruh pendengar","penceramah saja","pendengar saja","penceramah dan kelompoknya tanpa pendengar","Palang Merah Remaja saja"],
["m","Kata 'hendaknya' pada paragraf (3) termasuk kata persuasif berupa ...","anjuran","ajakan","larangan","pertanyaan","seruan"]]},

{t:"Teks 5: Ceramah Literasi Keuangan",p:[
"(1) Bapak dan Ibu guru serta adik-adik yang saya banggakan, uang itu ibarat air: jika tidak dialirkan dengan baik, ia akan menguap tanpa bekas.",
"(2) Siapa di antara kita yang tidak ingin punya tabungan? Namun, apabila setiap hari kita jajan tanpa batas, bagaimana tabungan itu dapat terbentuk?",
"(3) Menabung itu penting, penting untuk masa depan, penting untuk keluarga, dan penting untuk cita-cita kita.",
"(4) Gak usah nunggu kaya buat nabung, dong. Mulai aja dari sepuluh ribu per minggu.",
"(5) Agar supaya tabungan kita tumbuh, mari kita catat pengeluaran setiap hari."],
q:[
["e","Majas pada kalimat 'uang itu ibarat air' di paragraf (1) adalah ...","perumpamaan (simile)","hiperbola","personifikasi","repetisi","klimaks"],
["e","Kalimat 'Siapa di antara kita yang tidak ingin punya tabungan?' merupakan ...","kalimat retoris","kalimat perintah","kalimat larangan","kalimat berita","kalimat sapaan"],
["m","Pengulangan kata 'penting' pada paragraf (3) merupakan majas ...","repetisi","metafora","hiperbola","personifikasi","perumpamaan"],
["m","Bentuk baku dari 'Gak usah nunggu kaya buat nabung, dong.' adalah ...","Tidak usah menunggu kaya untuk menabung.","Gak usah menunggu kaya untuk menabung dong.","Tidak usah nunggu kaya buat menabung.","Tak usah nunggu kaya untuk nabung, deh.","Nggak usah tunggu kaya buat menabung."],
["h","Perbaikan paling tepat untuk kalimat paragraf (5) agar menjadi kalimat efektif adalah ...","Agar tabungan kita tumbuh, mari kita catat pengeluaran setiap hari (kata 'supaya' dihapus karena bermakna sama dengan 'agar').","mengganti 'mari' dengan 'ayo' saja","menambahkan 'demi untuk' di depan kalimat","mengubah kalimat menjadi kalimat tanya","menghapus kata 'tabungan'"]]},

{t:"Teks 6: Ceramah Kebersihan Kelas",p:[
"(1) Yang saya hormati Bapak dan Ibu guru serta teman-teman sekalian. Alhamdulillah, kita masih diberi kesempatan untuk berkumpul. Pada kesempatan ini saya akan berbicara tentang kebersihan kelas.",
"(2) Kelas yang bersih membuat kita nyaman belajar. Ruangan yang rapi membuat pikiran lebih tenang. Meja yang tertata membuat kita mudah menemukan buku. Karena itu, kebersihan kelas sangat memengaruhi kenyamanan belajar.",
"(3) Banyak siswa mengabaikan jadwal piket. Sebagian meninggalkan sampah di laci. Sebagian lain enggan menyapu karena merasa itu tugas petugas kebersihan. Inilah sebabnya kelas sering kotor.",
"(4) Kesimpulannya, kebersihan kelas adalah tanggung jawab kita bersama. Semoga kita semua dapat menjaganya. Terima kasih atas perhatian Bapak, Ibu, dan teman-teman. Wassalamualaikum warahmatullahi wabarakatuh."],
q:[
["e","Paragraf (1) pada ceramah tersebut berfungsi sebagai ...","pembukaan yang memuat sapaan, syukur, dan pengantar topik","isi yang memuat gagasan pokok","penutup yang memuat simpulan","bagian data pendukung","bagian ajakan akhir"],
["m","Pola paragraf (2) berdasarkan letak gagasan pokoknya adalah ...","campuran","deduktif","induktif","naratif","tidak memiliki gagasan pokok"],
["m","Pola paragraf (3) adalah ...","induktif, karena gagasan pokok ada di akhir paragraf","deduktif, karena gagasan pokok ada di awal paragraf","campuran, karena gagasan pokok ada di awal dan akhir","deduktif, karena didahului kalimat utama","induktif, karena tidak memiliki gagasan pendukung"],
["e","Gagasan pendukung pada paragraf (2) adalah ...","ruangan yang rapi membuat pikiran lebih tenang","kelas sering kotor","jadwal piket diabaikan","kebersihan kelas adalah tanggung jawab bersama","penceramah bersyukur atas pertemuan"],
["m","Kalimat 'Sebagian lain enggan menyapu karena merasa itu tugas petugas kebersihan' pada paragraf (3) berfungsi sebagai ...","gagasan pendukung berupa alasan penyebab kelas kotor","gagasan pokok paragraf","salam pembuka","simpulan ceramah","ajakan bertindak"]]},

{t:"Teks 7: Ceramah Seorang Konten Kreator tentang Investasi",p:[
"(1) Salam sejahtera, hadirin sekalian. Hari ini saya akan menjelaskan mengapa remaja harus berinvestasi saham sekarang juga.",
"(2) Saya adalah seorang konten kreator keuangan dengan satu juta pengikut. Saya yakin saham pasti selalu naik dalam jangka panjang, jadi tidak ada risiko sama sekali.",
"(3) Teman saya membeli saham sebuah perusahaan minggu lalu dan kini untungnya dua kali lipat. Buktinya jelas bahwa semua orang bisa kaya dalam seminggu.",
"(4) Selain itu, perlu diketahui bahwa Otoritas Jasa Keuangan menyediakan layanan edukasi dan pengaduan bagi investor pemula, dan produk investasi yang legal terdaftar di lembaga resmi.",
"(5) Maka, jangan tunggu lagi. Segera beli saham yang saya rekomendasikan."],
q:[
["e","Pernyataan 'saham pasti selalu naik, jadi tidak ada risiko sama sekali' tidak tepat karena ...","semua bentuk investasi mengandung risiko sehingga klaim itu tidak akurat","penceramah memakai sapaan formal","kalimat itu terlalu pendek","penceramah belum mengucapkan salam","saham hanya dijual pada akhir pekan"],
["m","Bukti berupa keuntungan teman penceramah pada paragraf (3) lemah karena ...","hanya berasal dari satu kasus pribadi lalu digeneralisasi untuk semua orang","teman penceramah tidak boleh membeli saham","keuntungan dua kali lipat tidak mungkin terjadi","ditulis tanpa memakai konjungsi","disampaikan pada paragraf ketiga"],
["m","Informasi yang paling kredibel dan dapat diverifikasi terdapat pada paragraf ...","(4), karena merujuk pada lembaga resmi (OJK)","(2), karena penceramah memiliki banyak pengikut","(3), karena berdasarkan pengalaman teman","(5), karena berisi ajakan membeli","(1), karena memuat salam"],
["h","Kelemahan paling serius dari sisi objektivitas ceramah tersebut adalah ...","mendorong pendengar membeli saham yang direkomendasikannya tanpa menyebut risiko dan kemungkinan kepentingan pribadi","tidak memakai kata ganti orang pertama","menyebut nama lembaga resmi","memakai salam pembuka yang sopan","menyampaikan pengalaman pribadi secara singkat"],
["h","Rekomendasi perbaikan yang paling tepat bagi penceramah adalah ...","menyertakan data resmi, menjelaskan risiko, dan membedakan fakta dari opini","memperbanyak ajakan agar pendengar segera membeli","menghapus semua data supaya lebih singkat","menambah jumlah pengikut sebelum berceramah","mengganti topik menjadi hiburan"]]},

{t:"Teks 8: Ceramah Persiapan Praktik Kerja Lapangan",p:[
"(1) Hadirin yang saya hormati, tahun ini kita akan melaksanakan Praktik Kerja Lapangan. Tujuan ceramah ini adalah mengajak kita semua menyiapkan diri agar disiplin selama PKL.",
"(2) Disiplin waktu adalah wajah pertama seorang pekerja. Pekerja yang datang tepat waktu menunjukkan bahwa ia menghargai orang lain. Dunia usaha menilai ketepatan waktu sebelum menilai keterampilan.",
"(3) Omong-omong, kantin sekolah kita sekarang menjual banyak jenis makanan baru, mulai dari mi ayam sampai es buah. Harganya terjangkau dan rasanya enak.",
"(4) Disiplin juga tampak pada cara kita berpakaian dan menaati prosedur kerja. Seragam yang rapi dan kepatuhan pada SOP mencerminkan tanggung jawab. Jadi, mari kita siapkan diri sejak sekarang."],
q:[
["e","Tujuan ceramah tersebut dinyatakan pada paragraf (1), yaitu ...","mengajak siswa menyiapkan diri agar disiplin selama PKL","memperkenalkan menu kantin baru","mengumumkan jadwal ujian","mengkritik pekerja yang terlambat","menjelaskan cara membuat SOP"],
["e","Gagasan pokok paragraf (2) adalah ...","disiplin waktu adalah wajah pertama seorang pekerja","dunia usaha menilai keterampilan lebih dulu","pekerja sering terlambat","seragam harus rapi","PKL dilaksanakan tahun ini"],
["m","Paragraf yang tidak sesuai dengan tujuan ceramah (kriteria kesesuaian tujuan) adalah ...","paragraf (3), karena membahas kantin sekolah","paragraf (2), karena membahas ketepatan waktu","paragraf (4), karena membahas seragam dan SOP","paragraf (1), karena memuat tujuan","tidak ada, semua paragraf sesuai"],
["m","Gagasan pendukung paragraf (4) adalah ...","seragam yang rapi dan kepatuhan pada SOP mencerminkan tanggung jawab","disiplin adalah wajah pertama pekerja","kantin menjual es buah","ketepatan waktu dinilai lebih dulu","PKL dilaksanakan tahun ini"],
["h","Kalimat 'Dunia usaha menilai ketepatan waktu sebelum menilai keterampilan' paling tepat dievaluasi sebagai ...","klaim yang perlu diverifikasi dengan data, misalnya survei industri","fakta mutlak karena diucapkan penceramah","opini yang tidak boleh dipakai dalam ceramah","gagasan pokok seluruh ceramah","kalimat retoris"]]},

{t:"Teks 9: Dua Teks tentang Menjaga Sungai",p:[
"Teks A (ceramah): Bapak dan Ibu yang dimuliakan, sungai adalah anugerah. Marilah kita jaga, jangan buang sampah ke dalamnya! Sungai yang bersih akan menghidupi anak cucu kita.",
"Teks B (artikel opini): Menurut data instansi lingkungan hidup, pencemaran sungai di wilayah perkotaan meningkat dalam lima tahun terakhir. Karena itu, pemerintah daerah perlu memperketat pengawasan pembuangan limbah dan menyediakan tempat sampah terpilah."],
q:[
["e","Perbedaan media penyampaian Teks A dan Teks B adalah ...","Teks A disampaikan lisan, Teks B berupa tulisan","Teks A tertulis, Teks B lisan","keduanya disampaikan lisan","keduanya berupa tulisan","Teks A direkam, Teks B disiarkan"],
["e","Ciri teks artikel opini yang tampak pada Teks B adalah ...","memakai rujukan data dari instansi resmi dan bahasa yang lebih objektif","menyapa pembaca dengan 'Bapak dan Ibu'","memakai kata ganti 'kita' berulang","memakai kalimat seru","menggunakan salam pembuka"],
["m","Kelebihan Teks A dibandingkan Teks B adalah ...","mampu menyentuh emosi pendengar secara langsung lewat sapaan, intonasi, dan ekspresi","dapat dibaca ulang kapan saja","memuat data resmi yang rinci","tersebar luas melalui media daring","bersifat sangat objektif"],
["m","Kekurangan Teks B dibandingkan Teks A adalah ...","tidak ada interaksi langsung sehingga kurang menyentuh emosi pembaca","tidak memuat data","tidak dapat dibaca ulang","tidak memiliki struktur","tidak membahas isu pencemaran"],
["h","Simpulan perbandingan yang paling tepat dan berbasis bukti dari kedua teks adalah ...","Teks A kuat pada kedekatan emosional lewat sapaan dan ajakan, sedangkan Teks B kuat pada argumen berbasis data yang dapat diverifikasi","Teks A lebih baik karena tidak memerlukan data apa pun","Teks B lebih baik karena memakai sapaan yang akrab","kedua teks sama persis karena membahas sungai","kedua teks tidak dapat dibandingkan karena topiknya berbeda"]]},

{t:"Teks 10: Kutipan Ceramah tentang Bahasa Baku di Dunia Kerja",p:[
"(1) Yang terhormat Bapak Kepala Sekolah, Bapak dan Ibu guru, serta rekan-rekan siswa.",
"(2) Kami meyakini bahwa kemampuan berbahasa yang baik membuka banyak pintu pekerjaan.",
"(3) Apabila kita terbiasa berbahasa baku, wawancara kerja akan terasa lebih mudah.",
"(4) Namun, banyak siswa masih memakai kata kayak dan bikin dalam surat lamaran.",
"(5) Sebaiknya kita membiasakan diri menggunakan kata seperti dan membuat."],
q:[
["e","Fragmen (1) menunjukkan kaidah kebahasaan ...","kata sapaan yang disusun dari yang paling dihormati","majas perumpamaan","kalimat retoris","kata kerja mental","kalimat efektif"],
["e","Kata kerja mental pada fragmen (2) adalah ...","meyakini","membuka","berbahasa","kemampuan","pekerjaan"],
["m","Konjungsi 'apabila' pada fragmen (3) menyatakan hubungan ...","syarat (pengandaian)","sebab","pertentangan","simpulan","urutan"],
["m","Konjungsi 'namun' pada fragmen (4) menyatakan ...","pertentangan antara harapan pada (3) dan kenyataan","sebab-akibat","simpulan akhir","penambahan","syarat"],
["h","Pasangan fragmen dan kaidah kebahasaan berikut yang tepat adalah ...","(2) kata kerja mental penanda opini; (3) konjungsi syarat; (4) kata tidak baku; (5) kalimat persuasif tingkat halus","(2) kalimat retoris; (3) konjungsi pertentangan; (4) kata teknis; (5) kalimat larangan","(2) majas hiperbola; (3) konjungsi simpulan; (4) kata baku; (5) kalimat berita","(2) kata ganti orang kedua; (3) konjungsi sebab; (4) kata baku; (5) kalimat tanya","(2) kata sapaan; (3) konjungsi urutan; (4) kata teknis; (5) kalimat seru"]]}
];

function $(id){return document.getElementById(id);}
function esc(s){return String(s).replace(/&amp;/g,"&amp;amp;").replace(/&lt;/g,"&amp;lt;").replace(/&gt;/g,"&amp;gt;").replace(/"/g,"&amp;quot;");}
function shuffle(a){for(var i=a.length-1;i&gt;0;i--){var j=Math.floor(Math.random()*(i+1));var t=a[i];a[i]=a[j];a[j]=t;}return a;}

/* ---------- penyimpanan ---------- */
function lsGet(k){try{var v=localStorage.getItem(k);return v?JSON.parse(v):null;}catch(e){return null;}}
function lsSet(k,o){try{localStorage.setItem(k,JSON.stringify(o));}catch(e){}}
function sGet(k){
  try{ if(window.storage&amp;&amp;window.storage.get){
    return window.storage.get(k,true).then(function(r){return (r&amp;&amp;r.value)?JSON.parse(r.value):lsGet(k);}).catch(function(){return lsGet(k);});
  }}catch(e){}
  return Promise.resolve(lsGet(k));
}
function sSet(k,o){
  lsSet(k,o);
  try{ if(window.storage&amp;&amp;window.storage.set){ return window.storage.set(k,JSON.stringify(o),true).catch(function(){}); } }catch(e){}
  return Promise.resolve();
}
function keyOf(kelas,absen){return "kqc:"+kelas.toLowerCase().replace(/\s+/g,"")+":"+absen;}

/* ---------- kuis ---------- */
function buildQuiz(){
  var gs=shuffle(G.slice()), out=[];
  gs.forEach(function(g){
    var qs=shuffle(g.q.slice()).map(function(q){
      var opts=shuffle([0,1,2,3,4].map(function(i){return {t:q[2+i],c:i===0};}));
      var ci=0; opts.forEach(function(o,i){if(o.c)ci=i;});
      return {lvl:q[0],q:q[1],o:opts,ci:ci};
    });
    out.push({g:g,items:qs});
  });
  return out;
}

var rec=null, quiz=null, ans=[], viol=0, active=false, attemptNo=1, startT=0, lastV=0, stage=null, keyStr="";

function renderStage(){
  var n=0,h='&lt;div class="top"&gt;&lt;b&gt;'+esc(MATERI)+'&lt;/b&gt;&lt;span&gt;&lt;span class="pill"&gt;Percobaan '+attemptNo+' dari '+MAXA+'&lt;/span&gt; &lt;span class="pill" id="kqCnt"&gt;Terjawab 0/50&lt;/span&gt; &lt;span class="pill" id="kqViol"&gt;Pelanggaran 0/'+MAXV+'&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="bar"&gt;&lt;i id="kqBar"&gt;&lt;/i&gt;&lt;/div&gt;&lt;div class="wrap"&gt;';
  h+='&lt;div class="stim" style="background:#eff6ff;border-color:#60a5fa"&gt;&lt;p&gt;&lt;b&gt;'+esc(rec.nama)+'&lt;/b&gt; | Kelas '+esc(rec.kelas)+' | No. Absen '+esc(rec.absen)+'&lt;/p&gt;&lt;p style="margin:0"&gt;Pilih satu jawaban paling tepat untuk setiap soal. Jangan berpindah tab atau aplikasi sampai jawaban dikirim.&lt;/p&gt;&lt;/div&gt;';
  quiz.forEach(function(blk){
    h+='&lt;div class="stim"&gt;&lt;h4&gt;'+esc(blk.g.t)+'&lt;/h4&gt;';
    blk.g.p.forEach(function(p){h+='&lt;p&gt;'+esc(p)+'&lt;/p&gt;';});
    h+='&lt;/div&gt;';
    blk.items.forEach(function(it){
      h+='&lt;div class="q"&gt;&lt;div class="qt"&gt;'+(n+1)+'. '+esc(it.q)+'&lt;/div&gt;';
      it.o.forEach(function(o,i){
        h+='&lt;label class="o" id="kqo'+n+'_'+i+'"&gt;&lt;input type="radio" name="kqq'+n+'" value="'+i+'"&gt;&lt;b&gt;'+LET[i]+'.&lt;/b&gt;&lt;span&gt;'+esc(o.t)+'&lt;/span&gt;&lt;/label&gt;';
      });
      h+='&lt;/div&gt;'; n++;
    });
  });
  h+='&lt;button class="b" id="kqSubmit" type="button"&gt;Kirim Jawaban&lt;/button&gt;&lt;/div&gt;';
  stage.innerHTML=h;
  stage.addEventListener("change",function(e){
    var t=e.target; if(!t||t.type!=="radio")return;
    var m=/^kqq(\d+)$/.exec(t.name); if(!m)return;
    var qi=+m[1]; ans[qi]=+t.value;
    for(var i=0;i&lt;5;i++){var el=$("kqo"+qi+"_"+i); if(el)el.className="o"+(i===ans[qi]?" sel":"");}
    var c=0; for(var k=0;k&lt;50;k++){if(ans[k]!==undefined)c++;}
    $("kqCnt").textContent="Terjawab "+c+"/50"; $("kqBar").style.width=(c*2)+"%";
  });
  $("kqSubmit").onclick=function(){submitAttempt(false);};
}

function modal(title,text){
  var old=$("kqModal"); if(old)old.parentNode.removeChild(old);
  var m=document.createElement("div"); m.id="kqModal";
  m.innerHTML='&lt;div&gt;&lt;h3&gt;'+esc(title)+'&lt;/h3&gt;&lt;p&gt;'+esc(text)+'&lt;/p&gt;&lt;button type="button" id="kqModalOk"&gt;Mengerti, kembali mengerjakan&lt;/button&gt;&lt;/div&gt;';
  document.body.appendChild(m);
  $("kqModalOk").onclick=function(){m.parentNode.removeChild(m); goFull();};
}
function goFull(){try{var e=stage||document.documentElement; var f=e.requestFullscreen||e.webkitRequestFullscreen; if(f&amp;&amp;!document.fullscreenElement)f.call(e);}catch(x){}}
function exitFull(){try{if(document.fullscreenElement&amp;&amp;document.exitFullscreen)document.exitFullscreen();}catch(x){}}

function violate(why){
  if(!active)return;
  var now=Date.now(); if(now-lastV&lt;1500)return; lastV=now;
  viol++;
  var el=$("kqViol"); if(el){el.textContent="Pelanggaran "+viol+"/"+MAXV; el.className="pill v";}
  if(viol&gt;=MAXV){ submitAttempt(true); return; }
  modal("Peringatan "+viol+" dari "+MAXV,"Terdeteksi: "+why+". Jangan berpindah halaman atau aplikasi. Pada pelanggaran ke-"+MAXV+", jawaban Anda otomatis dikirim dan dicatat ke guru.");
}
function onVis(){if(document.hidden)violate("berpindah tab atau aplikasi");}
function onBlur(){violate("meninggalkan halaman soal");}
function onPop(){ if(active){history.pushState({kq:1},"",location.href); violate("menekan tombol kembali");} }
function onUnload(e){ if(active){e.preventDefault(); e.returnValue="Jawaban belum dikirim."; return "Jawaban belum dikirim.";} }
function onClickCap(e){ if(!active)return; var a=e.target&amp;&amp;e.target.closest?e.target.closest("a"):null; if(a&amp;&amp;!(stage&amp;&amp;stage.contains(a))){e.preventDefault();e.stopPropagation();} }
function onCtx(e){if(active)e.preventDefault();}
function onCopy(e){if(active)e.preventDefault();}
function onKey(e){
  if(!active)return;
  var k=(e.key||"").toLowerCase();
  if(e.key==="F12"||((e.ctrlKey||e.metaKey)&amp;&amp;(k==="c"||k==="x"||k==="u"||k==="s"||k==="p"||k==="a"||k==="f"))||((e.ctrlKey||e.metaKey)&amp;&amp;e.shiftKey&amp;&amp;(k==="i"||k==="j"||k==="c"))||(e.altKey&amp;&amp;(k==="arrowleft"||k==="arrowright"))){e.preventDefault();e.stopPropagation();}
}
function lock(on){
  var f=on?"addEventListener":"removeEventListener";
  document[f]("visibilitychange",onVis); window[f]("blur",onBlur); window[f]("popstate",onPop);
  window[f]("beforeunload",onUnload); document[f]("click",onClickCap,true);
  document[f]("contextmenu",onCtx); document[f]("copy",onCopy); document[f]("cut",onCopy); document[f]("keydown",onKey,true);
  if(on){ document.body.style.overflow="hidden"; try{history.pushState({kq:1},"",location.href);}catch(e){} }
  else { document.body.style.overflow=""; }
}

function beginAttempt(){
  attemptNo=rec.attempts.length+1; quiz=buildQuiz(); ans=[]; viol=0; lastV=0; startT=Date.now();
  stage=document.createElement("div"); stage.id="kqStage"; document.body.appendChild(stage);
  renderStage(); active=true; lock(true); goFull(); stage.scrollTop=0;
}

function submitAttempt(auto){
  if(!active)return;
  var un=0,i; for(i=0;i&lt;50;i++){if(ans[i]===undefined)un++;}
  if(!auto&amp;&amp;un&gt;0&amp;&amp;!window.confirm("Masih ada "+un+" soal belum dijawab (dihitung salah). Kirim sekarang?"))return;
  active=false; lock(false); exitFull();
  var mo=$("kqModal"); if(mo)mo.parentNode.removeChild(mo);
  var det=[],benar=0,n=0;
  quiz.forEach(function(blk){blk.items.forEach(function(it){
    var a=ans[n], ok=(a===it.ci); if(ok)benar++;
    det.push({l:(a===undefined?"-":LET[a]),k:LET[it.ci],ok:ok,v:it.lvl}); n++;
  });});
  var score=Math.round(benar*100/50);
  var at={score:score,benar:benar,t:new Date().toISOString(),viol:viol,auto:!!auto,det:det};
  rec.attempts.push(at);
  var fin=null;
  if(score&gt;=KKM){ fin={score:score,source:"kkm",idx:rec.attempts.length-1}; }
  else if(rec.attempts.length&gt;=MAXA){
    var bi=0; rec.attempts.forEach(function(a,k){if(a.score&gt;rec.attempts[bi].score)bi=k;});
    fin={score:rec.attempts[bi].score,source:"tertinggi",idx:bi};
  }
  if(fin){ rec.final=fin; sendGas(); }
  sSet(keyStr,rec);
  showResult(at,fin,auto);
}

function sendGas(){
  if(!GAS_URL||!rec.final)return;
  var f=rec.final, fa=rec.attempts[f.idx], p={
    waktu:new Date().toLocaleString("id-ID"), nama:rec.nama, kelas:rec.kelas, absen:rec.absen, materi:MATERI,
    nilaiAkhir:f.score, skorPG:f.score, skorEsai:"-", benarPG:fa.benar, totalPG:50,
    sumber:(f.source==="kkm"?"Mencapai KKM":"Nilai tertinggi"), percobaan:rec.attempts.length,
    skor1:rec.attempts[0]?rec.attempts[0].score:"", skor2:rec.attempts[1]?rec.attempts[1].score:"", skor3:rec.attempts[2]?rec.attempts[2].score:"",
    pelanggaran:rec.attempts.reduce(function(s,a){return s+a.viol;},0),
    jawaban:fa.det.map(function(d,i){return (i+1)+":"+d.l;}).join(",")
  };
  try{fetch(GAS_URL,{method:"POST",mode:"no-cors",body:new URLSearchParams(p)}).catch(function(){});}catch(e){}
}

function showResult(at,fin,auto){
  var pass=at.score&gt;=KKM, left=MAXA-rec.attempts.length;
  var h='&lt;div class="top"&gt;&lt;b&gt;'+esc(MATERI)+'&lt;/b&gt;&lt;span class="pill"&gt;Hasil percobaan '+rec.attempts.length+'&lt;/span&gt;&lt;/div&gt;&lt;div class="wrap"&gt;&lt;div class="res"&gt;';
  if(auto)h+='&lt;p class="no"&gt;&lt;b&gt;Jawaban dikirim otomatis karena pelanggaran keamanan mencapai batas.&lt;/b&gt;&lt;/p&gt;';
  h+='&lt;p&gt;Skor percobaan ini:&lt;/p&gt;&lt;div class="big '+(pass?'ok':'no')+'"&gt;'+at.score+' / 100&lt;/div&gt;';
  h+='&lt;p&gt;Benar '+at.benar+' dari 50 soal. '+(pass?'Mencapai KKM ('+KKM+').':'Belum mencapai KKM ('+KKM+').')+'&lt;/p&gt;';
  if(fin){
    h+='&lt;p&gt;&lt;b&gt;Nilai akhir yang dikirim dan disimpan: '+fin.score+'&lt;/b&gt; ('+(fin.source==="kkm"?'mencapai KKM':'nilai tertinggi dari '+rec.attempts.length+' percobaan')+').&lt;/p&gt;';
    h+='&lt;p&gt;Silakan unduh bukti pengerjaan, cetak, dan serahkan kepada guru.&lt;/p&gt;';
    h+='&lt;button class="b" id="kqPdf" type="button"&gt;Unduh / Cetak Bukti (PDF)&lt;/button&gt;';
  } else {
    h+='&lt;p&gt;Sisa kesempatan: &lt;b&gt;'+left+'&lt;/b&gt;. Nilai belum dikirim; nilai dikirim jika Anda mencapai '+KKM+' atau setelah percobaan ke-'+MAXA+'.&lt;/p&gt;';
    h+='&lt;button class="b" id="kqAgain" type="button"&gt;Coba Lagi&lt;/button&gt;';
  }
  h+='&lt;button class="b g" id="kqClose" type="button"&gt;Tutup&lt;/button&gt;';
  if(fin){
    h+='&lt;div class="rv"&gt;&lt;b&gt;Rincian jawaban (percobaan terbaik):&lt;/b&gt;';
    rec.attempts[fin.idx].det.forEach(function(d,i){h+='&lt;div&gt;No. '+(i+1)+': jawaban '+d.l+', kunci '+d.k+' - '+(d.ok?'&lt;span class="ok"&gt;benar&lt;/span&gt;':'&lt;span class="no"&gt;salah&lt;/span&gt;')+'&lt;/div&gt;';});
    h+='&lt;/div&gt;';
  }
  h+='&lt;/div&gt;&lt;/div&gt;';
  stage.innerHTML=h; stage.scrollTop=0;
  if($("kqAgain"))$("kqAgain").onclick=function(){closeStage();beginAttempt();};
  if($("kqPdf"))$("kqPdf").onclick=printProof;
  $("kqClose").onclick=function(){closeStage();showStatus();};
}
function closeStage(){ if(stage&amp;&amp;stage.parentNode)stage.parentNode.removeChild(stage); stage=null; }

/* ---------- bukti cetak F4 ---------- */
function printProof(){
  if(!rec||!rec.final)return;
  var f=rec.final, fa=rec.attempts[f.idx], old=$("kqPrint"); if(old)old.parentNode.removeChild(old);
  var d=document.createElement("div"); d.id="kqPrint";
  var h='&lt;h1&gt;BUKTI PENGERJAAN LATIHAN SOAL TIPE AKM&lt;/h1&gt;&lt;p class="sub"&gt;'+esc(MATERI)+' - Bahasa Indonesia Kelas XI SMK&lt;/p&gt;';
  h+='&lt;table&gt;&lt;tr&gt;&lt;td style="width:28%"&gt;Nama&lt;/td&gt;&lt;td&gt;'+esc(rec.nama)+'&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Kelas&lt;/td&gt;&lt;td&gt;'+esc(rec.kelas)+'&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;No. Absen&lt;/td&gt;&lt;td&gt;'+esc(rec.absen)+'&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Tanggal cetak&lt;/td&gt;&lt;td&gt;'+esc(new Date().toLocaleString("id-ID"))+'&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;';
  h+='&lt;h2&gt;Riwayat percobaan&lt;/h2&gt;&lt;table&gt;&lt;tr&gt;&lt;th&gt;Percobaan&lt;/th&gt;&lt;th&gt;Waktu&lt;/th&gt;&lt;th&gt;Benar&lt;/th&gt;&lt;th&gt;Skor&lt;/th&gt;&lt;th&gt;Pelanggaran&lt;/th&gt;&lt;/tr&gt;';
  rec.attempts.forEach(function(a,i){h+='&lt;tr&gt;&lt;td&gt;'+(i+1)+(i===f.idx?' (dipakai)':'')+'&lt;/td&gt;&lt;td&gt;'+esc(new Date(a.t).toLocaleString("id-ID"))+'&lt;/td&gt;&lt;td&gt;'+a.benar+'/50&lt;/td&gt;&lt;td&gt;'+a.score+'&lt;/td&gt;&lt;td&gt;'+a.viol+'&lt;/td&gt;&lt;/tr&gt;';});
  h+='&lt;/table&gt;&lt;p&gt;&lt;b&gt;NILAI AKHIR: '+f.score+'&lt;/b&gt; (KKM '+KKM+') - '+(f.score&gt;=KKM?'Tuntas':'Belum tuntas')+'. Sumber nilai: '+(f.source==="kkm"?'percobaan yang mencapai KKM':'nilai tertinggi dari 3 percobaan')+'.&lt;/p&gt;';
  h+='&lt;h2&gt;Jawaban pada percobaan yang dipakai&lt;/h2&gt;&lt;div class="two"&gt;';
  for(var c=0;c&lt;2;c++){
    h+='&lt;table&gt;&lt;tr&gt;&lt;th&gt;No&lt;/th&gt;&lt;th&gt;Jawaban&lt;/th&gt;&lt;th&gt;Kunci&lt;/th&gt;&lt;th&gt;Hasil&lt;/th&gt;&lt;/tr&gt;';
    for(var i=c*25;i&lt;c*25+25;i++){var x=fa.det[i]; h+='&lt;tr&gt;&lt;td&gt;'+(i+1)+'&lt;/td&gt;&lt;td&gt;'+x.l+'&lt;/td&gt;&lt;td&gt;'+x.k+'&lt;/td&gt;&lt;td&gt;'+(x.ok?'Benar':'Salah')+'&lt;/td&gt;&lt;/tr&gt;';}
    h+='&lt;/table&gt;';
  }
  h+='&lt;/div&gt;&lt;p style="font-size:9pt"&gt;Catatan: urutan soal dan pilihan jawaban diacak untuk setiap siswa, sehingga nomor di atas mengikuti urutan tampilan pada layar siswa.&lt;/p&gt;';
  h+='&lt;div class="sig"&gt;&lt;div&gt;Siswa,&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;('+esc(rec.nama)+')&lt;/div&gt;&lt;div&gt;Guru Mata Pelajaran,&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;(................................)&lt;/div&gt;&lt;/div&gt;';
  d.innerHTML=h; document.body.appendChild(d);
  document.body.className+=" kq-printing";
  setTimeout(function(){
    window.print();
    setTimeout(function(){document.body.className=document.body.className.replace(/\s*kq-printing/g,"");},500);
  },150);
}

/* ---------- status &amp; mulai ---------- */
function showStatus(){
  var s=$("kqStatus"); if(!s)return;
  if(rec&amp;&amp;rec.final){
    s.innerHTML='&lt;div class="card done"&gt;&lt;h3&gt;Pengerjaan selesai&lt;/h3&gt;&lt;p&gt;Nilai akhir tersimpan: &lt;b&gt;'+rec.final.score+'&lt;/b&gt; ('+(rec.final.source==="kkm"?'mencapai KKM':'nilai tertinggi')+'). Semua kesempatan sudah selesai.&lt;/p&gt;&lt;button class="b" id="kqPdf2" type="button"&gt;Unduh / Cetak Bukti (PDF)&lt;/button&gt;&lt;/div&gt;';
    $("kqPdf2").onclick=printProof;
  } else s.innerHTML="";
}
function setMsg(t,e){var m=$("kqMsg"); m.textContent=t; m.className="msg"+(e?" e":"");}

function start(){
  var nama=$("kqNama").value.replace(/\s+/g," ").trim(), kelas=$("kqKelas").value.replace(/\s+/g," ").trim(), absen=$("kqAbsen").value.trim();
  if(nama.length&lt;3){setMsg("Isi nama lengkap dengan benar.",true);return;}
  if(!kelas){setMsg("Isi kelas.",true);return;}
  if(!/^\d{1,2}$/.test(absen)||+absen&lt;1){setMsg("No. Absen harus angka 1 sampai 99.",true);return;}
  absen=String(+absen); keyStr=keyOf(kelas,absen); setMsg("Memeriksa data...",false);
  sGet(keyStr).then(function(r){
    rec=r||{nama:nama,kelas:kelas,absen:absen,attempts:[],final:null};
    rec.nama=nama; rec.kelas=kelas; rec.absen=absen;
    if(rec.final||rec.attempts.length&gt;=MAXA){
      if(!rec.final&amp;&amp;rec.attempts.length&gt;=MAXA){ var bi=0; rec.attempts.forEach(function(a,k){if(a.score&gt;rec.attempts[bi].score)bi=k;}); rec.final={score:rec.attempts[bi].score,source:"tertinggi",idx:bi}; sendGas(); sSet(keyStr,rec); }
      setMsg("Kesempatan untuk No. Absen ini sudah selesai.",true); showStatus(); return;
    }
    setMsg("",false);
    if(!window.confirm("Mulai percobaan ke-"+(rec.attempts.length+1)+" dari "+MAXA+"?\n\nSoal tampil layar penuh. Jangan berpindah tab/aplikasi: pelanggaran ke-"+MAXV+" otomatis mengirim jawaban."))return;
    beginAttempt();
  });
}
$("kqStart").onclick=start;
})();
&lt;/script&gt;</description><link>http://kitab-investasi.blogspot.com/2026/10/latihan-soal-tipe-akm-pokok-bahasan.html</link><thr:total>0</thr:total><author>nof_rizal07@yahoo.co.id (abang_cool)</author></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-9000860041661554971.post-8348578144324146868</guid><pubDate>Mon, 12 Oct 2026 05:47:39 +0000</pubDate><atom:updated>2026-10-13T07:49:53.014+07:00</atom:updated><title>Analisis Data dan Fitur Lanjut Spreadsheet</title><description>&lt;!DOCTYPE html&gt;
&lt;html lang="id"&gt;
&lt;head&gt;
&lt;meta charset="UTF-8"&gt;
&lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&gt;
&lt;title&gt;Analisis Data dan Fitur Lanjut Spreadsheet - Informatika Kelas X SMK&lt;/title&gt;
&lt;link rel="preconnect" href="https://fonts.googleapis.com"&gt;
&lt;link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500;600;700&amp;family=IBM+Plex+Sans:wght@400;500;600;700&amp;display=swap" rel="stylesheet"&gt;
&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"&gt;&lt;/script&gt;
&lt;script src="https://cdn.jsdelivr.net/npm/jspdf-autotable@3.8.2/dist/jspdf.plugin.autotable.min.js"&gt;&lt;/script&gt;
&lt;style&gt;
  :root{
    --brand:#15803D; --brand-dark:#0D5A2A; --surface:#EEF7F1; --paper:#FFFFFF;
    --ink:#16221B; --ink-soft:#4C5C52; --line:#D7E6DC;
    --amber:#D99A1B; --green:#15803D; --red:#D6412C;
  }
  *{box-sizing:border-box; margin:0; padding:0;}
  html{scroll-behavior:smooth;}
  body{font-family:'IBM Plex Sans',sans-serif; background:#F3F7F4; color:var(--ink); line-height:1.6;}
  .mono{font-family:'IBM Plex Mono',monospace;}

  .page-shell{max-width:1100px; margin:16px auto; background:#FFFFFF; border-radius:14px;
    box-shadow:0 8px 32px rgba(10,40,20,.14),0 1px 3px rgba(10,40,20,.08); border:1px solid var(--line);}

  header.hero{background:var(--brand); color:#fff; padding:34px 5% 30px; border-radius:14px 14px 0 0; position:relative; overflow:hidden;}
  header.hero::before{content:""; position:absolute; inset:0; background-image:
    linear-gradient(rgba(255,255,255,.07) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255,255,255,.07) 1px, transparent 1px);
    background-size:28px 28px; pointer-events:none;}
  header.hero &gt; *{position:relative; z-index:1;}
  .kop{text-align:center; font-family:'IBM Plex Mono',monospace; font-size:.72rem; letter-spacing:.12em; text-transform:uppercase; color:#BFEBCF; margin-bottom:8px;}
  h1.title{font-family:'IBM Plex Mono',monospace; font-weight:700; font-size:clamp(1.5rem,3.6vw,2.3rem); text-align:center; line-height:1.3;}
  .subtitle{text-align:center; margin-top:10px; color:#DFF3E6; font-size:.98rem; max-width:70ch; margin-left:auto; margin-right:auto;}
  .meta-strip{margin-top:26px; display:grid; grid-template-columns:repeat(auto-fit,minmax(150px,1fr)); gap:1px; background:rgba(255,255,255,.18); border:1px solid rgba(255,255,255,.18);}
  .meta-cell{background:var(--brand-dark); padding:12px 14px; text-align:center;}
  .meta-cell .k{font-family:'IBM Plex Mono',monospace; font-size:.62rem; letter-spacing:.08em; text-transform:uppercase; color:#9FDFB5;}
  .meta-cell .v{margin-top:4px; font-size:.9rem; font-weight:700;}

  main{padding:0;}
  .section{padding:32px 5%; border-bottom:1px solid #ECEFF3;}
  .section:last-child{border-bottom:none;}
  .section-tag{font-family:'IBM Plex Mono',monospace; font-size:.7rem; letter-spacing:.12em; text-transform:uppercase; color:var(--ink-soft); margin-bottom:8px;}
  h2.section-title{font-family:'IBM Plex Mono',monospace; font-size:clamp(1.15rem,2vw,1.5rem); font-weight:700; color:var(--brand-dark); margin-bottom:14px;}
  h3.sub-title{font-family:'IBM Plex Mono',monospace; font-size:1rem; font-weight:600; color:var(--brand-dark); margin:20px 0 10px; display:flex; align-items:center; gap:9px;}
  h3.sub-title::before{content:""; width:8px; height:8px; background:var(--amber); display:inline-block; border-radius:1px;}
  p{color:#33403A; max-width:80ch; margin-bottom:10px;}
  ul,ol{margin:6px 0 14px 1.3em; max-width:80ch;}
  li{margin-bottom:6px; color:#33403A;}
  strong{color:var(--brand-dark);}

  .callout{border-left:3px solid var(--brand); background:var(--surface); padding:14px 18px; border-radius:0 8px 8px 0; margin:14px 0; max-width:80ch;}
  .callout .lbl{font-family:'IBM Plex Mono',monospace; font-size:.68rem; letter-spacing:.1em; text-transform:uppercase; color:var(--brand-dark); font-weight:700; margin-bottom:6px;}
  .callout.warn{border-left-color:var(--red); background:#FCEBE8;}
  .callout.warn .lbl{color:#9B3324;}

  .card-grid{display:grid; grid-template-columns:repeat(auto-fit,minmax(210px,1fr)); gap:14px; margin:16px 0 6px;}
  .card{background:#FFFFFF; border:1.5px solid var(--line); border-radius:8px; padding:16px 18px; box-shadow:0 2px 8px rgba(10,40,20,.05);}
  .card .tag{font-family:'IBM Plex Mono',monospace; font-size:.64rem; letter-spacing:.1em; text-transform:uppercase; color:#fff; background:var(--brand); padding:3px 8px; border-radius:3px; display:inline-block; margin-bottom:10px;}
  .card h4{font-family:'IBM Plex Mono',monospace; font-size:.94rem; margin-bottom:6px; color:var(--brand-dark);}
  .card p{font-size:.87rem; margin-bottom:0;}
  .card code{font-family:'IBM Plex Mono',monospace; background:var(--surface); padding:1px 6px; border-radius:3px; font-size:.85em; color:var(--brand-dark);}

  .table-scroll{overflow-x:auto; margin:16px 0;}
  table.compare{width:100%; border-collapse:collapse; font-size:.88rem; min-width:460px;}
  table.compare th, table.compare td{border:1px solid var(--line); padding:10px 12px; text-align:left;}
  table.compare th{background:var(--brand); color:#fff; font-family:'IBM Plex Mono',monospace; font-size:.72rem; letter-spacing:.04em; text-transform:uppercase;}
  table.compare tr:nth-child(even) td{background:var(--surface);}

  .summary-box{background:var(--brand-dark); color:#fff; border-radius:8px; padding:22px 24px; margin-top:8px;}
  .summary-box h4{font-family:'IBM Plex Mono',monospace; color:#B8ECC9; font-size:.82rem; letter-spacing:.08em; text-transform:uppercase; margin-bottom:12px;}
  .summary-box ul{margin:0 0 0 1.1em; max-width:none;}
  .summary-box li{color:#E3F4E9; margin-bottom:7px;}

  .task-panel{border:1.5px dashed var(--brand); border-radius:8px; padding:24px 26px; background:repeating-linear-gradient(135deg,#FFFFFF,#FFFFFF 18px,var(--surface) 18px,var(--surface) 19px);}
  .task-head{display:flex; align-items:center; gap:12px; flex-wrap:wrap; margin-bottom:12px;}
  .task-head .badge{font-family:'IBM Plex Mono',monospace; font-size:.7rem; letter-spacing:.08em; text-transform:uppercase; background:var(--amber); color:#3A2A00; padding:4px 10px; border-radius:3px; font-weight:700;}
  .task-panel h3{font-family:'IBM Plex Mono',monospace; font-size:1.2rem; color:var(--brand-dark);}
  .steps-num{counter-reset:step; margin:14px 0; max-width:80ch;}
  .steps-num li{counter-increment:step; list-style:none; position:relative; padding-left:32px; margin-bottom:12px;}
  .steps-num li::before{content:counter(step); position:absolute; left:0; top:0; font-family:'IBM Plex Mono',monospace; font-weight:700; color:#fff; background:var(--brand); width:22px; height:22px; border-radius:50%; display:flex; align-items:center; justify-content:center; font-size:.78rem;}
  table.rubrik{width:100%; border-collapse:collapse; margin-top:16px; font-size:.86rem;}
  table.rubrik th, table.rubrik td{border:1px solid #C9D6CC; padding:9px 11px; text-align:left;}
  table.rubrik th{background:var(--brand-dark); color:#fff; font-family:'IBM Plex Mono',monospace; font-size:.73rem; letter-spacing:.04em; text-transform:uppercase;}
  table.rubrik tr:nth-child(even) td{background:#EFF5F0;}

  .field label{display:block; font-family:'IBM Plex Mono',monospace; font-size:.68rem; letter-spacing:.06em; text-transform:uppercase; color:var(--brand-dark); margin-bottom:6px;}
  .field input,.field select{width:100%; padding:10px 12px; border-radius:6px; border:1px solid var(--line); background:#fff; font-size:.92rem;}
  .student-info{display:grid; grid-template-columns:repeat(auto-fit,minmax(180px,1fr)); gap:14px; margin:14px 0;}

  .primary-btn{font-family:'IBM Plex Mono',monospace; font-weight:600; font-size:.9rem; padding:13px 26px; border-radius:7px; border:none; cursor:pointer; background:var(--brand); color:#fff;}
  .primary-btn:hover{filter:brightness(1.08);}
  .primary-btn.ghost{background:#fff; color:var(--brand); border:1.5px solid var(--brand);}
  .primary-btn:disabled{opacity:.5; cursor:not-allowed;}

  .excel-grid{border-collapse:collapse; margin:10px 0 14px; font-family:'IBM Plex Mono',monospace; font-size:.82rem;}
  .excel-grid th, .excel-grid td{border:1px solid #BFD4C6; padding:6px 10px; text-align:center; min-width:70px;}
  .excel-grid th{background:#E3F0E7; color:var(--brand-dark); font-weight:700;}
  .excel-grid th.rownum{background:#E3F0E7; min-width:30px;}
  .sheet-grid td.g-label{text-align:left; background:#F7FAF8; color:var(--ink-soft); font-family:'IBM Plex Sans',sans-serif; font-size:.78rem; min-width:110px;}
  .sheet-input{width:100%; min-width:92px; border:1px solid var(--line); border-radius:4px; padding:5px 6px; font-family:'IBM Plex Mono',monospace; font-size:.8rem; text-align:right; background:#fff;}
  .sheet-input.formula{text-align:left; background:#FFFDF2;}
  .sheet-input:focus{outline:none; border-color:var(--brand); box-shadow:0 0 0 2px rgba(21,128,61,.18);}
  .sheet-input.err{border-color:var(--red); color:var(--red); background:#FCEBE8;}
  .sheet-input.ref{background:#F3F3F3; color:var(--ink-soft); text-align:center; cursor:not-allowed;}
  tr.hi-max td{background:#D9F2E1 !important; font-weight:700;}
  table.final-table td.cell-ok{background:#E3F7EA; color:#0D5A2A; font-weight:600;}
  table.final-table td.cell-bad{background:#FCE6E3; color:#9B3324; font-weight:600;}
  table.final-table td.cell-empty{background:#F3F3F3; color:#8A8A8A; font-style:italic;}
  .task-actions{display:flex; gap:10px; flex-wrap:wrap; margin:14px 0;}

  .flag{color:var(--red); font-weight:700; display:none;}
  .flag.show{display:inline;}

  .result-panel{display:none; margin-top:18px; background:#fff; border:1.5px solid var(--green); border-radius:8px; padding:22px 24px;}
  .score-lbl{font-family:'IBM Plex Mono',monospace; font-size:.7rem; letter-spacing:.1em; text-transform:uppercase; color:var(--ink-soft);}
  .score{font-family:'IBM Plex Mono',monospace; font-size:2.3rem; font-weight:700; color:var(--green);}
  #uploadMsg,#pdfMsg{font-family:'IBM Plex Mono',monospace; font-size:.82rem; color:#8A6A1E; margin-left:10px;}

  footer{background:var(--surface); text-align:center; padding:20px 5% 28px; font-family:'IBM Plex Mono',monospace; font-size:.72rem; color:var(--ink-soft); border-top:1px solid var(--line); border-radius:0 0 14px 14px;}

  @media(max-width:700px){header.hero{padding:26px 5% 24px;} .section{padding:24px 5%;}}
&lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;div class="page-shell"&gt;
&lt;header class="hero"&gt;
  &lt;div class="kop"&gt;Informatika - Fase E - Kelas X SMK&lt;/div&gt;
  &lt;h1 class="title"&gt;Analisis Data dan Fitur Lanjut Spreadsheet&lt;/h1&gt;
  &lt;p class="subtitle"&gt;Murid mampu menerapkan fungsi lanjutan, lookup, sort, filter, conditional formatting, grafik, dan PivotTable untuk menganalisis data secara efektif.&lt;/p&gt;
  &lt;div class="meta-strip"&gt;
    &lt;div class="meta-cell"&gt;&lt;div class="k"&gt;Elemen CP&lt;/div&gt;&lt;div class="v"&gt;Pengolah Angka Lanjut&lt;/div&gt;&lt;/div&gt;
    &lt;div class="meta-cell"&gt;&lt;div class="k"&gt;Jenjang&lt;/div&gt;&lt;div class="v"&gt;SMK Kelas X&lt;/div&gt;&lt;/div&gt;
    &lt;div class="meta-cell"&gt;&lt;div class="k"&gt;Alokasi Waktu&lt;/div&gt;&lt;div class="v"&gt;1 Pertemuan - 4 JP&lt;/div&gt;&lt;/div&gt;
    &lt;div class="meta-cell"&gt;&lt;div class="k"&gt;Model&lt;/div&gt;&lt;div class="v"&gt;Penjelasan, Praktik &amp; Evaluasi Individu&lt;/div&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/header&gt;

&lt;main&gt;
  &lt;section class="section" id="tujuan"&gt;
    &lt;div class="section-tag"&gt;Capaian &amp; Tujuan Pembelajaran&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Ke Mana Materi Ini Menuju&lt;/h2&gt;
    &lt;p&gt;Murid mampu menerapkan &lt;strong&gt;fungsi lanjutan, lookup, sort, filter, conditional formatting, grafik,&lt;/strong&gt; dan &lt;strong&gt;PivotTable&lt;/strong&gt; untuk menganalisis data secara efektif pada aplikasi spreadsheet.&lt;/p&gt;
    &lt;h3 class="sub-title"&gt;Rincian Kegiatan (4 JP x 45 menit)&lt;/h3&gt;
    &lt;div class="table-scroll"&gt;
    &lt;table class="compare"&gt;
      &lt;tr&gt;&lt;th&gt;Tahap&lt;/th&gt;&lt;th&gt;Kegiatan&lt;/th&gt;&lt;th&gt;Waktu&lt;/th&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Pendahuluan&lt;/td&gt;&lt;td&gt;Apersepsi ("Bagaimana toko besar bisa menganalisis ribuan transaksi hanya dalam hitungan detik?"), penyampaian tujuan&lt;/td&gt;&lt;td&gt;15 menit&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Inti - Eksplorasi Konsep&lt;/td&gt;&lt;td&gt;Penjelasan fungsi lanjutan (SUMIF/COUNTIF/AVERAGEIF), lookup (VLOOKUP/HLOOKUP), sort &amp; filter, conditional formatting, grafik, dan PivotTable&lt;/td&gt;&lt;td&gt;55 menit&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Inti - Demonstrasi&lt;/td&gt;&lt;td&gt;Guru mendemonstrasikan penerapan fungsi lanjutan dan lookup pada contoh data&lt;/td&gt;&lt;td&gt;25 menit&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Inti - Praktik Individu&lt;/td&gt;&lt;td&gt;Murid mengerjakan tugas praktik mandiri langsung pada Lembar Kerja Spreadsheet di halaman ini&lt;/td&gt;&lt;td&gt;45 menit&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Inti - Evaluasi &amp; Pengumpulan&lt;/td&gt;&lt;td&gt;Sistem menilai hasil kerja secara otomatis, murid mengunduh bukti PDF&lt;/td&gt;&lt;td&gt;20 menit&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Penutup&lt;/td&gt;&lt;td&gt;Refleksi dan penguatan konsep&lt;/td&gt;&lt;td&gt;10 menit&lt;/td&gt;&lt;/tr&gt;
    &lt;/table&gt;
    &lt;/div&gt;
  &lt;/section&gt;

  &lt;section class="section" id="fungsi-lanjutan"&gt;
    &lt;div class="section-tag"&gt;Analisis Data&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Fungsi Lanjutan (Fungsi Bersyarat)&lt;/h2&gt;
    &lt;p&gt;Fungsi lanjutan memungkinkan perhitungan dilakukan hanya pada data yang memenuhi &lt;strong&gt;syarat (kriteria)&lt;/strong&gt; tertentu, sehingga analisis data dalam tabel besar menjadi lebih cepat dan akurat tanpa harus memilah data secara manual.&lt;/p&gt;
    &lt;div class="card-grid"&gt;
      &lt;div class="card"&gt;&lt;span class="tag"&gt;Fungsi&lt;/span&gt;&lt;h4&gt;COUNTIF&lt;/h4&gt;&lt;p&gt;Menghitung banyak sel dalam suatu range yang memenuhi satu syarat. Contoh: &lt;code&gt;=COUNTIF(B2:B9,"Alat Tulis")&lt;/code&gt; menghitung berapa jenis barang berkategori Alat Tulis.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;span class="tag"&gt;Fungsi&lt;/span&gt;&lt;h4&gt;SUMIF&lt;/h4&gt;&lt;p&gt;Menjumlahkan nilai pada suatu range yang memenuhi satu syarat tertentu. Contoh: &lt;code&gt;=SUMIF(B2:B9,"Alat Tulis",E2:E9)&lt;/code&gt; menjumlahkan Total hanya untuk kategori Alat Tulis.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;span class="tag"&gt;Fungsi&lt;/span&gt;&lt;h4&gt;AVERAGEIF&lt;/h4&gt;&lt;p&gt;Menghitung rata-rata nilai pada suatu range yang memenuhi satu syarat tertentu. Contoh: &lt;code&gt;=AVERAGEIF(B2:B9,"Jasa",E2:E9)&lt;/code&gt; menghitung rata-rata Total khusus kategori Jasa.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;span class="tag"&gt;Fungsi&lt;/span&gt;&lt;h4&gt;SUMIFS / COUNTIFS&lt;/h4&gt;&lt;p&gt;Versi lanjutan dari SUMIF/COUNTIF yang mampu memeriksa &lt;strong&gt;lebih dari satu syarat sekaligus&lt;/strong&gt;. Contoh: &lt;code&gt;=SUMIFS(E2:E9,B2:B9,"Jasa",C2:C9,"&amp;gt;=20")&lt;/code&gt;.&lt;/p&gt;&lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="callout"&gt;
      &lt;div class="lbl"&gt;Catatan Penting&lt;/div&gt;
      &lt;p style="margin:0;"&gt;Syarat (kriteria) berupa teks ditulis dalam tanda kutip, misalnya &lt;code&gt;"Jasa"&lt;/code&gt;, sedangkan syarat berupa perbandingan angka ditulis seperti &lt;code&gt;"&amp;gt;=30"&lt;/code&gt; atau &lt;code&gt;"&amp;lt;15"&lt;/code&gt;, tetap di dalam tanda kutip.&lt;/p&gt;
    &lt;/div&gt;
  &lt;/section&gt;

  &lt;section class="section" id="fungsi-teks"&gt;
    &lt;div class="section-tag"&gt;Pengolahan Teks&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Fungsi Teks (STRING)&lt;/h2&gt;
    &lt;p&gt;Fungsi teks (string) digunakan untuk &lt;strong&gt;mengambil atau memotong sebagian karakter&lt;/strong&gt; dari sebuah teks/kode, misalnya mengambil kode kategori atau kode lokasi dari sebuah Kode Transaksi tanpa harus mengetik ulang secara manual.&lt;/p&gt;
    &lt;div class="card-grid"&gt;
      &lt;div class="card"&gt;&lt;span class="tag"&gt;Fungsi&lt;/span&gt;&lt;h4&gt;LEFT&lt;/h4&gt;&lt;p&gt;Mengambil sejumlah karakter dari &lt;strong&gt;sisi kiri (awal)&lt;/strong&gt; teks. Contoh: &lt;code&gt;=LEFT("AT01A",2)&lt;/code&gt; menghasilkan "AT".&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;span class="tag"&gt;Fungsi&lt;/span&gt;&lt;h4&gt;RIGHT&lt;/h4&gt;&lt;p&gt;Mengambil sejumlah karakter dari &lt;strong&gt;sisi kanan (akhir)&lt;/strong&gt; teks. Contoh: &lt;code&gt;=RIGHT("AT01A",1)&lt;/code&gt; menghasilkan "A".&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;span class="tag"&gt;Fungsi&lt;/span&gt;&lt;h4&gt;MID&lt;/h4&gt;&lt;p&gt;Mengambil sejumlah karakter mulai dari &lt;strong&gt;posisi tertentu di tengah&lt;/strong&gt; teks. Contoh: &lt;code&gt;=MID("AT01A",3,2)&lt;/code&gt; menghasilkan "01" (mulai karakter ke-3, sepanjang 2 karakter).&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;span class="tag"&gt;Fungsi&lt;/span&gt;&lt;h4&gt;LEN&lt;/h4&gt;&lt;p&gt;Menghitung &lt;strong&gt;jumlah karakter&lt;/strong&gt; dalam sebuah teks. Contoh: &lt;code&gt;=LEN("AT01A")&lt;/code&gt; menghasilkan 5.&lt;/p&gt;&lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="callout"&gt;
      &lt;div class="lbl"&gt;Contoh Penerapan&lt;/div&gt;
      &lt;p style="margin:0;"&gt;Sebuah Kode Transaksi "AT01A" dapat dipecah menjadi tiga informasi sekaligus: &lt;code&gt;LEFT(sel,2)&lt;/code&gt; mengambil "AT" (kode kategori), &lt;code&gt;MID(sel,3,2)&lt;/code&gt; mengambil "01" (nomor urut), dan &lt;code&gt;RIGHT(sel,1)&lt;/code&gt; mengambil "A" (kode gudang) - semua dari satu kode tanpa perlu kolom terpisah untuk tiap bagiannya.&lt;/p&gt;
    &lt;/div&gt;
  &lt;/section&gt;

  &lt;section class="section" id="lookup"&gt;
    &lt;div class="section-tag"&gt;Pencarian Data&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Fungsi Lookup (VLOOKUP &amp; HLOOKUP)&lt;/h2&gt;
    &lt;p&gt;Fungsi lookup digunakan untuk &lt;strong&gt;mencari data secara otomatis&lt;/strong&gt; dari tabel referensi berdasarkan satu kata kunci, sehingga tidak perlu mencari dan mengetik data referensi secara manual satu per satu.&lt;/p&gt;
    &lt;h3 class="sub-title"&gt;VLOOKUP (Vertical Lookup)&lt;/h3&gt;
    &lt;p&gt;Mencari data pada tabel referensi yang tersusun &lt;strong&gt;vertikal (per kolom)&lt;/strong&gt;. Struktur dasarnya: &lt;code&gt;=VLOOKUP(nilai_dicari, tabel_referensi, nomor_kolom, FALSE)&lt;/code&gt;.&lt;/p&gt;
    &lt;div class="table-scroll"&gt;
    &lt;table class="compare"&gt;
      &lt;tr&gt;&lt;th&gt;Kode&lt;/th&gt;&lt;th&gt;Nama Barang&lt;/th&gt;&lt;th&gt;Harga&lt;/th&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;K01&lt;/td&gt;&lt;td&gt;Kabel UTP&lt;/td&gt;&lt;td&gt;850000&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;K02&lt;/td&gt;&lt;td&gt;Router Wi-Fi&lt;/td&gt;&lt;td&gt;320000&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;K03&lt;/td&gt;&lt;td&gt;Switch 8 Port&lt;/td&gt;&lt;td&gt;275000&lt;/td&gt;&lt;/tr&gt;
    &lt;/table&gt;
    &lt;/div&gt;
    &lt;div class="callout"&gt;
      &lt;div class="lbl"&gt;Contoh Penerapan&lt;/div&gt;
      &lt;p style="margin:0;"&gt;Jika tabel referensi di atas berada pada range &lt;code&gt;H2:J4&lt;/code&gt;, rumus &lt;code&gt;=VLOOKUP("K02",H2:J4,3,FALSE)&lt;/code&gt; akan mencari baris dengan kode "K02" lalu mengambil nilai pada kolom ke-3 dari tabel referensi tersebut, yaitu 320000. Parameter terakhir &lt;code&gt;FALSE&lt;/code&gt; berarti pencarian harus &lt;strong&gt;persis sama (exact match)&lt;/strong&gt; - ini penting agar hasil pencarian tidak keliru.&lt;/p&gt;
    &lt;/div&gt;
    &lt;h3 class="sub-title"&gt;HLOOKUP (Horizontal Lookup)&lt;/h3&gt;
    &lt;p&gt;Prinsip kerjanya sama dengan VLOOKUP, namun digunakan ketika tabel referensi tersusun &lt;strong&gt;horizontal (per baris)&lt;/strong&gt;. Strukturnya: &lt;code&gt;=HLOOKUP(nilai_dicari, tabel_referensi, nomor_baris, FALSE)&lt;/code&gt;.&lt;/p&gt;
  &lt;/section&gt;

  &lt;section class="section" id="sort-filter"&gt;
    &lt;div class="section-tag"&gt;Penyajian Data&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Sort (Urutkan) dan Filter (Saring)&lt;/h2&gt;
    &lt;div class="card-grid"&gt;
      &lt;div class="card"&gt;&lt;span class="tag"&gt;Mengurutkan&lt;/span&gt;&lt;h4&gt;Sort Ascending / Descending&lt;/h4&gt;&lt;p&gt;Mengurutkan seluruh baris data berdasarkan satu kolom, dari terkecil ke terbesar (A-Z) atau sebaliknya (Z-A), tanpa menghilangkan data apa pun.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;span class="tag"&gt;Mengurutkan&lt;/span&gt;&lt;h4&gt;Custom Sort (Multi-level)&lt;/h4&gt;&lt;p&gt;Mengurutkan data berdasarkan lebih dari satu kolom sekaligus, misalnya urutkan dulu berdasarkan Kategori, baru berdasarkan Total di dalam tiap kategori.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;span class="tag"&gt;Menyaring&lt;/span&gt;&lt;h4&gt;Filter (AutoFilter)&lt;/h4&gt;&lt;p&gt;Menyembunyikan sementara baris yang tidak memenuhi kriteria tertentu, sehingga hanya baris yang relevan yang ditampilkan - data lain tidak terhapus, hanya disembunyikan.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;span class="tag"&gt;Menyaring&lt;/span&gt;&lt;h4&gt;Filter by Condition&lt;/h4&gt;&lt;p&gt;Menyaring data berdasarkan syarat tertentu, misalnya hanya menampilkan baris dengan Total di atas rata-rata, atau Kategori tertentu saja.&lt;/p&gt;&lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="callout"&gt;
      &lt;div class="lbl"&gt;Perbedaan Penting&lt;/div&gt;
      &lt;p style="margin:0;"&gt;&lt;strong&gt;Sort&lt;/strong&gt; mengubah urutan seluruh data secara permanen, sedangkan &lt;strong&gt;Filter&lt;/strong&gt; hanya menyembunyikan baris yang tidak sesuai kriteria sementara - data aslinya tetap utuh dan dapat ditampilkan kembali kapan saja.&lt;/p&gt;
    &lt;/div&gt;
  &lt;/section&gt;

  &lt;section class="section" id="conditional-formatting"&gt;
    &lt;div class="section-tag"&gt;Visual Data&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Conditional Formatting (Format Bersyarat)&lt;/h2&gt;
    &lt;p&gt;Conditional Formatting memberi tampilan visual (warna, bar, ikon) secara &lt;strong&gt;otomatis&lt;/strong&gt; pada sel berdasarkan nilainya, sehingga pola dan data penting pada tabel besar langsung terlihat tanpa harus membaca satu per satu.&lt;/p&gt;
    &lt;div class="table-scroll"&gt;
    &lt;table class="compare"&gt;
      &lt;tr&gt;&lt;th&gt;Jenis Aturan&lt;/th&gt;&lt;th&gt;Contoh Tampilan&lt;/th&gt;&lt;th&gt;Kegunaan&lt;/th&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Highlight Cell Rules&lt;/td&gt;&lt;td&gt;Sel merah untuk nilai &amp;lt; 60&lt;/td&gt;&lt;td&gt;Menyorot sel yang memenuhi syarat tertentu (lebih besar, lebih kecil, sama dengan, dsb)&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Color Scales&lt;/td&gt;&lt;td&gt;Gradasi hijau (tinggi) ke merah (rendah)&lt;/td&gt;&lt;td&gt;Menampilkan sebaran nilai tinggi-rendah dalam satu range secara visual&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Data Bars&lt;/td&gt;&lt;td&gt;Bilah warna sepanjang nilai sel&lt;/td&gt;&lt;td&gt;Membandingkan besar-kecilnya nilai antar sel secara sekilas&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Icon Sets&lt;/td&gt;&lt;td&gt;Panah/bintang/lampu lalu lintas&lt;/td&gt;&lt;td&gt;Memberi indikator status (naik/turun, baik/buruk) secara ringkas&lt;/td&gt;&lt;/tr&gt;
    &lt;/table&gt;
    &lt;/div&gt;
  &lt;/section&gt;

  &lt;section class="section" id="grafik"&gt;
    &lt;div class="section-tag"&gt;Visualisasi&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Grafik (Chart)&lt;/h2&gt;
    &lt;p&gt;Grafik mengubah data tabel menjadi bentuk visual agar pola, perbandingan, dan tren data lebih mudah dipahami secara sekilas.&lt;/p&gt;
    &lt;div class="card-grid"&gt;
      &lt;div class="card"&gt;&lt;span class="tag"&gt;Perbandingan&lt;/span&gt;&lt;h4&gt;Bar/Column Chart&lt;/h4&gt;&lt;p&gt;Cocok untuk membandingkan nilai antar kategori, misalnya total penjualan tiap jenis barang.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;span class="tag"&gt;Tren Waktu&lt;/span&gt;&lt;h4&gt;Line Chart&lt;/h4&gt;&lt;p&gt;Cocok untuk menunjukkan perubahan data dari waktu ke waktu, misalnya penjualan per bulan selama setahun.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;span class="tag"&gt;Proporsi&lt;/span&gt;&lt;h4&gt;Pie Chart&lt;/h4&gt;&lt;p&gt;Cocok untuk menunjukkan proporsi/persentase bagian terhadap keseluruhan, misalnya kontribusi tiap kategori terhadap total penjualan.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;span class="tag"&gt;Gabungan&lt;/span&gt;&lt;h4&gt;Combo Chart&lt;/h4&gt;&lt;p&gt;Menggabungkan dua jenis grafik (mis. bar dan line) dalam satu tampilan untuk membandingkan dua jenis data berbeda sekaligus.&lt;/p&gt;&lt;/div&gt;
    &lt;/div&gt;
  &lt;/section&gt;

  &lt;section class="section" id="pivot"&gt;
    &lt;div class="section-tag"&gt;Ringkasan Data&lt;/div&gt;
    &lt;h2 class="section-title"&gt;PivotTable&lt;/h2&gt;
    &lt;p&gt;PivotTable adalah fitur untuk &lt;strong&gt;meringkas dan mengelompokkan&lt;/strong&gt; data tabel besar menjadi tabel ringkasan baru secara otomatis - tanpa perlu menulis rumus manual - sehingga pola dan total per kelompok data langsung terlihat.&lt;/p&gt;
    &lt;h3 class="sub-title"&gt;Empat Area Utama PivotTable&lt;/h3&gt;
    &lt;div class="card-grid"&gt;
      &lt;div class="card"&gt;&lt;span class="tag"&gt;Area&lt;/span&gt;&lt;h4&gt;Filters&lt;/h4&gt;&lt;p&gt;Menyaring data mana saja yang akan ditampilkan dalam PivotTable, misalnya hanya data bulan tertentu.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;span class="tag"&gt;Area&lt;/span&gt;&lt;h4&gt;Rows&lt;/h4&gt;&lt;p&gt;Menentukan kategori yang menjadi baris pengelompokan, misalnya Kategori Barang/Jasa.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;span class="tag"&gt;Area&lt;/span&gt;&lt;h4&gt;Columns&lt;/h4&gt;&lt;p&gt;Menentukan kategori yang menjadi kolom pengelompokan, misalnya Bulan Transaksi.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;span class="tag"&gt;Area&lt;/span&gt;&lt;h4&gt;Values&lt;/h4&gt;&lt;p&gt;Nilai yang dihitung/diringkas (dijumlah, dirata-rata, dihitung) untuk tiap kelompok, misalnya Total Penjualan.&lt;/p&gt;&lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="callout"&gt;
      &lt;div class="lbl"&gt;Contoh Penerapan&lt;/div&gt;
      &lt;p style="margin:0;"&gt;Dari tabel transaksi berisi puluhan baris data penjualan per barang, PivotTable dapat langsung menghasilkan tabel ringkas "Total Penjualan per Kategori" hanya dengan menyeret (drag) kolom Kategori ke area Rows dan kolom Total ke area Values - tanpa menulis satu pun rumus SUM manual.&lt;/p&gt;
    &lt;/div&gt;
  &lt;/section&gt;

  &lt;section class="section" id="rangkuman"&gt;
    &lt;div class="section-tag"&gt;Penguatan Konsep&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Rangkuman Materi&lt;/h2&gt;
    &lt;div class="summary-box"&gt;
      &lt;h4&gt;Poin-Poin Kunci&lt;/h4&gt;
      &lt;ul&gt;
        &lt;li&gt;Fungsi lanjutan (COUNTIF, SUMIF, AVERAGEIF, SUMIFS/COUNTIFS) menghitung data berdasarkan satu atau lebih syarat tertentu.&lt;/li&gt;
        &lt;li&gt;Fungsi teks (LEFT, RIGHT, MID, LEN) mengambil atau memotong sebagian karakter dari sebuah teks/kode.&lt;/li&gt;
        &lt;li&gt;Fungsi lookup (VLOOKUP/HLOOKUP) mencari data secara otomatis dari tabel referensi berdasarkan kata kunci, dengan exact match (FALSE) agar hasil akurat.&lt;/li&gt;
        &lt;li&gt;Sort mengurutkan seluruh data secara permanen; Filter menyembunyikan sementara data yang tidak memenuhi kriteria.&lt;/li&gt;
        &lt;li&gt;Conditional Formatting menyorot data penting secara visual (warna, data bar, ikon) berdasarkan nilainya secara otomatis.&lt;/li&gt;
        &lt;li&gt;Grafik (Bar, Line, Pie, Combo) membantu memahami pola dan perbandingan data secara visual sesuai kebutuhan analisis.&lt;/li&gt;
        &lt;li&gt;PivotTable meringkas data besar menjadi tabel kelompok (Rows, Columns, Values, Filters) tanpa rumus manual.&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/div&gt;
  &lt;/section&gt;

  &lt;section class="section" id="identitas"&gt;
    &lt;div class="section-tag"&gt;Praktik &amp; Evaluasi Individu&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Isi Data Diri&lt;/h2&gt;
    &lt;p&gt;Kerjakan tugas praktik spreadsheet berikut secara &lt;strong&gt;mandiri&lt;/strong&gt; langsung di halaman ini. Hasil kerja dinilai otomatis oleh sistem dan langsung dikirim ke guru begitu tombol penilaian ditekan.&lt;/p&gt;
    &lt;div class="student-info"&gt;
      &lt;div class="field"&gt;&lt;label&gt;Kelas&lt;/label&gt;
        &lt;select id="kelasADFL"&gt;
          &lt;option value=""&gt;-- Pilih Kelas --&lt;/option&gt;
          &lt;option value="X TB1"&gt;X TB1&lt;/option&gt;&lt;option value="X TB2"&gt;X TB2&lt;/option&gt;
          &lt;option value="X TO1"&gt;X TO1&lt;/option&gt;&lt;option value="X TO2"&gt;X TO2&lt;/option&gt;
          &lt;option value="X TJKT1"&gt;X TJKT1&lt;/option&gt;&lt;option value="X TJKT2"&gt;X TJKT2&lt;/option&gt;
        &lt;/select&gt;
      &lt;/div&gt;
      &lt;div class="field"&gt;&lt;label&gt;No. Absen&lt;/label&gt;
        &lt;select id="noAbsenADFL" disabled&gt;
          &lt;option value=""&gt;- Pilih kelas dulu -&lt;/option&gt;
        &lt;/select&gt;
      &lt;/div&gt;
      &lt;div class="field"&gt;&lt;label&gt;Nama Lengkap (otomatis)&lt;/label&gt;&lt;input type="text" id="namaADFL" readonly placeholder="- Pilih no. absen dulu -"&gt;&lt;/div&gt;
    &lt;/div&gt;
  &lt;/section&gt;

  &lt;section class="section" id="praktik"&gt;
    &lt;div class="section-tag"&gt;Tugas Praktik Individu&lt;/div&gt;
    &lt;div class="task-panel"&gt;
      &lt;div class="task-head"&gt;
        &lt;span class="badge"&gt;Praktik Mandiri&lt;/span&gt;
        &lt;span class="badge" style="background:var(--brand-dark); color:#fff;"&gt;45 menit praktik + penilaian otomatis&lt;/span&gt;
      &lt;/div&gt;
      &lt;h3&gt;Analisis Penjualan Koperasi Sekolah&lt;/h3&gt;
      &lt;p&gt;Kamu berperan sebagai staf administrasi &lt;strong&gt;Koperasi Sekolah&lt;/strong&gt; yang mencatat penjualan barang dan jasa selama satu bulan terakhir. Kerjakan instruksi bernomor berikut &lt;strong&gt;secara langsung&lt;/strong&gt; dengan mengetikkan data dan rumus sendiri pada Lembar Kerja Spreadsheet di bawah - seluruh sel tidak menerima tempel (paste), harus diketik sendiri dan dihitung sungguhan oleh sistem, persis seperti bekerja di Excel/Google Sheets.&lt;/p&gt;

      &lt;div class="card" style="background:var(--surface); border-style:dashed; margin-top:16px;"&gt;
        &lt;span class="tag"&gt;Referensi Latihan - Jangan Disalin-Tempel&lt;/span&gt;

        &lt;p style="font-size:.78rem; font-weight:600; color:var(--brand-dark); margin-top:12px;"&gt;1. Keadaan Awal (Data Sebelum Latihan Dikerjakan)&lt;/p&gt;
        &lt;div class="table-scroll" id="dataAwalWrap" style="margin:8px 0 4px;"&gt;&lt;/div&gt;

        &lt;p style="font-size:.78rem; font-weight:600; color:var(--brand-dark); margin-top:16px;"&gt;2. Instruksi Soal (Ketikkan Sendiri di Lembar Kerja di Bawah)&lt;/p&gt;
        &lt;ol class="steps-num" id="instruksiSteps" style="margin-top:10px;"&gt;&lt;/ol&gt;

        &lt;p style="font-size:.78rem; font-weight:600; color:var(--brand-dark); margin-top:16px;"&gt;3. Keadaan Akhir (Patokan Setelah Instruksi Dikerjakan)&lt;/p&gt;
        &lt;p style="font-size:.8rem; color:var(--ink-soft); margin-top:2px;"&gt;Gunakan tabel ini sebagai patokan hasil akhir yang benar - bukan untuk disalin, tetapi untuk mengecek hasil pekerjaanmu sendiri setelah selesai mengetik rumus.&lt;/p&gt;
        &lt;div class="table-scroll" id="keadaanAkhirWrap" style="margin:8px 0 4px;"&gt;&lt;/div&gt;
      &lt;/div&gt;

      &lt;h3 class="sub-title" style="margin-top:22px;"&gt;Tabel Referensi VLOOKUP &amp; HLOOKUP (Tidak Bisa Diubah)&lt;/h3&gt;
      &lt;p style="font-size:.84rem;"&gt;Tabel berikut dipakai sebagai sumber data oleh rumus VLOOKUP dan HLOOKUP di Lembar Kerja - sudah terisi otomatis, tidak perlu dan tidak bisa diketik ulang.&lt;/p&gt;
      &lt;div class="table-scroll" id="refTableWrap"&gt;&lt;/div&gt;

      &lt;h3 class="sub-title" style="margin-top:22px;"&gt;Lembar Kerja Spreadsheet (Dihitung Langsung oleh Sistem)&lt;/h3&gt;
      &lt;p style="font-size:.86rem;"&gt;Ketikkan data pada kolom &lt;strong&gt;A&lt;/strong&gt; sampai &lt;strong&gt;D&lt;/strong&gt; dan &lt;strong&gt;G&lt;/strong&gt; (baris 2-9) sesuai contoh Data Awal, lalu ketikkan rumus pada kolom &lt;strong&gt;E&lt;/strong&gt; (Total), &lt;strong&gt;F&lt;/strong&gt; (Status), &lt;strong&gt;H-J&lt;/strong&gt; (fungsi STRING), &lt;strong&gt;K&lt;/strong&gt; (VLOOKUP), &lt;strong&gt;L&lt;/strong&gt; (HLOOKUP), serta sel ringkasan E11-E14, diawali tanda "=".&lt;/p&gt;
      &lt;div class="table-scroll" id="gridWrap"&gt;&lt;/div&gt;
      &lt;p class="flag" id="pasteWarning" style="margin:6px 0 0;"&gt;[PERINGATAN] Percobaan tempel terdeteksi pada lembar kerja - seluruh data dan rumus harus diketik sendiri.&lt;/p&gt;

      &lt;div class="task-actions"&gt;
        &lt;button id="btnSortGrid" class="primary-btn ghost"&gt;Urutkan Berdasarkan Total (Sort)&lt;/button&gt;
        &lt;button id="btnFilterGrid" class="primary-btn ghost"&gt;Tampilkan Hanya di Atas Rata-rata (Filter)&lt;/button&gt;
        &lt;button id="btnResetGrid" class="primary-btn ghost"&gt;Reset Lembar Kerja&lt;/button&gt;
      &lt;/div&gt;
      &lt;div id="sortedResult"&gt;&lt;/div&gt;
      &lt;div id="filterResult"&gt;&lt;/div&gt;

      &lt;h3 class="sub-title"&gt;Grafik Total Penjualan (Otomatis)&lt;/h3&gt;
      &lt;canvas id="dataChart" width="640" height="220" style="max-width:100%; background:#fff; border:1px solid var(--line); border-radius:8px; display:block;"&gt;&lt;/canvas&gt;

      &lt;div class="task-actions" style="margin-top:20px;"&gt;
        &lt;button id="btnHitung" class="primary-btn"&gt;Hitung Nilai &amp; Kirim ke Guru&lt;/button&gt;
        &lt;span id="uploadMsg"&gt;&lt;/span&gt;
      &lt;/div&gt;

      &lt;div class="result-panel" id="resultPanel"&gt;
        &lt;div class="score-lbl"&gt;Nilai Praktik (Otomatis)&lt;/div&gt;
        &lt;div class="score" id="scoreValue"&gt;0&lt;/div&gt;
        &lt;p id="resultDetail" style="font-size:.84rem; color:var(--ink-soft);"&gt;&lt;/p&gt;

        &lt;h3 class="sub-title" style="margin-top:18px;"&gt;Hasil Akhir Pengerjaan Tabel&lt;/h3&gt;
        &lt;p style="font-size:.8rem; color:var(--ink-soft);"&gt;Sel berwarna hijau = benar, merah = salah, abu-abu = belum diisi.&lt;/p&gt;
        &lt;div id="finalTableWrap"&gt;&lt;/div&gt;

        &lt;h3 class="sub-title" style="margin-top:18px;"&gt;Tabel Ringkasan per Kategori (Simulasi PivotTable)&lt;/h3&gt;
        &lt;div id="pivotTableWrap"&gt;&lt;/div&gt;

        &lt;div class="task-actions" style="margin-top:16px;"&gt;
          &lt;button id="btnUnduhPDF" class="primary-btn ghost"&gt;Unduh Bukti (PDF - 1 Halaman Tabel Hasil)&lt;/button&gt;
        &lt;/div&gt;
        &lt;span id="pdfMsg" class="mono" style="font-size:.78rem; color:var(--ink-soft);"&gt;&lt;/span&gt;
      &lt;/div&gt;

      &lt;h3 class="sub-title" style="margin-top:22px;"&gt;Format Penilaian&lt;/h3&gt;
      &lt;p&gt;Pekerjaan dinilai dari ketepatan data yang diketik, rumus Total dan Status, rumus ringkasan SUM/AVERAGE, fungsi lanjutan SUMIF/COUNTIF, fungsi STRING (LEFT/MID/RIGHT), serta fungsi VLOOKUP dan HLOOKUP, tanpa ada percobaan salin-tempel.&lt;/p&gt;
      &lt;table class="rubrik"&gt;
        &lt;tr&gt;&lt;th&gt;Aspek&lt;/th&gt;&lt;th&gt;Indikator&lt;/th&gt;&lt;th&gt;Bobot&lt;/th&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td&gt;Ketepatan Data Entri&lt;/td&gt;&lt;td&gt;Kolom A-D dan G terisi sesuai Data Awal, diketik sendiri tanpa salin-tempel&lt;/td&gt;&lt;td&gt;15%&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td&gt;Rumus Total &amp; Status&lt;/td&gt;&lt;td&gt;Kolom E (perkalian) dan F (IF bertingkat) terisi benar pada seluruh baris&lt;/td&gt;&lt;td&gt;15%&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td&gt;Rumus Ringkasan&lt;/td&gt;&lt;td&gt;SUM dan AVERAGE pada E11-E12 terisi dan bernilai benar&lt;/td&gt;&lt;td&gt;10%&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td&gt;Fungsi Lanjutan&lt;/td&gt;&lt;td&gt;SUMIF dan COUNTIF pada E13-E14 terisi dan bernilai benar&lt;/td&gt;&lt;td&gt;15%&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td&gt;Fungsi STRING&lt;/td&gt;&lt;td&gt;LEFT (H), MID (I), dan RIGHT (J) mengekstrak Kode Transaksi dengan tepat&lt;/td&gt;&lt;td&gt;20%&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td&gt;Fungsi Lookup&lt;/td&gt;&lt;td&gt;VLOOKUP (K - Diskon) dan HLOOKUP (L - Poin Reward) merujuk tabel referensi dengan tepat&lt;/td&gt;&lt;td&gt;25%&lt;/td&gt;&lt;/tr&gt;
      &lt;/table&gt;
    &lt;/div&gt;
  &lt;/section&gt;
&lt;/main&gt;
&lt;footer&gt;ANALISIS DATA DAN FITUR LANJUT SPREADSHEET - INFORMATIKA - FASE E KELAS X SMK&lt;/footer&gt;
&lt;/div&gt;

&lt;script&gt;
const GAS_ENDPOINT = "https://script.google.com/macros/s/AKfycbwKp7DrBTALJMlw8crjK7RgXIO8LVcU4yVEd9WJNs_vgSXkVxfw7fwkGbOT2IBNOjg3uQ/exec";
const JUDUL_MATERI = "Analisis Data dan Fitur Lanjut Spreadsheet";

// ===================== DAFTAR NAMA MURID (DARI ABSENSI) =====================
const STUDENTS = {"X TB1":[[1,"Adha Mirahayu Ningsih"],[2,"Angelina Agnes Noviola"],[3,"Anissa Vira Firmanda"],[4,"Awinda Rizqi Amru Anjani"],[5,"Chaudli Maulidina Azra"],[6,"Dhira Cahya Oktavianingrum"],[7,"Ema Deny Setyaningrum"],[8,"Evita Apriliani"],[9,"Fair Rochmatul Ishmah"],[10,"Fatma Nabila"],[11,"Fatmawati"],[12,"Fika Setya Wulandari"],[13,"Gelsi Zalika Thufaila"],[14,"Hidayatul Husna Maulida"],[15,"Izzatul Luthfa Imanda"],[16,"Meisha Ayu Berlia"],[17,"Meylisa Putri Murdiani"],[18,"Mita Tri Oktavia"],[19,"Mutiara Syabilla"],[20,"Nabila Saskia"],[21,"Nadya Vega Rahmadani"],[22,"Nafisa Nailal Husna"],[23,"Nawa Syiffa Maryam"],[24,"Nirin Fadillah"],[25,"Reni Restia Pramesti"],[26,"Rizkiya Maulida"],[27,"Shinta Aulia Mukti"],[28,"Shintia Amelia Putri"],[29,"Suci Nur Azahra"],[30,"Syah Uitta Jihan Makaela"],[31,"Varisca Indri Ariani"],[32,"Vilsa Safa Azzahra"],[33,"Yuanita Robbitotun Naja"],[34,"Zuni Arifah"]],"X TB2":[[1,"Adinda Eka Nur Aini"],[2,"Adinda Permata Sari"],[3,"Amanda Puspa Maharani"],[4,"Ana Amelliya"],[5,"Auliya Natasya Dewi"],[6,"Ayub Maulana"],[7,"Bilqis Ngizzatun Nisa'"],[8,"Ceysa Elvina Amanda"],[9,"Citra Aulia Baharizqi"],[10,"Desta Aura Azalia Sani"],[11,"Dinda Nurul Amalia"],[12,"Dwi Mayangsari"],[13,"Efrida Dewi Ananda"],[14,"Emi Rara Pramudita"],[15,"Firman Arya Dinaia"],[16,"Keisya Alisya Putri Ali"],[17,"Kusnul Kusuma Wardhani"],[18,"Liby Arumbiya"],[19,"Lutfia Putri"],[20,"Mariska Nur Aira"],[21,"Nadia Nur Azizah Irysati"],[22,"Nahla Aulia Salsabilla"],[23,"Naura Iza Azahra"],[24,"Nazwa Akayla Saputri"],[25,"Novita Adha Rizki Anggraini"],[26,"Pembayun Angger Widjaya"],[27,"Revalia Novianti Tamara"],[28,"Sahal Hanif Yusuf"],[29,"Sekar Wangi"],[30,"Silvi Dwi Noviyanti"],[31,"Sirvi Khunaifiyah Lina Aini Nisa"],[32,"Vito Adi Candra"],[33,"Zahwa"],[34,"Zidannaj Marosat"]],"X TO1":[[1,"Achmat Sapta Arya"],[2,"Ade Fasiyan Nando"],[3,"Albertus Adelio Ronald Fagundez"],[4,"Allan Fadli Muhammad Jibranni"],[5,"Arga Syarul Setiyawan"],[6,"Deddy Setiyawan"],[7,"Denniz Pradivta Alviandra"],[8,"Dimas Putra Erlangga"],[9,"Diyas Prasetyo"],[10,"Dzakie Az Zaahii"],[11,"Fadhil Diantoro"],[12,"Faqih Ubaidillah"],[13,"Faqiyuddin Asyraf"],[14,"Hanif Taufiqulhaqim"],[15,"Iqbal Haidar Ariq"],[16,"Irfan Bagas Vebyantino"],[17,"Marcelino Adi Santoso"],[18,"Muhamad Aftah Farkhan Naka"],[19,"Muhamad Amar Ma'Ruf"],[20,"Muhamad Ilham Prasetyo"],[21,"Muhammad Afwan Maulana Azidan"],[22,"Muhammad Kafa Bihi Fadlurrozag"],[23,"Muhammad Sony Tafrikhan"],[24,"Muhammad Syahid Syahputra"],[25,"Muhammad Zahrul Ulum Al Busthomi"],[26,"Nando Kurnia Eka Putra"],[27,"Naufal Zaky Muttaqin"],[28,"Nizham Zafir Hariz Saputra"],[29,"Nur Fathur Rahmatullah"],[30,"Raditya Putra Perdana"],[31,"Rafka Maulana Putra"],[32,"Raka Rafif Azmi"],[33,"Reyhan Yunazta Putra Hany"],[34,"Rizki Ibadallah Albaroya"],[35,"Septian Danang Prasetyo"],[36,"Yehuda Bayu Seno Abimanyu"]],"X TO2":[[1,"Adham Dzaki Ibrahim Mufid"],[2,"Aflah Raphael Windra Raditya"],[3,"Ahmad Davi Pria Utama"],[4,"Ahmad Maulana Abdul Malik"],[5,"Ahmad Shovi Maola"],[6,"Albarasya Herman"],[7,"Andik Febri Firmansyah"],[8,"Dimas Saputra"],[9,"Diska Indra Fata Widakdo"],[10,"Farel Andrian Pratama"],[11,"Ferdita Fatma Kusuma"],[12,"Galih Ginanjar Saputro"],[13,"Levi Fastabikhul Khoir"],[14,"Lionel Nathan Kurniawan"],[15,"Muhamad Firdiansyah"],[16,"Muhamad Khoirul Anwar"],[17,"Muhamad Rijal Alif Ibrahim"],[18,"Muhamad Tanfebro Permana"],[19,"Muhammad Akmal Farizky"],[20,"Muhammad Alwi Sihab"],[21,"Muhammad 'Aqila Azka"],[22,"Muhammad Fatih"],[23,"Muhammad Fauzi Novantyo"],[24,"Muhammad Rafka Adi Pratama"],[25,"Muhammad Toni Suprasetyo"],[26,"Novan Ananda Rizky"],[27,"Prakasa Tegar Andriyanto"],[28,"Rafael Bayu Pratama"],[29,"Randi Khoirul Azzam"],[30,"Ridho Amru Bain"],[31,"Sabri Radhitya Ganeswara"],[32,"Satria Firman Wibowo"],[33,"Syarif Hidayad"],[34,"Wildan Rizqi Arrumman"],[35,"Vicky Adika Chandra"]],"X TJKT1":[[1,"Adly Surya Hernawan"],[2,"Adrianus Ferdinand Barra Ardiona"],[3,"Aisyah Khoirun Nisa"],[4,"Alif Evan Sanjaya"],[5,"Alif Maulana Ashidiqie"],[6,"Alif Rizqullah Ramadhan"],[7,"Andika Billie Faustino"],[8,"Arvin Aryaseta Atmaja"],[9,"Bryliana Jihan Amir"],[10,"Dandry Kornelius Arisandi"],[11,"Daniel Revelino Feivel Widjanarko"],[12,"Dwi Apriella Nur Rahma"],[13,"Guntur Saktiawan"],[14,"Hanar Fairus Nadhir Amrullah"],[15,"Hani Dwi Rahmawati"],[16,"Ikhsan Abdul Rozak"],[17,"Javien Putra Mahendra"],[18,"Linda Putri Darmawan"],[19,"Lingga Mahardika Susatyo"],[20,"Muazarah Farras Amelia"],[21,"Muhammad Fa'Dlil Asyhari"],[22,"Muhammad Faqih Anwari"],[23,"Muhammad Sidiq Fathul Mu'Iz"],[24,"Nailatussakinah"],[25,"Najma Aulya"],[26,"Nazila Karrolina Aishi Azzahra"],[27,"Rakhul Surya Permana"],[28,"Raya Ghania Putri"],[29,"Revalina Aulia Zahra"],[30,"Salma Anggun Aurellia"],[31,"Sanrez Reksi Kusuma"],[32,"Setiya Rizky Maulana"],[33,"Shara Fatika Addahlani"],[34,"Sinta Puspa Sari"],[35,"Zulfa Ibnul Karim"]],"X TJKT2":[[1,"Akhmad Fakhri Hidayat"],[2,"Alia Nur Aisyah"],[3,"Andika Maulana Muhaimin"],[4,"Andriansyah Maulana"],[5,"Anum Manuraga"],[6,"Brianda Octa Pratama"],[7,"David Luqman"],[8,"Devandri Kusuma"],[9,"Dimas Salman Khafi"],[10,"Divani Aulia Najmi"],[11,"Dwi Ayu Saskiya"],[12,"Dyllan Deep Yoshan"],[13,"Dzikri Maulana"],[14,"Farel Radhitya Pradana"],[15,"Ghifari Sahila Dzaki"],[16,"Indah Nazifa"],[17,"Jati Weko Adi"],[18,"Jeriko Pranata"],[19,"Khoirul Muna"],[20,"Maylinda Qhonita Putri"],[21,"Miftakhul Adiyansyah"],[22,"Muhamad Restu Fauzi"],[23,"Muhammad Abadi"],[24,"Muhammad Faiz Firmansyah"],[25,"Muhammad Irfan Saputra"],[26,"Muhammad Reva Ibrahimmuviq"],[27,"Naja Adkar Khair"],[28,"Nizam Jati Wardoyo"],[29,"Nur Fidyah"],[30,"Okfal Nova Puji Satriawan"],[31,"Quinsha Virosya Pricillia"],[32,"Reza Hafid Ariyanto"],[33,"Ricky Ardiansyah"],[34,"Siti Ernawati"],[35,"Syahrina Laila Farhana"],[36,"Wildan Setio Firmansyah"]]}
;

function initIdentitasADFL(){
  var kelasSel = document.getElementById('kelasADFL');
  var noAbsenSel = document.getElementById('noAbsenADFL');
  var namaInput = document.getElementById('namaADFL');
  if(!kelasSel || !noAbsenSel || !namaInput){
    console.error('Field identitas (Kelas/No. Absen/Nama) tidak ditemukan di halaman - cek id kelasADFL/noAbsenADFL/namaADFL.');
    return;
  }
  kelasSel.addEventListener('change', function(e){
    var kelasVal = e.target.value;
    namaInput.value='';
    if(!kelasVal || !STUDENTS[kelasVal]){
      noAbsenSel.disabled=true;
      noAbsenSel.innerHTML='&lt;option value=""&gt;- Pilih kelas dulu -&lt;/option&gt;';
      namaInput.placeholder='- Pilih no. absen dulu -';
      return;
    }
    noAbsenSel.disabled=false;
    var opts = ['&lt;option value=""&gt;- Pilih No. Absen -&lt;/option&gt;'].concat(
      STUDENTS[kelasVal].map(function(s){ return '&lt;option value="'+s[0]+'"&gt;'+s[0]+'&lt;/option&gt;'; })
    );
    noAbsenSel.innerHTML = opts.join('');
    namaInput.placeholder='- Pilih no. absen dulu -';
  });

  noAbsenSel.addEventListener('change', function(e){
    var kelasVal = kelasSel.value;
    var noVal = parseInt(e.target.value);
    if(!kelasVal || !STUDENTS[kelasVal] || !noVal){ namaInput.value=''; namaInput.placeholder='- Pilih no. absen dulu -'; return; }
    var found = STUDENTS[kelasVal].find(function(s){ return s[0]===noVal; });
    namaInput.value = found ? found[1] : '';
    if(!found) namaInput.placeholder='Nama tidak ditemukan - hubungi guru';
  });
}

if(document.readyState === 'loading'){
  document.addEventListener('DOMContentLoaded', initIdentitasADFL);
} else {
  initIdentitasADFL();
}

// ===================== DATA AWAL (TUNGGAL - KOPERASI SEKOLAH) =====================
const DATA = {
  kolomA:"Nama Bahan/Jasa", kolomB:"Kategori",
  items:[
    ["Buku Tulis (pack)","Alat Tulis",42,18000,"AT01A"],
    ["Pulpen (pack)","Alat Tulis",55,15000,"AT02A"],
    ["Snack Ringan (pcs)","Makanan",80,5000,"MK01B"],
    ["Air Mineral (botol)","Minuman",95,4000,"MN01B"],
    ["Masker Medis (box)","Kesehatan",20,25000,"KS01C"],
    ["Map Plastik (pcs)","Alat Tulis",38,6000,"AT03A"],
    ["Jasa Fotokopi","Jasa",12,50000,"JS01D"],
    ["Jasa Print Tugas","Jasa",28,7000,"JS02D"]
  ]
};
// Tabel referensi VLOOKUP: Kode Kategori (2 huruf awal Kode Transaksi) -&gt; Diskon (%)
const VLOOKUP_REF = [["AT","Alat Tulis",5],["MK","Makanan",2],["MN","Minuman",2],["KS","Kesehatan",3],["JS","Jasa",0]];
// Tabel referensi HLOOKUP: Status -&gt; Poin Reward
const HLOOKUP_REF = [["Laris","Cukup Laris","Kurang Laris"],[20,10,5]];

let REG = {};
let gridPasteFlag = false;

function buildDataAwalTable(data){
  let html = `&lt;table class="compare"&gt;&lt;tr&gt;&lt;th&gt;Baris&lt;/th&gt;&lt;th&gt;${data.kolomA}&lt;/th&gt;&lt;th&gt;${data.kolomB}&lt;/th&gt;&lt;th&gt;Jumlah Terjual&lt;/th&gt;&lt;th&gt;Harga Satuan&lt;/th&gt;&lt;th&gt;Kode Transaksi&lt;/th&gt;&lt;/tr&gt;`;
  data.items.forEach((item,i)=&gt;{
    html += `&lt;tr&gt;&lt;td&gt;${i+2}&lt;/td&gt;&lt;td&gt;${item[0]}&lt;/td&gt;&lt;td&gt;${item[1]}&lt;/td&gt;&lt;td&gt;${item[2]}&lt;/td&gt;&lt;td&gt;${item[3].toLocaleString('id-ID')}&lt;/td&gt;&lt;td&gt;${item[4]}&lt;/td&gt;&lt;/tr&gt;`;
  });
  html += '&lt;/table&gt;';
  return html;
}

function buildInstruksiSteps(data){
  return [
    `Ketikkan data &lt;strong&gt;${data.kolomA}&lt;/strong&gt;, &lt;strong&gt;${data.kolomB}&lt;/strong&gt;, &lt;strong&gt;Jumlah Terjual&lt;/strong&gt;, dan &lt;strong&gt;Harga Satuan&lt;/strong&gt; sesuai cell masing-masing pada kolom A sampai D (baris 2 sampai 9), seperti contoh pada tabel Data Awal di atas.`,
    `Ketikkan &lt;strong&gt;Kode Transaksi&lt;/strong&gt; pada kolom G (baris 2 sampai 9) sesuai contoh pada tabel Data Awal di atas - kode ini akan dipakai oleh fungsi STRING dan Lookup di langkah berikutnya.`,
    `Hitunglah kolom &lt;strong&gt;TOTAL&lt;/strong&gt; (kolom E) dengan ketentuan Jumlah Terjual dikalikan Harga Satuan.&lt;br&gt;Cara: klik cell E2 &amp;gt; ketik &lt;span class="mono"&gt;=C2*D2&lt;/span&gt; &amp;gt; tekan Enter, lalu ulangi untuk E3 sampai E9.`,
    `Isilah kolom &lt;strong&gt;STATUS&lt;/strong&gt; (kolom F) menggunakan rumus IF bertingkat (nested IF): jika Jumlah Terjual 30 kali atau lebih maka "Laris", jika 15 sampai 29 kali maka "Cukup Laris", selain itu "Kurang Laris".&lt;br&gt;Cara: klik cell F2 &amp;gt; ketik &lt;span class="mono"&gt;=IF(C2&amp;gt;=30,"Laris",IF(C2&amp;gt;=15,"Cukup Laris","Kurang Laris"))&lt;/span&gt; &amp;gt; tekan Enter, lalu ulangi untuk F3 sampai F9.`,
    `Hitunglah &lt;strong&gt;Total Keseluruhan&lt;/strong&gt; penjualan pada cell E11.&lt;br&gt;Cara: klik cell E11 &amp;gt; ketik &lt;span class="mono"&gt;=SUM(E2:E9)&lt;/span&gt; &amp;gt; tekan Enter.`,
    `Hitunglah &lt;strong&gt;Rata-rata&lt;/strong&gt; Total penjualan pada cell E12.&lt;br&gt;Cara: klik cell E12 &amp;gt; ketik &lt;span class="mono"&gt;=AVERAGE(E2:E9)&lt;/span&gt; &amp;gt; tekan Enter.`,
    `Praktikkan &lt;strong&gt;fungsi lanjutan SUMIF&lt;/strong&gt;: hitung Total Penjualan khusus kategori "Alat Tulis" pada cell E13.&lt;br&gt;Cara: klik cell E13 &amp;gt; ketik &lt;span class="mono"&gt;=SUMIF(B2:B9,"Alat Tulis",E2:E9)&lt;/span&gt; &amp;gt; tekan Enter.`,
    `Praktikkan &lt;strong&gt;fungsi lanjutan COUNTIF&lt;/strong&gt;: hitung banyaknya jenis barang/jasa kategori "Alat Tulis" pada cell E14.&lt;br&gt;Cara: klik cell E14 &amp;gt; ketik &lt;span class="mono"&gt;=COUNTIF(B2:B9,"Alat Tulis")&lt;/span&gt; &amp;gt; tekan Enter.`,
    `Praktikkan &lt;strong&gt;fungsi STRING LEFT&lt;/strong&gt;: ambil 2 huruf pertama Kode Transaksi sebagai Kode Kategori pada kolom H.&lt;br&gt;Cara: klik cell H2 &amp;gt; ketik &lt;span class="mono"&gt;=LEFT(G2,2)&lt;/span&gt; &amp;gt; tekan Enter, lalu ulangi untuk H3 sampai H9.`,
    `Praktikkan &lt;strong&gt;fungsi STRING MID&lt;/strong&gt;: ambil 2 digit Nomor Urut mulai dari karakter ke-3 Kode Transaksi pada kolom I.&lt;br&gt;Cara: klik cell I2 &amp;gt; ketik &lt;span class="mono"&gt;=MID(G2,3,2)&lt;/span&gt; &amp;gt; tekan Enter, lalu ulangi untuk I3 sampai I9.`,
    `Praktikkan &lt;strong&gt;fungsi STRING RIGHT&lt;/strong&gt;: ambil 1 huruf terakhir Kode Transaksi sebagai Kode Gudang pada kolom J.&lt;br&gt;Cara: klik cell J2 &amp;gt; ketik &lt;span class="mono"&gt;=RIGHT(G2,1)&lt;/span&gt; &amp;gt; tekan Enter, lalu ulangi untuk J3 sampai J9.`,
    `Praktikkan &lt;strong&gt;fungsi VLOOKUP&lt;/strong&gt;: cari besar Diskon (%) dari Tabel Referensi VLOOKUP (N2:O6) berdasarkan Kode Kategori pada kolom H, isikan pada kolom K.&lt;br&gt;Cara: klik cell K2 &amp;gt; ketik &lt;span class="mono"&gt;=VLOOKUP(H2,$N$2:$O$6,2,FALSE)&lt;/span&gt; &amp;gt; tekan Enter, lalu ulangi untuk K3 sampai K9.`,
    `Praktikkan &lt;strong&gt;fungsi HLOOKUP&lt;/strong&gt;: cari besar Poin Reward dari Tabel Referensi HLOOKUP (Q2:S3) berdasarkan Status pada kolom F, isikan pada kolom L.&lt;br&gt;Cara: klik cell L2 &amp;gt; ketik &lt;span class="mono"&gt;=HLOOKUP(F2,$Q$2:$S$3,2,FALSE)&lt;/span&gt; &amp;gt; tekan Enter, lalu ulangi untuk L3 sampai L9.`,
    `Klik tombol "Urutkan Berdasarkan Total (Sort)" untuk mempraktikkan fitur &lt;strong&gt;Sort&lt;/strong&gt; - amati data terurut dari penjualan tertinggi ke terendah.`,
    `Klik tombol "Tampilkan Hanya di Atas Rata-rata (Filter)" untuk mempraktikkan fitur &lt;strong&gt;Filter&lt;/strong&gt; data.`,
    `Amati baris dengan Total tertinggi yang otomatis tersorot warna hijau (simulasi &lt;strong&gt;Conditional Formatting&lt;/strong&gt;) serta grafik batang (fitur &lt;strong&gt;Chart&lt;/strong&gt;) yang terbentuk otomatis dari data Total.`,
    `Klik tombol "Hitung Nilai &amp; Kirim ke Guru" untuk melihat penilaian otomatis, tabel hasil akhir, dan Tabel Ringkasan per Kategori (simulasi &lt;strong&gt;PivotTable&lt;/strong&gt;), lalu unduh bukti PDF.`
  ];
}

function statusTier(jumlah){
  if(jumlah&gt;=30) return 'Laris';
  if(jumlah&gt;=15) return 'Cukup Laris';
  return 'Kurang Laris';
}
function buildKeadaanAkhirTable(data){
  const totals = data.items.map(item=&gt;item[2]*item[3]);
  const sum = totals.reduce((a,b)=&gt;a+b,0);
  const avg = sum/totals.length;
  let sumifAlatTulis=0, countifAlatTulis=0;
  data.items.forEach((item,i)=&gt;{ if(item[1]==='Alat Tulis'){ sumifAlatTulis+=totals[i]; countifAlatTulis++; } });
  let html = `&lt;table class="compare"&gt;&lt;tr&gt;&lt;th&gt;Baris&lt;/th&gt;&lt;th&gt;${data.kolomA}&lt;/th&gt;&lt;th&gt;${data.kolomB}&lt;/th&gt;&lt;th&gt;Jumlah Terjual&lt;/th&gt;&lt;th&gt;Harga Satuan&lt;/th&gt;&lt;th&gt;Total&lt;/th&gt;&lt;th&gt;Status&lt;/th&gt;&lt;/tr&gt;`;
  data.items.forEach((item,i)=&gt;{
    html += `&lt;tr&gt;&lt;td&gt;${i+2}&lt;/td&gt;&lt;td&gt;${item[0]}&lt;/td&gt;&lt;td&gt;${item[1]}&lt;/td&gt;&lt;td&gt;${item[2]}&lt;/td&gt;&lt;td&gt;${item[3].toLocaleString('id-ID')}&lt;/td&gt;&lt;td&gt;${totals[i].toLocaleString('id-ID')}&lt;/td&gt;&lt;td&gt;${statusTier(item[2])}&lt;/td&gt;&lt;/tr&gt;`;
  });
  html += '&lt;/table&gt;';

  html += `&lt;p style="font-size:.78rem; font-weight:600; color:var(--brand-dark); margin-top:14px;"&gt;Hasil Fungsi STRING dan Lookup&lt;/p&gt;`;
  html += `&lt;table class="compare" style="margin-top:4px;"&gt;&lt;tr&gt;&lt;th&gt;Baris&lt;/th&gt;&lt;th&gt;Kode Transaksi&lt;/th&gt;&lt;th&gt;LEFT (Kode Kategori)&lt;/th&gt;&lt;th&gt;MID (No Urut)&lt;/th&gt;&lt;th&gt;RIGHT (Kode Gudang)&lt;/th&gt;&lt;th&gt;VLOOKUP (Diskon %)&lt;/th&gt;&lt;th&gt;HLOOKUP (Poin Reward)&lt;/th&gt;&lt;/tr&gt;`;
  data.items.forEach((item,i)=&gt;{
    const kode = item[4];
    const left = kode.slice(0,2);
    const mid = kode.slice(2,4);
    const right = kode.slice(-1);
    const refRow = VLOOKUP_REF.find(r=&gt;r[0]===left);
    const tier = statusTier(item[2]);
    const poin = tier==='Laris' ? HLOOKUP_REF[1][0] : tier==='Cukup Laris' ? HLOOKUP_REF[1][1] : HLOOKUP_REF[1][2];
    html += `&lt;tr&gt;&lt;td&gt;${i+2}&lt;/td&gt;&lt;td&gt;${kode}&lt;/td&gt;&lt;td&gt;${left}&lt;/td&gt;&lt;td&gt;${mid}&lt;/td&gt;&lt;td&gt;${right}&lt;/td&gt;&lt;td&gt;${refRow?refRow[2]:'-'}%&lt;/td&gt;&lt;td&gt;${poin}&lt;/td&gt;&lt;/tr&gt;`;
  });
  html += '&lt;/table&gt;';

  html += `&lt;table class="compare" style="margin-top:10px;"&gt;&lt;tr&gt;&lt;th&gt;Ringkasan (E11-E14)&lt;/th&gt;&lt;th&gt;Nilai Patokan&lt;/th&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;Total Keseluruhan (SUM)&lt;/td&gt;&lt;td&gt;${sum.toLocaleString('id-ID')}&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;Rata-rata (AVERAGE)&lt;/td&gt;&lt;td&gt;${avg.toLocaleString('id-ID')}&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;Total Kategori "Alat Tulis" (SUMIF)&lt;/td&gt;&lt;td&gt;${sumifAlatTulis.toLocaleString('id-ID')}&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;Jumlah Jenis Kategori "Alat Tulis" (COUNTIF)&lt;/td&gt;&lt;td&gt;${countifAlatTulis}&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;`;
  return html;
}

document.getElementById('dataAwalWrap').innerHTML = buildDataAwalTable(DATA);
document.getElementById('instruksiSteps').innerHTML = buildInstruksiSteps(DATA).map(s=&gt;`&lt;li&gt;${s}&lt;/li&gt;`).join('');
document.getElementById('keadaanAkhirWrap').innerHTML = buildKeadaanAkhirTable(DATA);

function buildRefTableWrap(){
  let html = '&lt;div style="display:flex; flex-wrap:wrap; gap:22px; align-items:flex-start;"&gt;';
  html += '&lt;div&gt;&lt;p class="mono" style="font-size:.74rem; font-weight:700; color:var(--brand-dark); margin-bottom:6px;"&gt;Tabel VLOOKUP (N2:O6) - Kode Kategori &amp;rarr; Diskon %&lt;/p&gt;&lt;table class="excel-grid"&gt;&lt;tr&gt;&lt;th&gt;N (Kode)&lt;/th&gt;&lt;th&gt;Kategori&lt;/th&gt;&lt;th&gt;O (Diskon %)&lt;/th&gt;&lt;/tr&gt;';
  VLOOKUP_REF.forEach((row,i)=&gt;{
    const r=i+2;
    html += `&lt;tr&gt;&lt;td&gt;&lt;input class="sheet-input ref" data-addr="N${r}" value="${row[0]}" readonly&gt;&lt;/td&gt;&lt;td class="g-label"&gt;${row[1]}&lt;/td&gt;&lt;td&gt;&lt;input class="sheet-input ref" data-addr="O${r}" value="${row[2]}" readonly&gt;&lt;/td&gt;&lt;/tr&gt;`;
  });
  html += '&lt;/table&gt;&lt;/div&gt;';
  html += '&lt;div&gt;&lt;p class="mono" style="font-size:.74rem; font-weight:700; color:var(--brand-dark); margin-bottom:6px;"&gt;Tabel HLOOKUP (Q2:S3) - Status &amp;rarr; Poin Reward&lt;/p&gt;&lt;table class="excel-grid"&gt;&lt;tr&gt;&lt;th&gt;&lt;/th&gt;&lt;th&gt;Q&lt;/th&gt;&lt;th&gt;R&lt;/th&gt;&lt;th&gt;S&lt;/th&gt;&lt;/tr&gt;';
  html += `&lt;tr&gt;&lt;th class="rownum"&gt;2&lt;/th&gt;&lt;td&gt;&lt;input class="sheet-input ref" data-addr="Q2" value="${HLOOKUP_REF[0][0]}" readonly&gt;&lt;/td&gt;&lt;td&gt;&lt;input class="sheet-input ref" data-addr="R2" value="${HLOOKUP_REF[0][1]}" readonly&gt;&lt;/td&gt;&lt;td&gt;&lt;input class="sheet-input ref" data-addr="S2" value="${HLOOKUP_REF[0][2]}" readonly&gt;&lt;/td&gt;&lt;/tr&gt;`;
  html += `&lt;tr&gt;&lt;th class="rownum"&gt;3&lt;/th&gt;&lt;td&gt;&lt;input class="sheet-input ref" data-addr="Q3" value="${HLOOKUP_REF[1][0]}" readonly&gt;&lt;/td&gt;&lt;td&gt;&lt;input class="sheet-input ref" data-addr="R3" value="${HLOOKUP_REF[1][1]}" readonly&gt;&lt;/td&gt;&lt;td&gt;&lt;input class="sheet-input ref" data-addr="S3" value="${HLOOKUP_REF[1][2]}" readonly&gt;&lt;/td&gt;&lt;/tr&gt;`;
  html += '&lt;/table&gt;&lt;/div&gt;';
  html += '&lt;/div&gt;';
  return html;
}

function renderGrid(){
  const data = DATA;
  document.getElementById('refTableWrap').innerHTML = buildRefTableWrap();
  let rows = '';
  rows += `&lt;tr&gt;&lt;th&gt;&lt;/th&gt;&lt;th&gt;A&lt;/th&gt;&lt;th&gt;B&lt;/th&gt;&lt;th&gt;C&lt;/th&gt;&lt;th&gt;D&lt;/th&gt;&lt;th&gt;E&lt;/th&gt;&lt;th&gt;F&lt;/th&gt;&lt;th&gt;G&lt;/th&gt;&lt;th&gt;H&lt;/th&gt;&lt;th&gt;I&lt;/th&gt;&lt;th&gt;J&lt;/th&gt;&lt;th&gt;K&lt;/th&gt;&lt;th&gt;L&lt;/th&gt;&lt;/tr&gt;`;
  rows += `&lt;tr&gt;&lt;th class="rownum"&gt;1&lt;/th&gt;&lt;td class="g-label"&gt;${data.kolomA}&lt;/td&gt;&lt;td class="g-label"&gt;${data.kolomB}&lt;/td&gt;&lt;td class="g-label"&gt;Jumlah Terjual&lt;/td&gt;&lt;td class="g-label"&gt;Harga Satuan&lt;/td&gt;&lt;td class="g-label"&gt;Total&lt;/td&gt;&lt;td class="g-label"&gt;Status&lt;/td&gt;&lt;td class="g-label"&gt;Kode Transaksi&lt;/td&gt;&lt;td class="g-label"&gt;Kode Kategori (LEFT)&lt;/td&gt;&lt;td class="g-label"&gt;No Urut (MID)&lt;/td&gt;&lt;td class="g-label"&gt;Kode Gudang (RIGHT)&lt;/td&gt;&lt;td class="g-label"&gt;Diskon % (VLOOKUP)&lt;/td&gt;&lt;td class="g-label"&gt;Poin Reward (HLOOKUP)&lt;/td&gt;&lt;/tr&gt;`;
  data.items.forEach((item,i)=&gt;{
    const r=i+2;
    rows += `&lt;tr&gt;
      &lt;th class="rownum"&gt;${r}&lt;/th&gt;
      &lt;td&gt;&lt;input type="text" class="sheet-input plain" data-addr="A${r}" value="" placeholder="Baris ${r} - lihat Data Awal"&gt;&lt;/td&gt;
      &lt;td&gt;&lt;input type="text" class="sheet-input plain" data-addr="B${r}" value="" placeholder="Kategori"&gt;&lt;/td&gt;
      &lt;td&gt;&lt;input type="number" class="sheet-input plain" data-addr="C${r}" value="" placeholder="Jumlah"&gt;&lt;/td&gt;
      &lt;td&gt;&lt;input type="number" class="sheet-input plain" data-addr="D${r}" value="" placeholder="Harga"&gt;&lt;/td&gt;
      &lt;td&gt;&lt;input type="text" class="sheet-input formula" data-addr="E${r}" data-raw="" placeholder="=C${r}*D${r}"&gt;&lt;/td&gt;
      &lt;td&gt;&lt;input type="text" class="sheet-input formula" data-addr="F${r}" data-raw="" placeholder='=IF(C${r}&amp;gt;=30,"Laris",IF(C${r}&amp;gt;=15,"Cukup Laris","Kurang Laris"))'&gt;&lt;/td&gt;
      &lt;td&gt;&lt;input type="text" class="sheet-input plain" data-addr="G${r}" value="" placeholder="Kode Transaksi"&gt;&lt;/td&gt;
      &lt;td&gt;&lt;input type="text" class="sheet-input formula" data-addr="H${r}" data-raw="" placeholder="=LEFT(G${r},2)"&gt;&lt;/td&gt;
      &lt;td&gt;&lt;input type="text" class="sheet-input formula" data-addr="I${r}" data-raw="" placeholder="=MID(G${r},3,2)"&gt;&lt;/td&gt;
      &lt;td&gt;&lt;input type="text" class="sheet-input formula" data-addr="J${r}" data-raw="" placeholder="=RIGHT(G${r},1)"&gt;&lt;/td&gt;
      &lt;td&gt;&lt;input type="text" class="sheet-input formula" data-addr="K${r}" data-raw="" placeholder="=VLOOKUP(H${r},$N$2:$O$6,2,FALSE)"&gt;&lt;/td&gt;
      &lt;td&gt;&lt;input type="text" class="sheet-input formula" data-addr="L${r}" data-raw="" placeholder="=HLOOKUP(F${r},$Q$2:$S$3,2,FALSE)"&gt;&lt;/td&gt;
    &lt;/tr&gt;`;
  });
  rows += `&lt;tr&gt;&lt;td colspan="13" style="height:6px; border:none; background:transparent;"&gt;&lt;/td&gt;&lt;/tr&gt;`;
  const sumRows = [
    ['11','Total Keseluruhan','E11', `=SUM(E2:E9)`],
    ['12','Rata-rata Penjualan','E12', `=AVERAGE(E2:E9)`],
    ['13','Total Kategori "Alat Tulis" (SUMIF)','E13', `=SUMIF(B2:B9,"Alat Tulis",E2:E9)`],
    ['14','Jumlah Jenis Kategori "Alat Tulis" (COUNTIF)','E14', `=COUNTIF(B2:B9,"Alat Tulis")`]
  ];
  sumRows.forEach(sr=&gt;{
    rows += `&lt;tr&gt;
      &lt;th class="rownum"&gt;${sr[0]}&lt;/th&gt;
      &lt;td class="g-label" colspan="4"&gt;${sr[1]}&lt;/td&gt;
      &lt;td&gt;&lt;input type="text" class="sheet-input formula" data-addr="${sr[2]}" data-raw="" placeholder="${sr[3]}"&gt;&lt;/td&gt;
      &lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;
    &lt;/tr&gt;`;
  });
  document.getElementById('gridWrap').innerHTML = `&lt;table class="excel-grid sheet-grid"&gt;${rows}&lt;/table&gt;`;
  gridPasteFlag = false;
  const warnEl = document.getElementById('pasteWarning');
  if(warnEl) warnEl.classList.remove('show');
  bindGridEvents();
  recalcAll();
}

function bindGridEvents(){
  document.querySelectorAll('.sheet-input').forEach(inp=&gt;{
    if(inp.classList.contains('ref')) return;
    inp.addEventListener('paste', (e)=&gt;{
      e.preventDefault();
      gridPasteFlag = true;
      const warnEl = document.getElementById('pasteWarning');
      if(warnEl) warnEl.classList.add('show');
    });
    if(inp.classList.contains('formula')){
      inp.addEventListener('focus', ()=&gt;{ inp.value = inp.dataset.raw || ''; });
      inp.addEventListener('input', ()=&gt;{ inp.dataset.raw = inp.value; recalcAll(inp); });
    } else {
      inp.addEventListener('input', ()=&gt;{ recalcAll(); });
    }
    inp.addEventListener('blur', ()=&gt;{ recalcAll(); });
  });
}

// ===================== FORMULA ENGINE =====================
function buildRegistry(){
  const reg = {};
  document.querySelectorAll('.sheet-input').forEach(inp=&gt;{ reg[inp.dataset.addr]=inp; });
  return reg;
}
function cellRawValue(addr){
  const el = REG[addr];
  if(!el) return '';
  if(el.classList.contains('formula')) return el.dataset.raw!==undefined ? el.dataset.raw : '';
  return el.value;
}
function evalAddr(addr, stack){
  addr = addr.toUpperCase().replace(/\$/g,'');
  if(stack.has(addr)) return 0;
  const raw = cellRawValue(addr);
  const s = String(raw===undefined||raw===null?'':raw).trim();
  if(s==='') return 0;
  if(s.startsWith('=')){
    stack.add(addr);
    const v = evalFormula(s.slice(1), stack);
    stack.delete(addr);
    return v;
  }
  const num = parseFloat(s);
  return isNaN(num) ? s : num;
}
function expandRange(a,b){
  const ma=a.match(/([A-Z]+)(\d+)/), mb=b.match(/([A-Z]+)(\d+)/);
  if(!ma||!mb) return [];
  const c1=ma[1].charCodeAt(0), c2=mb[1].charCodeAt(0);
  const r1=parseInt(ma[2]), r2=parseInt(mb[2]);
  const addrs=[];
  for(let c=Math.min(c1,c2); c&lt;=Math.max(c1,c2); c++){
    for(let r=Math.min(r1,r2); r&lt;=Math.max(r1,r2); r++) addrs.push(String.fromCharCode(c)+r);
  }
  return addrs;
}
function rangeValues(rangeStr, stack){
  const parts = rangeStr.split(':');
  if(parts.length!==2) return [];
  const addrs = expandRange(parts[0].replace(/\$/g,''), parts[1].replace(/\$/g,''));
  return addrs.map(addr=&gt;{ const v=evalAddr(addr, stack); const n=typeof v==='number'?v:parseFloat(v); return isNaN(n)?0:n; });
}
function resolveRefsInExpr(s, stack){
  return s.replace(/\$?([A-Z]{1,2})\$?(\d{1,3})/g, (m,col,row)=&gt;{
    const v=evalAddr(col+row, stack);
    return typeof v==='number' ? v : JSON.stringify(v);
  });
}
function evalAddr0(tok, stack){
  const t=tok.trim();
  if(/^\$?[A-Z]{1,2}\$?\d{1,3}$/.test(t)) return evalAddr(t.replace(/\$/g,''), stack);
  const n=parseFloat(t);
  return isNaN(n)?0:n;
}
function splitArgs(s){
  const args=[]; let depth=0, cur='', inQ=false;
  for(let i=0;i&lt;s.length;i++){
    const ch=s[i];
    if(ch==='"') inQ=!inQ;
    if(ch===',' &amp;&amp; !inQ &amp;&amp; depth===0){ args.push(cur); cur=''; continue; }
    if(ch==='(') depth++;
    if(ch===')') depth--;
    cur+=ch;
  }
  if(cur.trim().length || args.length) args.push(cur);
  return args.map(a=&gt;a.trim());
}
function resolveCriteriaArg(a, stack){
  let t = a.trim();
  if(/^".*"$/.test(t)) return t.slice(1,-1);
  if(/^\$?[A-Z]{1,2}\$?\d{1,3}$/.test(t)) return evalAddr(t.replace(/\$/g,''), stack);
  return t;
}
function matchCriteria(val, crit){
  crit = String(crit).trim();
  const m = crit.match(/^(&gt;=|&lt;=|&lt;&gt;|&gt;|&lt;|=)(.*)$/);
  if(m){
    const op = m[1]; const rhsRaw = m[2].trim();
    const rhsNum = parseFloat(rhsRaw);
    const valNum = parseFloat(val);
    if(!isNaN(rhsNum) &amp;&amp; !isNaN(valNum) &amp;&amp; String(rhsRaw).match(/^-?\d+(\.\d+)?$/)){
      switch(op){
        case '&gt;=': return valNum&gt;=rhsNum;
        case '&lt;=': return valNum&lt;=rhsNum;
        case '&gt;': return valNum&gt;rhsNum;
        case '&lt;': return valNum&lt;rhsNum;
        case '&lt;&gt;': return valNum!==rhsNum;
        case '=': return valNum===rhsNum;
      }
    }
    switch(op){
      case '&lt;&gt;': return String(val).trim().toLowerCase()!==rhsRaw.toLowerCase();
      case '=': return String(val).trim().toLowerCase()===rhsRaw.toLowerCase();
      default: return false;
    }
  }
  const critNum = parseFloat(crit);
  const valNum = parseFloat(val);
  if(!isNaN(critNum) &amp;&amp; String(crit).trim().match(/^-?\d+(\.\d+)?$/) &amp;&amp; !isNaN(valNum)) return valNum===critNum;
  return String(val).trim().toLowerCase()===crit.toLowerCase();
}
function computeFunc(fn, argsStr, stack){
  const args = splitArgs(argsStr);
  if(['SUM','AVERAGE','MAX','MIN','COUNT','COUNTA'].includes(fn)){
    let vals=[];
    args.forEach(a=&gt;{
      if(/^\$?[A-Z]{1,2}\$?\d{1,3}:\$?[A-Z]{1,2}\$?\d{1,3}$/.test(a)) vals=vals.concat(rangeValues(a, stack));
      else vals.push(evalAddr0(a, stack));
    });
    if(fn==='SUM') return String(vals.reduce((x,y)=&gt;x+y,0));
    if(fn==='AVERAGE') return String(vals.length?vals.reduce((x,y)=&gt;x+y,0)/vals.length:0);
    if(fn==='MAX') return String(vals.length?Math.max(...vals):0);
    if(fn==='MIN') return String(vals.length?Math.min(...vals):0);
    if(fn==='COUNT') return String(vals.filter(v=&gt;!isNaN(v)).length);
    if(fn==='COUNTA') return String(vals.length);
  }
  if(fn==='SUMIF' || fn==='COUNTIF'){
    const rangeStr = args[0].replace(/\$/g,'');
    const addrs = rangeStr.includes(':') ? expandRange(rangeStr.split(':')[0], rangeStr.split(':')[1]) : [rangeStr];
    const criteria = resolveCriteriaArg(args[1], stack);
    let sumAddrs = addrs;
    if(fn==='SUMIF' &amp;&amp; args[2]){
      const sumRangeStr = args[2].replace(/\$/g,'');
      sumAddrs = sumRangeStr.includes(':') ? expandRange(sumRangeStr.split(':')[0], sumRangeStr.split(':')[1]) : [sumRangeStr];
    }
    let count=0, sum=0;
    addrs.forEach((addr,i)=&gt;{
      const val = evalAddr(addr, stack);
      if(matchCriteria(val, criteria)){
        count++;
        if(fn==='SUMIF'){
          const sAddr = sumAddrs[i]!==undefined ? sumAddrs[i] : addr;
          const sv = evalAddr(sAddr, stack);
          const n = typeof sv==='number'?sv:parseFloat(sv);
          sum += isNaN(n)?0:n;
        }
      }
    });
    return fn==='SUMIF' ? String(sum) : String(count);
  }
  if(fn==='ROUND'){
    const resolved = resolveRefsInExpr(args[0], stack);
    const val = parseFloat(resolved)||0;
    const digits = parseInt(args[1])||0;
    return String(Math.round(val*Math.pow(10,digits))/Math.pow(10,digits));
  }
  if(fn==='LEFT'||fn==='RIGHT'||fn==='MID'||fn==='LEN'){
    const text = String(resolveCriteriaArg(args[0], stack));
    if(fn==='LEN') return String(text.length);
    if(fn==='LEFT'){
      const n = args[1]!==undefined ? (parseInt(resolveCriteriaArg(args[1], stack))||0) : 1;
      return JSON.stringify(text.slice(0, n));
    }
    if(fn==='RIGHT'){
      const n = args[1]!==undefined ? (parseInt(resolveCriteriaArg(args[1], stack))||0) : 1;
      return JSON.stringify(n&gt;0 ? text.slice(-n) : '');
    }
    if(fn==='MID'){
      const start = parseInt(resolveCriteriaArg(args[1], stack))||1;
      const n = parseInt(resolveCriteriaArg(args[2], stack))||0;
      return JSON.stringify(text.slice(start-1, start-1+n));
    }
  }
  if(fn==='VLOOKUP' || fn==='HLOOKUP'){
    const lookupVal = resolveCriteriaArg(args[0], stack);
    const tableStr = args[1].replace(/\$/g,'');
    const [startAddr, endAddr] = tableStr.split(':');
    const mA = startAddr.match(/([A-Z]+)(\d+)/), mB = endAddr.match(/([A-Z]+)(\d+)/);
    const colStart = mA[1].charCodeAt(0), colEnd = mB[1].charCodeAt(0);
    const rowStart = parseInt(mA[2]), rowEnd = parseInt(mB[2]);
    const idx = parseInt(resolveCriteriaArg(args[2], stack))||1;
    let result = '#N/A';
    if(fn==='VLOOKUP'){
      for(let r=rowStart; r&lt;=rowEnd; r++){
        const firstVal = evalAddr(String.fromCharCode(colStart)+r, stack);
        if(String(firstVal).trim().toLowerCase()===String(lookupVal).trim().toLowerCase()){
          const targetCol = colStart + idx - 1;
          result = evalAddr(String.fromCharCode(targetCol)+r, stack);
          break;
        }
      }
    } else {
      for(let c=colStart; c&lt;=colEnd; c++){
        const firstVal = evalAddr(String.fromCharCode(c)+rowStart, stack);
        if(String(firstVal).trim().toLowerCase()===String(lookupVal).trim().toLowerCase()){
          const targetRow = rowStart + idx - 1;
          result = evalAddr(String.fromCharCode(c)+targetRow, stack);
          break;
        }
      }
    }
    return typeof result==='number' ? String(result) : JSON.stringify(result);
  }
  if(fn==='AND'||fn==='OR'){
    const bools = args.map(a=&gt;{
      const resolved = resolveRefsInExpr(a, stack);
      try{ return !!Function('"use strict"; return ('+resolved+')')(); }catch(e){ return false; }
    });
    const result = fn==='AND' ? bools.every(Boolean) : bools.some(Boolean);
    return String(result);
  }
  if(fn==='IF'){
    const condResolved = resolveRefsInExpr(args[0], stack);
    let condVal=false;
    try{ condVal = !!Function('"use strict"; return ('+condResolved+')')(); }catch(e){ condVal=false; }
    return condVal ? args[1] : args[2];
  }
  return '0';
}
function evalFormula(expr, stack){
  expr = expr.trim();
  let changed=true, safety=0;
  while(changed &amp;&amp; safety&lt;40){
    changed=false; safety++;
    const next = expr.replace(/\b(VLOOKUP|HLOOKUP|SUMIF|COUNTIF|LEFT|RIGHT|MID|LEN|SUM|AVERAGE|MAX|MIN|COUNT|COUNTA|ROUND|AND|OR|IF)\s*\(([^()]*)\)/i, (m, fn, argsStr)=&gt;{
      changed=true;
      return computeFunc(fn.toUpperCase(), argsStr, stack);
    });
    expr = next;
  }
  expr = expr.replace(/\$?([A-Z]{1,2})\$?(\d{1,3})/g, (m, col, row)=&gt;{
    const v = evalAddr(col+row, stack);
    return typeof v==='number' ? v : JSON.stringify(v);
  });
  try{
    return Function('"use strict"; return ('+expr+')')();
  }catch(e){ return '#ERROR'; }
}
function formatNum(n){
  if(Number.isInteger(n)) return String(n);
  return (Math.round(n*100)/100).toString();
}
function recalcAll(activeInput){
  REG = buildRegistry();
  document.querySelectorAll('.sheet-input.formula').forEach(inp=&gt;{
    if(inp===activeInput || inp===document.activeElement) return;
    const addr = inp.dataset.addr;
    const raw = (inp.dataset.raw!==undefined ? inp.dataset.raw : '').trim();
    if(raw===''){ inp.value=''; inp.classList.remove('err'); return; }
    let val;
    try{ val = raw.startsWith('=') ? evalFormula(raw.slice(1), new Set()) : raw; }
    catch(e){ val='#ERROR'; }
    if(val==='#ERROR' || (typeof val==='number' &amp;&amp; Number.isNaN(val))){
      inp.value='#ERROR'; inp.classList.add('err');
    } else {
      inp.classList.remove('err');
      inp.value = (typeof val==='number') ? formatNum(val) : val;
    }
  });
  highlightTopRow();
  drawChart();
}
function highlightTopRow(){
  let maxVal=-Infinity, maxRow=null;
  for(let r=2;r&lt;=9;r++){
    const el=REG['E'+r];
    if(!el) continue;
    const v=parseFloat(el.value);
    if(!isNaN(v) &amp;&amp; v&gt;maxVal){ maxVal=v; maxRow=r; }
  }
  document.querySelectorAll('#gridWrap tr').forEach(tr=&gt;tr.classList.remove('hi-max'));
  if(maxRow){
    const marker=REG['E'+maxRow];
    if(marker){ const tr=marker.closest('tr'); if(tr) tr.classList.add('hi-max'); }
  }
}
function drawChart(){
  const canvas=document.getElementById('dataChart');
  if(!canvas) return;
  const ctx=canvas.getContext('2d');
  const w=canvas.width, h=canvas.height;
  ctx.clearRect(0,0,w,h);
  const vals=[];
  for(let r=2;r&lt;=9;r++){
    const el=REG['E'+r];
    const v=el?parseFloat(el.value):NaN;
    vals.push(isNaN(v)?0:v);
  }
  const maxV=Math.max(...vals,1);
  const padding=30, barGap=10;
  const barW=(w-padding*2-barGap*(vals.length-1))/vals.length;
  ctx.textAlign='center'; ctx.font='9px IBM Plex Mono, monospace';
  vals.forEach((v,i)=&gt;{
    const barH = maxV&gt;0 ? (v/maxV)*(h-60) : 0;
    const x = padding + i*(barW+barGap);
    const y = h-30-barH;
    ctx.fillStyle='#15803D';
    ctx.fillRect(x,y,barW,barH);
    ctx.fillStyle='#16221B';
    const aEl = REG['A'+(i+2)];
    const label = (aEl &amp;&amp; aEl.value.trim()) ? aEl.value.trim() : DATA.items[i][0];
    ctx.fillText(label.split(' ')[0], x+barW/2, h-14);
  });
}
function formatRupiah(n){
  if(isNaN(n)) return '-';
  return 'Rp' + Math.round(n).toLocaleString('id-ID');
}

document.getElementById('btnSortGrid').addEventListener('click', ()=&gt;{
  const rows = DATA.items.map((item,i)=&gt;{
    const r=i+2;
    const aEl=REG['A'+r], bEl=REG['B'+r], eEl=REG['E'+r], fEl=REG['F'+r];
    const nama = (aEl &amp;&amp; aEl.value.trim()) ? aEl.value.trim() : '(belum diisi)';
    const kategori = (bEl &amp;&amp; bEl.value.trim()) ? bEl.value.trim() : '-';
    const total = eEl?parseFloat(eEl.value):NaN;
    const status = fEl?fEl.value:'';
    return {nama, kategori, total:isNaN(total)?0:total, status};
  });
  rows.sort((a,b)=&gt;b.total-a.total);
  let html = `&lt;div class="table-scroll"&gt;&lt;table class="compare"&gt;&lt;tr&gt;&lt;th&gt;Peringkat&lt;/th&gt;&lt;th&gt;${DATA.kolomA}&lt;/th&gt;&lt;th&gt;${DATA.kolomB}&lt;/th&gt;&lt;th&gt;Total&lt;/th&gt;&lt;th&gt;Status&lt;/th&gt;&lt;/tr&gt;`;
  rows.forEach((row,i)=&gt;{
    html += `&lt;tr&gt;&lt;td&gt;${i+1}&lt;/td&gt;&lt;td&gt;${row.nama}&lt;/td&gt;&lt;td&gt;${row.kategori}&lt;/td&gt;&lt;td&gt;${formatRupiah(row.total)}&lt;/td&gt;&lt;td&gt;${row.status &amp;&amp; row.status!=='#ERROR' ? row.status : '-'}&lt;/td&gt;&lt;/tr&gt;`;
  });
  html += '&lt;/table&gt;&lt;/div&gt;';
  document.getElementById('sortedResult').innerHTML = html;
});

document.getElementById('btnFilterGrid').addEventListener('click', ()=&gt;{
  REG = buildRegistry();
  const avgEl = REG['E12'];
  const avg = avgEl ? parseFloat(avgEl.value) : NaN;
  if(isNaN(avg)){ document.getElementById('filterResult').innerHTML = '&lt;p style="font-size:.84rem; color:var(--red);"&gt;Isi dahulu rumus Rata-rata (E12) sebelum menggunakan fitur Filter.&lt;/p&gt;'; return; }
  const rows = DATA.items.map((item,i)=&gt;{
    const r=i+2;
    const aEl=REG['A'+r], bEl=REG['B'+r], eEl=REG['E'+r], fEl=REG['F'+r];
    const nama = (aEl &amp;&amp; aEl.value.trim()) ? aEl.value.trim() : '(belum diisi)';
    const kategori = (bEl &amp;&amp; bEl.value.trim()) ? bEl.value.trim() : '-';
    const total = eEl?parseFloat(eEl.value):NaN;
    const status = fEl?fEl.value:'';
    return {nama, kategori, total:isNaN(total)?0:total, status};
  }).filter(row=&gt;row.total&gt;avg);
  let html = `&lt;div class="table-scroll"&gt;&lt;p style="font-size:.8rem; color:var(--ink-soft); margin-bottom:6px;"&gt;Menampilkan baris dengan Total di atas rata-rata (&amp;gt; ${formatRupiah(avg)})&lt;/p&gt;&lt;table class="compare"&gt;&lt;tr&gt;&lt;th&gt;${DATA.kolomA}&lt;/th&gt;&lt;th&gt;${DATA.kolomB}&lt;/th&gt;&lt;th&gt;Total&lt;/th&gt;&lt;th&gt;Status&lt;/th&gt;&lt;/tr&gt;`;
  if(rows.length===0) html += `&lt;tr&gt;&lt;td colspan="4" style="text-align:center; color:var(--ink-soft);"&gt;Tidak ada baris di atas rata-rata&lt;/td&gt;&lt;/tr&gt;`;
  rows.forEach(row=&gt;{
    html += `&lt;tr&gt;&lt;td&gt;${row.nama}&lt;/td&gt;&lt;td&gt;${row.kategori}&lt;/td&gt;&lt;td&gt;${formatRupiah(row.total)}&lt;/td&gt;&lt;td&gt;${row.status &amp;&amp; row.status!=='#ERROR' ? row.status : '-'}&lt;/td&gt;&lt;/tr&gt;`;
  });
  html += '&lt;/table&gt;&lt;/div&gt;';
  document.getElementById('filterResult').innerHTML = html;
});

document.getElementById('btnResetGrid').addEventListener('click', ()=&gt;{
  if(confirm('Reset seluruh rumus pada lembar kerja?')){
    document.getElementById('sortedResult').innerHTML='';
    document.getElementById('filterResult').innerHTML='';
    document.getElementById('resultPanel').style.display='none';
    lastResult = null;
    renderGrid();
  }
});

// ===================== PENILAIAN OTOMATIS =====================
function evaluateWork(){
  REG = buildRegistry();
  const data = DATA;
  const rows = data.items.map((item,i)=&gt;{
    const r=i+2;
    const nama = REG['A'+r] ? REG['A'+r].value.trim() : '';
    const kategori = REG['B'+r] ? REG['B'+r].value.trim() : '';
    const jumlahRaw = REG['C'+r] ? REG['C'+r].value.trim() : '';
    const hargaRaw = REG['D'+r] ? REG['D'+r].value.trim() : '';
    const totalRaw = REG['E'+r] ? REG['E'+r].value : '';
    const statusRaw = REG['F'+r] ? REG['F'+r].value.trim() : '';

    const namaOk = nama.length&gt;0 &amp;&amp; nama.toLowerCase()===item[0].toLowerCase();
    const kategoriOk = kategori.length&gt;0 &amp;&amp; kategori.toLowerCase()===item[1].toLowerCase();
    const jumlahOk = jumlahRaw!=='' &amp;&amp; parseFloat(jumlahRaw)===item[2];
    const hargaOk = hargaRaw!=='' &amp;&amp; parseFloat(hargaRaw)===item[3];

    const expectedTotal = evalFormula(`C${r}*D${r}`, new Set());
    const totalOk = totalRaw!=='' &amp;&amp; totalRaw!=='#ERROR' &amp;&amp; !isNaN(parseFloat(totalRaw)) &amp;&amp; Math.round(parseFloat(totalRaw))===Math.round(expectedTotal);

    const expectedStatus = evalFormula(`IF(C${r}&gt;=30,"Laris",IF(C${r}&gt;=15,"Cukup Laris","Kurang Laris"))`, new Set());
    const statusOk = statusRaw!=='' &amp;&amp; statusRaw!=='#ERROR' &amp;&amp; statusRaw.toLowerCase()===String(expectedStatus).toLowerCase();

    const kodeRaw = REG['G'+r] ? REG['G'+r].value.trim() : '';
    const kodeOk = kodeRaw.length&gt;0 &amp;&amp; kodeRaw.toUpperCase()===item[4].toUpperCase();

    const leftRaw = REG['H'+r] ? REG['H'+r].value.trim() : '';
    const expectedLeft = evalFormula(`LEFT(G${r},2)`, new Set());
    const leftOk = leftRaw!=='' &amp;&amp; leftRaw!=='#ERROR' &amp;&amp; leftRaw.toUpperCase()===String(expectedLeft).toUpperCase();

    const midRaw = REG['I'+r] ? REG['I'+r].value.trim() : '';
    const expectedMid = evalFormula(`MID(G${r},3,2)`, new Set());
    const midOk = midRaw!=='' &amp;&amp; midRaw!=='#ERROR' &amp;&amp; midRaw.toUpperCase()===String(expectedMid).toUpperCase();

    const rightRaw = REG['J'+r] ? REG['J'+r].value.trim() : '';
    const expectedRight = evalFormula(`RIGHT(G${r},1)`, new Set());
    const rightOk = rightRaw!=='' &amp;&amp; rightRaw!=='#ERROR' &amp;&amp; rightRaw.toUpperCase()===String(expectedRight).toUpperCase();

    const vlookupRaw = REG['K'+r] ? REG['K'+r].value.trim() : '';
    const expectedVlookup = evalFormula(`VLOOKUP(H${r},$N$2:$O$6,2,FALSE)`, new Set());
    const vlookupOk = vlookupRaw!=='' &amp;&amp; vlookupRaw!=='#ERROR' &amp;&amp; vlookupRaw!=='#N/A' &amp;&amp; !isNaN(parseFloat(vlookupRaw)) &amp;&amp; !isNaN(parseFloat(expectedVlookup)) &amp;&amp; parseFloat(vlookupRaw)===parseFloat(expectedVlookup);

    const hlookupRaw = REG['L'+r] ? REG['L'+r].value.trim() : '';
    const expectedHlookup = evalFormula(`HLOOKUP(F${r},$Q$2:$S$3,2,FALSE)`, new Set());
    const hlookupOk = hlookupRaw!=='' &amp;&amp; hlookupRaw!=='#ERROR' &amp;&amp; hlookupRaw!=='#N/A' &amp;&amp; !isNaN(parseFloat(hlookupRaw)) &amp;&amp; !isNaN(parseFloat(expectedHlookup)) &amp;&amp; parseFloat(hlookupRaw)===parseFloat(expectedHlookup);

    return {no:i+1, r, nama, kategori, jumlah:jumlahRaw, harga:hargaRaw, total:totalRaw, status:statusRaw,
      kode:kodeRaw, left:leftRaw, mid:midRaw, right:rightRaw, vlookup:vlookupRaw, hlookup:hlookupRaw,
      namaOk, kategoriOk, jumlahOk, hargaOk, totalOk, statusOk, kodeOk, leftOk, midOk, rightOk, vlookupOk, hlookupOk};
  });

  const expectedSum = evalFormula('SUM(E2:E9)', new Set());
  const expectedAvg = evalFormula('AVERAGE(E2:E9)', new Set());
  const expectedSumif = evalFormula('SUMIF(B2:B9,"Alat Tulis",E2:E9)', new Set());
  const expectedCountif = evalFormula('COUNTIF(B2:B9,"Alat Tulis")', new Set());

  const sumRaw = REG['E11']?REG['E11'].value:'';
  const avgRaw = REG['E12']?REG['E12'].value:'';
  const sumifRaw = REG['E13']?REG['E13'].value:'';
  const countifRaw = REG['E14']?REG['E14'].value:'';

  const closeEnough=(raw,expected)=&gt;{ const x=parseFloat(raw); return raw!=='' &amp;&amp; raw!=='#ERROR' &amp;&amp; !isNaN(x) &amp;&amp; Math.abs(x-expected)&lt;1; };

  const summary = {
    sum:{raw:sumRaw, ok:closeEnough(sumRaw, expectedSum), label:'Total Keseluruhan (SUM)'},
    avg:{raw:avgRaw, ok:closeEnough(avgRaw, expectedAvg), label:'Rata-rata (AVERAGE)'},
    sumif:{raw:sumifRaw, ok:closeEnough(sumifRaw, expectedSumif), label:'Total Kategori Alat Tulis (SUMIF)'},
    countif:{raw:countifRaw, ok:closeEnough(countifRaw, expectedCountif), label:'Jumlah Jenis Alat Tulis (COUNTIF)'}
  };

  return {rows, summary};
}

function scoreWork(){
  const ev = evaluateWork();
  const n = ev.rows.length;
  let dataCorrect=0, totalCorrect=0, statusCorrect=0, leftCorrect=0, midCorrect=0, rightCorrect=0, vlookupCorrect=0, hlookupCorrect=0;
  ev.rows.forEach(row=&gt;{
    if(row.namaOk &amp;&amp; row.kategoriOk &amp;&amp; row.jumlahOk &amp;&amp; row.hargaOk &amp;&amp; row.kodeOk) dataCorrect++;
    if(row.totalOk) totalCorrect++;
    if(row.statusOk) statusCorrect++;
    if(row.leftOk) leftCorrect++;
    if(row.midOk) midCorrect++;
    if(row.rightOk) rightCorrect++;
    if(row.vlookupOk) vlookupCorrect++;
    if(row.hlookupOk) hlookupCorrect++;
  });
  const dataScore = Math.round(dataCorrect/n*100);
  const totalScore = Math.round(totalCorrect/n*100);
  const statusScore = Math.round(statusCorrect/n*100);
  const totalStatusScore = Math.round((totalScore+statusScore)/2);
  const ringkasanCorrect = [ev.summary.sum.ok, ev.summary.avg.ok].filter(Boolean).length;
  const ringkasanScore = Math.round(ringkasanCorrect/2*100);
  const lanjutCorrect = [ev.summary.sumif.ok, ev.summary.countif.ok].filter(Boolean).length;
  const lanjutScore = Math.round(lanjutCorrect/2*100);
  const leftScore = Math.round(leftCorrect/n*100);
  const midScore = Math.round(midCorrect/n*100);
  const rightScore = Math.round(rightCorrect/n*100);
  const stringScore = Math.round((leftScore+midScore+rightScore)/3);
  const vlookupScore = Math.round(vlookupCorrect/n*100);
  const hlookupScore = Math.round(hlookupCorrect/n*100);
  const lookupScore = Math.round((vlookupScore+hlookupScore)/2);

  let finalScore = Math.round(dataScore*0.15 + totalStatusScore*0.15 + ringkasanScore*0.10 + lanjutScore*0.15 + stringScore*0.20 + lookupScore*0.25);
  const pastePenalty = gridPasteFlag;
  if(pastePenalty) finalScore = Math.round(finalScore*0.5);

  return {ev, dataScore, totalScore, statusScore, totalStatusScore, ringkasanScore, lanjutScore,
    leftScore, midScore, rightScore, stringScore, vlookupScore, hlookupScore, lookupScore,
    finalScore, pastePenalty};
}

function cellClass(val, ok){
  if(!val || String(val).trim()==='') return 'cell-empty';
  return ok ? 'cell-ok' : 'cell-bad';
}

function buildPivotSummary(ev){
  const groups = {};
  ev.rows.forEach(row=&gt;{
    const kat = row.kategori &amp;&amp; row.kategori.trim() ? row.kategori.trim() : '(belum diisi)';
    const total = parseFloat(row.total);
    if(!groups[kat]) groups[kat] = {count:0, sum:0};
    groups[kat].count++;
    if(!isNaN(total)) groups[kat].sum += total;
  });
  let html = `&lt;div class="table-scroll"&gt;&lt;table class="compare"&gt;&lt;tr&gt;&lt;th&gt;Kategori&lt;/th&gt;&lt;th&gt;Jumlah Jenis&lt;/th&gt;&lt;th&gt;Total Penjualan&lt;/th&gt;&lt;/tr&gt;`;
  Object.keys(groups).forEach(kat=&gt;{
    html += `&lt;tr&gt;&lt;td&gt;${kat}&lt;/td&gt;&lt;td&gt;${groups[kat].count}&lt;/td&gt;&lt;td&gt;${formatRupiah(groups[kat].sum)}&lt;/td&gt;&lt;/tr&gt;`;
  });
  html += '&lt;/table&gt;&lt;/div&gt;';
  return html;
}

let lastResult = null;

document.getElementById('btnHitung').addEventListener('click', ()=&gt;{
  const noAbsen=document.getElementById('noAbsenADFL').value.trim();
  const nama=document.getElementById('namaADFL').value.trim();
  const kelas=document.getElementById('kelasADFL').value.trim();
  const msg=document.getElementById('uploadMsg');
  if(!noAbsen||!nama||!kelas){ msg.textContent='Lengkapi Kelas, No. Absen, dan Nama terlebih dahulu.'; return; }

  const result = scoreWork();
  lastResult = {noAbsen, nama, kelas, result};

  msg.textContent='';
  const panel=document.getElementById('resultPanel');
  panel.style.display='block';
  document.getElementById('scoreValue').textContent = result.finalScore;
  document.getElementById('resultDetail').innerHTML =
    `Data Entri (15%): &lt;strong&gt;${result.dataScore}&lt;/strong&gt; &amp;nbsp;|&amp;nbsp; ` +
    `Rumus Total &amp; Status (15%): &lt;strong&gt;${result.totalStatusScore}&lt;/strong&gt; &amp;nbsp;|&amp;nbsp; ` +
    `Rumus Ringkasan (10%): &lt;strong&gt;${result.ringkasanScore}&lt;/strong&gt; &amp;nbsp;|&amp;nbsp; ` +
    `Fungsi Lanjutan (15%): &lt;strong&gt;${result.lanjutScore}&lt;/strong&gt; &amp;nbsp;|&amp;nbsp; ` +
    `Fungsi STRING (20%): &lt;strong&gt;${result.stringScore}&lt;/strong&gt; &amp;nbsp;|&amp;nbsp; ` +
    `Fungsi Lookup (25%): &lt;strong&gt;${result.lookupScore}&lt;/strong&gt;` +
    (result.pastePenalty ? '&lt;br&gt;&lt;span style="color:var(--red); font-weight:700;"&gt;[PERINGATAN] Terdeteksi percobaan tempel pada lembar kerja - nilai dipotong 50%&lt;/span&gt;' : '') +
    ' - Mengirim ke guru...';

  const ev = result.ev;
  let html = `&lt;div class="table-scroll"&gt;&lt;table class="compare final-table"&gt;
    &lt;tr&gt;&lt;th&gt;No&lt;/th&gt;&lt;th&gt;${DATA.kolomA}&lt;/th&gt;&lt;th&gt;${DATA.kolomB}&lt;/th&gt;&lt;th&gt;Jumlah Terjual&lt;/th&gt;&lt;th&gt;Harga Satuan&lt;/th&gt;&lt;th&gt;Total&lt;/th&gt;&lt;th&gt;Status&lt;/th&gt;&lt;/tr&gt;`;
  ev.rows.forEach(row=&gt;{
    html += `&lt;tr&gt;&lt;td&gt;${row.no}&lt;/td&gt;
      &lt;td class="${cellClass(row.nama,row.namaOk)}"&gt;${row.nama||'-'}&lt;/td&gt;
      &lt;td class="${cellClass(row.kategori,row.kategoriOk)}"&gt;${row.kategori||'-'}&lt;/td&gt;
      &lt;td class="${cellClass(row.jumlah,row.jumlahOk)}"&gt;${row.jumlah||'-'}&lt;/td&gt;
      &lt;td class="${cellClass(row.harga,row.hargaOk)}"&gt;${row.harga||'-'}&lt;/td&gt;
      &lt;td class="${cellClass(row.total,row.totalOk)}"&gt;${row.total||'-'}&lt;/td&gt;
      &lt;td class="${cellClass(row.status,row.statusOk)}"&gt;${row.status||'-'}&lt;/td&gt;
    &lt;/tr&gt;`;
  });
  html += '&lt;/table&gt;&lt;/div&gt;';
  html += `&lt;p style="font-size:.8rem; font-weight:600; color:var(--brand-dark); margin-top:14px;"&gt;Hasil Fungsi STRING dan Lookup&lt;/p&gt;`;
  html += `&lt;div class="table-scroll"&gt;&lt;table class="compare final-table"&gt;
    &lt;tr&gt;&lt;th&gt;No&lt;/th&gt;&lt;th&gt;Kode Transaksi&lt;/th&gt;&lt;th&gt;LEFT&lt;/th&gt;&lt;th&gt;MID&lt;/th&gt;&lt;th&gt;RIGHT&lt;/th&gt;&lt;th&gt;VLOOKUP (Diskon)&lt;/th&gt;&lt;th&gt;HLOOKUP (Poin)&lt;/th&gt;&lt;/tr&gt;`;
  ev.rows.forEach(row=&gt;{
    html += `&lt;tr&gt;&lt;td&gt;${row.no}&lt;/td&gt;
      &lt;td class="${cellClass(row.kode,row.kodeOk)}"&gt;${row.kode||'-'}&lt;/td&gt;
      &lt;td class="${cellClass(row.left,row.leftOk)}"&gt;${row.left||'-'}&lt;/td&gt;
      &lt;td class="${cellClass(row.mid,row.midOk)}"&gt;${row.mid||'-'}&lt;/td&gt;
      &lt;td class="${cellClass(row.right,row.rightOk)}"&gt;${row.right||'-'}&lt;/td&gt;
      &lt;td class="${cellClass(row.vlookup,row.vlookupOk)}"&gt;${row.vlookup||'-'}&lt;/td&gt;
      &lt;td class="${cellClass(row.hlookup,row.hlookupOk)}"&gt;${row.hlookup||'-'}&lt;/td&gt;
    &lt;/tr&gt;`;
  });
  html += '&lt;/table&gt;&lt;/div&gt;';
  html += `&lt;div class="table-scroll" style="margin-top:10px;"&gt;&lt;table class="compare final-table"&gt;
    &lt;tr&gt;&lt;th&gt;Ringkasan&lt;/th&gt;&lt;th&gt;Nilai&lt;/th&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;${ev.summary.sum.label}&lt;/td&gt;&lt;td class="${cellClass(ev.summary.sum.raw, ev.summary.sum.ok)}"&gt;${ev.summary.sum.raw||'-'}&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;${ev.summary.avg.label}&lt;/td&gt;&lt;td class="${cellClass(ev.summary.avg.raw, ev.summary.avg.ok)}"&gt;${ev.summary.avg.raw||'-'}&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;${ev.summary.sumif.label}&lt;/td&gt;&lt;td class="${cellClass(ev.summary.sumif.raw, ev.summary.sumif.ok)}"&gt;${ev.summary.sumif.raw||'-'}&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;${ev.summary.countif.label}&lt;/td&gt;&lt;td class="${cellClass(ev.summary.countif.raw, ev.summary.countif.ok)}"&gt;${ev.summary.countif.raw||'-'}&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;&lt;/div&gt;`;
  document.getElementById('finalTableWrap').innerHTML = html;
  document.getElementById('pivotTableWrap').innerHTML = buildPivotSummary(ev);
  document.getElementById('pdfMsg').textContent='';

  fetch(GAS_ENDPOINT,{method:'POST',mode:'no-cors',headers:{'Content-Type':'application/json'},
    body:JSON.stringify({noAbsen,nama,kelas,skor:result.finalScore,judulMateri:JUDUL_MATERI})
  }).then(()=&gt;{
    document.getElementById('resultDetail').innerHTML = document.getElementById('resultDetail').innerHTML.replace('Mengirim ke guru...','Nilai sudah terkirim ke guru.');
  }).catch(()=&gt;{
    document.getElementById('resultDetail').innerHTML = document.getElementById('resultDetail').innerHTML.replace('Mengirim ke guru...','Gagal terkirim otomatis, tunjukkan skor ini ke guru.');
  });
});

// ===================== UNDUH BUKTI (PDF 1 HALAMAN - TABEL HASIL AKHIR) =====================
document.getElementById('btnUnduhPDF').addEventListener('click', downloadHasilPDF);

function downloadHasilPDF(){
  const msg = document.getElementById('pdfMsg');
  if(!lastResult){ msg.textContent='Klik "Hitung Nilai &amp; Kirim ke Guru" terlebih dahulu.'; return; }
  if(!window.jspdf){ alert('Pustaka pembuat PDF gagal dimuat. Pastikan koneksi internet aktif lalu muat ulang halaman.'); return; }

  const { jsPDF } = window.jspdf;
  const doc = new jsPDF({ unit:'mm', format:'a4' });
  const marginX = 14;
  let y = 16;
  const ev = lastResult.result.ev;

  doc.setFont('helvetica','bold'); doc.setFontSize(13); doc.setTextColor(20,30,25);
  doc.text('HASIL AKHIR TUGAS PRAKTIK INDIVIDU', marginX, y); y+=6;
  doc.setFontSize(10); doc.setTextColor(21,128,61);
  doc.text(JUDUL_MATERI, marginX, y); y+=6;
  doc.setFont('helvetica','normal'); doc.setFontSize(9.5); doc.setTextColor(50,60,55);
  doc.text(`Kelas: ${lastResult.kelas}   |   No. Absen: ${lastResult.noAbsen}   |   Nama: ${lastResult.nama}`, marginX, y); y+=6;
  doc.setFont('helvetica','bold'); doc.setFontSize(11); doc.setTextColor(13,90,42);
  doc.text(`Nilai Praktik (Otomatis): ${lastResult.result.finalScore}`, marginX, y); y+=8;

  doc.autoTable({
    startY: y,
    head: [[ 'No', DATA.kolomA, DATA.kolomB, 'Jumlah Terjual', 'Harga Satuan', 'Total', 'Status' ]],
    body: ev.rows.map(row=&gt;[row.no, row.nama||'-', row.kategori||'-', row.jumlah||'-', row.harga||'-', row.total||'-', row.status||'-']),
    theme: 'grid',
    headStyles: { fillColor: [21,128,61], textColor: 255, fontStyle: 'bold', fontSize: 8 },
    bodyStyles: { fontSize: 8 },
    margin: { left: marginX, right: marginX },
    didParseCell: function(d){
      if(d.section==='body'){
        const row = ev.rows[d.row.index];
        const okMap = [true, row.namaOk, row.kategoriOk, row.jumlahOk, row.hargaOk, row.totalOk, row.statusOk];
        if(d.column.index&gt;0){
          d.cell.styles.fillColor = okMap[d.column.index] ? [227,247,234] : [252,230,227];
          d.cell.styles.textColor = okMap[d.column.index] ? [13,90,42] : [155,51,36];
        }
      }
    }
  });

  let yStr = doc.lastAutoTable.finalY + 6;
  doc.setFont('helvetica','bold'); doc.setFontSize(9); doc.setTextColor(20,30,25);
  doc.text('Hasil Fungsi STRING dan Lookup', marginX, yStr); yStr+=4;
  doc.autoTable({
    startY: yStr,
    head: [[ 'No', 'Kode Transaksi', 'LEFT', 'MID', 'RIGHT', 'VLOOKUP (Diskon)', 'HLOOKUP (Poin)' ]],
    body: ev.rows.map(row=&gt;[row.no, row.kode||'-', row.left||'-', row.mid||'-', row.right||'-', row.vlookup||'-', row.hlookup||'-']),
    theme: 'grid',
    headStyles: { fillColor: [21,128,61], textColor: 255, fontStyle: 'bold', fontSize: 8 },
    bodyStyles: { fontSize: 8 },
    margin: { left: marginX, right: marginX },
    didParseCell: function(d){
      if(d.section==='body'){
        const row = ev.rows[d.row.index];
        const okMap = [true, row.kodeOk, row.leftOk, row.midOk, row.rightOk, row.vlookupOk, row.hlookupOk];
        if(d.column.index&gt;0){
          d.cell.styles.fillColor = okMap[d.column.index] ? [227,247,234] : [252,230,227];
          d.cell.styles.textColor = okMap[d.column.index] ? [13,90,42] : [155,51,36];
        }
      }
    }
  });

  let y2 = doc.lastAutoTable.finalY + 6;
  doc.autoTable({
    startY: y2,
    head: [['Ringkasan','Nilai']],
    body: [
      [ev.summary.sum.label, ev.summary.sum.raw||'-'],
      [ev.summary.avg.label, ev.summary.avg.raw||'-'],
      [ev.summary.sumif.label, ev.summary.sumif.raw||'-'],
      [ev.summary.countif.label, ev.summary.countif.raw||'-']
    ],
    theme: 'grid',
    headStyles: { fillColor: [13,90,42], textColor: 255, fontStyle: 'bold', fontSize: 8 },
    bodyStyles: { fontSize: 8 },
    margin: { left: marginX, right: marginX },
    didParseCell: function(d){
      if(d.section==='body' &amp;&amp; d.column.index===1){
        const keys=['sum','avg','sumif','countif'];
        const ok = ev.summary[keys[d.row.index]].ok;
        d.cell.styles.fillColor = ok ? [227,247,234] : [252,230,227];
        d.cell.styles.textColor = ok ? [13,90,42] : [155,51,36];
      }
    }
  });

  let y3 = doc.lastAutoTable.finalY + 8;
  doc.setFont('helvetica','normal'); doc.setFontSize(8); doc.setTextColor(90,100,95);
  doc.text('Dokumen ini dicetak otomatis oleh sistem sebagai bukti hasil akhir pengerjaan tugas praktik individu.', marginX, y3); y3+=12;
  doc.setFontSize(9.5); doc.setTextColor(20,30,25);
  const todayStr = new Date().toLocaleDateString('id-ID',{day:'numeric',month:'long',year:'numeric'});
  doc.text('......................, ' + todayStr, marginX, y3); y3+=14;
  doc.text('( ' + lastResult.nama + ' )', marginX, y3); y3+=5;
  doc.setFontSize(8.5); doc.setTextColor(90,100,95);
  doc.text('Siswa', marginX, y3);

  msg.textContent='';
  const safeNama = lastResult.nama.replace(/[^a-z0-9]+/gi,'_');
  doc.save('Hasil-Praktik-Spreadsheet-' + safeNama + '.pdf');
}

renderGrid();
&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;</description><link>http://kitab-investasi.blogspot.com/2026/10/analisis-data-dan-fitur-lanjut.html</link><thr:total>0</thr:total><author>nof_rizal07@yahoo.co.id (abang_cool)</author></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-9000860041661554971.post-8762818644595775780</guid><pubDate>Thu, 08 Oct 2026 03:55:31 +0000</pubDate><atom:updated>2026-10-08T10:55:31.647+07:00</atom:updated><title>SIM-Asesmen CBT 2026</title><description>&lt;!-- KODE ASESMEN CBT UNTUK BLOGGER / BLOGSPOT - SMK NEGERI 1 TUNTANG --&gt;
&lt;div style="position: relative; width: 100%; max-width: 100%; margin: 20px auto; font-family: system-ui, -apple-system, sans-serif;"&gt;
  &lt;div style="background: linear-gradient(135deg, #1e40af, #3b82f6); color: white; padding: 12px 18px; border-radius: 14px 14px 0 0; display: flex; justify-content: space-between; align-items: center; box-shadow: 0 4px 6px -1px rgba(0,0,0,0.1);"&gt;
    &lt;div style="display: flex; align-items: center; gap: 8px;"&gt;
      &lt;span style="display: inline-block; width: 10px; height: 10px; background: #10b981; border-radius: 50%;"&gt;&lt;/span&gt;
      &lt;strong style="font-size: 14px;"&gt;PORTAL ULANGAN DIGITAL CBT - SMK N 1 TUNTANG&lt;/strong&gt;
    &lt;/div&gt;
    &lt;a href="https://ais-dev-lmzrqdc6fuqxt3vuandtt7-270455445011.asia-southeast1.run.app?embed=true" target="_blank" rel="noopener noreferrer" style="background: rgba(255,255,255,0.2); color: white; padding: 6px 14px; border-radius: 8px; font-size: 12px; font-weight: 600; text-decoration: none; border: 1px solid rgba(255,255,255,0.3);"&gt;
      Buka Layar Penuh ↗
    &lt;/a&gt;
  &lt;/div&gt;
  &lt;div style="width: 100%; height: 850px; min-height: 600px; background: #f8fafc; border: 2px solid #3b82f6; border-top: none; border-radius: 0 0 14px 14px; overflow: hidden; box-shadow: 0 10px 25px -5px rgba(0,0,0,0.1);"&gt;
    &lt;iframe 
      src="https://ais-dev-lmzrqdc6fuqxt3vuandtt7-270455445011.asia-southeast1.run.app?embed=true" 
      style="width: 100%; height: 100%; border: none; display: block;" 
      title="SIM-Asesmen Digital CBT"
      allow="fullscreen; clipboard-read; clipboard-write;" 
      allowfullscreen="true"
      loading="lazy"&gt;
    &lt;/iframe&gt;
  &lt;/div&gt;
&lt;/div&gt;</description><link>http://kitab-investasi.blogspot.com/2026/10/sim-asesmen-cbt-2026.html</link><thr:total>0</thr:total><author>nof_rizal07@yahoo.co.id (abang_cool)</author></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-9000860041661554971.post-5019502899315011722</guid><pubDate>Thu, 08 Oct 2026 03:07:20 +0000</pubDate><atom:updated>2026-10-08T10:07:20.795+07:00</atom:updated><title>Kaidah Kebahasaan Teks Ceramah (Bagian 2) dan Menulis Teks Ceramah</title><description>&lt;style&gt;
.kbt{--ink:#14213D;--ink2:#46526A;--paper:#F5F2EA;--card:#FFFFFF;--line:#DDD6C5;--amber:#E8A33D;--amberd:#7A4D0B;--blue:#1F5FA8;--green:#2F7D57;--red:#B83A32;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;color:var(--ink);background:var(--paper);line-height:1.65;font-size:15px;border-radius:14px;overflow:hidden;max-width:900px;margin:0 auto;text-align:left}
.kbt *{box-sizing:border-box}
.kbt .hero{background:linear-gradient(135deg,#14213D 0%,#243B6E 100%);color:#fff;padding:30px 26px 26px}
.kbt .hero .code{font-size:12px;letter-spacing:.06em;color:#F5D493;font-weight:700}
.kbt .hero h1{font-size:27px;line-height:1.25;margin:8px 0 6px;color:#fff;font-weight:800}
.kbt .hero p.sub{margin:0;font-size:14px;color:#D9E2F5}
.kbt .hero .tp{background:rgba(255,255,255,.12);border-left:4px solid var(--amber);padding:12px 14px;border-radius:6px;margin-top:16px;font-size:14px;color:#fff}
.kbt .nav{position:sticky;top:0;z-index:20;display:flex;gap:8px;flex-wrap:wrap;padding:10px 16px;background:#FFFFFF;border-bottom:1px solid var(--line)}
.kbt .nav a{font-size:13px;font-weight:700;text-decoration:none;color:var(--ink);background:#F1EEE4;border:1px solid var(--line);padding:7px 13px;border-radius:20px}
.kbt .nav a:hover{background:#E8E2D0}
.kbt .body{padding:20px 16px 10px}
.kbt .card{background:var(--card);border:1px solid var(--line);border-radius:12px;padding:22px 20px;margin-bottom:20px}
.kbt .sec-head{display:flex;align-items:center;gap:12px;margin:0 0 16px;padding-bottom:12px;border-bottom:3px solid var(--ink)}
.kbt .sec-head .num{flex:0 0 auto;width:34px;height:34px;border-radius:50%;background:var(--ink);color:#fff;font-weight:800;display:flex;align-items:center;justify-content:center;font-size:15px}
.kbt .sec-head h2{margin:0;font-size:20px;line-height:1.3;color:var(--ink)}
.kbt h3{font-size:16.5px;color:var(--amberd);margin:24px 0 8px;line-height:1.35}
.kbt h3.first{margin-top:4px}
.kbt h4{font-size:15px;margin:16px 0 6px;color:var(--ink)}
.kbt p{font-size:15px;margin:8px 0;color:var(--ink)}
.kbt ul,.kbt ol{font-size:15px;padding-left:22px;margin:8px 0}
.kbt li{margin-bottom:6px;color:var(--ink)}
.kbt .callout{border-radius:8px;padding:12px 14px;margin:14px 0;font-size:14.5px;border:1px solid var(--line);border-left-width:5px}
.kbt .callout b.t{display:block;margin-bottom:3px}
.kbt .callout.info{background:#EAF2FC;border-color:#B9D2EE;border-left-color:var(--blue)}
.kbt .callout.tip{background:#E8F5EE;border-color:#B5DCC6;border-left-color:var(--green)}
.kbt .callout.warn{background:#FFF4DD;border-color:#F0D49A;border-left-color:var(--amber)}
.kbt .tw{overflow-x:auto;margin:10px 0 16px;border:1px solid var(--line);border-radius:8px}
.kbt table.tb{width:100%;border-collapse:collapse;font-size:13.5px;min-width:520px}
.kbt table.tb th{background:var(--ink);color:#fff;text-align:left;padding:9px 10px;font-weight:700}
.kbt table.tb td{padding:9px 10px;border-top:1px solid var(--line);vertical-align:top;color:var(--ink)}
.kbt table.tb tr:nth-child(even) td{background:#FAF8F2}
.kbt .flow{display:flex;flex-wrap:wrap;gap:8px;margin:12px 0}
.kbt .flow span{background:#F1EEE4;border:1px solid var(--line);border-radius:20px;padding:6px 12px;font-size:13px;font-weight:700}
.kbt .flow span.go{background:var(--ink);color:#fff;border-color:var(--ink)}
.kbt .legend{display:flex;flex-wrap:wrap;gap:8px;margin:10px 0}
.kbt .hl{padding:1px 4px;border-radius:4px;font-weight:600}
.kbt .hl.s{background:#DCEBFF;color:#0E3A73}
.kbt .hl.r{background:#FFD9D6;color:#8A1F17}
.kbt .hl.a{background:#D9F2E3;color:#145A36}
.kbt .hl.j{background:#EBDDFB;color:#4B2380}
.kbt .hl.m{background:#FFF0A0;color:#5B4B00}
.kbt .hl.d{background:#D5F0F2;color:#0B4F55}
.kbt .hl.v{background:#FADCEE;color:#7A1B55}
.kbt .sample{background:#FCFBF7;border:1px solid var(--line);border-left:5px solid var(--amber);border-radius:8px;padding:16px 18px;margin:12px 0}
.kbt .sample .lbl{font-size:12px;font-weight:800;letter-spacing:.05em;color:var(--amberd);margin:10px 0 2px}
.kbt .sample .lbl:first-child{margin-top:0}
.kbt .sample p{margin:4px 0 8px}
.kbt .sample h4.judul{font-size:17px;margin:0 0 8px}
.kbt details{border:1px solid var(--line);border-radius:8px;padding:10px 14px;margin:10px 0;background:#FFFFFF}
.kbt details summary{cursor:pointer;font-weight:700;font-size:14.5px;color:var(--ink)}
.kbt details[open] summary{margin-bottom:8px}
.kbt .qbox{background:#FAF8F2;border:1px solid var(--line);border-radius:8px;padding:12px 14px;margin:12px 0}
.kbt .qbox .qn{font-size:12px;font-weight:800;color:var(--amberd);letter-spacing:.05em}
.kbt .rangkuman{background:#E8F5EE;border:1px solid #B5DCC6;border-radius:8px;padding:14px 18px}
.kbt .grid3{display:grid;grid-template-columns:repeat(3,1fr);gap:12px}
.kbt label.fl{display:block;font-size:13px;font-weight:600;color:var(--ink2);margin:12px 0 4px}
.kbt input[type=text],.kbt input[type=number],.kbt textarea{width:100%;padding:10px 12px;border:1.5px solid #C9C1AC;border-radius:8px;font-size:15px;background:#fff;color:var(--ink);font-family:inherit}
.kbt textarea{min-height:120px;resize:vertical;line-height:1.55}
.kbt input:focus,.kbt textarea:focus{outline:3px solid #F5D493;border-color:var(--amber)}
.kbt .cnt{font-size:12px;color:var(--ink2);text-align:right;margin-top:3px}
.kbt .pwarn{display:none;font-size:13px;color:var(--red);font-weight:700;margin-top:4px}
.kbt .pwarn.show{display:block}
.kbt .btn{display:inline-block;border:none;border-radius:8px;padding:12px 20px;font-size:15px;font-weight:700;cursor:pointer;margin:14px 8px 0 0;font-family:inherit}
.kbt .btn.pri{background:var(--ink);color:#fff}
.kbt .btn.pri:hover{background:#000}
.kbt .btn.grn{background:var(--green);color:#fff}
.kbt .btn.grn:hover{background:#256646}
.kbt .btn.ghost{background:#fff;color:var(--ink);border:1.5px solid #C9C1AC}
.kbt .btn.chip{padding:6px 12px;font-size:13px;margin:4px 6px 0 0;background:#F1EEE4;color:var(--ink);border:1px solid var(--line);border-radius:20px}
.kbt .btn.chip:hover{background:#E8E2D0}
.kbt .hidden{display:none}
.kbt .err{display:none;background:#FBEAE8;border:1px solid #E5B4AF;color:#8A1F17;border-radius:8px;padding:10px 12px;font-size:14px;margin-top:12px;font-weight:600}
.kbt .resbox{border-radius:12px;padding:20px;text-align:center;margin-top:18px;border:2px solid var(--line);background:#FAF8F2}
.kbt .resbox.pass{background:#E8F5EE;border-color:var(--green)}
.kbt .resbox.fail{background:#FBEAE8;border-color:var(--red)}
.kbt .resbox .big{font-size:56px;font-weight:800;line-height:1.1}
.kbt .resbox.pass .big{color:var(--green)}
.kbt .resbox.fail .big{color:var(--red)}
.kbt .resbox .cat{font-size:16px;font-weight:700;margin-top:2px}
.kbt .resbox .meta{font-size:13px;color:var(--ink2);margin-top:6px}
.kbt .gbar{margin:12px 0}
.kbt .gbar .gl{display:flex;justify-content:space-between;font-size:13.5px;font-weight:700;margin-bottom:4px}
.kbt .gbar .track{height:10px;background:#E4DFD0;border-radius:6px;overflow:hidden}
.kbt .gbar .fill{height:100%;background:var(--amber);border-radius:6px}
.kbt .irow{display:flex;gap:10px;padding:9px 0;border-top:1px solid var(--line);font-size:14px}
.kbt .irow .bd{flex:0 0 auto;min-width:74px;text-align:center;font-size:12px;font-weight:800;border-radius:6px;padding:3px 6px;height:fit-content}
.kbt .irow .bd.ok{background:#D9F2E3;color:#145A36}
.kbt .irow .bd.pt{background:#FFF0A0;color:#5B4B00}
.kbt .irow .bd.no{background:#FFD9D6;color:#8A1F17}
.kbt .irow .tx{flex:1 1 auto}
.kbt .irow .tx small{display:block;color:var(--ink2);font-size:12.5px;margin-top:2px}
.kbt .irow .sc{flex:0 0 auto;font-weight:800;font-size:13px;white-space:nowrap}
.kbt .foot{padding:6px 20px 24px;text-align:center;font-size:12px;color:var(--ink2)}
@media (max-width:640px){.kbt .grid3{grid-template-columns:1fr}.kbt .hero h1{font-size:23px}.kbt .card{padding:18px 14px}.kbt .resbox .big{font-size:46px}}
#kbtPrint{display:none}
@media print{
  body &gt; *:not(#kbtPrint){display:none !important}
  #kbtPrint{display:block !important;position:static;width:100%;color:#000;background:#fff;font-family:Arial,Helvetica,sans-serif}
  @page{size:215mm 330mm;margin:14mm}
}
#kbtPrint .kop{text-align:center;border-bottom:3px solid #000;padding-bottom:8px;margin-bottom:10px}
#kbtPrint .kop h2{margin:0;font-size:16px}
#kbtPrint .kop p{margin:2px 0 0;font-size:11.5px}
#kbtPrint table.idt{width:100%;border-collapse:collapse;font-size:12.5px;margin-bottom:10px}
#kbtPrint table.idt td{padding:3px 4px;vertical-align:top}
#kbtPrint table.idt td.l{width:110px;color:#333}
#kbtPrint .skor{border:2px solid #000;border-radius:4px;padding:8px 12px;margin-bottom:12px;display:flex;justify-content:space-between;gap:8px;flex-wrap:wrap}
#kbtPrint .skor div{font-size:11px}
#kbtPrint .skor b{display:block;font-size:19px}
#kbtPrint h3{font-size:13px;margin:12px 0 4px;border-bottom:1px solid #000;padding-bottom:2px}
#kbtPrint .jdl{font-size:15px;font-weight:700;margin:4px 0 6px}
#kbtPrint .lb{font-size:11px;font-weight:700;margin-top:6px;color:#333}
#kbtPrint .tk{font-size:12px;line-height:1.5;white-space:pre-wrap;border:1px solid #999;border-radius:3px;padding:6px 8px;margin-top:2px}
#kbtPrint table.rb{width:100%;border-collapse:collapse;font-size:11px;margin-top:4px}
#kbtPrint table.rb th,#kbtPrint table.rb td{border:1px solid #777;padding:3px 5px;text-align:left;vertical-align:top}
#kbtPrint table.rb th{background:#E5E5E5}
#kbtPrint table.rb tr.gh td{background:#F0F0F0;font-weight:700}
#kbtPrint table.rb tr{break-inside:avoid;page-break-inside:avoid}
#kbtPrint .ttd{display:flex;justify-content:space-between;margin-top:26px;font-size:12px;break-inside:avoid;page-break-inside:avoid}
#kbtPrint .ttd div{width:45%;text-align:center}
#kbtPrint .ttd .gr{margin-top:48px;border-top:1px solid #000;padding-top:3px}
#kbtPrint .nt{font-size:10.5px;color:#444;margin-top:10px}
&lt;/style&gt;

&lt;div class="kbt" id="kbtRoot"&gt;

&lt;div class="hero"&gt;
  &lt;div class="code"&gt;DOK/B.INDO/XI/CERAMAH-02&lt;/div&gt;
  &lt;h1&gt;Kaidah Kebahasaan Teks Ceramah (Bagian 2) dan Menulis Teks Ceramah&lt;/h1&gt;
  &lt;p class="sub"&gt;Bahasa Indonesia - Kelas XI SMK - Materi, contoh beranotasi, latihan, dan tugas individu menulis ceramah dengan penilaian otomatis&lt;/p&gt;
  &lt;div class="tp"&gt;&lt;b&gt;Tujuan Pembelajaran:&lt;/b&gt; Murid mampu menganalisis kaidah kebahasaan secara mendalam dan menulis teks ceramah secara kreatif.&lt;/div&gt;
&lt;/div&gt;

&lt;div class="nav" id="kbtNav"&gt;
  &lt;a href="#kbt-peta"&gt;Peta Materi&lt;/a&gt;
  &lt;a href="#kbt-kaidah"&gt;Kaidah Kebahasaan&lt;/a&gt;
  &lt;a href="#kbt-menulis"&gt;Menulis Ceramah&lt;/a&gt;
  &lt;a href="#kbt-contoh"&gt;Contoh&lt;/a&gt;
  &lt;a href="#kbt-latihan"&gt;Latihan&lt;/a&gt;
  &lt;a href="#kbt-tugas"&gt;Tugas Individu&lt;/a&gt;
&lt;/div&gt;

&lt;div class="body"&gt;

&lt;!-- ================= 1. PETA MATERI ================= --&gt;
&lt;div class="card" id="kbt-peta"&gt;
  &lt;div class="sec-head"&gt;&lt;div class="num"&gt;1&lt;/div&gt;&lt;h2&gt;Peta Materi dan Tujuan Belajar&lt;/h2&gt;&lt;/div&gt;

  &lt;div class="callout info"&gt;&lt;b class="t"&gt;Ingat kembali (Bagian 1)&lt;/b&gt;
  Teks ceramah adalah pemaparan gagasan secara lisan di hadapan pendengar. Strukturnya: &lt;b&gt;pembukaan&lt;/b&gt;, &lt;b&gt;isi&lt;/b&gt;, dan &lt;b&gt;penutup&lt;/b&gt;. Isi ceramah dibangun dari &lt;b&gt;gagasan pokok&lt;/b&gt; (kalimat utama) dan &lt;b&gt;gagasan pendukung&lt;/b&gt; (data, contoh, alasan). Informasinya perlu dievaluasi dengan enam kriteria: kredibilitas, keakuratan, kelogisan, objektivitas, kelengkapan, dan kesesuaian tujuan. Pada Bagian 2 ini kita mendalami &lt;b&gt;bahasanya&lt;/b&gt; lalu &lt;b&gt;menulis ceramah sendiri&lt;/b&gt;.&lt;/div&gt;

  &lt;h3 class="first"&gt;Indikator Pencapaian&lt;/h3&gt;
  &lt;ol&gt;
    &lt;li&gt;Menjelaskan fungsi sembilan kaidah kebahasaan teks ceramah beserta penandanya.&lt;/li&gt;
    &lt;li&gt;Mengidentifikasi dan menganalisis kaidah kebahasaan pada teks ceramah.&lt;/li&gt;
    &lt;li&gt;Memperbaiki kalimat agar baku, efektif, dan persuasif.&lt;/li&gt;
    &lt;li&gt;Menyusun kerangka dan menulis teks ceramah yang runtut, persuasif, dan kreatif.&lt;/li&gt;
    &lt;li&gt;Menyunting tulisan sendiri berdasarkan rubrik penilaian.&lt;/li&gt;
  &lt;/ol&gt;

  &lt;h3&gt;Alur Belajar&lt;/h3&gt;
  &lt;div class="flow"&gt;
    &lt;span&gt;1. Pelajari kaidah&lt;/span&gt;&lt;span&gt;2. Pelajari langkah menulis&lt;/span&gt;&lt;span&gt;3. Amati contoh beranotasi&lt;/span&gt;&lt;span&gt;4. Kerjakan latihan&lt;/span&gt;&lt;span&gt;5. Tulis ceramahmu&lt;/span&gt;&lt;span&gt;6. Dinilai otomatis&lt;/span&gt;&lt;span class="go"&gt;7. Unduh PDF, cetak, serahkan ke guru&lt;/span&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;!-- ================= 2. KAIDAH KEBAHASAAN ================= --&gt;
&lt;div class="card" id="kbt-kaidah"&gt;
  &lt;div class="sec-head"&gt;&lt;div class="num"&gt;2&lt;/div&gt;&lt;h2&gt;Kaidah Kebahasaan Teks Ceramah (Pendalaman)&lt;/h2&gt;&lt;/div&gt;

  &lt;p&gt;&lt;b&gt;Kaidah kebahasaan&lt;/b&gt; adalah ciri-ciri bahasa yang khas pada suatu jenis teks. Ceramah dibawakan secara lisan, sehingga pendengar hanya sekali mendengar dan tidak bisa membaca ulang. Karena itu bahasa ceramah harus memenuhi tiga tuntutan: (1) &lt;b&gt;jelas&lt;/b&gt; dalam sekali dengar, (2) &lt;b&gt;akrab&lt;/b&gt; sehingga membangun hubungan dengan pendengar, dan (3) &lt;b&gt;meyakinkan&lt;/b&gt; karena didukung alasan dan data. Sembilan kaidah berikut perlu kamu kuasai.&lt;/p&gt;

  &lt;h3&gt;2.1 Kata Sapaan dan Salam&lt;/h3&gt;
  &lt;p&gt;Kata sapaan dipakai untuk menyapa pendengar, sedangkan salam dipakai untuk membuka dan menutup ceramah. Keduanya menunjukkan rasa hormat dan membuka kontak dengan pendengar.&lt;/p&gt;
  &lt;ul&gt;
    &lt;li&gt;Sapaan disusun dari yang paling dihormati ke yang lain: &lt;i&gt;Bapak dan Ibu guru yang saya hormati, teman-teman yang saya banggakan&lt;/i&gt;.&lt;/li&gt;
    &lt;li&gt;Salam disesuaikan dengan situasi dan keberagaman pendengar: &lt;i&gt;Assalamualaikum warahmatullahi wabarakatuh, Selamat pagi, Salam sejahtera, Om Swastiastu, Namo Buddhaya, Shalom&lt;/i&gt;.&lt;/li&gt;
    &lt;li&gt;Sapaan boleh diulang di bagian penutup untuk menegaskan kedekatan: &lt;i&gt;Hadirin yang saya hormati, demikian ceramah singkat saya&lt;/i&gt;.&lt;/li&gt;
  &lt;/ul&gt;

  &lt;h3&gt;2.2 Kata Ganti Orang (Persona)&lt;/h3&gt;
  &lt;div class="tw"&gt;&lt;table class="tb"&gt;
    &lt;tr&gt;&lt;th&gt;Kata&lt;/th&gt;&lt;th&gt;Makna&lt;/th&gt;&lt;th&gt;Efek bagi pendengar&lt;/th&gt;&lt;th&gt;Contoh&lt;/th&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;b&gt;saya&lt;/b&gt;&lt;/td&gt;&lt;td&gt;Penceramah sendiri&lt;/td&gt;&lt;td&gt;Personal dan jujur&lt;/td&gt;&lt;td&gt;Saya yakin kita mampu berubah.&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;b&gt;kita&lt;/b&gt;&lt;/td&gt;&lt;td&gt;Penceramah dan pendengar (inklusif)&lt;/td&gt;&lt;td&gt;Dekat, tidak menggurui, terasa senasib&lt;/td&gt;&lt;td&gt;Marilah kita jaga kebersihan sekolah.&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;b&gt;kami&lt;/b&gt;&lt;/td&gt;&lt;td&gt;Penceramah dan kelompoknya, tanpa pendengar (eksklusif)&lt;/td&gt;&lt;td&gt;Formal, mewakili kelompok&lt;/td&gt;&lt;td&gt;Kami dari OSIS mengimbau seluruh siswa menaati tata tertib.&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;b&gt;Anda, Saudara, kalian&lt;/b&gt;&lt;/td&gt;&lt;td&gt;Pendengar&lt;/td&gt;&lt;td&gt;Langsung menyapa, tetapi bisa terasa menunjuk&lt;/td&gt;&lt;td&gt;Apakah Anda sudah memeriksa kebenaran berita itu?&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;&lt;/div&gt;
  &lt;div class="callout tip"&gt;&lt;b class="t"&gt;Tips&lt;/b&gt;Gunakan &lt;b&gt;kita&lt;/b&gt; saat membahas kesalahan atau kebiasaan buruk bersama agar pendengar tidak merasa dihakimi. Gunakan &lt;b&gt;saya&lt;/b&gt; saat menyatakan pendapat atau keyakinan pribadi.&lt;/div&gt;

  &lt;h3&gt;2.3 Kalimat Persuasif dan Imperatif (Ajakan)&lt;/h3&gt;
  &lt;p&gt;Tujuan ceramah bukan hanya memberi tahu, tetapi juga &lt;b&gt;mengajak&lt;/b&gt; pendengar bertindak. Kalimat persuasif berisi bujukan yang disertai alasan, sedangkan kalimat imperatif berisi perintah atau larangan. Penanda umumnya: &lt;i&gt;mari, marilah, ayo, hendaknya, hendaklah, janganlah, mohon, harap, sebaiknya&lt;/i&gt;, dan akhiran &lt;i&gt;-lah&lt;/i&gt; pada kata kerja (&lt;i&gt;periksalah, jagalah, ingatlah&lt;/i&gt;).&lt;/p&gt;
  &lt;div class="tw"&gt;&lt;table class="tb"&gt;
    &lt;tr&gt;&lt;th&gt;Tingkat&lt;/th&gt;&lt;th&gt;Ciri&lt;/th&gt;&lt;th&gt;Contoh&lt;/th&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;b&gt;Halus&lt;/b&gt;&lt;/td&gt;&lt;td&gt;Saran dan harapan, tidak memaksa&lt;/td&gt;&lt;td&gt;Sebaiknya kita memeriksa sumber berita sebelum membagikannya.&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;b&gt;Sedang&lt;/b&gt;&lt;/td&gt;&lt;td&gt;Ajakan bersama dengan kata mari atau marilah&lt;/td&gt;&lt;td&gt;Marilah kita biasakan membuang sampah pada tempatnya.&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;b&gt;Tegas&lt;/b&gt;&lt;/td&gt;&lt;td&gt;Larangan atau perintah, dipakai untuk hal yang berbahaya&lt;/td&gt;&lt;td&gt;Janganlah mengoperasikan mesin tanpa alat pelindung diri!&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;&lt;/div&gt;
  &lt;div class="callout tip"&gt;&lt;b class="t"&gt;Rumus ajakan yang meyakinkan&lt;/b&gt;Alasan dahulu, ajakan kemudian. Contoh: &lt;i&gt;Hoaks dapat memecah belah masyarakat. Oleh karena itu, marilah kita periksa kebenaran berita sebelum membagikannya.&lt;/i&gt; Ajakan tanpa alasan terasa seperti perintah kosong.&lt;/div&gt;

  &lt;h3&gt;2.4 Kalimat Retoris&lt;/h3&gt;
  &lt;p&gt;&lt;b&gt;Kalimat retoris&lt;/b&gt; adalah kalimat tanya yang tidak menuntut jawaban karena jawabannya sudah jelas bagi pendengar. Fungsinya menggugah perhatian, memancing pendengar berpikir, atau menegaskan gagasan.&lt;/p&gt;
  &lt;ul&gt;
    &lt;li&gt;Sebagai pengait di pembukaan: &lt;i&gt;Pernahkah kita membayangkan sekolah tanpa sampah berserakan?&lt;/i&gt;&lt;/li&gt;
    &lt;li&gt;Sebagai peralihan: &lt;i&gt;Lalu, apa yang dapat kita lakukan mulai hari ini?&lt;/i&gt;&lt;/li&gt;
    &lt;li&gt;Sebagai penegas: &lt;i&gt;Siapa lagi yang akan menjaga masa depan kita kalau bukan kita sendiri?&lt;/i&gt;&lt;/li&gt;
  &lt;/ul&gt;
  &lt;div class="callout warn"&gt;&lt;b class="t"&gt;Batasi pemakaian&lt;/b&gt;Cukup dua sampai tiga kalimat retoris dalam satu ceramah. Terlalu banyak pertanyaan membuat pendengar lelah dan ceramah terasa menginterogasi.&lt;/div&gt;

  &lt;h3&gt;2.5 Konjungsi (Kata Penghubung)&lt;/h3&gt;
  &lt;p&gt;Konjungsi menjaga alur penalaran ceramah supaya pendengar mudah mengikuti hubungan antargagasan.&lt;/p&gt;
  &lt;div class="tw"&gt;&lt;table class="tb"&gt;
    &lt;tr&gt;&lt;th&gt;Jenis&lt;/th&gt;&lt;th&gt;Fungsi&lt;/th&gt;&lt;th&gt;Contoh kata&lt;/th&gt;&lt;th&gt;Contoh kalimat&lt;/th&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;b&gt;Sebab-akibat&lt;/b&gt;&lt;/td&gt;&lt;td&gt;Menyatakan alasan atau akibat&lt;/td&gt;&lt;td&gt;karena, sebab, sehingga, akibatnya&lt;/td&gt;&lt;td&gt;Sampah menumpuk sehingga selokan tersumbat.&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;b&gt;Simpulan&lt;/b&gt;&lt;/td&gt;&lt;td&gt;Menarik kesimpulan dari alasan&lt;/td&gt;&lt;td&gt;oleh karena itu, dengan demikian, jadi&lt;/td&gt;&lt;td&gt;Dengan demikian, disiplin adalah bekal utama dunia kerja.&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;b&gt;Pertentangan&lt;/b&gt;&lt;/td&gt;&lt;td&gt;Membandingkan atau membantah&lt;/td&gt;&lt;td&gt;namun, tetapi, akan tetapi, sebaliknya&lt;/td&gt;&lt;td&gt;Teknologi memudahkan hidup, namun penggunaannya perlu bijak.&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;b&gt;Penambahan&lt;/b&gt;&lt;/td&gt;&lt;td&gt;Menambah gagasan&lt;/td&gt;&lt;td&gt;selain itu, bahkan, lagi pula&lt;/td&gt;&lt;td&gt;Selain itu, kebiasaan baik dapat menular kepada teman.&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;b&gt;Urutan&lt;/b&gt;&lt;/td&gt;&lt;td&gt;Mengurutkan gagasan&lt;/td&gt;&lt;td&gt;pertama, kedua, selanjutnya, terakhir&lt;/td&gt;&lt;td&gt;Pertama, kita perlu menyadari bahayanya.&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;b&gt;Pengandaian&lt;/b&gt;&lt;/td&gt;&lt;td&gt;Menyatakan syarat&lt;/td&gt;&lt;td&gt;jika, apabila, seandainya&lt;/td&gt;&lt;td&gt;Jika kita teliti, kecelakaan kerja dapat dicegah.&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;&lt;/div&gt;
  &lt;div class="callout warn"&gt;&lt;b class="t"&gt;Kesalahan umum&lt;/b&gt;Jangan menjadikan anak kalimat sebagai kalimat berdiri sendiri. Salah: &lt;i&gt;Karena sampah menumpuk.&lt;/i&gt; Benar: &lt;i&gt;Banjir terjadi karena sampah menumpuk di selokan.&lt;/i&gt;&lt;/div&gt;

  &lt;h3&gt;2.6 Kata Kerja Mental dan Ungkapan Sikap&lt;/h3&gt;
  &lt;p&gt;Kata kerja mental menyatakan aktivitas batin: &lt;i&gt;menyadari, meyakini, percaya, berpendapat, menyimpulkan, memahami, berharap, mengimbau&lt;/i&gt;. Kata-kata ini menandai bahwa penceramah sedang menyampaikan &lt;b&gt;pendapat atau sikap&lt;/b&gt;, bukan fakta yang bisa langsung diuji.&lt;/p&gt;
  &lt;div class="tw"&gt;&lt;table class="tb"&gt;
    &lt;tr&gt;&lt;th&gt;Jenis informasi&lt;/th&gt;&lt;th&gt;Ciri&lt;/th&gt;&lt;th&gt;Contoh&lt;/th&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;b&gt;Fakta&lt;/b&gt;&lt;/td&gt;&lt;td&gt;Dapat dibuktikan dengan data atau sumber&lt;/td&gt;&lt;td&gt;Menurut data lembaga resmi, ribuan aplikasi pinjaman ilegal telah diblokir.&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;b&gt;Opini&lt;/b&gt;&lt;/td&gt;&lt;td&gt;Pandangan penceramah, ditandai kata kerja mental&lt;/td&gt;&lt;td&gt;Saya yakin siswa SMK mampu bersikap teliti.&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;&lt;/div&gt;
  &lt;p&gt;Ceramah yang baik memadukan keduanya: opini diperkuat fakta. Opini tanpa fakta mudah dibantah, sedangkan fakta tanpa opini terasa dingin.&lt;/p&gt;

  &lt;h3&gt;2.7 Kosakata: Istilah Teknis, Kata Baku, dan Diksi&lt;/h3&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;b&gt;Istilah teknis&lt;/b&gt; sesuai topik (misalnya &lt;i&gt;hoaks, literasi digital, alat pelindung diri, wirausaha&lt;/i&gt;) menunjukkan penguasaan materi. Jelaskan istilah yang mungkin asing: &lt;i&gt;hoaks, yaitu berita bohong yang sengaja disebarkan&lt;/i&gt;.&lt;/li&gt;
    &lt;li&gt;&lt;b&gt;Kata baku&lt;/b&gt; dipakai karena ceramah adalah situasi resmi. Hindari kata percakapan sehari-hari.&lt;/li&gt;
    &lt;li&gt;&lt;b&gt;Diksi&lt;/b&gt; (pilihan kata) harus tepat, santun, dan mudah dipahami pendengar.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;div class="tw"&gt;&lt;table class="tb"&gt;
    &lt;tr&gt;&lt;th&gt;Tidak baku&lt;/th&gt;&lt;th&gt;Baku&lt;/th&gt;&lt;th&gt;Tidak baku&lt;/th&gt;&lt;th&gt;Baku&lt;/th&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;gak, nggak, enggak&lt;/td&gt;&lt;td&gt;tidak&lt;/td&gt;&lt;td&gt;kayak&lt;/td&gt;&lt;td&gt;seperti&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;banget&lt;/td&gt;&lt;td&gt;sekali, sangat&lt;/td&gt;&lt;td&gt;gimana&lt;/td&gt;&lt;td&gt;bagaimana&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;aja&lt;/td&gt;&lt;td&gt;saja&lt;/td&gt;&lt;td&gt;emang&lt;/td&gt;&lt;td&gt;memang&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;udah&lt;/td&gt;&lt;td&gt;sudah&lt;/td&gt;&lt;td&gt;cuma&lt;/td&gt;&lt;td&gt;hanya&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;bikin&lt;/td&gt;&lt;td&gt;membuat&lt;/td&gt;&lt;td&gt;pake&lt;/td&gt;&lt;td&gt;pakai&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;tapi&lt;/td&gt;&lt;td&gt;tetapi&lt;/td&gt;&lt;td&gt;gue, lo&lt;/td&gt;&lt;td&gt;saya, Anda&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;nih, dong, sih, deh&lt;/td&gt;&lt;td&gt;(dihilangkan)&lt;/td&gt;&lt;td&gt;kok, lho&lt;/td&gt;&lt;td&gt;(dihilangkan)&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;&lt;/div&gt;

  &lt;h3&gt;2.8 Majas dan Gaya Bahasa untuk Kreativitas&lt;/h3&gt;
  &lt;p&gt;Majas membuat ceramah berkesan dan mudah diingat. Namun majas hanya bumbu: gunakan secukupnya dan pastikan tetap benar secara isi.&lt;/p&gt;
  &lt;div class="tw"&gt;&lt;table class="tb"&gt;
    &lt;tr&gt;&lt;th&gt;Majas&lt;/th&gt;&lt;th&gt;Pengertian&lt;/th&gt;&lt;th&gt;Contoh&lt;/th&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;b&gt;Perumpamaan (simile)&lt;/b&gt;&lt;/td&gt;&lt;td&gt;Perbandingan langsung memakai kata ibarat, bagaikan, laksana, bak&lt;/td&gt;&lt;td&gt;Disiplin ibarat kompas yang menuntun kita menuju tujuan.&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;b&gt;Metafora&lt;/b&gt;&lt;/td&gt;&lt;td&gt;Perbandingan tanpa kata pembanding&lt;/td&gt;&lt;td&gt;Jempol kita adalah senjata: bisa menyebar kebenaran, bisa menyebar kebohongan.&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;b&gt;Repetisi (anafora)&lt;/b&gt;&lt;/td&gt;&lt;td&gt;Pengulangan kata di awal kalimat untuk penekanan&lt;/td&gt;&lt;td&gt;Jangan malas belajar. Jangan takut mencoba. Jangan menyerah sebelum berusaha.&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;b&gt;Hiperbola&lt;/b&gt;&lt;/td&gt;&lt;td&gt;Pernyataan dilebih-lebihkan untuk menegaskan&lt;/td&gt;&lt;td&gt;Hoaks menyebar secepat kilat.&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;b&gt;Personifikasi&lt;/b&gt;&lt;/td&gt;&lt;td&gt;Benda diberi sifat manusia&lt;/td&gt;&lt;td&gt;Sampah menjerit minta dipungut.&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;b&gt;Klimaks&lt;/b&gt;&lt;/td&gt;&lt;td&gt;Urutan gagasan dari yang ringan ke yang paling penting&lt;/td&gt;&lt;td&gt;Mulailah dari diri sendiri, keluarga, sekolah, hingga bangsa.&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;b&gt;Peribahasa&lt;/b&gt;&lt;/td&gt;&lt;td&gt;Ungkapan tetap berisi nasihat&lt;/td&gt;&lt;td&gt;Sedia payung sebelum hujan.&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;&lt;/div&gt;
  &lt;div class="callout tip"&gt;&lt;b class="t"&gt;Aturan praktis&lt;/b&gt;Maksimal satu majas yang menonjol per paragraf, dan pilih majas yang berkaitan dengan dunia pendengar (misalnya bengkel, dapur, atau kantor untuk siswa SMK).&lt;/div&gt;

  &lt;h3&gt;2.9 Kalimat Efektif untuk Telinga&lt;/h3&gt;
  &lt;p&gt;Kalimat dalam ceramah sebaiknya pendek sampai sedang (sekitar 10 sampai 20 kata), memuat satu gagasan, dan bervariasi panjangnya agar tidak monoton. Hindari kata mubazir dan susunan yang berbelit.&lt;/p&gt;
  &lt;div class="tw"&gt;&lt;table class="tb"&gt;
    &lt;tr&gt;&lt;th&gt;Kurang efektif&lt;/th&gt;&lt;th&gt;Efektif&lt;/th&gt;&lt;th&gt;Alasan&lt;/th&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;Para hadirin sekalian yang saya hormati&lt;/td&gt;&lt;td&gt;Hadirin yang saya hormati&lt;/td&gt;&lt;td&gt;Para dan sekalian berlebihan (mubazir)&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;Agar supaya kita semua sehat&lt;/td&gt;&lt;td&gt;Agar kita semua sehat&lt;/td&gt;&lt;td&gt;Agar dan supaya bermakna sama&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;Demi untuk masa depan kita&lt;/td&gt;&lt;td&gt;Demi masa depan kita&lt;/td&gt;&lt;td&gt;Demi dan untuk bermakna sama&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;Kita harus saling bantu-membantu satu sama lain&lt;/td&gt;&lt;td&gt;Kita harus saling membantu&lt;/td&gt;&lt;td&gt;Saling sudah bermakna timbal balik&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;Narkoba itu bahaya, kita harus menghindarinya, itu merusak&lt;/td&gt;&lt;td&gt;Narkoba merusak masa depan sehingga kita harus menjauhinya.&lt;/td&gt;&lt;td&gt;Gagasan dirangkai dengan konjungsi&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;&lt;/div&gt;

  &lt;h3&gt;Ringkasan Sembilan Kaidah&lt;/h3&gt;
  &lt;div class="tw"&gt;&lt;table class="tb"&gt;
    &lt;tr&gt;&lt;th&gt;Kaidah&lt;/th&gt;&lt;th&gt;Fungsi&lt;/th&gt;&lt;th&gt;Penanda&lt;/th&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;Salam dan sapaan&lt;/td&gt;&lt;td&gt;Membuka kontak dan menghormati&lt;/td&gt;&lt;td&gt;Assalamualaikum, Selamat pagi, Bapak dan Ibu, hadirin&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;Kata ganti kita/kami&lt;/td&gt;&lt;td&gt;Membangun kedekatan&lt;/td&gt;&lt;td&gt;kita, kami, saya&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;Kalimat ajakan&lt;/td&gt;&lt;td&gt;Mendorong pendengar bertindak&lt;/td&gt;&lt;td&gt;mari, marilah, hendaknya, janganlah, -lah&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;Kalimat retoris&lt;/td&gt;&lt;td&gt;Menggugah dan menegaskan&lt;/td&gt;&lt;td&gt;kalimat tanya tanpa jawaban&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;Konjungsi&lt;/td&gt;&lt;td&gt;Menjaga alur penalaran&lt;/td&gt;&lt;td&gt;karena, sehingga, oleh karena itu, namun, pertama&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;Kata kerja mental&lt;/td&gt;&lt;td&gt;Menyatakan sikap dan pendapat&lt;/td&gt;&lt;td&gt;menyadari, meyakini, berpendapat, menyimpulkan&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;Kosakata baku dan istilah teknis&lt;/td&gt;&lt;td&gt;Resmi, tepat, dan berwibawa&lt;/td&gt;&lt;td&gt;sudah, tidak, sangat, istilah topik&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;Majas&lt;/td&gt;&lt;td&gt;Membuat ceramah berkesan&lt;/td&gt;&lt;td&gt;ibarat, bagaikan, repetisi, metafora&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;Kalimat efektif&lt;/td&gt;&lt;td&gt;Jelas dalam sekali dengar&lt;/td&gt;&lt;td&gt;kalimat ringkas, tanpa kata mubazir&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;!-- ================= 3. MENULIS CERAMAH ================= --&gt;
&lt;div class="card" id="kbt-menulis"&gt;
  &lt;div class="sec-head"&gt;&lt;div class="num"&gt;3&lt;/div&gt;&lt;h2&gt;Menulis Teks Ceramah&lt;/h2&gt;&lt;/div&gt;
  &lt;p&gt;Menulis ceramah berarti &lt;b&gt;menulis untuk didengar&lt;/b&gt;. Naskahnya harus enak diucapkan, mudah diikuti dalam sekali dengar, dan membuat pendengar tergerak. Ikuti lima langkah berikut.&lt;/p&gt;

  &lt;h3&gt;Langkah 1. Rumuskan Topik, Tujuan, dan Pendengar&lt;/h3&gt;
  &lt;div class="tw"&gt;&lt;table class="tb"&gt;
    &lt;tr&gt;&lt;th&gt;Pertanyaan&lt;/th&gt;&lt;th&gt;Yang perlu diputuskan&lt;/th&gt;&lt;th&gt;Contoh&lt;/th&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;Apa topiknya?&lt;/td&gt;&lt;td&gt;Satu topik sempit dan dekat dengan dunia siswa SMK&lt;/td&gt;&lt;td&gt;Saring Sebelum Sharing: Cerdas Menghadapi Hoaks&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;Apa tujuannya?&lt;/td&gt;&lt;td&gt;Menginformasikan, menyadarkan, atau mengajak&lt;/td&gt;&lt;td&gt;Menyadarkan dan mengajak memeriksa berita&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;Siapa pendengarnya?&lt;/td&gt;&lt;td&gt;Usia, latar belakang, dan tingkat pengetahuan&lt;/td&gt;&lt;td&gt;Guru dan teman sekelas&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;Di mana dan berapa lama?&lt;/td&gt;&lt;td&gt;Situasi dan durasi&lt;/td&gt;&lt;td&gt;Upacara atau kegiatan kelas, 2 sampai 3 menit (sekitar 250 sampai 400 kata)&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;&lt;/div&gt;

  &lt;h3&gt;Langkah 2. Kumpulkan Bahan&lt;/h3&gt;
  &lt;ul&gt;
    &lt;li&gt;Tentukan &lt;b&gt;tiga gagasan pokok&lt;/b&gt; yang akan dibahas pada bagian isi.&lt;/li&gt;
    &lt;li&gt;Siapkan &lt;b&gt;minimal dua gagasan pendukung&lt;/b&gt; untuk setiap gagasan pokok: data, contoh nyata, alasan logis, atau kutipan.&lt;/li&gt;
    &lt;li&gt;Gunakan &lt;b&gt;sumber yang jelas&lt;/b&gt; (lembaga resmi, buku, artikel ilmiah, media terpercaya) dan sebutkan sumbernya dalam teks.&lt;/li&gt;
    &lt;li&gt;Uji bahanmu dengan &lt;b&gt;enam kriteria evaluasi&lt;/b&gt; pada Bagian 1. Jangan mengarang data atau angka.&lt;/li&gt;
  &lt;/ul&gt;

  &lt;h3&gt;Langkah 3. Susun Kerangka&lt;/h3&gt;
  &lt;div class="tw"&gt;&lt;table class="tb"&gt;
    &lt;tr&gt;&lt;th&gt;Bagian&lt;/th&gt;&lt;th&gt;Unsur yang perlu ada&lt;/th&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;b&gt;Pembukaan&lt;/b&gt;&lt;/td&gt;&lt;td&gt;1) Salam pembuka. 2) Sapaan kepada pendengar. 3) Pengait perhatian (pertanyaan retoris, cerita singkat, fakta, atau peribahasa). 4) Pengantar topik dalam satu kalimat.&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;b&gt;Isi&lt;/b&gt;&lt;/td&gt;&lt;td&gt;Tiga paragraf. Setiap paragraf memuat gagasan pokok, bukti atau contoh, penjelasan, dan penghubung ke paragraf berikutnya. Sisipkan ajakan dan satu majas.&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;&lt;b&gt;Penutup&lt;/b&gt;&lt;/td&gt;&lt;td&gt;1) Simpulan satu kalimat. 2) Harapan. 3) Ajakan akhir atau slogan. 4) Ucapan terima kasih. 5) Salam penutup.&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;&lt;/div&gt;

  &lt;h3&gt;Langkah 4. Kembangkan Menjadi Teks&lt;/h3&gt;
  &lt;h4&gt;Rumus paragraf isi: P-B-P-A&lt;/h4&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;b&gt;P&lt;/b&gt;ernyataan: kalimat utama berisi gagasan pokok.&lt;/li&gt;
    &lt;li&gt;&lt;b&gt;B&lt;/b&gt;ukti: data, sumber, atau contoh (gagasan pendukung).&lt;/li&gt;
    &lt;li&gt;&lt;b&gt;P&lt;/b&gt;enjelasan: akibat atau hubungan bukti dengan gagasan pokok, gunakan konjungsi sebab-akibat.&lt;/li&gt;
    &lt;li&gt;&lt;b&gt;A&lt;/b&gt;jakan atau penghubung: kalimat ajakan atau transisi ke gagasan berikutnya.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;div class="qbox"&gt;&lt;div class="qn"&gt;CONTOH SATU PARAGRAF P-B-P-A&lt;/div&gt;
  (P) Kita perlu menyadari bahwa hoaks menyebar lebih cepat daripada klarifikasi. (B) Menurut data lembaga resmi, ribuan konten hoaks ditemukan setiap tahun. (P) Akibatnya, banyak orang termakan kabar bohong sehingga muncul kepanikan. (A) Oleh karena itu, marilah kita periksa kebenaran berita sebelum membagikannya.&lt;/div&gt;

  &lt;h4&gt;Teknik pembuka yang kreatif&lt;/h4&gt;
  &lt;ul&gt;
    &lt;li&gt;&lt;b&gt;Pertanyaan retoris:&lt;/b&gt; Pernahkah kita menyesal setelah menekan tombol kirim?&lt;/li&gt;
    &lt;li&gt;&lt;b&gt;Cerita singkat:&lt;/b&gt; Minggu lalu, seorang teman saya hampir tertipu pesan hadiah palsu...&lt;/li&gt;
    &lt;li&gt;&lt;b&gt;Fakta atau data:&lt;/b&gt; Setiap hari, jutaan pesan beredar di media sosial, dan tidak semuanya benar...&lt;/li&gt;
    &lt;li&gt;&lt;b&gt;Peribahasa:&lt;/b&gt; Sedia payung sebelum hujan, begitu pula kita perlu waspada sebelum membagikan berita.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;h4&gt;Teknik penutup yang berkesan&lt;/h4&gt;
  &lt;ul&gt;
    &lt;li&gt;Simpulkan inti ceramah dalam satu kalimat.&lt;/li&gt;
    &lt;li&gt;Tutup dengan slogan singkat yang mudah diingat, misalnya &lt;i&gt;Saring sebelum sharing!&lt;/i&gt;&lt;/li&gt;
    &lt;li&gt;Berikan satu aksi kecil yang bisa dilakukan pendengar hari ini.&lt;/li&gt;
  &lt;/ul&gt;

  &lt;h3&gt;Langkah 5. Sunting dan Latih&lt;/h3&gt;
  &lt;p&gt;Baca naskah dengan suara nyaring dan ukur waktunya. Bagian yang sulit diucapkan biasanya terlalu panjang atau berbelit. Gunakan daftar periksa berikut.&lt;/p&gt;
  &lt;ol&gt;
    &lt;li&gt;Ada salam pembuka dan sapaan di pembukaan.&lt;/li&gt;
    &lt;li&gt;Topik disebut jelas di pembukaan.&lt;/li&gt;
    &lt;li&gt;Isi terdiri atas tiga paragraf dengan gagasan pokok berbeda.&lt;/li&gt;
    &lt;li&gt;Setiap gagasan pokok punya pendukung berupa contoh atau data bersumber.&lt;/li&gt;
    &lt;li&gt;Kata ganti kita atau kami digunakan untuk membangun kedekatan.&lt;/li&gt;
    &lt;li&gt;Ada kalimat ajakan dan konjungsi yang menjaga alur.&lt;/li&gt;
    &lt;li&gt;Ada kata kerja mental yang menyatakan sikap.&lt;/li&gt;
    &lt;li&gt;Tidak ada kata tidak baku, dan kalimat tidak berbelit.&lt;/li&gt;
    &lt;li&gt;Ada kalimat retoris dan minimal satu majas.&lt;/li&gt;
    &lt;li&gt;Penutup memuat simpulan, harapan, terima kasih, dan salam.&lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;

&lt;!-- ================= 4. CONTOH ================= --&gt;
&lt;div class="card" id="kbt-contoh"&gt;
  &lt;div class="sec-head"&gt;&lt;div class="num"&gt;4&lt;/div&gt;&lt;h2&gt;Contoh Teks Ceramah Beranotasi&lt;/h2&gt;&lt;/div&gt;
  &lt;p&gt;Perhatikan bagaimana kaidah kebahasaan ditandai dengan warna pada contoh berikut. Teks ini hanya contoh model. Ceramahmu harus karya sendiri dengan topik pilihanmu.&lt;/p&gt;
  &lt;div class="legend"&gt;
    &lt;span class="hl s"&gt;Salam dan sapaan&lt;/span&gt;&lt;span class="hl r"&gt;Kalimat retoris&lt;/span&gt;&lt;span class="hl a"&gt;Kalimat ajakan&lt;/span&gt;&lt;span class="hl j"&gt;Konjungsi&lt;/span&gt;&lt;span class="hl m"&gt;Majas&lt;/span&gt;&lt;span class="hl d"&gt;Contoh, data, sumber&lt;/span&gt;&lt;span class="hl v"&gt;Kata kerja mental, harapan&lt;/span&gt;
  &lt;/div&gt;
  &lt;div class="sample"&gt;
    &lt;h4 class="judul"&gt;Saring Sebelum Sharing: Cerdas Menghadapi Hoaks&lt;/h4&gt;
    &lt;div class="lbl"&gt;PEMBUKAAN&lt;/div&gt;
    &lt;p&gt;&lt;span class="hl s"&gt;Assalamualaikum warahmatullahi wabarakatuh. Selamat pagi, Bapak dan Ibu guru serta teman-teman yang saya hormati.&lt;/span&gt; &lt;span class="hl r"&gt;Pernahkah kita menerima pesan berantai yang membuat jantung berdebar, lalu tanpa berpikir panjang langsung kita teruskan ke banyak grup?&lt;/span&gt; Pagi ini saya akan menyampaikan ceramah singkat bertema Saring Sebelum Sharing, yaitu cara cerdas menghadapi hoaks di media sosial.&lt;/p&gt;
    &lt;div class="lbl"&gt;ISI&lt;/div&gt;
    &lt;p&gt;&lt;span class="hl j"&gt;Pertama&lt;/span&gt;, kita perlu &lt;span class="hl v"&gt;menyadari&lt;/span&gt; bahwa hoaks menyebar jauh lebih cepat daripada klarifikasi. &lt;span class="hl d"&gt;Menurut data Kementerian Komunikasi dan Informatika&lt;/span&gt;, ribuan konten hoaks berhasil diidentifikasi setiap tahun. &lt;span class="hl j"&gt;Akibatnya&lt;/span&gt;, banyak orang termakan kabar bohong &lt;span class="hl j"&gt;sehingga&lt;/span&gt; terjadi kepanikan, kerugian, bahkan perpecahan di tengah masyarakat.&lt;/p&gt;
    &lt;p&gt;&lt;span class="hl j"&gt;Kedua&lt;/span&gt;, kita harus mengenali ciri-ciri hoaks. &lt;span class="hl d"&gt;Misalnya&lt;/span&gt;, judulnya provokatif dan memakai huruf kapital berlebihan, sumbernya tidak jelas, serta mendesak kita untuk segera menyebarkannya. &lt;span class="hl m"&gt;Hoaks ibarat api kecil di tumpukan jerami&lt;/span&gt;; jika tidak segera dipadamkan, ia akan membakar apa saja. &lt;span class="hl j"&gt;Oleh karena itu&lt;/span&gt;, sebelum membagikan pesan apa pun, &lt;span class="hl a"&gt;periksalah&lt;/span&gt; dahulu kebenarannya.&lt;/p&gt;
    &lt;p&gt;&lt;span class="hl j"&gt;Ketiga&lt;/span&gt;, kita dapat membiasakan tiga langkah sederhana: cek sumbernya, cek faktanya, dan cek pemberitaan di media resmi. &lt;span class="hl v"&gt;Saya yakin&lt;/span&gt; siswa SMK yang terbiasa teliti di bengkel dan laboratorium pasti mampu teliti pula di dunia digital. &lt;span class="hl j"&gt;Jadi&lt;/span&gt;, &lt;span class="hl a"&gt;marilah kita jadikan&lt;/span&gt; &lt;span class="hl m"&gt;jempol kita sebagai penebar kebenaran, bukan penyebar kebohongan&lt;/span&gt;.&lt;/p&gt;
    &lt;div class="lbl"&gt;PENUTUP&lt;/div&gt;
    &lt;p&gt;&lt;span class="hl s"&gt;Hadirin yang saya hormati&lt;/span&gt;, demikian ceramah singkat dari saya. &lt;span class="hl j"&gt;Dengan demikian&lt;/span&gt;, &lt;span class="hl a"&gt;mari kita bersama-sama menjaga&lt;/span&gt; ruang digital agar tetap sehat. &lt;span class="hl v"&gt;Semoga&lt;/span&gt; kita menjadi generasi yang cerdas, jujur, dan bertanggung jawab. &lt;span class="hl a"&gt;Ingat, saring sebelum sharing!&lt;/span&gt; &lt;span class="hl s"&gt;Terima kasih atas perhatian Bapak, Ibu, dan teman-teman. Wassalamualaikum warahmatullahi wabarakatuh.&lt;/span&gt;&lt;/p&gt;
  &lt;/div&gt;

  &lt;h3&gt;Analisis Singkat&lt;/h3&gt;
  &lt;div class="tw"&gt;&lt;table class="tb"&gt;
    &lt;tr&gt;&lt;th&gt;Aspek&lt;/th&gt;&lt;th&gt;Temuan pada contoh&lt;/th&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;Gagasan pokok isi&lt;/td&gt;&lt;td&gt;(1) Hoaks menyebar lebih cepat daripada klarifikasi, (2) ciri-ciri hoaks, (3) langkah sederhana menangkal hoaks.&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;Gagasan pendukung&lt;/td&gt;&lt;td&gt;Data lembaga resmi, contoh ciri hoaks (judul provokatif, sumber tidak jelas), tiga langkah cek sumber, fakta, dan media resmi.&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;Pengait pembukaan&lt;/td&gt;&lt;td&gt;Kalimat retoris tentang pesan berantai yang langsung diteruskan.&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;Majas&lt;/td&gt;&lt;td&gt;Perumpamaan (hoaks ibarat api kecil) dan metafora (jempol sebagai penebar kebenaran).&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;Persuasi&lt;/td&gt;&lt;td&gt;Setiap ajakan didahului alasan (marilah, mari kita, periksalah) dan ditegaskan dengan slogan.&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;!-- ================= 5. LATIHAN ================= --&gt;
&lt;div class="card" id="kbt-latihan"&gt;
  &lt;div class="sec-head"&gt;&lt;div class="num"&gt;5&lt;/div&gt;&lt;h2&gt;Latihan Analisis Cepat&lt;/h2&gt;&lt;/div&gt;
  &lt;p&gt;Kerjakan dahulu di buku catatanmu, lalu buka pembahasan untuk memeriksa jawabanmu.&lt;/p&gt;

  &lt;div class="qbox"&gt;&lt;div class="qn"&gt;LATIHAN 1 - MENGIDENTIFIKASI KAIDAH&lt;/div&gt;
  Sebutkan kaidah kebahasaan pada kalimat: &lt;i&gt;"Mengapa kita sering lupa bahwa sampah kecil pun dapat menyumbat sungai?"&lt;/i&gt;
  &lt;details&gt;&lt;summary&gt;Lihat pembahasan&lt;/summary&gt;Kalimat tersebut memuat &lt;b&gt;kalimat retoris&lt;/b&gt; (pertanyaan yang tidak menuntut jawaban) dan &lt;b&gt;kata ganti kita&lt;/b&gt; (inklusif) yang membangun kedekatan dengan pendengar.&lt;/details&gt;&lt;/div&gt;

  &lt;div class="qbox"&gt;&lt;div class="qn"&gt;LATIHAN 2 - MEMBAKUKAN KALIMAT&lt;/div&gt;
  Ubahlah menjadi kalimat baku dan persuasif: &lt;i&gt;"Gue udah bilang, jangan nyontek aja, nggak keren banget!"&lt;/i&gt;
  &lt;details&gt;&lt;summary&gt;Lihat pembahasan&lt;/summary&gt;Contoh jawaban: &lt;i&gt;Saya sudah mengingatkan, janganlah menyontek, sebab perbuatan itu tidak terpuji.&lt;/i&gt; Kata gue, udah, nyontek, aja, nggak, banget diganti kata baku, dan ditambahkan alasan (sebab) agar ajakan lebih meyakinkan.&lt;/details&gt;&lt;/div&gt;

  &lt;div class="qbox"&gt;&lt;div class="qn"&gt;LATIHAN 3 - MENGGUNAKAN KONJUNGSI&lt;/div&gt;
  Gabungkan dengan konjungsi yang tepat: &lt;i&gt;Banyak siswa terlambat. Pelajaran pertama sering terlewat.&lt;/i&gt;
  &lt;details&gt;&lt;summary&gt;Lihat pembahasan&lt;/summary&gt;Contoh jawaban: &lt;i&gt;Banyak siswa terlambat sehingga pelajaran pertama sering terlewat.&lt;/i&gt; Konjungsi &lt;b&gt;sehingga&lt;/b&gt; menyatakan hubungan sebab-akibat.&lt;/details&gt;&lt;/div&gt;

  &lt;div class="qbox"&gt;&lt;div class="qn"&gt;LATIHAN 4 - MENENTUKAN MAJAS&lt;/div&gt;
  Tentukan majas pada kalimat: &lt;i&gt;"Disiplin ibarat kompas yang menuntun kita menuju tujuan."&lt;/i&gt;
  &lt;details&gt;&lt;summary&gt;Lihat pembahasan&lt;/summary&gt;&lt;b&gt;Perumpamaan (simile)&lt;/b&gt;, karena membandingkan disiplin dengan kompas secara langsung memakai kata pembanding &lt;i&gt;ibarat&lt;/i&gt;.&lt;/details&gt;&lt;/div&gt;

  &lt;div class="qbox"&gt;&lt;div class="qn"&gt;LATIHAN 5 - MENYUNTING KALIMAT EFEKTIF&lt;/div&gt;
  Sunting kalimat berikut: &lt;i&gt;"Para hadirin sekalian yang saya hormati, agar supaya kita semua dapat sukses, kita harus saling bantu-membantu."&lt;/i&gt;
  &lt;details&gt;&lt;summary&gt;Lihat pembahasan&lt;/summary&gt;Contoh jawaban: &lt;i&gt;Hadirin yang saya hormati, agar kita semua dapat sukses, kita harus saling membantu.&lt;/i&gt; Kata mubazir yang dihapus: para, sekalian, supaya, dan bentuk bantu-membantu diganti membantu.&lt;/details&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;!-- ================= 6. RANGKUMAN ================= --&gt;
&lt;div class="card" id="kbt-rangkuman"&gt;
  &lt;div class="sec-head"&gt;&lt;div class="num"&gt;6&lt;/div&gt;&lt;h2&gt;Rangkuman&lt;/h2&gt;&lt;/div&gt;
  &lt;div class="rangkuman"&gt;&lt;ul&gt;
    &lt;li&gt;Kaidah kebahasaan ceramah: salam dan sapaan, kata ganti kita atau kami, kalimat ajakan, kalimat retoris, konjungsi, kata kerja mental, kosakata baku dan istilah teknis, majas, serta kalimat efektif.&lt;/li&gt;
    &lt;li&gt;Ajakan yang meyakinkan selalu didahului alasan, dan opini diperkuat data yang bersumber jelas.&lt;/li&gt;
    &lt;li&gt;Langkah menulis ceramah: rumuskan topik dan pendengar, kumpulkan bahan, susun kerangka, kembangkan dengan rumus P-B-P-A, lalu sunting dan latih.&lt;/li&gt;
    &lt;li&gt;Ceramah ditulis untuk didengar, sehingga kalimatnya ringkas, runtut, dan enak diucapkan.&lt;/li&gt;
  &lt;/ul&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;!-- ================= 7. TUGAS INDIVIDU ================= --&gt;
&lt;div class="card" id="kbt-tugas"&gt;
  &lt;div class="sec-head"&gt;&lt;div class="num"&gt;7&lt;/div&gt;&lt;h2&gt;Tugas Individu: Menulis Teks Ceramah&lt;/h2&gt;&lt;/div&gt;

  &lt;p&gt;Tulislah &lt;b&gt;satu teks ceramah&lt;/b&gt; bertopik pilihanmu secara kreatif, langsung di halaman ini. Sistem menilai tulisanmu secara &lt;b&gt;otomatis&lt;/b&gt; berdasarkan rubrik 100 poin. Kamu boleh memeriksa dan memperbaiki tulisanmu berulang kali sebelum mengunduh hasil akhir.&lt;/p&gt;

  &lt;div class="callout warn"&gt;&lt;b class="t"&gt;Ketentuan&lt;/b&gt;
  &lt;ol style="margin:4px 0 0"&gt;
    &lt;li&gt;Naskah &lt;b&gt;wajib diketik sendiri&lt;/b&gt;. Fitur tempel (paste) dan tarik-lepas teks dinonaktifkan.&lt;/li&gt;
    &lt;li&gt;Panjang naskah minimal &lt;b&gt;200 kata&lt;/b&gt;: pembukaan, isi (minimal &lt;b&gt;3 paragraf&lt;/b&gt;, pisahkan dengan menekan Enter), dan penutup.&lt;/li&gt;
    &lt;li&gt;Topik bebas dan harus sesuai dengan judul yang kamu tulis. Gunakan data atau sumber yang benar, jangan mengarang angka.&lt;/li&gt;
    &lt;li&gt;Setelah nilai muncul, &lt;b&gt;unduh&lt;/b&gt; bukti mengerjakan (PDF F4), &lt;b&gt;cetak&lt;/b&gt;, lalu &lt;b&gt;serahkan ke guru mata pelajaran&lt;/b&gt;.&lt;/li&gt;
  &lt;/ol&gt;&lt;/div&gt;

  &lt;h3&gt;Rubrik Penilaian Otomatis&lt;/h3&gt;
  &lt;div id="kbtRubrik"&gt;&lt;/div&gt;

  &lt;h3&gt;Identitas&lt;/h3&gt;
  &lt;div class="grid3"&gt;
    &lt;div&gt;&lt;label class="fl" for="kbtAbsen"&gt;No. Absen&lt;/label&gt;&lt;input type="number" id="kbtAbsen" min="1" placeholder="Contoh: 14"&gt;&lt;/div&gt;
    &lt;div&gt;&lt;label class="fl" for="kbtNama"&gt;Nama Lengkap&lt;/label&gt;&lt;input type="text" id="kbtNama" placeholder="Nama lengkapmu"&gt;&lt;/div&gt;
    &lt;div&gt;&lt;label class="fl" for="kbtKelas"&gt;Kelas&lt;/label&gt;&lt;input type="text" id="kbtKelas" placeholder="Contoh: XI TKR 1"&gt;&lt;/div&gt;
  &lt;/div&gt;

  &lt;h3&gt;Naskah Ceramah&lt;/h3&gt;
  &lt;label class="fl" for="kbtJudul"&gt;Judul / Topik Ceramah&lt;/label&gt;
  &lt;input type="text" id="kbtJudul" maxlength="120" placeholder="Contoh: Saring Sebelum Sharing: Cerdas Menghadapi Hoaks"&gt;
  &lt;div class="pwarn" id="kbtW0"&gt;Menempel (paste) tidak diperbolehkan. Silakan ketik sendiri.&lt;/div&gt;
  &lt;div style="margin-top:6px"&gt;&lt;span style="font-size:12.5px;color:var(--ink2)"&gt;Butuh ide topik? Klik salah satu:&lt;/span&gt;&lt;br&gt;
    &lt;button type="button" class="btn chip" data-topik="Disiplin Kerja Bekal Menuju Dunia Industri"&gt;Disiplin Kerja&lt;/button&gt;
    &lt;button type="button" class="btn chip" data-topik="Waspada Pinjaman Online Ilegal bagi Generasi Muda"&gt;Pinjaman Online Ilegal&lt;/button&gt;
    &lt;button type="button" class="btn chip" data-topik="Budaya Keselamatan dan Kesehatan Kerja di Bengkel Sekolah"&gt;Keselamatan Kerja&lt;/button&gt;
    &lt;button type="button" class="btn chip" data-topik="Bijak Bermedia Sosial di Era Digital"&gt;Bijak Bermedia Sosial&lt;/button&gt;
    &lt;button type="button" class="btn chip" data-topik="Berani Berwirausaha Sejak Bangku SMK"&gt;Wirausaha Siswa SMK&lt;/button&gt;
    &lt;button type="button" class="btn chip" data-topik="Jaga Kebersihan Lingkungan Sekolah Kita"&gt;Kebersihan Lingkungan&lt;/button&gt;
  &lt;/div&gt;

  &lt;label class="fl" for="kbtPem"&gt;1. Pembukaan (salam, sapaan, pengait, pengantar topik)&lt;/label&gt;
  &lt;textarea id="kbtPem" maxlength="900" placeholder="Ketik pembukaan ceramahmu di sini (tempel/paste tidak diperbolehkan)..."&gt;&lt;/textarea&gt;
  &lt;div class="cnt" id="kbtC1"&gt;0 kata&lt;/div&gt;&lt;div class="pwarn" id="kbtW1"&gt;Menempel (paste) tidak diperbolehkan. Silakan ketik sendiri.&lt;/div&gt;

  &lt;label class="fl" for="kbtIsi"&gt;2. Isi (minimal 3 paragraf, tekan Enter untuk paragraf baru)&lt;/label&gt;
  &lt;textarea id="kbtIsi" maxlength="3000" style="min-height:240px" placeholder="Ketik isi ceramahmu di sini: tiga gagasan pokok beserta pendukungnya..."&gt;&lt;/textarea&gt;
  &lt;div class="cnt" id="kbtC2"&gt;0 kata&lt;/div&gt;&lt;div class="pwarn" id="kbtW2"&gt;Menempel (paste) tidak diperbolehkan. Silakan ketik sendiri.&lt;/div&gt;

  &lt;label class="fl" for="kbtPen"&gt;3. Penutup (simpulan, harapan, ajakan, terima kasih, salam)&lt;/label&gt;
  &lt;textarea id="kbtPen" maxlength="900" placeholder="Ketik penutup ceramahmu di sini..."&gt;&lt;/textarea&gt;
  &lt;div class="cnt" id="kbtC3"&gt;0 kata&lt;/div&gt;&lt;div class="pwarn" id="kbtW3"&gt;Menempel (paste) tidak diperbolehkan. Silakan ketik sendiri.&lt;/div&gt;

  &lt;div style="font-size:14px;font-weight:700;margin-top:10px"&gt;Total: &lt;span id="kbtTotal"&gt;0&lt;/span&gt; kata (target minimal 200)&lt;/div&gt;

  &lt;div class="err" id="kbtErr"&gt;&lt;/div&gt;

  &lt;button type="button" class="btn pri" id="kbtBtnNilai"&gt;Nilai Tulisan Saya&lt;/button&gt;
  &lt;button type="button" class="btn ghost" id="kbtBtnReset"&gt;Hapus Semua&lt;/button&gt;

  &lt;div id="kbtHasil" class="hidden"&gt;
    &lt;div id="kbtResBox"&gt;&lt;/div&gt;
    &lt;div id="kbtGroups"&gt;&lt;/div&gt;
    &lt;h3&gt;Rincian per Indikator&lt;/h3&gt;
    &lt;div id="kbtItems"&gt;&lt;/div&gt;
    &lt;div class="callout info"&gt;&lt;b class="t"&gt;Catatan&lt;/b&gt;Penilaian otomatis memeriksa penanda kaidah kebahasaan dan struktur pada tulisanmu. Perbaiki indikator yang belum tercapai lalu tekan Nilai Tulisan Saya lagi. Guru tetap dapat meninjau kualitas isi tulisanmu secara langsung.&lt;/div&gt;
    &lt;button type="button" class="btn grn" id="kbtBtnPdf"&gt;Unduh Bukti Mengerjakan (PDF F4)&lt;/button&gt;
    &lt;p style="font-size:13px;color:var(--ink2);margin-top:8px"&gt;Pada jendela cetak, pilih &lt;b&gt;Simpan sebagai PDF&lt;/b&gt; (ukuran kertas F4 atau 215 x 330 mm sudah diatur otomatis). Cetak dokumen tersebut, lalu &lt;b&gt;serahkan ke guru mata pelajaran&lt;/b&gt; sebagai bukti pengerjaan.&lt;/p&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;&lt;!-- /body --&gt;

&lt;div class="foot"&gt;DOK/B.INDO/XI/CERAMAH-02 - Kaidah Kebahasaan Teks Ceramah (Bagian 2) dan Menulis Teks Ceramah&lt;/div&gt;
&lt;/div&gt;&lt;!-- /kbt --&gt;

&lt;script&gt;
(function(){
var GAS_URL = ""; /* Opsional: isi dengan alamat Google Apps Script untuk mengirim skor ke guru. Kosongkan jika tidak dipakai. */

/*ENGINE-START*/
var GROUPS = {
  A:'Struktur Teks',
  B:'Kaidah Kebahasaan',
  C:'Gagasan Pokok dan Pendukung',
  D:'Kreativitas dan Gaya Bahasa',
  E:'Panjang dan Kerapian'
};
var SALAM = ["assalamualaikum","assalamu'alaikum","salam sejahtera","selamat pagi","selamat siang","selamat sore","selamat malam","om swastiastu","shalom","namo buddhaya","salam damai","salam hormat","salam kebajikan"];
var SAPAAN = ["hadirin","bapak","ibu","saudara","saudari","teman","adik","rekan","sahabat","yang terhormat","yang saya hormati","yang kami hormati","yang saya banggakan","yang saya cintai","yang saya sayangi","para guru","para siswa","para peserta"];
var AJAKAN = ["mari","marilah","ayo","ayolah","hendaknya","hendaklah","janganlah","jangan","mohon","harap","sebaiknya","periksalah","jagalah","ingatlah","cobalah","belajarlah","perhatikanlah","camkanlah","bersikaplah","gunakanlah","lakukanlah","hindarilah","tingkatkanlah","biasakanlah","jadikanlah","bersatulah","bersyukurlah","laksanakanlah"];
var KONJ = ["oleh karena itu","oleh sebab itu","dengan demikian","akan tetapi","selain itu","lagi pula","akibatnya","sehingga","namun","tetapi","sebaliknya","bahkan","apabila","jika","seandainya","sedangkan","jadi","karena","sebab"];
var MENTAL = ["menyadari","sadar","meyakini","yakin","percaya","berpendapat","menyimpulkan","merasa","memahami","mengetahui","berharap","mengharapkan","mengimbau","menurut saya","saya rasa","saya kira"];
var CONTOH = ["misalnya","contohnya","contoh","umpamanya","semisal","sebagai contoh"];
var URUTAN = ["pertama-tama","pertama","kedua","ketiga","keempat","selanjutnya","berikutnya","terakhir","kemudian","lalu"];
var MAJAS = ["ibarat","ibaratnya","bagaikan","bagai","laksana","bak","umpama","umpamanya","pepatah","peribahasa"];
var TIDAKBAKU = ["gak","nggak","ngga","enggak","banget","aja","udah","nih","dong","sih","kayak","gimana","emang","cuma","kok","deh","lho","loh","gue","lo","lu","pake","bikin","tapi"];
var STOP = ["yang","dengan","untuk","dalam","pada","dari","bagi","sebagai","adalah","agar","tentang","serta","atau","kita","cara","akan","dapat","lebih","antara","oleh","kami","saya"];
var SUMBER_RE = /(\bmenurut (?!saya|aku)[a-z]+|\bberdasarkan\b|\bdata\b|\bsurvei\b|\bpenelitian\b|\briset\b|\blaporan\b|\bkementerian\b|\bbadan\b|\blembaga\b|\bstatistik\b|\bpersen\b|%|\b(19|20)[0-9]{2}\b)/i;

function kbtRe(list, flags){ return new RegExp('\\b(?:' + list.join('|') + ')\\b', flags || 'gi'); }
function kbtCount(t, list){ var m = t.match(kbtRe(list)); return m ? m.length : 0; }
function kbtDistinct(t, list){
  var s = t.toLowerCase(), found = [];
  list.forEach(function(p){
    var re = new RegExp('\\b' + p + '\\b','g');
    if(re.test(s)){ found.push(p); re.lastIndex = 0; s = s.replace(re,' '); }
  });
  return found;
}
function kbtWords(t){ var m = (t || '').trim().match(/[A-Za-z0-9']+/g); return m ? m.length : 0; }
function kbtSentences(t){
  var m = (t || '').replace(/\s+/g,' ').match(/[^.!?]+[.!?]*/g) || [];
  return m.map(function(s){ return s.trim(); }).filter(function(s){ return s.length &gt; 2; });
}
function kbtParas(t){
  return (t || '').split(/\n+/).map(function(s){ return s.trim(); }).filter(function(s){ return s.length &gt; 0; });
}
function kbtKeywords(judul){
  var w = (judul || '').toLowerCase().match(/[a-z]{4,}/g) || [];
  var out = [];
  w.forEach(function(x){ if(STOP.indexOf(x) &lt; 0 &amp;&amp; out.indexOf(x) &lt; 0) out.push(x); });
  return out;
}

var IND = [
 {g:'A', label:'Salam pembuka pada bagian pembukaan', max:5,
  tip:'Awali ceramah dengan salam, misalnya Assalamualaikum atau Selamat pagi.',
  fn:function(c){ var m = c.pem.match(kbtRe(SALAM)); return [m ? 5 : 0, m ? 'Ditemukan salam: ' + m[0] : 'Belum ada salam pembuka.']; }},
 {g:'A', label:'Topik disebut jelas di pembukaan', max:5,
  tip:'Sebutkan topik ceramah (kata kunci judul) pada pembukaan.',
  fn:function(c){ var lp = c.pem.toLowerCase(); var h = c.kw.filter(function(k){ return lp.indexOf(k) &gt;= 0; }); return [h.length ? 5 : 0, h.length ? 'Kata kunci di pembukaan: ' + h.slice(0,3).join(', ') : 'Kata kunci judul belum muncul di pembukaan.']; }},
 {g:'A', label:'Isi terdiri atas minimal 3 paragraf', max:5,
  tip:'Pisahkan isi menjadi tiga paragraf atau lebih dengan menekan Enter.',
  fn:function(c){ var n = c.paras.length; return [n &gt;= 3 ? 5 : (n === 2 ? 3 : (n === 1 ? 1 : 0)), 'Jumlah paragraf isi: ' + n]; }},
 {g:'A', label:'Penutup memuat simpulan/harapan dan salam/terima kasih', max:5,
  tip:'Tutup dengan simpulan atau harapan, lalu terima kasih dan salam penutup.',
  fn:function(c){
    var a = /\b(demikian|semoga|harapan|berharap|mengharapkan|simpulan|kesimpulan|akhir kata|sekian)\b/i.test(c.pen);
    var b = /(terima kasih|wassalam|salam|sampai jumpa|om shanti)/i.test(c.pen);
    return [(a &amp;&amp; b) ? 5 : ((a || b) ? 3 : 0), 'Simpulan/harapan: ' + (a ? 'ada' : 'belum') + ', salam/terima kasih: ' + (b ? 'ada' : 'belum')];
  }},

 {g:'B', label:'Kata sapaan kepada pendengar di pembukaan', max:5,
  tip:'Sapa pendengar, misalnya Bapak dan Ibu guru serta teman-teman yang saya hormati.',
  fn:function(c){ var m = c.pem.match(kbtRe(SAPAAN)); return [m ? 5 : 0, m ? 'Ditemukan sapaan: ' + m[0] : 'Belum ada kata sapaan.']; }},
 {g:'B', label:'Kata ganti kita atau kami (minimal 3 kali)', max:5,
  tip:'Gunakan kata kita atau kami untuk membangun kedekatan dengan pendengar.',
  fn:function(c){ var n = kbtCount(c.all, ["kita","kami"]); return [n &gt;= 3 ? 5 : (n &gt;= 1 ? 3 : 0), 'Jumlah kita/kami: ' + n]; }},
 {g:'B', label:'Kalimat ajakan atau persuasif (minimal 2)', max:5,
  tip:'Tambahkan ajakan dengan penanda seperti marilah, mari kita, hendaknya, atau janganlah.',
  fn:function(c){ var n = kbtCount(c.all, AJAKAN); return [n &gt;= 2 ? 5 : (n === 1 ? 3 : 0), 'Penanda ajakan ditemukan: ' + n]; }},
 {g:'B', label:'Konjungsi penalaran (minimal 3 jenis berbeda)', max:5,
  tip:'Gunakan konjungsi seperti karena, sehingga, oleh karena itu, dengan demikian, namun, atau jika.',
  fn:function(c){ var f = kbtDistinct(c.all, KONJ); return [f.length &gt;= 3 ? 5 : (f.length === 2 ? 3 : (f.length === 1 ? 1 : 0)), 'Konjungsi ditemukan: ' + (f.length ? f.slice(0,5).join(', ') : 'tidak ada')]; }},
 {g:'B', label:'Kata kerja mental atau ungkapan sikap (minimal 2 jenis)', max:5,
  tip:'Nyatakan sikapmu dengan kata seperti menyadari, meyakini, berpendapat, menyimpulkan, atau berharap.',
  fn:function(c){ var f = kbtDistinct(c.all, MENTAL); return [f.length &gt;= 2 ? 5 : (f.length === 1 ? 3 : 0), 'Ditemukan: ' + (f.length ? f.slice(0,4).join(', ') : 'tidak ada')]; }},
 {g:'B', label:'Istilah dan kata kunci topik konsisten di seluruh teks', max:5,
  tip:'Ulangi kata kunci dari judul secara wajar di seluruh teks agar ceramah tetap fokus pada topik.',
  fn:function(c){
    var low = c.all.toLowerCase(), n = 0;
    c.kw.forEach(function(k){ var m = low.match(new RegExp(k,'g')); n += m ? m.length : 0; });
    return [n &gt;= 4 ? 5 : (n &gt;= 2 ? 3 : (n &gt;= 1 ? 1 : 0)), 'Kemunculan kata kunci judul: ' + n + ' kali'];
  }},
 {g:'B', label:'Menggunakan kata baku (tanpa kata percakapan)', max:5,
  tip:'Ganti kata tidak baku dengan kata baku, misalnya gak menjadi tidak, banget menjadi sekali.',
  fn:function(c){ var f = kbtDistinct(c.all, TIDAKBAKU); return [f.length === 0 ? 5 : (f.length &lt;= 2 ? 3 : 0), f.length ? 'Kata tidak baku: ' + f.join(', ') : 'Tidak ditemukan kata tidak baku.']; }},

 {g:'C', label:'Gagasan pendukung berupa contoh', max:5,
  tip:'Tambahkan contoh nyata pada isi dengan kata penanda seperti misalnya atau contohnya.',
  fn:function(c){ var n = kbtCount(c.isi, CONTOH); return [n &gt;= 1 ? 5 : 0, 'Penanda contoh pada isi: ' + n]; }},
 {g:'C', label:'Gagasan pendukung berupa data atau sumber', max:5,
  tip:'Sertakan data atau sumber yang jelas, misalnya menurut lembaga resmi, berdasarkan survei, atau tahun tertentu.',
  fn:function(c){ var ok = SUMBER_RE.test(c.isi); return [ok ? 5 : 0, ok ? 'Penanda data/sumber ditemukan pada isi.' : 'Belum ada penanda data atau sumber pada isi.']; }},
 {g:'C', label:'Penanda urutan gagasan pokok (pertama, kedua, dan seterusnya)', max:5,
  tip:'Awali tiap paragraf isi dengan penanda urutan: pertama, kedua, ketiga, selanjutnya, atau terakhir.',
  fn:function(c){ var f = kbtDistinct(c.isi, URUTAN); return [f.length &gt;= 2 ? 5 : (f.length === 1 ? 3 : 0), 'Penanda urutan: ' + (f.length ? f.join(', ') : 'tidak ada')]; }},
 {g:'C', label:'Paragraf isi berkembang (minimal 2 kalimat per paragraf)', max:5,
  tip:'Kembangkan setiap paragraf isi dengan kalimat utama dan kalimat penjelas (rumus P-B-P-A).',
  fn:function(c){
    if(!c.paras.length) return [0, 'Belum ada paragraf isi.'];
    var good = c.paras.filter(function(p){ return kbtSentences(p).length &gt;= 2; }).length;
    var r = good / c.paras.length;
    return [r &gt;= 0.67 ? 5 : (r &gt;= 0.34 ? 3 : 0), good + ' dari ' + c.paras.length + ' paragraf memiliki minimal 2 kalimat'];
  }},

 {g:'D', label:'Kalimat retoris (kalimat tanya penggugah)', max:5,
  tip:'Tambahkan satu pertanyaan retoris, misalnya Pernahkah kita membayangkan ...?',
  fn:function(c){ var n = (c.all.match(/\?/g) || []).length; return [n &gt;= 1 ? 5 : 0, 'Jumlah kalimat tanya: ' + n]; }},
 {g:'D', label:'Majas atau peribahasa (perumpamaan kreatif)', max:5,
  tip:'Gunakan perumpamaan dengan ibarat, bagaikan, atau laksana, atau sisipkan peribahasa.',
  fn:function(c){ var m = c.all.match(kbtRe(MAJAS)); return [m ? 5 : 0, m ? 'Penanda majas: ' + m[0] : 'Belum ada majas atau peribahasa.']; }},
 {g:'D', label:'Penegasan: seruan atau pengulangan (repetisi)', max:5,
  tip:'Tutup dengan seruan atau slogan berakhiran tanda seru, atau ulangi kata di awal tiga kalimat (anafora).',
  fn:function(c){
    var ex = (c.all.match(/!/g) || []).length;
    var map = {}, best = 0, bw = '';
    c.sents.forEach(function(s){ var w = (s.toLowerCase().match(/[a-z]+/) || [''])[0]; if(w.length &gt;= 3){ map[w] = (map[w] || 0) + 1; if(map[w] &gt; best){ best = map[w]; bw = w; } } });
    var ok = ex &gt;= 1 || best &gt;= 3;
    return [ok ? 5 : 0, ex &gt;= 1 ? 'Ada seruan (tanda seru): ' + ex : (best &gt;= 3 ? 'Pengulangan kata awal kalimat: ' + bw : 'Belum ada seruan atau repetisi.')];
  }},

 {g:'E', label:'Panjang naskah (minimal 200 kata)', max:5,
  tip:'Tambahkan gagasan pendukung, contoh, atau penjelasan hingga naskah mencapai minimal 200 kata.',
  fn:function(c){ var w = c.words; return [w &gt;= 200 ? 5 : (w &gt;= 150 ? 3 : (w &gt;= 100 ? 1 : 0)), 'Jumlah kata: ' + w]; }},
 {g:'E', label:'Ejaan: huruf kapital awal kalimat dan tanda baca akhir', max:5,
  tip:'Awali setiap kalimat dengan huruf kapital dan akhiri setiap paragraf dengan tanda baca (titik, tanya, atau seru).',
  fn:function(c){
    var tot = c.sents.length, okc = 0;
    c.sents.forEach(function(s){ if(/^[A-Z0-9"'(]/.test(s)) okc++; });
    var ratio = tot ? okc / tot : 0;
    var blocks = [c.pem].concat(c.paras).concat([c.pen]);
    var punct = blocks.every(function(b){ return /[.!?]["')]?$/.test(b.trim()); });
    var capOk = ratio &gt;= 0.9;
    return [(capOk &amp;&amp; punct) ? 5 : ((capOk || punct) ? 3 : 0), 'Kalimat berawal kapital: ' + okc + ' dari ' + tot + '; akhir paragraf bertanda baca: ' + (punct ? 'ya' : 'belum semua')];
  }}
];

function kbtEvaluate(judul, pem, isi, pen){
  var all = pem + '\n' + isi + '\n' + pen;
  var c = {judul:judul, pem:pem, isi:isi, pen:pen, all:all, paras:kbtParas(isi), kw:kbtKeywords(judul), sents:kbtSentences(all), words:kbtWords(all)};
  var items = [], gs = {}, total = 0;
  Object.keys(GROUPS).forEach(function(k){ gs[k] = {score:0, max:0}; });
  IND.forEach(function(it){
    var r = it.fn(c);
    items.push({g:it.g, label:it.label, max:it.max, score:r[0], detail:r[1], tip:it.tip});
    gs[it.g].score += r[0]; gs[it.g].max += it.max; total += r[0];
  });
  var capped = false;
  if(c.words &lt; 100 &amp;&amp; total &gt; 60){ total = 60; capped = true; }
  var cat = total &gt;= 90 ? 'Sangat Baik' : (total &gt;= 80 ? 'Baik' : (total &gt;= 75 ? 'Cukup Baik (mencapai KKM)' : (total &gt;= 60 ? 'Perlu Ditingkatkan' : 'Belum Memadai')));
  return {total:total, cat:cat, items:items, groups:gs, words:c.words, paras:c.paras.length, sents:c.sents.length, capped:capped};
}
/*ENGINE-END*/

function $(id){ return document.getElementById(id); }
function esc(s){ var d = document.createElement('div'); d.textContent = s; return d.innerHTML; }

/* ---- Rubrik statis dari IND ---- */
(function(){
  var h = '&lt;div class="tw"&gt;&lt;table class="tb"&gt;&lt;tr&gt;&lt;th&gt;Aspek&lt;/th&gt;&lt;th&gt;Indikator&lt;/th&gt;&lt;th&gt;Skor&lt;/th&gt;&lt;/tr&gt;';
  Object.keys(GROUPS).forEach(function(k){
    var sum = 0, rows = '';
    IND.forEach(function(it){ if(it.g === k){ sum += it.max; rows += '&lt;tr&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;' + esc(it.label) + '&lt;/td&gt;&lt;td&gt;' + it.max + '&lt;/td&gt;&lt;/tr&gt;'; } });
    h += '&lt;tr&gt;&lt;td&gt;&lt;b&gt;' + esc(GROUPS[k]) + '&lt;/b&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;b&gt;' + sum + '&lt;/b&gt;&lt;/td&gt;&lt;/tr&gt;' + rows;
  });
  h += '&lt;tr&gt;&lt;td&gt;&lt;b&gt;Total&lt;/b&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;b&gt;100&lt;/b&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;';
  h += '&lt;p style="font-size:13px;color:var(--ink2)"&gt;KKM = 75. Jika naskah kurang dari 100 kata, nilai akhir dibatasi maksimal 60.&lt;/p&gt;';
  $('kbtRubrik').innerHTML = h;
})();

/* ---- Navigasi ---- */
Array.prototype.forEach.call(document.querySelectorAll('#kbtNav a'), function(a){
  a.addEventListener('click', function(e){
    e.preventDefault();
    var t = $(a.getAttribute('href').slice(1));
    if(t &amp;&amp; t.scrollIntoView) t.scrollIntoView({behavior:'smooth', block:'start'});
  });
});

/* ---- Editor: hitung kata dan blokir paste ---- */
var fields = [
  {el:'kbtPem', cnt:'kbtC1', warn:'kbtW1'},
  {el:'kbtIsi', cnt:'kbtC2', warn:'kbtW2'},
  {el:'kbtPen', cnt:'kbtC3', warn:'kbtW3'},
  {el:'kbtJudul', cnt:null, warn:'kbtW0'}
];
var downloaded = false;
function updateCounts(){
  var tot = 0;
  fields.forEach(function(f){
    if(!f.cnt) return;
    var n = kbtWords($(f.el).value);
    $(f.cnt).textContent = n + ' kata';
    tot += n;
  });
  $('kbtTotal').textContent = tot;
}
fields.forEach(function(f){
  var ta = $(f.el);
  var warn = function(){
    var w = $(f.warn); if(!w) return;
    w.classList.add('show');
    clearTimeout(w._t);
    w._t = setTimeout(function(){ w.classList.remove('show'); }, 3500);
  };
  ta.addEventListener('input', function(){ downloaded = false; updateCounts(); });
  ta.addEventListener('paste', function(e){ e.preventDefault(); warn(); });
  ta.addEventListener('drop', function(e){ e.preventDefault(); warn(); });
  ta.addEventListener('dragover', function(e){ e.preventDefault(); });
  ta.addEventListener('contextmenu', function(e){ e.preventDefault(); warn(); });
  ta.addEventListener('beforeinput', function(e){
    var t = e.inputType || '';
    if(t === 'insertFromPaste' || t === 'insertFromDrop' || t === 'insertFromYank' || t === 'insertFromPasteAsQuotation'){ e.preventDefault(); warn(); }
  });
  ta.addEventListener('keydown', function(e){
    var k = (e.key || '').toLowerCase();
    if(((e.ctrlKey || e.metaKey) &amp;&amp; k === 'v') || (e.shiftKey &amp;&amp; k === 'insert')){ e.preventDefault(); warn(); }
  });
});
Array.prototype.forEach.call(document.querySelectorAll('#kbt-tugas button[data-topik]'), function(b){
  b.addEventListener('click', function(){ $('kbtJudul').value = b.getAttribute('data-topik'); updateCounts(); });
});

/* ---- Penilaian ---- */
var last = null;
function showErr(msg){ var e = $('kbtErr'); e.textContent = msg; e.style.display = 'block'; }
function hideErr(){ $('kbtErr').style.display = 'none'; }

$('kbtBtnNilai').addEventListener('click', function(){
  var absen = $('kbtAbsen').value.trim(), nama = $('kbtNama').value.trim(), kelas = $('kbtKelas').value.trim();
  var judul = $('kbtJudul').value.trim(), pem = $('kbtPem').value.trim(), isi = $('kbtIsi').value.trim(), pen = $('kbtPen').value.trim();
  if(!absen || !nama || !kelas){ showErr('Isi No. Absen, Nama Lengkap, dan Kelas terlebih dahulu.'); return; }
  if(kbtWords(judul) &lt; 2){ showErr('Tulis judul atau topik ceramah (minimal 2 kata).'); return; }
  if(!pem || !isi || !pen){ showErr('Lengkapi pembukaan, isi, dan penutup ceramahmu sebelum dinilai.'); return; }
  hideErr();
  var r = kbtEvaluate(judul, pem, isi, pen);
  last = {absen:absen, nama:nama, kelas:kelas, judul:judul, pem:pem, isi:isi, pen:pen, res:r, time:new Date()};
  renderResult(r);
});

function renderResult(r){
  var pass = r.total &gt;= 75;
  $('kbtResBox').innerHTML = '&lt;div class="resbox ' + (pass ? 'pass' : 'fail') + '"&gt;&lt;div style="font-size:13px;color:var(--ink2);font-weight:700"&gt;Nilai Otomatis&lt;/div&gt;&lt;div class="big"&gt;' + r.total + '&lt;/div&gt;&lt;div class="cat"&gt;' + esc(r.cat) + '&lt;/div&gt;&lt;div class="meta"&gt;' + r.words + ' kata - ' + r.paras + ' paragraf isi - ' + r.sents + ' kalimat - KKM 75' + (r.capped ? ' - nilai dibatasi 60 karena naskah kurang dari 100 kata' : '') + '&lt;/div&gt;&lt;/div&gt;';
  var g = '';
  Object.keys(GROUPS).forEach(function(k){
    var s = r.groups[k], pct = s.max ? Math.round(s.score / s.max * 100) : 0;
    g += '&lt;div class="gbar"&gt;&lt;div class="gl"&gt;&lt;span&gt;' + esc(GROUPS[k]) + '&lt;/span&gt;&lt;span&gt;' + s.score + ' / ' + s.max + '&lt;/span&gt;&lt;/div&gt;&lt;div class="track"&gt;&lt;div class="fill" style="width:' + pct + '%"&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;';
  });
  $('kbtGroups').innerHTML = g;
  var it = '';
  r.items.forEach(function(x){
    var cls = x.score &gt;= x.max ? 'ok' : (x.score &gt; 0 ? 'pt' : 'no');
    var lab = x.score &gt;= x.max ? 'Tercapai' : (x.score &gt; 0 ? 'Sebagian' : 'Belum');
    it += '&lt;div class="irow"&gt;&lt;span class="bd ' + cls + '"&gt;' + lab + '&lt;/span&gt;&lt;div class="tx"&gt;' + esc(x.label) + '&lt;small&gt;' + esc(x.detail) + (x.score &lt; x.max ? ' - Saran: ' + esc(x.tip) : '') + '&lt;/small&gt;&lt;/div&gt;&lt;span class="sc"&gt;' + x.score + ' / ' + x.max + '&lt;/span&gt;&lt;/div&gt;';
  });
  $('kbtItems').innerHTML = it;
  $('kbtHasil').classList.remove('hidden');
  $('kbtHasil').scrollIntoView({behavior:'smooth', block:'start'});
}

$('kbtBtnReset').addEventListener('click', function(){
  if(!window.confirm('Hapus seluruh isian dan hasil penilaian?')) return;
  ['kbtAbsen','kbtNama','kbtKelas','kbtJudul','kbtPem','kbtIsi','kbtPen'].forEach(function(id){ $(id).value = ''; });
  $('kbtHasil').classList.add('hidden');
  hideErr(); updateCounts(); last = null; downloaded = false;
});

/* ---- Kirim opsional ke Google Apps Script ---- */
var lastSentSig = '';
function sendToSheet(){
  if(!GAS_URL || !last) return;
  var r = last.res;
  var sig = last.absen + '|' + last.nama + '|' + r.total + '|' + (last.pem + last.isi + last.pen).length;
  if(sig === lastSentSig) return;
  lastSentSig = sig;
  try{
    var p = new URLSearchParams();
    var payload = {waktu:last.time.toISOString(), nama:last.nama, kelas:last.kelas, absen:last.absen, materi:'Menulis Teks Ceramah', judul:last.judul, nilaiAkhir:r.total, skorA:r.groups.A.score, skorB:r.groups.B.score, skorC:r.groups.C.score, skorD:r.groups.D.score, skorE:r.groups.E.score, jumlahKata:r.words, pembukaan:last.pem, isi:last.isi, penutup:last.pen};
    Object.keys(payload).forEach(function(k){ p.append(k, String(payload[k])); });
    fetch(GAS_URL, {method:'POST', mode:'no-cors', body:p}).catch(function(){});
  }catch(e){}
}

/* ---- PDF F4 (cetak) ---- */
var pa = document.getElementById('kbtPrint');
if(!pa){ pa = document.createElement('div'); pa.id = 'kbtPrint'; document.body.appendChild(pa); }

function buildPrint(){
  var d = last, r = d.res;
  var tgl = d.time.toLocaleDateString('id-ID', {day:'numeric', month:'long', year:'numeric'});
  var h = '';
  h += '&lt;div class="kop"&gt;&lt;h2&gt;Bukti Mengerjakan Tugas Individu - Menulis Teks Ceramah&lt;/h2&gt;&lt;p&gt;Mata Pelajaran Bahasa Indonesia - Kelas XI SMK - Kaidah Kebahasaan Teks Ceramah (Bagian 2) dan Menulis Teks Ceramah&lt;/p&gt;&lt;/div&gt;';
  h += '&lt;table class="idt"&gt;&lt;tr&gt;&lt;td class="l"&gt;Nama Lengkap&lt;/td&gt;&lt;td&gt;: ' + esc(d.nama) + '&lt;/td&gt;&lt;td class="l"&gt;No. Absen&lt;/td&gt;&lt;td&gt;: ' + esc(d.absen) + '&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="l"&gt;Kelas&lt;/td&gt;&lt;td&gt;: ' + esc(d.kelas) + '&lt;/td&gt;&lt;td class="l"&gt;Tanggal&lt;/td&gt;&lt;td&gt;: ' + esc(tgl) + '&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;';
  h += '&lt;div class="skor"&gt;&lt;div&gt;Nilai Akhir (otomatis)&lt;b&gt;' + r.total + ' / 100&lt;/b&gt;&lt;/div&gt;';
  Object.keys(GROUPS).forEach(function(k){ h += '&lt;div&gt;' + esc(GROUPS[k]) + '&lt;b&gt;' + r.groups[k].score + ' / ' + r.groups[k].max + '&lt;/b&gt;&lt;/div&gt;'; });
  h += '&lt;div&gt;Kategori&lt;b style="font-size:13px"&gt;' + esc(r.cat) + '&lt;/b&gt;&lt;/div&gt;&lt;/div&gt;';
  h += '&lt;h3&gt;Naskah Ceramah Siswa&lt;/h3&gt;';
  h += '&lt;div class="jdl"&gt;' + esc(d.judul) + '&lt;/div&gt;';
  h += '&lt;div class="lb"&gt;PEMBUKAAN&lt;/div&gt;&lt;div class="tk"&gt;' + esc(d.pem) + '&lt;/div&gt;';
  h += '&lt;div class="lb"&gt;ISI&lt;/div&gt;&lt;div class="tk"&gt;' + esc(d.isi) + '&lt;/div&gt;';
  h += '&lt;div class="lb"&gt;PENUTUP&lt;/div&gt;&lt;div class="tk"&gt;' + esc(d.pen) + '&lt;/div&gt;';
  h += '&lt;div class="nt"&gt;Jumlah kata: ' + r.words + ' - Paragraf isi: ' + r.paras + ' - Kalimat: ' + r.sents + '&lt;/div&gt;';
  h += '&lt;h3&gt;Rincian Penilaian Otomatis&lt;/h3&gt;&lt;table class="rb"&gt;&lt;tr&gt;&lt;th style="width:26px"&gt;No&lt;/th&gt;&lt;th&gt;Indikator&lt;/th&gt;&lt;th style="width:60px"&gt;Skor&lt;/th&gt;&lt;th&gt;Keterangan&lt;/th&gt;&lt;/tr&gt;';
  var no = 0;
  Object.keys(GROUPS).forEach(function(k){
    h += '&lt;tr class="gh"&gt;&lt;td colspan="2"&gt;' + esc(GROUPS[k]) + '&lt;/td&gt;&lt;td&gt;' + r.groups[k].score + ' / ' + r.groups[k].max + '&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;';
    r.items.forEach(function(x){ if(x.g === k){ no++; h += '&lt;tr&gt;&lt;td&gt;' + no + '&lt;/td&gt;&lt;td&gt;' + esc(x.label) + '&lt;/td&gt;&lt;td&gt;' + x.score + ' / ' + x.max + '&lt;/td&gt;&lt;td&gt;' + esc(x.detail) + '&lt;/td&gt;&lt;/tr&gt;'; } });
  });
  h += '&lt;/table&gt;';
  h += '&lt;div class="ttd"&gt;&lt;div&gt;Peserta Didik&lt;div class="gr"&gt;' + esc(d.nama) + '&lt;/div&gt;&lt;/div&gt;&lt;div&gt;Guru Mata Pelajaran&lt;div class="gr"&gt;.............................&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;';
  h += '&lt;p class="nt"&gt;&lt;b&gt;Dokumen ini wajib dicetak dan diserahkan kepada guru mata pelajaran Bahasa Indonesia&lt;/b&gt; sebagai bukti fisik pengerjaan tugas. Nilai dihitung otomatis berdasarkan rubrik 100 poin (KKM 75); guru dapat meninjau kembali kualitas isi naskah.&lt;/p&gt;';
  pa.innerHTML = h;
}

$('kbtBtnPdf').addEventListener('click', function(){
  if(!last){ window.alert('Tekan Nilai Tulisan Saya terlebih dahulu.'); return; }
  buildPrint();
  sendToSheet();
  downloaded = true;
  setTimeout(function(){ window.print(); }, 150);
});

window.addEventListener('beforeunload', function(e){
  var any = $('kbtPem').value || $('kbtIsi').value || $('kbtPen').value;
  if(any &amp;&amp; !downloaded){ e.preventDefault(); e.returnValue = ''; }
});

updateCounts();
})();
&lt;/script&gt;</description><link>http://kitab-investasi.blogspot.com/2026/10/kaidah-kebahasaan-teks-ceramah-bagian-2.html</link><thr:total>0</thr:total><author>nof_rizal07@yahoo.co.id (abang_cool)</author></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-9000860041661554971.post-3146553586869073198</guid><pubDate>Tue, 06 Oct 2026 00:37:56 +0000</pubDate><atom:updated>2026-10-07T15:32:31.276+07:00</atom:updated><title>Pengenalan Aplikasi Pengolah Angka (Spreadsheet)</title><description>&lt;!DOCTYPE html&gt;
&lt;html lang="id"&gt;
&lt;head&gt;
&lt;meta charset="UTF-8"&gt;
&lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&gt;
&lt;title&gt;Pengenalan Aplikasi Pengolah Angka (Spreadsheet) - Informatika Kelas X SMK&lt;/title&gt;
&lt;link rel="preconnect" href="https://fonts.googleapis.com"&gt;
&lt;link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500;600;700&amp;family=IBM+Plex+Sans:wght@400;500;600;700&amp;display=swap" rel="stylesheet"&gt;
&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"&gt;&lt;/script&gt;
&lt;script src="https://cdn.jsdelivr.net/npm/jspdf-autotable@3.8.2/dist/jspdf.plugin.autotable.min.js"&gt;&lt;/script&gt;
&lt;style&gt;
  :root{
    --brand:#15803D; --brand-dark:#0D5A2A; --surface:#EEF7F1; --paper:#FFFFFF;
    --ink:#16221B; --ink-soft:#4C5C52; --line:#D7E6DC;
    --amber:#D99A1B; --green:#15803D; --red:#D6412C;
  }
  *{box-sizing:border-box; margin:0; padding:0;}
  html{scroll-behavior:smooth;}
  body{font-family:'IBM Plex Sans',sans-serif; background:#F3F7F4; color:var(--ink); line-height:1.6;}
  .mono{font-family:'IBM Plex Mono',monospace;}

  .page-shell{max-width:1100px; margin:16px auto; background:#FFFFFF; border-radius:14px;
    box-shadow:0 8px 32px rgba(10,40,20,.14),0 1px 3px rgba(10,40,20,.08); border:1px solid var(--line);}

  header.hero{background:var(--brand); color:#fff; padding:34px 5% 30px; border-radius:14px 14px 0 0; position:relative; overflow:hidden;}
  header.hero::before{content:""; position:absolute; inset:0; background-image:
    linear-gradient(rgba(255,255,255,.07) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255,255,255,.07) 1px, transparent 1px);
    background-size:28px 28px; pointer-events:none;}
  header.hero &gt; *{position:relative; z-index:1;}
  .kop{text-align:center; font-family:'IBM Plex Mono',monospace; font-size:.72rem; letter-spacing:.12em; text-transform:uppercase; color:#BFEBCF; margin-bottom:8px;}
  h1.title{font-family:'IBM Plex Mono',monospace; font-weight:700; font-size:clamp(1.5rem,3.6vw,2.3rem); text-align:center; line-height:1.3;}
  .subtitle{text-align:center; margin-top:10px; color:#DFF3E6; font-size:.98rem; max-width:70ch; margin-left:auto; margin-right:auto;}
  .meta-strip{margin-top:26px; display:grid; grid-template-columns:repeat(auto-fit,minmax(150px,1fr)); gap:1px; background:rgba(255,255,255,.18); border:1px solid rgba(255,255,255,.18);}
  .meta-cell{background:var(--brand-dark); padding:12px 14px; text-align:center;}
  .meta-cell .k{font-family:'IBM Plex Mono',monospace; font-size:.62rem; letter-spacing:.08em; text-transform:uppercase; color:#9FDFB5;}
  .meta-cell .v{margin-top:4px; font-size:.9rem; font-weight:700;}

  main{padding:0;}
  .section{padding:32px 5%; border-bottom:1px solid #ECEFF3;}
  .section:last-child{border-bottom:none;}
  .section-tag{font-family:'IBM Plex Mono',monospace; font-size:.7rem; letter-spacing:.12em; text-transform:uppercase; color:var(--ink-soft); margin-bottom:8px;}
  h2.section-title{font-family:'IBM Plex Mono',monospace; font-size:clamp(1.15rem,2vw,1.5rem); font-weight:700; color:var(--brand-dark); margin-bottom:14px;}
  h3.sub-title{font-family:'IBM Plex Mono',monospace; font-size:1rem; font-weight:600; color:var(--brand-dark); margin:20px 0 10px; display:flex; align-items:center; gap:9px;}
  h3.sub-title::before{content:""; width:8px; height:8px; background:var(--amber); display:inline-block; border-radius:1px;}
  p{color:#33403A; max-width:80ch; margin-bottom:10px;}
  ul,ol{margin:6px 0 14px 1.3em; max-width:80ch;}
  li{margin-bottom:6px; color:#33403A;}
  strong{color:var(--brand-dark);}

  .callout{border-left:3px solid var(--brand); background:var(--surface); padding:14px 18px; border-radius:0 8px 8px 0; margin:14px 0; max-width:80ch;}
  .callout .lbl{font-family:'IBM Plex Mono',monospace; font-size:.68rem; letter-spacing:.1em; text-transform:uppercase; color:var(--brand-dark); font-weight:700; margin-bottom:6px;}
  .callout.warn{border-left-color:var(--red); background:#FCEBE8;}
  .callout.warn .lbl{color:#9B3324;}

  .card-grid{display:grid; grid-template-columns:repeat(auto-fit,minmax(210px,1fr)); gap:14px; margin:16px 0 6px;}
  .card{background:#FFFFFF; border:1.5px solid var(--line); border-radius:8px; padding:16px 18px; box-shadow:0 2px 8px rgba(10,40,20,.05);}
  .card .tag{font-family:'IBM Plex Mono',monospace; font-size:.64rem; letter-spacing:.1em; text-transform:uppercase; color:#fff; background:var(--brand); padding:3px 8px; border-radius:3px; display:inline-block; margin-bottom:10px;}
  .card h4{font-family:'IBM Plex Mono',monospace; font-size:.94rem; margin-bottom:6px; color:var(--brand-dark);}
  .card p{font-size:.87rem; margin-bottom:0;}
  .card code{font-family:'IBM Plex Mono',monospace; background:var(--surface); padding:1px 6px; border-radius:3px; font-size:.85em; color:var(--brand-dark);}

  .table-scroll{overflow-x:auto; margin:16px 0;}
  table.compare{width:100%; border-collapse:collapse; font-size:.88rem; min-width:460px;}
  table.compare th, table.compare td{border:1px solid var(--line); padding:10px 12px; text-align:left;}
  table.compare th{background:var(--brand); color:#fff; font-family:'IBM Plex Mono',monospace; font-size:.72rem; letter-spacing:.04em; text-transform:uppercase;}
  table.compare tr:nth-child(even) td{background:var(--surface);}

  .summary-box{background:var(--brand-dark); color:#fff; border-radius:8px; padding:22px 24px; margin-top:8px;}
  .summary-box h4{font-family:'IBM Plex Mono',monospace; color:#B8ECC9; font-size:.82rem; letter-spacing:.08em; text-transform:uppercase; margin-bottom:12px;}
  .summary-box ul{margin:0 0 0 1.1em; max-width:none;}
  .summary-box li{color:#E3F4E9; margin-bottom:7px;}

  .task-panel{border:1.5px dashed var(--brand); border-radius:8px; padding:24px 26px; background:repeating-linear-gradient(135deg,#FFFFFF,#FFFFFF 18px,var(--surface) 18px,var(--surface) 19px);}
  .task-head{display:flex; align-items:center; gap:12px; flex-wrap:wrap; margin-bottom:12px;}
  .task-head .badge{font-family:'IBM Plex Mono',monospace; font-size:.7rem; letter-spacing:.08em; text-transform:uppercase; background:var(--amber); color:#3A2A00; padding:4px 10px; border-radius:3px; font-weight:700;}
  .task-panel h3{font-family:'IBM Plex Mono',monospace; font-size:1.2rem; color:var(--brand-dark);}
  .steps-num{counter-reset:step; margin:14px 0; max-width:80ch;}
  .steps-num li{counter-increment:step; list-style:none; position:relative; padding-left:32px; margin-bottom:12px;}
  .steps-num li::before{content:counter(step); position:absolute; left:0; top:0; font-family:'IBM Plex Mono',monospace; font-weight:700; color:#fff; background:var(--brand); width:22px; height:22px; border-radius:50%; display:flex; align-items:center; justify-content:center; font-size:.78rem;}
  table.rubrik{width:100%; border-collapse:collapse; margin-top:16px; font-size:.86rem;}
  table.rubrik th, table.rubrik td{border:1px solid #C9D6CC; padding:9px 11px; text-align:left;}
  table.rubrik th{background:var(--brand-dark); color:#fff; font-family:'IBM Plex Mono',monospace; font-size:.73rem; letter-spacing:.04em; text-transform:uppercase;}
  table.rubrik tr:nth-child(even) td{background:#EFF5F0;}

  .field label{display:block; font-family:'IBM Plex Mono',monospace; font-size:.68rem; letter-spacing:.06em; text-transform:uppercase; color:var(--brand-dark); margin-bottom:6px;}
  .field input,.field select{width:100%; padding:10px 12px; border-radius:6px; border:1px solid var(--line); background:#fff; font-size:.92rem;}
  .student-info{display:grid; grid-template-columns:repeat(auto-fit,minmax(180px,1fr)); gap:14px; margin:14px 0;}

  .primary-btn{font-family:'IBM Plex Mono',monospace; font-weight:600; font-size:.9rem; padding:13px 26px; border-radius:7px; border:none; cursor:pointer; background:var(--brand); color:#fff;}
  .primary-btn:hover{filter:brightness(1.08);}
  .primary-btn.ghost{background:#fff; color:var(--brand); border:1.5px solid var(--brand);}
  .primary-btn:disabled{opacity:.5; cursor:not-allowed;}

  .q-card{background:#FBFCFB; border:1px solid var(--line); border-radius:8px; padding:16px 18px; margin-bottom:12px;}
  .q-num{font-family:'IBM Plex Mono',monospace; font-size:.68rem; color:var(--brand); letter-spacing:.06em; margin-bottom:6px;}
  .q-text{font-size:.95rem; color:var(--ink); margin-bottom:10px; font-weight:500;}
  .options{display:flex; flex-direction:column; gap:7px;}
  .opt{display:flex; gap:9px; padding:8px 11px; border:1px solid var(--line); border-radius:6px; cursor:pointer; background:#fff;}
  .opt:hover{border-color:var(--brand);}
  .opt.selected{border-color:var(--brand); background:#E9F7EE;}
  .opt input{margin-top:3px; accent-color:var(--brand);}
  .opt span{font-size:.88rem; color:#33403A;}

  .excel-grid{border-collapse:collapse; margin:10px 0 14px; font-family:'IBM Plex Mono',monospace; font-size:.82rem;}
  .excel-grid th, .excel-grid td{border:1px solid #BFD4C6; padding:6px 10px; text-align:center; min-width:70px;}
  .excel-grid th{background:#E3F0E7; color:var(--brand-dark); font-weight:700;}
  .excel-grid th.rownum{background:#E3F0E7; min-width:30px;}
  .excel-grid td.label-cell{text-align:left; background:#F7FAF8; color:var(--ink-soft); font-family:'IBM Plex Sans',sans-serif;}
  .excel-grid td.target-cell{background:#FFF6DC; border:2px dashed var(--amber); color:#8A6A1E; font-weight:700;}

  .sheet-grid td.g-label{text-align:left; background:#F7FAF8; color:var(--ink-soft); font-family:'IBM Plex Sans',sans-serif; font-size:.78rem; min-width:110px;}
  .sheet-input{width:100%; min-width:92px; border:1px solid var(--line); border-radius:4px; padding:5px 6px; font-family:'IBM Plex Mono',monospace; font-size:.8rem; text-align:right; background:#fff;}
  .sheet-input.formula{text-align:left; background:#FFFDF2;}
  .sheet-input:focus{outline:none; border-color:var(--brand); box-shadow:0 0 0 2px rgba(21,128,61,.18);}
  .sheet-input.err{border-color:var(--red); color:var(--red); background:#FCEBE8;}
  tr.hi-max td{background:#D9F2E1 !important; font-weight:700;}
  table.final-table td.cell-ok{background:#E3F7EA; color:#0D5A2A; font-weight:600;}
  table.final-table td.cell-bad{background:#FCE6E3; color:#9B3324; font-weight:600;}
  table.final-table td.cell-empty{background:#F3F3F3; color:#8A8A8A; font-style:italic;}
  .group-score-panel{display:none; margin-top:16px; background:#fff; border:1.5px solid var(--green); border-radius:8px; padding:20px 22px;}
  .group-actions{display:flex; gap:10px; flex-wrap:wrap; margin:14px 0;}

  .formula-input{width:100%; max-width:360px; padding:10px 12px; border-radius:6px; border:1.5px solid var(--line); font-family:'IBM Plex Mono',monospace; font-size:.92rem;}
  .formula-input:focus{outline:none; border-color:var(--brand); box-shadow:0 0 0 3px rgba(21,128,61,.14);}
  .formula-input.wrong-paste{border-color:var(--red);}

  .essay-box{width:100%; min-height:110px; border:1px solid var(--line); border-radius:6px; padding:12px 14px; font-family:'IBM Plex Sans',sans-serif; font-size:.94rem; resize:vertical;}
  .essay-box:focus{outline:none; border-color:var(--brand); box-shadow:0 0 0 3px rgba(21,128,61,.14);}

  .editor-meta{display:flex; justify-content:space-between; font-family:'IBM Plex Mono',monospace; font-size:.7rem; color:var(--ink-soft); margin-top:6px;}
  .flag{color:var(--red); font-weight:700; display:none;}
  .flag.show{display:inline;}

  .result-panel{display:none; margin-top:18px; background:#fff; border:1.5px solid var(--green); border-radius:8px; padding:22px 24px;}
  .score-lbl{font-family:'IBM Plex Mono',monospace; font-size:.7rem; letter-spacing:.1em; text-transform:uppercase; color:var(--ink-soft);}
  .score{font-family:'IBM Plex Mono',monospace; font-size:2.3rem; font-weight:700; color:var(--green);}
  #uploadMsg{font-family:'IBM Plex Mono',monospace; font-size:.82rem; color:#8A6A1E; margin-left:10px;}

  footer{background:var(--surface); text-align:center; padding:20px 5% 28px; font-family:'IBM Plex Mono',monospace; font-size:.72rem; color:var(--ink-soft); border-top:1px solid var(--line); border-radius:0 0 14px 14px;}

  @media(max-width:700px){header.hero{padding:26px 5% 24px;} .section{padding:24px 5%;}}
&lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;div class="page-shell"&gt;
&lt;header class="hero"&gt;
  &lt;div class="kop"&gt;Informatika - Fase E - Kelas X SMK&lt;/div&gt;
  &lt;h1 class="title"&gt;Pengenalan Aplikasi Pengolah Angka (Spreadsheet)&lt;/h1&gt;
  &lt;p class="subtitle"&gt;Mengenal antarmuka spreadsheet, format sel, rumus dasar, fungsi matematika, logika, dan statistik sederhana untuk mengolah data secara cepat dan akurat.&lt;/p&gt;
  &lt;div class="meta-strip"&gt;
    &lt;div class="meta-cell"&gt;&lt;div class="k"&gt;Elemen CP&lt;/div&gt;&lt;div class="v"&gt;Pengolah Angka&lt;/div&gt;&lt;/div&gt;
    &lt;div class="meta-cell"&gt;&lt;div class="k"&gt;Jenjang&lt;/div&gt;&lt;div class="v"&gt;SMK Kelas X&lt;/div&gt;&lt;/div&gt;
    &lt;div class="meta-cell"&gt;&lt;div class="k"&gt;Alokasi Waktu&lt;/div&gt;&lt;div class="v"&gt;1 Pertemuan - 4 JP&lt;/div&gt;&lt;/div&gt;
    &lt;div class="meta-cell"&gt;&lt;div class="k"&gt;Model&lt;/div&gt;&lt;div class="v"&gt;Penjelasan, Praktik &amp; Evaluasi&lt;/div&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/header&gt;

&lt;main&gt;
  &lt;section class="section" id="tujuan"&gt;
    &lt;div class="section-tag"&gt;Capaian &amp; Tujuan Pembelajaran&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Ke Mana Materi Ini Menuju&lt;/h2&gt;
    &lt;p&gt;Murid mampu mengolah data menggunakan format sel, rumus dasar, fungsi matematika, logika, dan statistik sederhana pada aplikasi spreadsheet.&lt;/p&gt;
    &lt;h3 class="sub-title"&gt;Rincian Kegiatan (4 JP x 45 menit)&lt;/h3&gt;
    &lt;div class="table-scroll"&gt;
    &lt;table class="compare"&gt;
      &lt;tr&gt;&lt;th&gt;Tahap&lt;/th&gt;&lt;th&gt;Kegiatan&lt;/th&gt;&lt;th&gt;Waktu&lt;/th&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Pendahuluan&lt;/td&gt;&lt;td&gt;Apersepsi ("Bagaimana toko kecil menghitung ratusan transaksi tanpa kalkulator manual?"), penyampaian tujuan&lt;/td&gt;&lt;td&gt;15 menit&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Inti - Eksplorasi Konsep&lt;/td&gt;&lt;td&gt;Penjelasan antarmuka spreadsheet, format sel, rumus dasar, fungsi matematika, logika, dan statistik&lt;/td&gt;&lt;td&gt;55 menit&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Inti - Kerja Kelompok&lt;/td&gt;&lt;td&gt;Diskusi dan praktik membuat laporan data sederhana dengan spreadsheet&lt;/td&gt;&lt;td&gt;45 menit&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Inti - Presentasi&lt;/td&gt;&lt;td&gt;Presentasi singkat tiap kelompok dan tanggapan guru&lt;/td&gt;&lt;td&gt;20 menit&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Inti - Evaluasi Individu&lt;/td&gt;&lt;td&gt;Mengerjakan soal pilihan ganda, praktik rumus, dan esai secara mandiri&lt;/td&gt;&lt;td&gt;35 menit&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Penutup&lt;/td&gt;&lt;td&gt;Refleksi dan penguatan konsep&lt;/td&gt;&lt;td&gt;10 menit&lt;/td&gt;&lt;/tr&gt;
    &lt;/table&gt;
    &lt;/div&gt;
  &lt;/section&gt;

  &lt;section class="section" id="pengenalan"&gt;
    &lt;div class="section-tag"&gt;Konsep Dasar&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Apa Itu Aplikasi Pengolah Angka?&lt;/h2&gt;
    &lt;p&gt;&lt;strong&gt;Aplikasi pengolah angka (spreadsheet)&lt;/strong&gt; adalah perangkat lunak yang digunakan untuk mengolah, menghitung, menganalisis, dan menyajikan data berbentuk angka maupun teks dalam format tabel yang tersusun atas baris dan kolom. Contoh aplikasi: Microsoft Excel, Google Sheets, dan LibreOffice Calc.&lt;/p&gt;

    &lt;h3 class="sub-title"&gt;Istilah Dasar dalam Spreadsheet&lt;/h3&gt;
    &lt;div class="card-grid"&gt;
      &lt;div class="card"&gt;&lt;span class="tag"&gt;Wadah Utama&lt;/span&gt;&lt;h4&gt;Workbook&lt;/h4&gt;&lt;p&gt;Satu file spreadsheet yang dapat berisi banyak sheet (lembar kerja) di dalamnya.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;span class="tag"&gt;Lembar Kerja&lt;/span&gt;&lt;h4&gt;Sheet&lt;/h4&gt;&lt;p&gt;Satu halaman kerja berisi grid sel tempat data dimasukkan dan diolah.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;span class="tag"&gt;Satuan Data&lt;/span&gt;&lt;h4&gt;Cell (Sel)&lt;/h4&gt;&lt;p&gt;Kotak perpotongan antara kolom dan baris, diberi alamat seperti A1, B2, C7.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;span class="tag"&gt;Vertikal&lt;/span&gt;&lt;h4&gt;Kolom (Column)&lt;/h4&gt;&lt;p&gt;Diberi label huruf (A, B, C, ...) tersusun vertikal.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;span class="tag"&gt;Horizontal&lt;/span&gt;&lt;h4&gt;Baris (Row)&lt;/h4&gt;&lt;p&gt;Diberi label angka (1, 2, 3, ...) tersusun horizontal.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;span class="tag"&gt;Kumpulan Sel&lt;/span&gt;&lt;h4&gt;Range&lt;/h4&gt;&lt;p&gt;Sekumpulan sel yang dipilih bersama, ditulis dengan tanda titik dua, mis. B2:B6.&lt;/p&gt;&lt;/div&gt;
    &lt;/div&gt;
  &lt;/section&gt;

  &lt;section class="section" id="format-sel"&gt;
    &lt;div class="section-tag"&gt;Tampilan Data&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Format Sel (Cell Formatting)&lt;/h2&gt;
    &lt;p&gt;Format sel mengatur bagaimana nilai di dalam sel ditampilkan, tanpa mengubah nilai aslinya. Pemformatan yang tepat membuat data lebih mudah dibaca dan dipahami.&lt;/p&gt;
    &lt;div class="table-scroll"&gt;
    &lt;table class="compare"&gt;
      &lt;tr&gt;&lt;th&gt;Format&lt;/th&gt;&lt;th&gt;Contoh Tampilan&lt;/th&gt;&lt;th&gt;Kegunaan&lt;/th&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;General/Number&lt;/td&gt;&lt;td&gt;12000&lt;/td&gt;&lt;td&gt;Angka standar tanpa pemformatan khusus.&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Currency (Mata Uang)&lt;/td&gt;&lt;td&gt;Rp12.000&lt;/td&gt;&lt;td&gt;Menampilkan nilai sebagai nominal uang.&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Percentage&lt;/td&gt;&lt;td&gt;75%&lt;/td&gt;&lt;td&gt;Menampilkan pecahan sebagai persentase (0,75 menjadi 75%).&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Comma Style (Pemisah Ribuan)&lt;/td&gt;&lt;td&gt;9.999&lt;/td&gt;&lt;td&gt;Menambahkan pemisah ribuan agar angka besar mudah dibaca.&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Date&lt;/td&gt;&lt;td&gt;06/10/2026&lt;/td&gt;&lt;td&gt;Menampilkan nilai tanggal dalam format kalender.&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Conditional Formatting&lt;/td&gt;&lt;td&gt;Warna/Data Bar otomatis&lt;/td&gt;&lt;td&gt;Memberi warna atau indikator visual otomatis berdasarkan nilai sel.&lt;/td&gt;&lt;/tr&gt;
    &lt;/table&gt;
    &lt;/div&gt;
    &lt;div class="callout"&gt;
      &lt;div class="lbl"&gt;Catatan Penting&lt;/div&gt;
      &lt;p style="margin:0;"&gt;Format sel hanya mengubah &lt;strong&gt;tampilan&lt;/strong&gt;, bukan nilai sebenarnya. Sel yang diformat Currency menjadi "Rp12.000" nilainya tetap 12000 saat dihitung dalam rumus.&lt;/p&gt;
    &lt;/div&gt;
  &lt;/section&gt;

  &lt;section class="section" id="rumus-dasar"&gt;
    &lt;div class="section-tag"&gt;Perhitungan&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Rumus Dasar (Basic Formula)&lt;/h2&gt;
    &lt;p&gt;Setiap rumus di spreadsheet selalu diawali tanda sama dengan (&lt;span class="mono"&gt;=&lt;/span&gt;). Rumus dapat menggunakan angka langsung maupun &lt;strong&gt;referensi sel&lt;/strong&gt; (alamat sel seperti A1, B2) agar hasil otomatis diperbarui saat data sumber berubah.&lt;/p&gt;
    &lt;div class="table-scroll"&gt;
    &lt;table class="compare"&gt;
      &lt;tr&gt;&lt;th&gt;Operator&lt;/th&gt;&lt;th&gt;Fungsi&lt;/th&gt;&lt;th&gt;Contoh Rumus&lt;/th&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;+&lt;/td&gt;&lt;td&gt;Penjumlahan&lt;/td&gt;&lt;td&gt;=A1+A2&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;-&lt;/td&gt;&lt;td&gt;Pengurangan&lt;/td&gt;&lt;td&gt;=A1-A2&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;*&lt;/td&gt;&lt;td&gt;Perkalian&lt;/td&gt;&lt;td&gt;=A1*A2&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;/&lt;/td&gt;&lt;td&gt;Pembagian&lt;/td&gt;&lt;td&gt;=A1/A2&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;( )&lt;/td&gt;&lt;td&gt;Mengatur prioritas perhitungan&lt;/td&gt;&lt;td&gt;=(A1+A2)*B1&lt;/td&gt;&lt;/tr&gt;
    &lt;/table&gt;
    &lt;/div&gt;
    &lt;h3 class="sub-title"&gt;Referensi Relatif vs Referensi Absolut&lt;/h3&gt;
    &lt;p&gt;Saat sebuah rumus disalin (copy) ke sel lain, &lt;strong&gt;referensi relatif&lt;/strong&gt; (mis. B2) akan otomatis bergeser mengikuti posisi baru, sedangkan &lt;strong&gt;referensi absolut&lt;/strong&gt; (mis. $B$7, dikunci dengan tanda dolar) akan selalu menunjuk ke sel yang sama meskipun disalin ke mana pun. Referensi absolut penting digunakan saat sebuah rumus perlu selalu merujuk ke satu sel tetap, misalnya sel total keseluruhan atau sel tarif pajak.&lt;/p&gt;
  &lt;/section&gt;

  &lt;section class="section" id="fungsi"&gt;
    &lt;div class="section-tag"&gt;Fungsi Spreadsheet&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Fungsi Matematika, Logika, dan Statistik&lt;/h2&gt;

    &lt;h3 class="sub-title"&gt;Fungsi Matematika &amp; Statistik Dasar&lt;/h3&gt;
    &lt;div class="card-grid"&gt;
      &lt;div class="card"&gt;&lt;span class="tag"&gt;Fungsi&lt;/span&gt;&lt;h4&gt;SUM&lt;/h4&gt;&lt;p&gt;Menjumlahkan seluruh nilai dalam suatu range. Contoh: &lt;code&gt;=SUM(B2:B6)&lt;/code&gt;&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;span class="tag"&gt;Fungsi&lt;/span&gt;&lt;h4&gt;AVERAGE&lt;/h4&gt;&lt;p&gt;Menghitung nilai rata-rata dari suatu range. Contoh: &lt;code&gt;=AVERAGE(B2:B6)&lt;/code&gt;&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;span class="tag"&gt;Fungsi&lt;/span&gt;&lt;h4&gt;MAX / MIN&lt;/h4&gt;&lt;p&gt;Mencari nilai tertinggi/terendah dalam suatu range. Contoh: &lt;code&gt;=MAX(B2:B6)&lt;/code&gt;&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;span class="tag"&gt;Fungsi&lt;/span&gt;&lt;h4&gt;COUNT / COUNTA&lt;/h4&gt;&lt;p&gt;COUNT menghitung sel berisi angka; COUNTA menghitung seluruh sel yang terisi (termasuk teks).&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;span class="tag"&gt;Fungsi&lt;/span&gt;&lt;h4&gt;ROUND&lt;/h4&gt;&lt;p&gt;Membulatkan angka ke sejumlah desimal tertentu. Contoh: &lt;code&gt;=ROUND(A1,2)&lt;/code&gt;&lt;/p&gt;&lt;/div&gt;
    &lt;/div&gt;

    &lt;h3 class="sub-title"&gt;Fungsi Logika&lt;/h3&gt;
    &lt;p&gt;Fungsi &lt;strong&gt;IF&lt;/strong&gt; digunakan untuk membuat keputusan otomatis berdasarkan suatu syarat (kondisi). Struktur dasarnya: &lt;code&gt;=IF(syarat, nilai_jika_benar, nilai_jika_salah)&lt;/code&gt;.&lt;/p&gt;
    &lt;div class="callout"&gt;
      &lt;div class="lbl"&gt;Contoh Penerapan&lt;/div&gt;
      &lt;p style="margin:0;"&gt;&lt;code&gt;=IF(B2&gt;=75,"Lulus","Tidak Lulus")&lt;/code&gt; akan menampilkan "Lulus" jika nilai di B2 adalah 75 atau lebih, dan "Tidak Lulus" jika kurang dari itu. Fungsi IF dapat digabung dengan &lt;strong&gt;AND&lt;/strong&gt; (semua syarat harus benar) atau &lt;strong&gt;OR&lt;/strong&gt; (salah satu syarat benar) untuk kondisi yang lebih kompleks, misalnya &lt;code&gt;=IF(AND(B2&gt;=75,C2&gt;=80),"Lulus","Tidak Lulus")&lt;/code&gt;.&lt;/p&gt;
    &lt;/div&gt;

    &lt;h3 class="sub-title"&gt;Fungsi Statistik Bersyarat&lt;/h3&gt;
    &lt;div class="card-grid"&gt;
      &lt;div class="card"&gt;&lt;span class="tag"&gt;Fungsi&lt;/span&gt;&lt;h4&gt;COUNTIF&lt;/h4&gt;&lt;p&gt;Menghitung banyak sel dalam suatu range yang memenuhi satu syarat. Contoh: &lt;code&gt;=COUNTIF(B2:B10,"&amp;gt;=80")&lt;/code&gt;&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;span class="tag"&gt;Fungsi&lt;/span&gt;&lt;h4&gt;SUMIF&lt;/h4&gt;&lt;p&gt;Menjumlahkan nilai dalam suatu range yang memenuhi satu syarat tertentu. Contoh: &lt;code&gt;=SUMIF(A2:A10,"Elektronik",B2:B10)&lt;/code&gt;&lt;/p&gt;&lt;/div&gt;
    &lt;/div&gt;
  &lt;/section&gt;

  &lt;section class="section" id="fitur-lain"&gt;
    &lt;div class="section-tag"&gt;Produktivitas&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Fitur Pendukung Lainnya&lt;/h2&gt;
    &lt;div class="card-grid"&gt;
      &lt;div class="card"&gt;&lt;span class="tag"&gt;Otomasi&lt;/span&gt;&lt;h4&gt;Fill Handle (AutoFill)&lt;/h4&gt;&lt;p&gt;Menarik kotak kecil di sudut sel untuk mengisi data berpola (nomor urut, tanggal) secara otomatis tanpa mengetik satu per satu.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;span class="tag"&gt;Penyajian&lt;/span&gt;&lt;h4&gt;Sorting (A-Z/Z-A)&lt;/h4&gt;&lt;p&gt;Mengurutkan data tabel berdasarkan satu kolom, dari terkecil ke terbesar atau sebaliknya.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;span class="tag"&gt;Visualisasi&lt;/span&gt;&lt;h4&gt;Chart (Grafik)&lt;/h4&gt;&lt;p&gt;Mengubah data tabel menjadi grafik batang, garis, atau pie agar lebih mudah dianalisis secara visual.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;span class="tag"&gt;Tampilan&lt;/span&gt;&lt;h4&gt;Merge &amp; Center&lt;/h4&gt;&lt;p&gt;Menggabungkan beberapa sel menjadi satu sekaligus menengahkan isinya, umum dipakai untuk judul tabel.&lt;/p&gt;&lt;/div&gt;
    &lt;/div&gt;
  &lt;/section&gt;

  &lt;section class="section" id="rangkuman"&gt;
    &lt;div class="section-tag"&gt;Penguatan Konsep&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Rangkuman Materi&lt;/h2&gt;
    &lt;div class="summary-box"&gt;
      &lt;h4&gt;Poin-Poin Kunci&lt;/h4&gt;
      &lt;ul&gt;
        &lt;li&gt;Spreadsheet mengolah data dalam bentuk sel, baris, kolom, dan range di dalam sheet dan workbook.&lt;/li&gt;
        &lt;li&gt;Format sel mengubah tampilan data (Currency, Percentage, Comma Style) tanpa mengubah nilai aslinya.&lt;/li&gt;
        &lt;li&gt;Rumus selalu diawali tanda "=" dan dapat memakai referensi relatif maupun absolut ($).&lt;/li&gt;
        &lt;li&gt;Fungsi matematika dasar: SUM, AVERAGE, MAX, MIN, COUNT/COUNTA, ROUND.&lt;/li&gt;
        &lt;li&gt;Fungsi logika IF membuat keputusan otomatis, dapat digabung dengan AND/OR.&lt;/li&gt;
        &lt;li&gt;Fungsi statistik bersyarat COUNTIF dan SUMIF menghitung/menjumlahkan data berdasarkan kriteria tertentu.&lt;/li&gt;
        &lt;li&gt;Fitur pendukung seperti Fill Handle, Sorting, Chart, dan Merge &amp; Center meningkatkan efisiensi dan kualitas penyajian data.&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/div&gt;
  &lt;/section&gt;

  &lt;section class="section" id="tugas-kelompok"&gt;
    &lt;div class="section-tag"&gt;Aktivitas Belajar&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Tugas Kelompok&lt;/h2&gt;
    &lt;div class="task-panel"&gt;
      &lt;div class="task-head"&gt;
        &lt;span class="badge"&gt;Kerja Kelompok - maksimal 6 orang&lt;/span&gt;
        &lt;span class="badge" style="background:var(--brand-dark); color:#fff;"&gt;45 menit praktik + 20 menit presentasi&lt;/span&gt;
      &lt;/div&gt;
      &lt;h3&gt;Mengerjakan Instruksi Soal Bernomor Sesuai Jurusan&lt;/h3&gt;
      &lt;p&gt;Setiap kelompok mengerjakan instruksi soal bernomor berikut &lt;strong&gt;secara langsung&lt;/strong&gt; dengan mengetikkan data dan rumus sesuai cell masing-masing pada Lembar Kerja Spreadsheet &lt;strong&gt;langsung di halaman web ini&lt;/strong&gt; - persis seperti latihan entri data yang pernah dikerjakan. Seluruh data dan rumus harus diketik sendiri (tidak bisa disalin-tempel) dan dihitung sungguhan oleh sistem, persis seperti bekerja di Excel/Google Sheets.&lt;/p&gt;

      &lt;div class="field" style="max-width:440px; margin:16px 0;"&gt;
        &lt;label&gt;Pilih Jurusan Kelompok&lt;/label&gt;
        &lt;select id="jurusanSelect"&gt;
          &lt;option value=""&gt;-- Pilih Jurusan --&lt;/option&gt;
          &lt;option value="TB"&gt;Tata Busana (TB)&lt;/option&gt;
          &lt;option value="TO"&gt;Teknik Otomotif (TO)&lt;/option&gt;
          &lt;option value="TJKT"&gt;Teknik Jaringan Komputer dan Telekomunikasi (TJKT)&lt;/option&gt;
        &lt;/select&gt;
      &lt;/div&gt;

      &lt;div id="groupTaskBody" style="display:none;"&gt;
        &lt;h3 class="sub-title"&gt;Nama Anggota Kelompok (maksimal 6 orang)&lt;/h3&gt;
        &lt;div class="student-info" id="groupMembersWrap"&gt;
          &lt;div class="field"&gt;&lt;label&gt;Anggota 1&lt;/label&gt;&lt;input type="text" class="group-member" data-n="1" placeholder="Nama anggota 1"&gt;&lt;/div&gt;
          &lt;div class="field"&gt;&lt;label&gt;Anggota 2&lt;/label&gt;&lt;input type="text" class="group-member" data-n="2" placeholder="Nama anggota 2"&gt;&lt;/div&gt;
          &lt;div class="field"&gt;&lt;label&gt;Anggota 3&lt;/label&gt;&lt;input type="text" class="group-member" data-n="3" placeholder="Nama anggota 3"&gt;&lt;/div&gt;
          &lt;div class="field"&gt;&lt;label&gt;Anggota 4&lt;/label&gt;&lt;input type="text" class="group-member" data-n="4" placeholder="Nama anggota 4 (opsional)"&gt;&lt;/div&gt;
          &lt;div class="field"&gt;&lt;label&gt;Anggota 5&lt;/label&gt;&lt;input type="text" class="group-member" data-n="5" placeholder="Nama anggota 5 (opsional)"&gt;&lt;/div&gt;
          &lt;div class="field"&gt;&lt;label&gt;Anggota 6&lt;/label&gt;&lt;input type="text" class="group-member" data-n="6" placeholder="Nama anggota 6 (opsional)"&gt;&lt;/div&gt;
        &lt;/div&gt;

        &lt;div class="callout"&gt;
          &lt;div class="lbl"&gt;Peran Kelompok&lt;/div&gt;
          &lt;p style="margin:0;"&gt;Kelompok berperan sebagai &lt;strong id="groupTaskPeran"&gt;&lt;/strong&gt; (&lt;span id="groupTaskTitleJurusan"&gt;&lt;/span&gt;) yang diminta menyelesaikan kasus berikut menggunakan spreadsheet.&lt;/p&gt;
        &lt;/div&gt;

        &lt;h3 class="sub-title" style="margin-top:22px;"&gt;Baca dan Kerjakan Instruksi Berikut&lt;/h3&gt;
        &lt;div class="card" style="background:var(--surface); border-style:dashed;"&gt;
          &lt;span class="tag"&gt;Instruksi Soal (Referensi - Jangan Disalin-Tempel)&lt;/span&gt;
          &lt;p id="groupInstruksiIntro" style="font-size:.88rem; color:var(--ink);"&gt;&lt;/p&gt;
          &lt;p style="font-size:.78rem; font-weight:600; color:var(--brand-dark); margin-top:10px;"&gt;Data Awal (Contoh - Ketikkan ke Lembar Kerja di Bawah)&lt;/p&gt;
          &lt;div class="table-scroll" id="groupDataAwalWrap" style="margin:8px 0 4px;"&gt;&lt;/div&gt;
          &lt;ol class="steps-num" id="groupInstruksiSteps" style="margin-top:14px;"&gt;&lt;/ol&gt;
        &lt;/div&gt;

        &lt;h3 class="sub-title" style="margin-top:22px;"&gt;Lembar Kerja Spreadsheet (Dihitung Langsung oleh Sistem)&lt;/h3&gt;
        &lt;p style="font-size:.86rem;"&gt;Kerjakan instruksi bernomor di atas langsung pada lembar kerja berikut. Ketikkan data pada kolom &lt;strong&gt;C&lt;/strong&gt; (Jumlah Terjual) dan &lt;strong&gt;D&lt;/strong&gt; (Harga Satuan), lalu ketikkan rumus pada kolom &lt;strong&gt;E&lt;/strong&gt; (Total) dan &lt;strong&gt;F&lt;/strong&gt; (Status), diawali tanda "=". Seluruh sel tidak menerima tempel (paste) - semua harus diketik sendiri.&lt;/p&gt;
        &lt;div class="table-scroll" id="groupGridWrap"&gt;&lt;/div&gt;
        &lt;p class="flag" id="groupPasteWarning" style="margin:6px 0 0;"&gt;[PERINGATAN] Percobaan tempel terdeteksi pada lembar kerja - seluruh data dan rumus harus diketik sendiri.&lt;/p&gt;
        &lt;div class="group-actions"&gt;
          &lt;button id="btnSortGrid" class="primary-btn ghost"&gt;Urutkan Berdasarkan Total&lt;/button&gt;
          &lt;button id="btnResetGrid" class="primary-btn ghost"&gt;Reset Lembar Kerja&lt;/button&gt;
        &lt;/div&gt;
        &lt;div id="sortedResult"&gt;&lt;/div&gt;

        &lt;h3 class="sub-title"&gt;Grafik Total Penjualan (Otomatis)&lt;/h3&gt;
        &lt;canvas id="groupChart" width="640" height="220" style="max-width:100%; background:#fff; border:1px solid var(--line); border-radius:8px; display:block;"&gt;&lt;/canvas&gt;

        &lt;div class="group-actions" style="margin-top:20px;"&gt;
          &lt;button id="btnNilaiKelompok" class="primary-btn"&gt;Hitung Penilaian &amp;amp; Tampilkan Hasil Akhir&lt;/button&gt;
        &lt;/div&gt;

        &lt;div class="group-score-panel" id="groupScorePanel"&gt;
          &lt;div class="score-lbl"&gt;Nilai Tugas Kelompok (Otomatis)&lt;/div&gt;
          &lt;div class="score" id="groupScoreValue"&gt;0&lt;/div&gt;
          &lt;p id="groupScoreDetail" style="font-size:.84rem; color:var(--ink-soft);"&gt;&lt;/p&gt;

          &lt;h3 class="sub-title" style="margin-top:18px;"&gt;Hasil Akhir Pengerjaan Tabel&lt;/h3&gt;
          &lt;p style="font-size:.8rem; color:var(--ink-soft);"&gt;Sel berwarna hijau = benar, merah = salah, abu-abu = belum diisi.&lt;/p&gt;
          &lt;div id="groupFinalTableWrap"&gt;&lt;/div&gt;

          &lt;div class="group-actions" style="margin-top:16px;"&gt;
            &lt;button id="btnUnduhTugasPDF" class="primary-btn ghost"&gt;Unduh Bukti (PDF - Tabel Hasil Akhir)&lt;/button&gt;
          &lt;/div&gt;
          &lt;span id="groupPdfMsg" class="mono" style="font-size:.78rem; color:var(--ink-soft);"&gt;&lt;/span&gt;
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;h3 class="sub-title" style="margin-top:22px;"&gt;Format Penilaian&lt;/h3&gt;
      &lt;p&gt;Pekerjaan dinilai dari ketepatan mengikuti instruksi bernomor dan hasil praktik pada lembar kerja (data, rumus Total, Status, ringkasan SUM/AVERAGE/MAX/MIN, hasil urutan, dan grafik), tanpa ada percobaan salin-tempel. Kelompok tetap mempresentasikan hasil dan alasannya di depan kelas.&lt;/p&gt;
      &lt;h3 class="sub-title"&gt;Rubrik Penilaian&lt;/h3&gt;
      &lt;table class="rubrik"&gt;
        &lt;tr&gt;&lt;th&gt;Aspek&lt;/th&gt;&lt;th&gt;Indikator&lt;/th&gt;&lt;th&gt;Skor Maks.&lt;/th&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td&gt;Ketepatan Mengikuti Instruksi&lt;/td&gt;&lt;td&gt;Data dan rumus dientri langsung sesuai instruksi bernomor, diketik sendiri tanpa salin-tempel&lt;/td&gt;&lt;td&gt;15&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td&gt;Ketepatan Rumus Total&lt;/td&gt;&lt;td&gt;Kolom Total (E) terisi rumus perkalian yang benar pada seluruh baris&lt;/td&gt;&lt;td&gt;15&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td&gt;Fungsi Logika&lt;/td&gt;&lt;td&gt;Kolom Status (F) menggunakan fungsi IF bertingkat (nested IF) tiga kategori dengan logika yang tepat&lt;/td&gt;&lt;td&gt;15&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td&gt;Fungsi Ringkasan&lt;/td&gt;&lt;td&gt;SUM, AVERAGE, MAX, MIN pada baris ringkasan terisi dan bernilai benar&lt;/td&gt;&lt;td&gt;20&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td&gt;Analisis Urutan &amp; Grafik&lt;/td&gt;&lt;td&gt;Kelompok mampu menjelaskan hasil urutan data dan membaca grafik dengan tepat&lt;/td&gt;&lt;td&gt;15&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td&gt;Kerja Sama &amp; Presentasi&lt;/td&gt;&lt;td&gt;Seluruh anggota berkontribusi; presentasi jelas dan percaya diri&lt;/td&gt;&lt;td&gt;20&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td colspan="2" style="text-align:right; font-weight:600;"&gt;Total&lt;/td&gt;&lt;td&gt;100&lt;/td&gt;&lt;/tr&gt;
      &lt;/table&gt;
    &lt;/div&gt;
  &lt;/section&gt;

  &lt;section class="section" id="identitas"&gt;
    &lt;div class="section-tag"&gt;Evaluasi Individu&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Isi Data Diri&lt;/h2&gt;
    &lt;p&gt;Kerjakan 10 soal pilihan ganda, 10 soal praktik rumus, dan 5 esai berikut secara mandiri. Skor dihitung otomatis dan langsung terkirim ke guru begitu tombol dikirim ditekan.&lt;/p&gt;
    &lt;div class="student-info"&gt;
      &lt;div class="field"&gt;&lt;label&gt;Kelas&lt;/label&gt;
        &lt;select id="kelas"&gt;
          &lt;option value=""&gt;-- Pilih Kelas --&lt;/option&gt;
          &lt;option value="X TB1"&gt;X TB1&lt;/option&gt;&lt;option value="X TB2"&gt;X TB2&lt;/option&gt;
          &lt;option value="X TO1"&gt;X TO1&lt;/option&gt;&lt;option value="X TO2"&gt;X TO2&lt;/option&gt;
          &lt;option value="X TJKT1"&gt;X TJKT1&lt;/option&gt;&lt;option value="X TJKT2"&gt;X TJKT2&lt;/option&gt;
        &lt;/select&gt;
      &lt;/div&gt;
      &lt;div class="field"&gt;&lt;label&gt;No. Absen&lt;/label&gt;&lt;input type="number" id="noAbsen" min="1" placeholder="- Pilih kelas dulu -" disabled&gt;&lt;/div&gt;
      &lt;div class="field"&gt;&lt;label&gt;Nama Lengkap&lt;/label&gt;&lt;input type="text" id="nama"&gt;&lt;/div&gt;
    &lt;/div&gt;
  &lt;/section&gt;

  &lt;section class="section" id="pg"&gt;
    &lt;div class="section-tag"&gt;Bagian A - Bobot 35%&lt;/div&gt;
    &lt;h2 class="section-title"&gt;10 Soal Pilihan Ganda (HOTS)&lt;/h2&gt;
    &lt;div id="pgContainer"&gt;&lt;/div&gt;
  &lt;/section&gt;

  &lt;section class="section" id="praktik"&gt;
    &lt;div class="section-tag"&gt;Bagian B - Bobot 40%&lt;/div&gt;
    &lt;h2 class="section-title"&gt;10 Soal Praktik Mengoperasikan Spreadsheet&lt;/h2&gt;
    &lt;p&gt;Perhatikan tabel data pada tiap soal, lalu tuliskan rumus yang tepat untuk sel yang ditandai (kotak kuning putus-putus). Tulis rumus lengkap diawali tanda "=".&lt;/p&gt;
    &lt;div id="practiceContainer"&gt;&lt;/div&gt;
  &lt;/section&gt;

  &lt;section class="section" id="esai"&gt;
    &lt;div class="section-tag"&gt;Bagian C - Bobot 25%&lt;/div&gt;
    &lt;h2 class="section-title"&gt;5 Soal Esai&lt;/h2&gt;
    &lt;p&gt;Jawab dengan kalimat sendiri berdasarkan pemahamanmu. Dilarang menyalin-tempel.&lt;/p&gt;
    &lt;div id="essayContainer"&gt;&lt;/div&gt;
  &lt;/section&gt;

  &lt;section class="section" id="submit"&gt;
    &lt;div class="section-tag"&gt;Pengumpulan&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Kirim Jawaban&lt;/h2&gt;
    &lt;button id="btnHitung" class="primary-btn"&gt;Hitung &amp; Kirim Nilai&lt;/button&gt;
    &lt;span id="uploadMsg"&gt;&lt;/span&gt;
    &lt;div class="result-panel" id="resultPanel"&gt;
      &lt;div class="score-lbl"&gt;Nilai Akhir&lt;/div&gt;
      &lt;div class="score" id="scoreValue"&gt;0&lt;/div&gt;
      &lt;p id="resultDetail"&gt;&lt;/p&gt;
      &lt;button id="btnUnduhPDF" class="primary-btn ghost" style="margin-top:14px;" disabled&gt;Unduh Bukti Mengerjakan (PDF)&lt;/button&gt;
    &lt;/div&gt;
  &lt;/section&gt;
&lt;/main&gt;
&lt;footer&gt;PENGENALAN APLIKASI PENGOLAH ANGKA (SPREADSHEET) - INFORMATIKA - FASE E KELAS X SMK&lt;/footer&gt;
&lt;/div&gt;

&lt;script&gt;
const GAS_ENDPOINT = "https://script.google.com/macros/s/AKfycbwKp7DrBTALJMlw8crjK7RgXIO8LVcU4yVEd9WJNs_vgSXkVxfw7fwkGbOT2IBNOjg3uQ/exec";
const JUDUL_MATERI = "Pengenalan Aplikasi Pengolah Angka (Spreadsheet)";

document.getElementById('kelas').addEventListener('change', (e)=&gt;{
  const noAbsenInput=document.getElementById('noAbsen');
  if(e.target.value){ noAbsenInput.disabled=false; noAbsenInput.placeholder='mis. 12'; }
  else { noAbsenInput.disabled=true; noAbsenInput.value=''; noAbsenInput.placeholder='- Pilih kelas dulu -'; }
});

// ===================== TUGAS KELOMPOK: SPREADSHEET INTERAKTIF PER JURUSAN =====================
const JURUSAN_DATA = {
  TB: {
    label:"Tata Busana (TB)",
    peran:"staf administrasi sebuah usaha konveksi dan jasa jahit",
    kolomA:"Nama Bahan/Jasa", kolomB:"Kategori",
    instruksiIntro:"Sebuah usaha konveksi dan jasa jahit mencatat penjualan bahan serta jasa selama satu bulan. Kerjakan langsung instruksi bernomor berikut pada Lembar Kerja Spreadsheet di bawah, persis seperti latihan entri data Daftar Penjualan Barang yang pernah dikerjakan.",
    items:[
      ["Kain Katun (meter)","Bahan Dasar",40,35000],
      ["Kain Denim (meter)","Bahan Dasar",13,55000],
      ["Benang Jahit (gulung)","Aksesoris",60,8000],
      ["Kancing (pack)","Aksesoris",50,12000],
      ["Resleting (pcs)","Aksesoris",45,7000],
      ["Pola Baju (lembar)","Desain",20,15000],
      ["Jasa Jahit Baju","Jasa",32,85000],
      ["Jasa Bordir","Jasa",10,65000]
    ]
  },
  TO: {
    label:"Teknik Otomotif (TO)",
    peran:"staf administrasi sebuah bengkel kendaraan bermotor",
    kolomA:"Nama Sparepart/Jasa", kolomB:"Kategori",
    instruksiIntro:"Sebuah bengkel kendaraan bermotor mencatat penjualan sparepart serta jasa servis selama satu bulan. Kerjakan langsung instruksi bernomor berikut pada Lembar Kerja Spreadsheet di bawah, persis seperti latihan entri data Daftar Penjualan Barang yang pernah dikerjakan.",
    items:[
      ["Oli Mesin 1L","Pelumas",32,65000],
      ["Ban Luar Motor","Sparepart",14,320000],
      ["Aki Motor","Sparepart",9,410000],
      ["Busi","Sparepart",40,18000],
      ["Kampas Rem","Sparepart",26,55000],
      ["Filter Udara","Sparepart",20,45000],
      ["Lampu Depan LED","Aksesoris",15,95000],
      ["Jasa Servis Ringan","Jasa",38,75000]
    ]
  },
  TJKT: {
    label:"Teknik Jaringan Komputer dan Telekomunikasi (TJKT)",
    peran:"staf administrasi sebuah toko dan jasa instalasi jaringan",
    kolomA:"Nama Produk/Jasa", kolomB:"Kategori",
    instruksiIntro:"Sebuah toko sekaligus penyedia jasa instalasi jaringan mencatat penjualan produk serta jasa selama satu bulan. Kerjakan langsung instruksi bernomor berikut pada Lembar Kerja Spreadsheet di bawah, persis seperti latihan entri data Daftar Penjualan Barang yang pernah dikerjakan.",
    items:[
      ["Kabel UTP Cat6 (roll)","Perangkat Pasif",12,850000],
      ["Router Wi-Fi","Perangkat Aktif",18,320000],
      ["Switch 8 Port","Perangkat Aktif",10,275000],
      ["Access Point","Perangkat Aktif",14,410000],
      ["Paket Internet Bulanan","Jasa Layanan",45,250000],
      ["Modem ONT","Perangkat Aktif",16,180000],
      ["Konektor RJ45 (pack)","Perangkat Pasif",28,25000],
      ["Jasa Instalasi Jaringan","Jasa",20,150000]
    ]
  }
};

let currentJurusan = null;
let REG = {};
let groupGridPasteFlag = false;

function buildDataAwalTable(data){
  let html = `&lt;table class="compare"&gt;&lt;tr&gt;&lt;th&gt;Baris&lt;/th&gt;&lt;th&gt;${data.kolomA}&lt;/th&gt;&lt;th&gt;${data.kolomB}&lt;/th&gt;&lt;th&gt;Jumlah Terjual&lt;/th&gt;&lt;th&gt;Harga Satuan&lt;/th&gt;&lt;/tr&gt;`;
  data.items.forEach((item,i)=&gt;{
    html += `&lt;tr&gt;&lt;td&gt;${i+2}&lt;/td&gt;&lt;td&gt;${item[0]}&lt;/td&gt;&lt;td&gt;${item[1]}&lt;/td&gt;&lt;td&gt;${item[2]}&lt;/td&gt;&lt;td&gt;${item[3].toLocaleString('id-ID')}&lt;/td&gt;&lt;/tr&gt;`;
  });
  html += '&lt;/table&gt;';
  return html;
}

function buildInstruksiSteps(data){
  return [
    `Ketikkan data &lt;strong&gt;${data.kolomA}&lt;/strong&gt;, &lt;strong&gt;${data.kolomB}&lt;/strong&gt;, &lt;strong&gt;Jumlah Terjual&lt;/strong&gt;, dan &lt;strong&gt;Harga Satuan&lt;/strong&gt; sesuai cell masing-masing pada kolom A sampai D (baris 2 sampai 9), seperti contoh pada tabel Data Awal di atas.`,
    `Hitunglah kolom &lt;strong&gt;TOTAL&lt;/strong&gt; (kolom E) dengan ketentuan Jumlah Terjual dikalikan Harga Satuan.&lt;br&gt;Cara: klik cell E2 &amp;gt; ketik &lt;span class="mono"&gt;=C2*D2&lt;/span&gt; &amp;gt; tekan Enter, lalu ulangi untuk E3 sampai E9.`,
    `Isilah kolom &lt;strong&gt;STATUS&lt;/strong&gt; (kolom F) menggunakan rumus IF bertingkat (nested IF): jika Jumlah Terjual 30 kali atau lebih maka "Laris", jika 15 sampai 29 kali maka "Cukup Laris", selain itu "Kurang Laris".&lt;br&gt;Cara: klik cell F2 &amp;gt; ketik &lt;span class="mono"&gt;=IF(C2&amp;gt;=30,"Laris",IF(C2&amp;gt;=15,"Cukup Laris","Kurang Laris"))&lt;/span&gt; &amp;gt; tekan Enter, lalu ulangi untuk F3 sampai F9.`,
    `Hitunglah &lt;strong&gt;Total Keseluruhan&lt;/strong&gt; pada cell E11.&lt;br&gt;Cara: klik cell E11 &amp;gt; ketik &lt;span class="mono"&gt;=SUM(E2:E9)&lt;/span&gt; &amp;gt; tekan Enter.`,
    `Hitunglah &lt;strong&gt;Rata-rata Penjualan&lt;/strong&gt; pada cell E12.&lt;br&gt;Cara: klik cell E12 &amp;gt; ketik &lt;span class="mono"&gt;=AVERAGE(E2:E9)&lt;/span&gt; &amp;gt; tekan Enter.`,
    `Carilah penjualan &lt;strong&gt;Tertinggi&lt;/strong&gt; pada cell E13.&lt;br&gt;Cara: klik cell E13 &amp;gt; ketik &lt;span class="mono"&gt;=MAX(E2:E9)&lt;/span&gt; &amp;gt; tekan Enter.`,
    `Carilah penjualan &lt;strong&gt;Terendah&lt;/strong&gt; pada cell E14.&lt;br&gt;Cara: klik cell E14 &amp;gt; ketik &lt;span class="mono"&gt;=MIN(E2:E9)&lt;/span&gt; &amp;gt; tekan Enter.`,
    `Amati baris dengan Total tertinggi yang otomatis tersorot warna hijau (simulasi Conditional Formatting), lalu klik tombol "Urutkan Berdasarkan Total" untuk melihat data terurut dari penjualan tertinggi ke terendah.`,
    `Amati grafik batang yang otomatis terbentuk dari kolom Total, lalu presentasikan hasil dan alasan kerja kelompok di depan kelas maksimal 5 menit.`
  ];
}

document.getElementById('jurusanSelect').addEventListener('change', (e)=&gt;{
  const val = e.target.value;
  const body = document.getElementById('groupTaskBody');
  if(!val){ body.style.display='none'; return; }
  body.style.display='block';
  const data = JURUSAN_DATA[val];
  document.getElementById('groupTaskTitleJurusan').textContent = data.label;
  document.getElementById('groupTaskPeran').textContent = data.peran;
  document.getElementById('groupInstruksiIntro').textContent = data.instruksiIntro;
  document.getElementById('groupDataAwalWrap').innerHTML = buildDataAwalTable(data);
  const stepsList = document.getElementById('groupInstruksiSteps');
  stepsList.innerHTML = buildInstruksiSteps(data).map(s=&gt;`&lt;li&gt;${s}&lt;/li&gt;`).join('');
  document.getElementById('sortedResult').innerHTML='';
  document.getElementById('groupScorePanel').style.display='none';
  lastGroupScore = null;
  renderGrid(val);
});

function renderGrid(key){
  currentJurusan = key;
  const data = JURUSAN_DATA[key];
  let rows = '';
  rows += `&lt;tr&gt;&lt;th&gt;&lt;/th&gt;&lt;th&gt;A&lt;/th&gt;&lt;th&gt;B&lt;/th&gt;&lt;th&gt;C&lt;/th&gt;&lt;th&gt;D&lt;/th&gt;&lt;th&gt;E&lt;/th&gt;&lt;th&gt;F&lt;/th&gt;&lt;/tr&gt;`;
  rows += `&lt;tr&gt;&lt;th class="rownum"&gt;1&lt;/th&gt;&lt;td class="g-label"&gt;${data.kolomA}&lt;/td&gt;&lt;td class="g-label"&gt;${data.kolomB}&lt;/td&gt;&lt;td class="g-label"&gt;Jumlah Terjual&lt;/td&gt;&lt;td class="g-label"&gt;Harga Satuan&lt;/td&gt;&lt;td class="g-label"&gt;Total&lt;/td&gt;&lt;td class="g-label"&gt;Status&lt;/td&gt;&lt;/tr&gt;`;
  data.items.forEach((item,i)=&gt;{
    const r=i+2;
    rows += `&lt;tr&gt;
      &lt;th class="rownum"&gt;${r}&lt;/th&gt;
      &lt;td&gt;&lt;input type="text" class="sheet-input plain" data-addr="A${r}" value="" placeholder="Baris ${r} - lihat Data Awal"&gt;&lt;/td&gt;
      &lt;td&gt;&lt;input type="text" class="sheet-input plain" data-addr="B${r}" value="" placeholder="Kategori"&gt;&lt;/td&gt;
      &lt;td&gt;&lt;input type="number" class="sheet-input plain" data-addr="C${r}" value="" placeholder="Jumlah"&gt;&lt;/td&gt;
      &lt;td&gt;&lt;input type="number" class="sheet-input plain" data-addr="D${r}" value="" placeholder="Harga"&gt;&lt;/td&gt;
      &lt;td&gt;&lt;input type="text" class="sheet-input formula" data-addr="E${r}" data-raw="" placeholder="=C${r}*D${r}"&gt;&lt;/td&gt;
      &lt;td&gt;&lt;input type="text" class="sheet-input formula" data-addr="F${r}" data-raw="" placeholder='=IF(C${r}&amp;gt;=30,"Laris",IF(C${r}&amp;gt;=15,"Cukup Laris","Kurang Laris"))'&gt;&lt;/td&gt;
    &lt;/tr&gt;`;
  });
  rows += `&lt;tr&gt;&lt;td colspan="7" style="height:6px; border:none; background:transparent;"&gt;&lt;/td&gt;&lt;/tr&gt;`;
  const sumRows = [
    ['11','Total Keseluruhan','E11', `=SUM(E2:E9)`],
    ['12','Rata-rata Penjualan','E12', `=AVERAGE(E2:E9)`],
    ['13','Produk/Jasa Terlaris (Total Tertinggi)','E13', `=MAX(E2:E9)`],
    ['14','Produk/Jasa Kurang Laris (Total Terendah)','E14', `=MIN(E2:E9)`]
  ];
  sumRows.forEach(sr=&gt;{
    rows += `&lt;tr&gt;
      &lt;th class="rownum"&gt;${sr[0]}&lt;/th&gt;
      &lt;td class="g-label" colspan="4"&gt;${sr[1]}&lt;/td&gt;
      &lt;td&gt;&lt;input type="text" class="sheet-input formula" data-addr="${sr[2]}" data-raw="" placeholder="${sr[3]}"&gt;&lt;/td&gt;
      &lt;td&gt;&lt;/td&gt;
    &lt;/tr&gt;`;
  });
  document.getElementById('groupGridWrap').innerHTML = `&lt;table class="excel-grid sheet-grid"&gt;${rows}&lt;/table&gt;`;
  groupGridPasteFlag = false;
  const warnEl = document.getElementById('groupPasteWarning');
  if(warnEl) warnEl.classList.remove('show');
  bindGridEvents();
  recalcAll();
}

function bindGridEvents(){
  document.querySelectorAll('.sheet-input').forEach(inp=&gt;{
    inp.addEventListener('paste', (e)=&gt;{
      e.preventDefault();
      groupGridPasteFlag = true;
      const warnEl = document.getElementById('groupPasteWarning');
      if(warnEl) warnEl.classList.add('show');
    });
    if(inp.classList.contains('formula')){
      inp.addEventListener('focus', ()=&gt;{ inp.value = inp.dataset.raw || ''; });
      inp.addEventListener('input', ()=&gt;{ inp.dataset.raw = inp.value; recalcAll(inp); });
    } else {
      inp.addEventListener('input', ()=&gt;{ recalcAll(); });
    }
    inp.addEventListener('blur', ()=&gt;{ recalcAll(); });
  });
}

function buildRegistry(){
  const reg = {};
  document.querySelectorAll('.sheet-input').forEach(inp=&gt;{ reg[inp.dataset.addr]=inp; });
  return reg;
}
function cellRawValue(addr){
  const el = REG[addr];
  if(!el) return '';
  if(el.classList.contains('formula')) return el.dataset.raw!==undefined ? el.dataset.raw : '';
  return el.value;
}
function evalAddr(addr, stack){
  addr = addr.toUpperCase().replace(/\$/g,'');
  if(stack.has(addr)) return 0;
  const raw = cellRawValue(addr);
  const s = String(raw===undefined||raw===null?'':raw).trim();
  if(s==='') return 0;
  if(s.startsWith('=')){
    stack.add(addr);
    const v = evalFormula(s.slice(1), stack);
    stack.delete(addr);
    return v;
  }
  const num = parseFloat(s);
  return isNaN(num) ? s : num;
}
function expandRange(a,b){
  const ma=a.match(/([A-Z]+)(\d+)/), mb=b.match(/([A-Z]+)(\d+)/);
  if(!ma||!mb) return [];
  const c1=ma[1].charCodeAt(0), c2=mb[1].charCodeAt(0);
  const r1=parseInt(ma[2]), r2=parseInt(mb[2]);
  const addrs=[];
  for(let c=Math.min(c1,c2); c&lt;=Math.max(c1,c2); c++){
    for(let r=Math.min(r1,r2); r&lt;=Math.max(r1,r2); r++) addrs.push(String.fromCharCode(c)+r);
  }
  return addrs;
}
function rangeValues(rangeStr, stack){
  const parts = rangeStr.split(':');
  if(parts.length!==2) return [];
  const addrs = expandRange(parts[0].replace(/\$/g,''), parts[1].replace(/\$/g,''));
  return addrs.map(addr=&gt;{ const v=evalAddr(addr, stack); const n=typeof v==='number'?v:parseFloat(v); return isNaN(n)?0:n; });
}
function resolveRefsInExpr(s, stack){
  return s.replace(/\$?([A-Z]{1,2})\$?(\d{1,3})/g, (m,col,row)=&gt;{
    const v=evalAddr(col+row, stack);
    return typeof v==='number' ? v : JSON.stringify(v);
  });
}
function evalAddr0(tok, stack){
  const t=tok.trim();
  if(/^\$?[A-Z]{1,2}\$?\d{1,3}$/.test(t)) return evalAddr(t.replace(/\$/g,''), stack);
  const n=parseFloat(t);
  return isNaN(n)?0:n;
}
function splitArgs(s){
  const args=[]; let depth=0, cur='', inQ=false;
  for(let i=0;i&lt;s.length;i++){
    const ch=s[i];
    if(ch==='"') inQ=!inQ;
    if(ch===',' &amp;&amp; !inQ &amp;&amp; depth===0){ args.push(cur); cur=''; continue; }
    if(ch==='(') depth++;
    if(ch===')') depth--;
    cur+=ch;
  }
  if(cur.trim().length || args.length) args.push(cur);
  return args.map(a=&gt;a.trim());
}
function computeFunc(fn, argsStr, stack){
  const args = splitArgs(argsStr);
  if(['SUM','AVERAGE','MAX','MIN','COUNT','COUNTA'].includes(fn)){
    let vals=[];
    args.forEach(a=&gt;{
      if(/^\$?[A-Z]{1,2}\$?\d{1,3}:\$?[A-Z]{1,2}\$?\d{1,3}$/.test(a)) vals=vals.concat(rangeValues(a, stack));
      else vals.push(evalAddr0(a, stack));
    });
    if(fn==='SUM') return String(vals.reduce((x,y)=&gt;x+y,0));
    if(fn==='AVERAGE') return String(vals.length?vals.reduce((x,y)=&gt;x+y,0)/vals.length:0);
    if(fn==='MAX') return String(vals.length?Math.max(...vals):0);
    if(fn==='MIN') return String(vals.length?Math.min(...vals):0);
    if(fn==='COUNT') return String(vals.filter(v=&gt;!isNaN(v)).length);
    if(fn==='COUNTA') return String(vals.length);
  }
  if(fn==='ROUND'){
    const resolved = resolveRefsInExpr(args[0], stack);
    const val = parseFloat(resolved)||0;
    const digits = parseInt(args[1])||0;
    return String(Math.round(val*Math.pow(10,digits))/Math.pow(10,digits));
  }
  if(fn==='AND'||fn==='OR'){
    const bools = args.map(a=&gt;{
      const resolved = resolveRefsInExpr(a, stack);
      try{ return !!Function('"use strict"; return ('+resolved+')')(); }catch(e){ return false; }
    });
    const result = fn==='AND' ? bools.every(Boolean) : bools.some(Boolean);
    return String(result);
  }
  if(fn==='IF'){
    const condResolved = resolveRefsInExpr(args[0], stack);
    let condVal=false;
    try{ condVal = !!Function('"use strict"; return ('+condResolved+')')(); }catch(e){ condVal=false; }
    return condVal ? args[1] : args[2];
  }
  return '0';
}
function evalFormula(expr, stack){
  expr = expr.trim();
  let changed=true, safety=0;
  while(changed &amp;&amp; safety&lt;40){
    changed=false; safety++;
    const next = expr.replace(/\b(SUM|AVERAGE|MAX|MIN|COUNT|COUNTA|ROUND|AND|OR|IF)\s*\(([^()]*)\)/i, (m, fn, argsStr)=&gt;{
      changed=true;
      return computeFunc(fn.toUpperCase(), argsStr, stack);
    });
    expr = next;
  }
  expr = expr.replace(/\$?([A-Z]{1,2})\$?(\d{1,3})/g, (m, col, row)=&gt;{
    const v = evalAddr(col+row, stack);
    return typeof v==='number' ? v : JSON.stringify(v);
  });
  try{
    return Function('"use strict"; return ('+expr+')')();
  }catch(e){ return '#ERROR'; }
}
function formatNum(n){
  if(Number.isInteger(n)) return String(n);
  return (Math.round(n*100)/100).toString();
}
function recalcAll(activeInput){
  REG = buildRegistry();
  document.querySelectorAll('.sheet-input.formula').forEach(inp=&gt;{
    if(inp===activeInput || inp===document.activeElement) return;
    const addr = inp.dataset.addr;
    const raw = (inp.dataset.raw!==undefined ? inp.dataset.raw : '').trim();
    if(raw===''){ inp.value=''; inp.classList.remove('err'); return; }
    let val;
    try{ val = raw.startsWith('=') ? evalFormula(raw.slice(1), new Set()) : raw; }
    catch(e){ val='#ERROR'; }
    if(val==='#ERROR' || (typeof val==='number' &amp;&amp; Number.isNaN(val))){
      inp.value='#ERROR'; inp.classList.add('err');
    } else {
      inp.classList.remove('err');
      inp.value = (typeof val==='number') ? formatNum(val) : val;
    }
  });
  highlightTopRow();
  drawChart();
}
function highlightTopRow(){
  let maxVal=-Infinity, maxRow=null;
  for(let r=2;r&lt;=9;r++){
    const el=REG['E'+r];
    if(!el) continue;
    const v=parseFloat(el.value);
    if(!isNaN(v) &amp;&amp; v&gt;maxVal){ maxVal=v; maxRow=r; }
  }
  document.querySelectorAll('#groupGridWrap tr').forEach(tr=&gt;tr.classList.remove('hi-max'));
  if(maxRow){
    const marker=REG['E'+maxRow];
    if(marker){ const tr=marker.closest('tr'); if(tr) tr.classList.add('hi-max'); }
  }
}
function drawChart(){
  const canvas=document.getElementById('groupChart');
  if(!canvas || !currentJurusan) return;
  const ctx=canvas.getContext('2d');
  const w=canvas.width, h=canvas.height;
  ctx.clearRect(0,0,w,h);
  const data=JURUSAN_DATA[currentJurusan];
  const vals=[];
  for(let r=2;r&lt;=9;r++){
    const el=REG['E'+r];
    const v=el?parseFloat(el.value):NaN;
    vals.push(isNaN(v)?0:v);
  }
  const maxV=Math.max(...vals,1);
  const padding=30, barGap=10;
  const barW=(w-padding*2-barGap*(vals.length-1))/vals.length;
  ctx.textAlign='center'; ctx.font='9px IBM Plex Mono, monospace';
  vals.forEach((v,i)=&gt;{
    const barH = maxV&gt;0 ? (v/maxV)*(h-60) : 0;
    const x = padding + i*(barW+barGap);
    const y = h-30-barH;
    ctx.fillStyle='#15803D';
    ctx.fillRect(x,y,barW,barH);
    ctx.fillStyle='#16221B';
    const aEl = REG['A'+(i+2)];
    const label = (aEl &amp;&amp; aEl.value.trim()) ? aEl.value.trim() : data.items[i][0];
    ctx.fillText(label.split(' ')[0], x+barW/2, h-14);
  });
}
function formatRupiah(n){
  if(isNaN(n)) return '-';
  return 'Rp' + Math.round(n).toLocaleString('id-ID');
}
document.getElementById('btnSortGrid').addEventListener('click', ()=&gt;{
  if(!currentJurusan) return;
  const data = JURUSAN_DATA[currentJurusan];
  const rows = data.items.map((item,i)=&gt;{
    const r=i+2;
    const aEl=REG['A'+r], bEl=REG['B'+r], eEl=REG['E'+r], fEl=REG['F'+r];
    const nama = (aEl &amp;&amp; aEl.value.trim()) ? aEl.value.trim() : '(belum diisi)';
    const kategori = (bEl &amp;&amp; bEl.value.trim()) ? bEl.value.trim() : '-';
    const total = eEl?parseFloat(eEl.value):NaN;
    const status = fEl?fEl.value:'';
    return {nama, kategori, total:isNaN(total)?0:total, status};
  });
  rows.sort((a,b)=&gt;b.total-a.total);
  let html = `&lt;div class="table-scroll"&gt;&lt;table class="compare"&gt;&lt;tr&gt;&lt;th&gt;Peringkat&lt;/th&gt;&lt;th&gt;${data.kolomA}&lt;/th&gt;&lt;th&gt;${data.kolomB}&lt;/th&gt;&lt;th&gt;Total&lt;/th&gt;&lt;th&gt;Status&lt;/th&gt;&lt;/tr&gt;`;
  rows.forEach((row,i)=&gt;{
    html += `&lt;tr&gt;&lt;td&gt;${i+1}&lt;/td&gt;&lt;td&gt;${row.nama}&lt;/td&gt;&lt;td&gt;${row.kategori}&lt;/td&gt;&lt;td&gt;${formatRupiah(row.total)}&lt;/td&gt;&lt;td&gt;${row.status &amp;&amp; row.status!=='#ERROR' ? row.status : '-'}&lt;/td&gt;&lt;/tr&gt;`;
  });
  html += '&lt;/table&gt;&lt;/div&gt;';
  document.getElementById('sortedResult').innerHTML = html;
});
document.getElementById('btnResetGrid').addEventListener('click', ()=&gt;{
  if(!currentJurusan) return;
  if(confirm('Reset seluruh rumus pada lembar kerja kelompok ini?')){
    document.getElementById('sortedResult').innerHTML='';
    document.getElementById('groupScorePanel').style.display='none';
    lastGroupScore = null;
    renderGrid(currentJurusan);
  }
});

function getGroupMembers(){
  return Array.from(document.querySelectorAll('.group-member'))
    .map(inp=&gt;inp.value.trim())
    .filter(v=&gt;v.length&gt;0);
}

function evaluateGroupWork(){
  if(!currentJurusan) return null;
  REG = buildRegistry();
  const data = JURUSAN_DATA[currentJurusan];
  const rows = data.items.map((item,i)=&gt;{
    const r=i+2;
    const nama = REG['A'+r] ? REG['A'+r].value.trim() : '';
    const kategori = REG['B'+r] ? REG['B'+r].value.trim() : '';
    const jumlahRaw = REG['C'+r] ? REG['C'+r].value.trim() : '';
    const hargaRaw = REG['D'+r] ? REG['D'+r].value.trim() : '';
    const totalRaw = REG['E'+r] ? REG['E'+r].value : '';
    const statusRaw = REG['F'+r] ? REG['F'+r].value.trim() : '';

    const namaOk = nama.length&gt;0 &amp;&amp; nama.toLowerCase()===item[0].toLowerCase();
    const kategoriOk = kategori.length&gt;0 &amp;&amp; kategori.toLowerCase()===item[1].toLowerCase();
    const jumlahOk = jumlahRaw!=='' &amp;&amp; parseFloat(jumlahRaw)===item[2];
    const hargaOk = hargaRaw!=='' &amp;&amp; parseFloat(hargaRaw)===item[3];

    const expectedTotal = evalFormula(`C${r}*D${r}`, new Set());
    const totalOk = totalRaw!=='' &amp;&amp; totalRaw!=='#ERROR' &amp;&amp; !isNaN(parseFloat(totalRaw)) &amp;&amp; Math.round(parseFloat(totalRaw))===Math.round(expectedTotal);

    const expectedStatus = evalFormula(`IF(C${r}&gt;=30,"Laris",IF(C${r}&gt;=15,"Cukup Laris","Kurang Laris"))`, new Set());
    const statusOk = statusRaw!=='' &amp;&amp; statusRaw!=='#ERROR' &amp;&amp; statusRaw.toLowerCase()===String(expectedStatus).toLowerCase();

    return {no:i+1, r, nama, kategori, jumlah:jumlahRaw, harga:hargaRaw, total:totalRaw, status:statusRaw,
      namaOk, kategoriOk, jumlahOk, hargaOk, totalOk, statusOk};
  });

  const expectedSum = evalFormula('SUM(E2:E9)', new Set());
  const expectedAvg = evalFormula('AVERAGE(E2:E9)', new Set());
  const expectedMax = evalFormula('MAX(E2:E9)', new Set());
  const expectedMin = evalFormula('MIN(E2:E9)', new Set());

  const sumRaw = REG['E11']?REG['E11'].value:'';
  const avgRaw = REG['E12']?REG['E12'].value:'';
  const maxRaw = REG['E13']?REG['E13'].value:'';
  const minRaw = REG['E14']?REG['E14'].value:'';

  const closeEnough=(raw,expected)=&gt;{ const x=parseFloat(raw); return raw!=='' &amp;&amp; raw!=='#ERROR' &amp;&amp; !isNaN(x) &amp;&amp; Math.abs(x-expected)&lt;1; };

  const summary = {
    sum:{raw:sumRaw, ok:closeEnough(sumRaw, expectedSum)},
    avg:{raw:avgRaw, ok:closeEnough(avgRaw, expectedAvg)},
    max:{raw:maxRaw, ok:closeEnough(maxRaw, expectedMax)},
    min:{raw:minRaw, ok:closeEnough(minRaw, expectedMin)}
  };

  return {label:data.label, kolomA:data.kolomA, kolomB:data.kolomB, rows, summary};
}

function scoreGroupWork(){
  const ev = evaluateGroupWork();
  if(!ev) return null;
  const n = ev.rows.length;
  let dataCorrect=0, totalCorrect=0, statusCorrect=0;
  ev.rows.forEach(row=&gt;{
    if(row.namaOk &amp;&amp; row.kategoriOk &amp;&amp; row.jumlahOk &amp;&amp; row.hargaOk) dataCorrect++;
    if(row.totalOk) totalCorrect++;
    if(row.statusOk) statusCorrect++;
  });
  const dataScore = Math.round(dataCorrect/n*100);
  const totalScore = Math.round(totalCorrect/n*100);
  const statusScore = Math.round(statusCorrect/n*100);
  const summaryCorrect = [ev.summary.sum.ok, ev.summary.avg.ok, ev.summary.max.ok, ev.summary.min.ok].filter(Boolean).length;
  const summaryScore = Math.round(summaryCorrect/4*100);

  let finalScore = Math.round(dataScore*0.20 + totalScore*0.25 + statusScore*0.25 + summaryScore*0.30);
  const pastePenalty = groupGridPasteFlag;
  if(pastePenalty) finalScore = Math.round(finalScore*0.5);

  return {ev, dataScore, totalScore, statusScore, summaryScore, finalScore, pastePenalty};
}

let lastGroupScore = null;

function cellClass(val, ok){
  if(!val || String(val).trim()==='') return 'cell-empty';
  return ok ? 'cell-ok' : 'cell-bad';
}

function renderGroupAssessment(){
  if(!currentJurusan){ alert('Pilih jurusan terlebih dahulu.'); return; }
  const members = getGroupMembers();
  if(members.length===0){ alert('Isi minimal satu nama anggota kelompok terlebih dahulu.'); return; }

  const result = scoreGroupWork();
  lastGroupScore = result;
  const data = JURUSAN_DATA[currentJurusan];

  document.getElementById('groupScoreValue').textContent = result.finalScore;
  document.getElementById('groupScoreDetail').innerHTML =
    `Data Entri (20%): &lt;strong&gt;${result.dataScore}&lt;/strong&gt; &amp;nbsp;|&amp;nbsp; ` +
    `Rumus Total (25%): &lt;strong&gt;${result.totalScore}&lt;/strong&gt; &amp;nbsp;|&amp;nbsp; ` +
    `Rumus Status (25%): &lt;strong&gt;${result.statusScore}&lt;/strong&gt; &amp;nbsp;|&amp;nbsp; ` +
    `Rumus Ringkasan (30%): &lt;strong&gt;${result.summaryScore}&lt;/strong&gt;` +
    (result.pastePenalty ? '&lt;br&gt;&lt;span style="color:var(--red); font-weight:700;"&gt;[PERINGATAN] Terdeteksi percobaan tempel pada lembar kerja - nilai dipotong 50%&lt;/span&gt;' : '');

  const ev = result.ev;
  let html = `&lt;div class="table-scroll"&gt;&lt;table class="compare final-table"&gt;
    &lt;tr&gt;&lt;th&gt;No&lt;/th&gt;&lt;th&gt;${data.kolomA}&lt;/th&gt;&lt;th&gt;${data.kolomB}&lt;/th&gt;&lt;th&gt;Jumlah Terjual&lt;/th&gt;&lt;th&gt;Harga Satuan&lt;/th&gt;&lt;th&gt;Total&lt;/th&gt;&lt;th&gt;Status&lt;/th&gt;&lt;/tr&gt;`;
  ev.rows.forEach(row=&gt;{
    html += `&lt;tr&gt;&lt;td&gt;${row.no}&lt;/td&gt;
      &lt;td class="${cellClass(row.nama,row.namaOk)}"&gt;${row.nama||'-'}&lt;/td&gt;
      &lt;td class="${cellClass(row.kategori,row.kategoriOk)}"&gt;${row.kategori||'-'}&lt;/td&gt;
      &lt;td class="${cellClass(row.jumlah,row.jumlahOk)}"&gt;${row.jumlah||'-'}&lt;/td&gt;
      &lt;td class="${cellClass(row.harga,row.hargaOk)}"&gt;${row.harga||'-'}&lt;/td&gt;
      &lt;td class="${cellClass(row.total,row.totalOk)}"&gt;${row.total||'-'}&lt;/td&gt;
      &lt;td class="${cellClass(row.status,row.statusOk)}"&gt;${row.status||'-'}&lt;/td&gt;
    &lt;/tr&gt;`;
  });
  html += '&lt;/table&gt;&lt;/div&gt;';
  html += `&lt;div class="table-scroll" style="margin-top:10px;"&gt;&lt;table class="compare final-table"&gt;
    &lt;tr&gt;&lt;th&gt;Ringkasan&lt;/th&gt;&lt;th&gt;Nilai&lt;/th&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;Total Keseluruhan (SUM)&lt;/td&gt;&lt;td class="${cellClass(ev.summary.sum.raw, ev.summary.sum.ok)}"&gt;${ev.summary.sum.raw||'-'}&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;Rata-rata (AVERAGE)&lt;/td&gt;&lt;td class="${cellClass(ev.summary.avg.raw, ev.summary.avg.ok)}"&gt;${ev.summary.avg.raw||'-'}&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;Tertinggi (MAX)&lt;/td&gt;&lt;td class="${cellClass(ev.summary.max.raw, ev.summary.max.ok)}"&gt;${ev.summary.max.raw||'-'}&lt;/td&gt;&lt;/tr&gt;
    &lt;tr&gt;&lt;td&gt;Terendah (MIN)&lt;/td&gt;&lt;td class="${cellClass(ev.summary.min.raw, ev.summary.min.ok)}"&gt;${ev.summary.min.raw||'-'}&lt;/td&gt;&lt;/tr&gt;
  &lt;/table&gt;&lt;/div&gt;`;
  document.getElementById('groupFinalTableWrap').innerHTML = html;

  document.getElementById('groupScorePanel').style.display='block';
  document.getElementById('groupPdfMsg').textContent='';
}

document.getElementById('btnNilaiKelompok').addEventListener('click', renderGroupAssessment);
document.getElementById('btnUnduhTugasPDF').addEventListener('click', downloadTugasKelompokPDF);

function downloadTugasKelompokPDF(){
  const msg = document.getElementById('groupPdfMsg');
  if(!lastGroupScore){ msg.textContent='Klik "Hitung Penilaian &amp; Tampilkan Hasil Akhir" terlebih dahulu.'; return; }
  if(!window.jspdf){ alert('Pustaka pembuat PDF gagal dimuat. Pastikan koneksi internet aktif lalu muat ulang halaman.'); return; }
  const members = getGroupMembers();
  const data = JURUSAN_DATA[currentJurusan];
  const ev = lastGroupScore.ev;

  const { jsPDF } = window.jspdf;
  const doc = new jsPDF({ unit:'mm', format:[215,330] }); // Ukuran F4
  const pageW=215, marginX=16;
  let y = 16;

  doc.setFont('helvetica','bold'); doc.setFontSize(13); doc.setTextColor(20,30,25);
  doc.text('HASIL AKHIR TUGAS KELOMPOK', marginX, y); y+=6;
  doc.setFontSize(10); doc.setTextColor(21,128,61);
  doc.text(JUDUL_MATERI, marginX, y); y+=6;
  doc.setFont('helvetica','normal'); doc.setFontSize(9.5); doc.setTextColor(50,60,55);
  doc.text(`Jurusan: ${ev.label}   |   Anggota: ${members.join(', ')}`, marginX, y); y+=6;
  doc.setFont('helvetica','bold'); doc.setFontSize(11); doc.setTextColor(13,90,42);
  doc.text(`Nilai Tugas Kelompok (Otomatis): ${lastGroupScore.finalScore}`, marginX, y); y+=8;

  doc.autoTable({
    startY: y,
    head: [[ 'No', data.kolomA, data.kolomB, 'Jumlah Terjual', 'Harga Satuan', 'Total', 'Status' ]],
    body: ev.rows.map(row=&gt;[row.no, row.nama||'-', row.kategori||'-', row.jumlah||'-', row.harga||'-', row.total||'-', row.status||'-']),
    theme: 'grid',
    headStyles: { fillColor: [21,128,61], textColor: 255, fontStyle: 'bold', fontSize: 8.5 },
    bodyStyles: { fontSize: 8.5 },
    margin: { left: marginX, right: marginX },
    didParseCell: function(d){
      if(d.section==='body'){
        const row = ev.rows[d.row.index];
        const okMap = [true, row.namaOk, row.kategoriOk, row.jumlahOk, row.hargaOk, row.totalOk, row.statusOk];
        if(d.column.index&gt;0){
          d.cell.styles.fillColor = okMap[d.column.index] ? [227,247,234] : [252,230,227];
          d.cell.styles.textColor = okMap[d.column.index] ? [13,90,42] : [155,51,36];
        }
      }
    }
  });

  let y2 = doc.lastAutoTable.finalY + 8;
  doc.autoTable({
    startY: y2,
    head: [['Ringkasan','Nilai']],
    body: [
      ['Total Keseluruhan (SUM)', ev.summary.sum.raw||'-'],
      ['Rata-rata (AVERAGE)', ev.summary.avg.raw||'-'],
      ['Tertinggi (MAX)', ev.summary.max.raw||'-'],
      ['Terendah (MIN)', ev.summary.min.raw||'-']
    ],
    theme: 'grid',
    headStyles: { fillColor: [13,90,42], textColor: 255, fontStyle: 'bold', fontSize: 8.5 },
    bodyStyles: { fontSize: 8.5 },
    margin: { left: marginX, right: marginX },
    didParseCell: function(d){
      if(d.section==='body' &amp;&amp; d.column.index===1){
        const keys=['sum','avg','max','min'];
        const ok = ev.summary[keys[d.row.index]].ok;
        d.cell.styles.fillColor = ok ? [227,247,234] : [252,230,227];
        d.cell.styles.textColor = ok ? [13,90,42] : [155,51,36];
      }
    }
  });

  let y3 = doc.lastAutoTable.finalY + 10;
  doc.setFont('helvetica','normal'); doc.setFontSize(8); doc.setTextColor(90,100,95);
  doc.text('Dokumen ini dicetak otomatis oleh sistem sebagai bukti hasil akhir pengerjaan Tugas Kelompok.', marginX, y3); y3+=14;
  doc.setFontSize(10); doc.setTextColor(20,30,25);
  const todayStr = new Date().toLocaleDateString('id-ID',{day:'numeric',month:'long',year:'numeric'});
  doc.text('......................, ' + todayStr, marginX, y3); y3+=16;
  doc.text('( ' + (members[0]||'...........................') + ' )', marginX, y3); y3+=5;
  doc.setFontSize(9); doc.setTextColor(90,100,95);
  doc.text('Perwakilan Kelompok', marginX, y3);

  msg.textContent='';
  doc.save('Hasil-Tugas-Kelompok-' + currentJurusan + '-' + Date.now() + '.pdf');
}

const LETTERS=["A","B","C","D","E"];
let lastPGDetail=[], lastPracticeDetail=[], lastEssayDetail=[], lastSubmission=null;

// ===================== 10 SOAL PG (HOTS) =====================
const PG = [
 {q:"Seorang siswa membuat rumus pajak 10% dari harga barang dengan menulis tarif pajak di sel B1, lalu rumus =A2*B1 disalin ke A3, A4, dst. Namun hasilnya salah karena B1 ikut bergeser. Perbaikan yang tepat adalah mengubah rumus menjadi...",o:["=A2*B2","=A2*$B$1","=A2+B1","=$A2*B1","=A2*B1$"],a:1},
 {q:"Seorang kasir mengetik total belanja dengan mengetik langsung angka hasil penjumlahan manual di setiap transaksi, bukan dengan rumus. Risiko utama dari kebiasaan ini adalah...",o:["Data akan otomatis diperbarui jika harga berubah","Total tidak akan ikut berubah otomatis saat data sumber diubah","Spreadsheet akan berjalan lebih cepat","Format Currency tidak akan berfungsi","Tidak ada risiko karena hasilnya tetap akurat"],a:1},
 {q:"Sebuah sel menampilkan 12000 sebagai Rp12.000 setelah diformat Currency. Saat sel tersebut dipakai dalam rumus SUM, nilai yang dihitung sistem adalah...",o:["12000 (nilai asli)","Rp12.000 (termasuk simbol Rp)","0 karena formatnya berubah","12.000 sebagai teks","Error karena format tidak dikenali"],a:0},
 {q:"Seorang siswa ingin mengisi nomor urut 1 sampai 50 di kolom A tanpa mengetik satu per satu. Cara paling efisien yang sebaiknya digunakan adalah...",o:["Mengetik manual seluruh angka","Menggunakan Fill Handle (AutoFill) dari dua angka awal yang membentuk pola","Menyalin angka 1 ke seluruh sel","Menggunakan fungsi SUM","Mengubah format sel menjadi Number"],a:1},
 {q:"Sebuah tabel gaji menampilkan angka 2500000 tanpa pemisah ribuan sehingga sulit dibaca dengan cepat. Format yang paling tepat diterapkan adalah...",o:["Percentage","Date","Comma Style (pemisah ribuan)","General","Text"],a:2},
 {q:"Seorang guru ingin mengurutkan data nilai siswa dari yang tertinggi ke terendah agar mudah menentukan peringkat kelas. Fitur yang paling tepat digunakan adalah...",o:["Conditional Formatting","Merge &amp; Center","Sorting (urutkan Z-A)","Fill Handle","Chart"],a:2},
 {q:"Sebuah tabel penjualan ingin menyorot otomatis sel dengan nilai di atas rata-rata menggunakan warna berbeda tanpa menandai manual satu per satu. Fitur yang tepat digunakan adalah...",o:["Sorting","Conditional Formatting","Merge &amp; Center","Freeze Panes","Text Wrap"],a:1},
 {q:"Seorang siswa ingin membuat grafik yang membandingkan hanya kolom Nama Produk dan Total Penjualan, sementara kolom Kategori di antara keduanya tidak ikut disertakan. Cara memilih kedua kolom yang tidak berdampingan tersebut adalah...",o:["Blok semua kolom lalu hapus kolom Kategori","Tahan tombol CTRL sambil mengklik kedua kolom yang diinginkan","Hanya bisa memilih kolom yang berdampingan","Menggunakan fungsi SUM terlebih dahulu","Mengubah format sel menjadi Date"],a:1},
 {q:"Judul laporan \"LAPORAN PENJUALAN BULAN OKTOBER\" perlu ditampilkan memanjang dan berada tepat di tengah atas tabel yang terdiri dari 5 kolom. Fitur yang paling tepat digunakan adalah...",o:["Merge &amp; Center","Conditional Formatting","Sorting","Fill Handle","Freeze Panes"],a:0},
 {q:"Setelah data penjualan bulan lalu direvisi, laporan yang memakai rumus SUM(B2:B6) otomatis memperbarui hasil totalnya tanpa perlu dihitung ulang manual. Hal ini terjadi karena...",o:["Spreadsheet menyimpan nilai lama secara permanen","Rumus merujuk ke referensi sel, bukan nilai tetap, sehingga hasil otomatis mengikuti perubahan data sumber","Fitur Conditional Formatting bekerja otomatis","Format Currency memperbarui nilai secara otomatis","Fill Handle menghitung ulang semua sel"],a:1}
];

pgC_render();
function pgC_render(){
  const pgC=document.getElementById('pgContainer');
  PG.forEach((item,idx)=&gt;{
    const card=document.createElement('div'); card.className='q-card';
    card.innerHTML=`&lt;div class="q-num"&gt;SOAL ${idx+1} / ${PG.length}&lt;/div&gt;&lt;div class="q-text"&gt;${idx+1}. ${item.q}&lt;/div&gt;&lt;div class="options"&gt;&lt;/div&gt;`;
    const opts=card.querySelector('.options');
    item.o.forEach((optText,oi)=&gt;{
      const label=document.createElement('label'); label.className='opt';
      label.innerHTML=`&lt;input type="radio" name="pg${idx}" value="${oi}"&gt;&lt;span&gt;${LETTERS[oi]}. ${optText}&lt;/span&gt;`;
      label.querySelector('input').addEventListener('change',()=&gt;{
        opts.querySelectorAll('.opt').forEach(o=&gt;o.classList.remove('selected'));
        label.classList.add('selected');
      });
      opts.appendChild(label);
    });
    pgC.appendChild(card);
  });
}

function scorePG(){
  let correct=0; lastPGDetail=[];
  PG.forEach((item,idx)=&gt;{
    const picked=document.querySelector(`input[name="pg${idx}"]:checked`);
    const pickedIdx = picked ? parseInt(picked.value) : null;
    const isCorrect = pickedIdx!==null &amp;&amp; pickedIdx===item.a;
    if(isCorrect) correct++;
    lastPGDetail.push({
      no: idx+1,
      q: item.q,
      picked: pickedIdx!==null ? (LETTERS[pickedIdx]+'. '+item.o[pickedIdx]) : '(tidak dijawab)',
      correct: LETTERS[item.a]+'. '+item.o[item.a],
      isCorrect
    });
  });
  return {score:Math.round(correct/PG.length*100), correct, total:PG.length};
}

// ===================== 10 SOAL PRAKTIK (HOTS) =====================
const PRACTICE = [
 {
   title:"Menjumlahkan Total Penjualan",
   instruksi:"Sebuah toko mencatat penjualan 5 bulan terakhir. Tuliskan rumus yang tepat di sel B7 untuk menghitung Total Penjualan.",
   grid:`&lt;table class="excel-grid"&gt;&lt;tr&gt;&lt;th&gt;&lt;/th&gt;&lt;th&gt;A&lt;/th&gt;&lt;th&gt;B&lt;/th&gt;&lt;/tr&gt;
     &lt;tr&gt;&lt;th class="rownum"&gt;1&lt;/th&gt;&lt;td class="label-cell"&gt;Bulan&lt;/td&gt;&lt;td class="label-cell"&gt;Penjualan&lt;/td&gt;&lt;/tr&gt;
     &lt;tr&gt;&lt;th class="rownum"&gt;2&lt;/th&gt;&lt;td class="label-cell"&gt;Januari&lt;/td&gt;&lt;td&gt;12000000&lt;/td&gt;&lt;/tr&gt;
     &lt;tr&gt;&lt;th class="rownum"&gt;3&lt;/th&gt;&lt;td class="label-cell"&gt;Februari&lt;/td&gt;&lt;td&gt;15000000&lt;/td&gt;&lt;/tr&gt;
     &lt;tr&gt;&lt;th class="rownum"&gt;4&lt;/th&gt;&lt;td class="label-cell"&gt;Maret&lt;/td&gt;&lt;td&gt;9000000&lt;/td&gt;&lt;/tr&gt;
     &lt;tr&gt;&lt;th class="rownum"&gt;5&lt;/th&gt;&lt;td class="label-cell"&gt;April&lt;/td&gt;&lt;td&gt;18000000&lt;/td&gt;&lt;/tr&gt;
     &lt;tr&gt;&lt;th class="rownum"&gt;6&lt;/th&gt;&lt;td class="label-cell"&gt;Mei&lt;/td&gt;&lt;td&gt;21000000&lt;/td&gt;&lt;/tr&gt;
     &lt;tr&gt;&lt;th class="rownum"&gt;7&lt;/th&gt;&lt;td class="label-cell"&gt;Total&lt;/td&gt;&lt;td class="target-cell"&gt;B7 = ?&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;`,
   func:"SUM", refs:["B2","B6"], exact:/^=?SUM\(B2:B6\)$/, contoh:"=SUM(B2:B6)"
 },
 {
   title:"Menghitung Rata-Rata Nilai",
   instruksi:"Tuliskan rumus yang tepat di sel B7 untuk menghitung rata-rata nilai 5 siswa berikut.",
   grid:`&lt;table class="excel-grid"&gt;&lt;tr&gt;&lt;th&gt;&lt;/th&gt;&lt;th&gt;A&lt;/th&gt;&lt;th&gt;B&lt;/th&gt;&lt;/tr&gt;
     &lt;tr&gt;&lt;th class="rownum"&gt;1&lt;/th&gt;&lt;td class="label-cell"&gt;Nama&lt;/td&gt;&lt;td class="label-cell"&gt;Nilai&lt;/td&gt;&lt;/tr&gt;
     &lt;tr&gt;&lt;th class="rownum"&gt;2&lt;/th&gt;&lt;td class="label-cell"&gt;Andi&lt;/td&gt;&lt;td&gt;80&lt;/td&gt;&lt;/tr&gt;
     &lt;tr&gt;&lt;th class="rownum"&gt;3&lt;/th&gt;&lt;td class="label-cell"&gt;Budi&lt;/td&gt;&lt;td&gt;75&lt;/td&gt;&lt;/tr&gt;
     &lt;tr&gt;&lt;th class="rownum"&gt;4&lt;/th&gt;&lt;td class="label-cell"&gt;Citra&lt;/td&gt;&lt;td&gt;90&lt;/td&gt;&lt;/tr&gt;
     &lt;tr&gt;&lt;th class="rownum"&gt;5&lt;/th&gt;&lt;td class="label-cell"&gt;Dewi&lt;/td&gt;&lt;td&gt;65&lt;/td&gt;&lt;/tr&gt;
     &lt;tr&gt;&lt;th class="rownum"&gt;6&lt;/th&gt;&lt;td class="label-cell"&gt;Eka&lt;/td&gt;&lt;td&gt;85&lt;/td&gt;&lt;/tr&gt;
     &lt;tr&gt;&lt;th class="rownum"&gt;7&lt;/th&gt;&lt;td class="label-cell"&gt;Rata-rata&lt;/td&gt;&lt;td class="target-cell"&gt;B7 = ?&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;`,
   func:"AVERAGE", refs:["B2","B6"], exact:/^=?AVERAGE\(B2:B6\)$/, contoh:"=AVERAGE(B2:B6)"
 },
 {
   title:"Mencari Nilai Tertinggi",
   instruksi:"Dari data penjualan 5 sales berikut, tuliskan rumus di sel B7 untuk menemukan nilai penjualan TERTINGGI.",
   grid:`&lt;table class="excel-grid"&gt;&lt;tr&gt;&lt;th&gt;&lt;/th&gt;&lt;th&gt;A&lt;/th&gt;&lt;th&gt;B&lt;/th&gt;&lt;/tr&gt;
     &lt;tr&gt;&lt;th class="rownum"&gt;1&lt;/th&gt;&lt;td class="label-cell"&gt;Sales&lt;/td&gt;&lt;td class="label-cell"&gt;Penjualan&lt;/td&gt;&lt;/tr&gt;
     &lt;tr&gt;&lt;th class="rownum"&gt;2&lt;/th&gt;&lt;td class="label-cell"&gt;Rini&lt;/td&gt;&lt;td&gt;3200000&lt;/td&gt;&lt;/tr&gt;
     &lt;tr&gt;&lt;th class="rownum"&gt;3&lt;/th&gt;&lt;td class="label-cell"&gt;Doni&lt;/td&gt;&lt;td&gt;4100000&lt;/td&gt;&lt;/tr&gt;
     &lt;tr&gt;&lt;th class="rownum"&gt;4&lt;/th&gt;&lt;td class="label-cell"&gt;Sari&lt;/td&gt;&lt;td&gt;2800000&lt;/td&gt;&lt;/tr&gt;
     &lt;tr&gt;&lt;th class="rownum"&gt;5&lt;/th&gt;&lt;td class="label-cell"&gt;Tono&lt;/td&gt;&lt;td&gt;3900000&lt;/td&gt;&lt;/tr&gt;
     &lt;tr&gt;&lt;th class="rownum"&gt;6&lt;/th&gt;&lt;td class="label-cell"&gt;Wati&lt;/td&gt;&lt;td&gt;4500000&lt;/td&gt;&lt;/tr&gt;
     &lt;tr&gt;&lt;th class="rownum"&gt;7&lt;/th&gt;&lt;td class="label-cell"&gt;Tertinggi&lt;/td&gt;&lt;td class="target-cell"&gt;B7 = ?&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;`,
   func:"MAX", refs:["B2","B6"], exact:/^=?MAX\(B2:B6\)$/, contoh:"=MAX(B2:B6)"
 },
 {
   title:"Mencari Nilai Terendah",
   instruksi:"Dari data suhu harian berikut, tuliskan rumus di sel B7 untuk menemukan suhu TERENDAH.",
   grid:`&lt;table class="excel-grid"&gt;&lt;tr&gt;&lt;th&gt;&lt;/th&gt;&lt;th&gt;A&lt;/th&gt;&lt;th&gt;B&lt;/th&gt;&lt;/tr&gt;
     &lt;tr&gt;&lt;th class="rownum"&gt;1&lt;/th&gt;&lt;td class="label-cell"&gt;Hari&lt;/td&gt;&lt;td class="label-cell"&gt;Suhu (°C)&lt;/td&gt;&lt;/tr&gt;
     &lt;tr&gt;&lt;th class="rownum"&gt;2&lt;/th&gt;&lt;td class="label-cell"&gt;Senin&lt;/td&gt;&lt;td&gt;28&lt;/td&gt;&lt;/tr&gt;
     &lt;tr&gt;&lt;th class="rownum"&gt;3&lt;/th&gt;&lt;td class="label-cell"&gt;Selasa&lt;/td&gt;&lt;td&gt;26&lt;/td&gt;&lt;/tr&gt;
     &lt;tr&gt;&lt;th class="rownum"&gt;4&lt;/th&gt;&lt;td class="label-cell"&gt;Rabu&lt;/td&gt;&lt;td&gt;30&lt;/td&gt;&lt;/tr&gt;
     &lt;tr&gt;&lt;th class="rownum"&gt;5&lt;/th&gt;&lt;td class="label-cell"&gt;Kamis&lt;/td&gt;&lt;td&gt;24&lt;/td&gt;&lt;/tr&gt;
     &lt;tr&gt;&lt;th class="rownum"&gt;6&lt;/th&gt;&lt;td class="label-cell"&gt;Jumat&lt;/td&gt;&lt;td&gt;27&lt;/td&gt;&lt;/tr&gt;
     &lt;tr&gt;&lt;th class="rownum"&gt;7&lt;/th&gt;&lt;td class="label-cell"&gt;Terendah&lt;/td&gt;&lt;td class="target-cell"&gt;B7 = ?&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;`,
   func:"MIN", refs:["B2","B6"], exact:/^=?MIN\(B2:B6\)$/, contoh:"=MIN(B2:B6)"
 },
 {
   title:"Menghitung Jumlah Data Terisi",
   instruksi:"Kolom Nama berisi campuran teks, dan baris ke-9 kosong (belum diisi). Tuliskan rumus di sel A9 untuk menghitung BERAPA BANYAK data nama yang sudah terisi dari A2 sampai A8 (tanpa menghitung sel kosong).",
   grid:`&lt;table class="excel-grid"&gt;&lt;tr&gt;&lt;th&gt;&lt;/th&gt;&lt;th&gt;A&lt;/th&gt;&lt;/tr&gt;
     &lt;tr&gt;&lt;th class="rownum"&gt;1&lt;/th&gt;&lt;td class="label-cell"&gt;Nama Peserta&lt;/td&gt;&lt;/tr&gt;
     &lt;tr&gt;&lt;th class="rownum"&gt;2&lt;/th&gt;&lt;td class="label-cell"&gt;Arka&lt;/td&gt;&lt;/tr&gt;
     &lt;tr&gt;&lt;th class="rownum"&gt;3&lt;/th&gt;&lt;td class="label-cell"&gt;Bela&lt;/td&gt;&lt;/tr&gt;
     &lt;tr&gt;&lt;th class="rownum"&gt;4&lt;/th&gt;&lt;td class="label-cell"&gt;Cici&lt;/td&gt;&lt;/tr&gt;
     &lt;tr&gt;&lt;th class="rownum"&gt;5&lt;/th&gt;&lt;td class="label-cell"&gt;(kosong)&lt;/td&gt;&lt;/tr&gt;
     &lt;tr&gt;&lt;th class="rownum"&gt;6&lt;/th&gt;&lt;td class="label-cell"&gt;Dini&lt;/td&gt;&lt;/tr&gt;
     &lt;tr&gt;&lt;th class="rownum"&gt;7&lt;/th&gt;&lt;td class="label-cell"&gt;Eno&lt;/td&gt;&lt;/tr&gt;
     &lt;tr&gt;&lt;th class="rownum"&gt;8&lt;/th&gt;&lt;td class="label-cell"&gt;Fira&lt;/td&gt;&lt;/tr&gt;
     &lt;tr&gt;&lt;th class="rownum"&gt;9&lt;/th&gt;&lt;td class="target-cell"&gt;A9 = ?&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;`,
   func:"COUNTA", refs:["A2","A8"], exact:/^=?COUNTA\(A2:A8\)$/, contoh:"=COUNTA(A2:A8)"
 },
 {
   title:"Menentukan Status Kelulusan (IF)",
   instruksi:"Nilai siswa ada di sel B2. Tuliskan rumus di sel C2 agar menampilkan \"Lulus\" jika nilai 75 atau lebih, dan \"Tidak Lulus\" jika kurang dari itu.",
   grid:`&lt;table class="excel-grid"&gt;&lt;tr&gt;&lt;th&gt;&lt;/th&gt;&lt;th&gt;A&lt;/th&gt;&lt;th&gt;B&lt;/th&gt;&lt;th&gt;C&lt;/th&gt;&lt;/tr&gt;
     &lt;tr&gt;&lt;th class="rownum"&gt;1&lt;/th&gt;&lt;td class="label-cell"&gt;Nama&lt;/td&gt;&lt;td class="label-cell"&gt;Nilai&lt;/td&gt;&lt;td class="label-cell"&gt;Status&lt;/td&gt;&lt;/tr&gt;
     &lt;tr&gt;&lt;th class="rownum"&gt;2&lt;/th&gt;&lt;td class="label-cell"&gt;Hadi&lt;/td&gt;&lt;td&gt;80&lt;/td&gt;&lt;td class="target-cell"&gt;C2 = ?&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;`,
   func:"IF", refs:["B2","75","LULUS"], exact:/^=?IF\(B2&gt;=75,"LULUS","TIDAKLULUS"\)$/, contoh:'=IF(B2&gt;=75,"Lulus","Tidak Lulus")'
 },
 {
   title:"Kelulusan dengan Dua Syarat (IF + AND)",
   instruksi:"Siswa dinyatakan Lulus hanya jika Nilai (B2) minimal 75 DAN Kehadiran (C2) minimal 80. Tuliskan rumus yang tepat di sel D2.",
   grid:`&lt;table class="excel-grid"&gt;&lt;tr&gt;&lt;th&gt;&lt;/th&gt;&lt;th&gt;A&lt;/th&gt;&lt;th&gt;B&lt;/th&gt;&lt;th&gt;C&lt;/th&gt;&lt;th&gt;D&lt;/th&gt;&lt;/tr&gt;
     &lt;tr&gt;&lt;th class="rownum"&gt;1&lt;/th&gt;&lt;td class="label-cell"&gt;Nama&lt;/td&gt;&lt;td class="label-cell"&gt;Nilai&lt;/td&gt;&lt;td class="label-cell"&gt;Kehadiran(%)&lt;/td&gt;&lt;td class="label-cell"&gt;Status&lt;/td&gt;&lt;/tr&gt;
     &lt;tr&gt;&lt;th class="rownum"&gt;2&lt;/th&gt;&lt;td class="label-cell"&gt;Rara&lt;/td&gt;&lt;td&gt;80&lt;/td&gt;&lt;td&gt;85&lt;/td&gt;&lt;td class="target-cell"&gt;D2 = ?&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;`,
   func:"IF", refs:["AND","B2","C2"], exact:/^=?IF\(AND\(B2&gt;=75,C2&gt;=80\),"LULUS","TIDAKLULUS"\)$/, contoh:'=IF(AND(B2&gt;=75,C2&gt;=80),"Lulus","Tidak Lulus")'
 },
 {
   title:"Menghitung Banyak Siswa Bernilai Tinggi (COUNTIF)",
   instruksi:"Data nilai 9 siswa ada di B2 sampai B10. Tuliskan rumus untuk menghitung BERAPA BANYAK siswa yang nilainya 80 atau lebih.",
   grid:`&lt;table class="excel-grid"&gt;&lt;tr&gt;&lt;th&gt;&lt;/th&gt;&lt;th&gt;A&lt;/th&gt;&lt;th&gt;B&lt;/th&gt;&lt;/tr&gt;
     &lt;tr&gt;&lt;th class="rownum"&gt;1&lt;/th&gt;&lt;td class="label-cell"&gt;Nama&lt;/td&gt;&lt;td class="label-cell"&gt;Nilai&lt;/td&gt;&lt;/tr&gt;
     &lt;tr&gt;&lt;th class="rownum"&gt;2-10&lt;/th&gt;&lt;td class="label-cell"&gt;(9 siswa)&lt;/td&gt;&lt;td class="label-cell"&gt;60 - 95&lt;/td&gt;&lt;/tr&gt;
     &lt;tr&gt;&lt;th class="rownum"&gt;11&lt;/th&gt;&lt;td class="label-cell"&gt;Jumlah Nilai Tinggi&lt;/td&gt;&lt;td class="target-cell"&gt;B11 = ?&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;`,
   func:"COUNTIF", refs:["B2","B10","&gt;=80"], exact:/^=?COUNTIF\(B2:B10,"&gt;=80"\)$/, contoh:'=COUNTIF(B2:B10,"&gt;=80")'
 },
 {
   title:"Menjumlahkan Penjualan per Kategori (SUMIF)",
   instruksi:"Kolom A berisi Kategori, kolom B berisi Jumlah Terjual. Tuliskan rumus untuk menjumlahkan HANYA penjualan dengan kategori \"Elektronik\" dari A2:A10 dan B2:B10.",
   grid:`&lt;table class="excel-grid"&gt;&lt;tr&gt;&lt;th&gt;&lt;/th&gt;&lt;th&gt;A&lt;/th&gt;&lt;th&gt;B&lt;/th&gt;&lt;/tr&gt;
     &lt;tr&gt;&lt;th class="rownum"&gt;1&lt;/th&gt;&lt;td class="label-cell"&gt;Kategori&lt;/td&gt;&lt;td class="label-cell"&gt;Jumlah&lt;/td&gt;&lt;/tr&gt;
     &lt;tr&gt;&lt;th class="rownum"&gt;2-10&lt;/th&gt;&lt;td class="label-cell"&gt;Elektronik/Fashion/dll&lt;/td&gt;&lt;td class="label-cell"&gt;Angka&lt;/td&gt;&lt;/tr&gt;
     &lt;tr&gt;&lt;th class="rownum"&gt;11&lt;/th&gt;&lt;td class="label-cell"&gt;Total Elektronik&lt;/td&gt;&lt;td class="target-cell"&gt;B11 = ?&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;`,
   func:"SUMIF", refs:["A2","A10","ELEKTRONIK","B2","B10"], exact:/^=?SUMIF\(A2:A10,"ELEKTRONIK",B2:B10\)$/, contoh:'=SUMIF(A2:A10,"Elektronik",B2:B10)'
 },
 {
   title:"Menghitung Persentase Kontribusi (Referensi Absolut)",
   instruksi:"B7 berisi Total keseluruhan. Tuliskan rumus di sel C2 untuk menghitung persentase kontribusi B2 terhadap Total, dengan referensi ke B7 DIKUNCI (absolut) agar tetap benar saat rumus disalin ke C3, C4, dst.",
   grid:`&lt;table class="excel-grid"&gt;&lt;tr&gt;&lt;th&gt;&lt;/th&gt;&lt;th&gt;A&lt;/th&gt;&lt;th&gt;B&lt;/th&gt;&lt;th&gt;C&lt;/th&gt;&lt;/tr&gt;
     &lt;tr&gt;&lt;th class="rownum"&gt;1&lt;/th&gt;&lt;td class="label-cell"&gt;Bulan&lt;/td&gt;&lt;td class="label-cell"&gt;Penjualan&lt;/td&gt;&lt;td class="label-cell"&gt;% Kontribusi&lt;/td&gt;&lt;/tr&gt;
     &lt;tr&gt;&lt;th class="rownum"&gt;2&lt;/th&gt;&lt;td class="label-cell"&gt;Januari&lt;/td&gt;&lt;td&gt;12000000&lt;/td&gt;&lt;td class="target-cell"&gt;C2 = ?&lt;/td&gt;&lt;/tr&gt;
     &lt;tr&gt;&lt;th class="rownum"&gt;7&lt;/th&gt;&lt;td class="label-cell"&gt;Total&lt;/td&gt;&lt;td&gt;75000000&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;`,
   func:null, refs:["B2","B7","$"], exact:/^=?B2\/\$B\$7$/, contoh:"=B2/$B$7"
 }
];

practice_render();
function practice_render(){
  const pc=document.getElementById('practiceContainer');
  PRACTICE.forEach((item,idx)=&gt;{
    const card=document.createElement('div'); card.className='q-card';
    card.innerHTML=`&lt;div class="q-num"&gt;PRAKTIK ${idx+1} / ${PRACTICE.length} - ${item.title}&lt;/div&gt;
      &lt;div class="q-text" style="font-weight:400; font-size:.88rem; color:var(--ink-soft);"&gt;${item.instruksi}&lt;/div&gt;
      &lt;div class="table-scroll"&gt;${item.grid}&lt;/div&gt;
      &lt;input type="text" class="formula-input practice-input" data-idx="${idx}" placeholder="Ketik rumus di sini, contoh: =SUM(A1:A5)" autocomplete="off" autocapitalize="off" spellcheck="false"&gt;
      &lt;div class="editor-meta"&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="flag"&gt;[PERINGATAN] Percobaan tempel terdeteksi - bernilai 0&lt;/span&gt;&lt;/div&gt;`;
    const input=card.querySelector('.practice-input');
    const flag=card.querySelector('.flag');
    input.addEventListener('paste',(e)=&gt;{ e.preventDefault(); practicePasteFlags[idx]=true; flag.classList.add('show'); input.classList.add('wrong-paste'); });
    pc.appendChild(card);
  });
}
const practicePasteFlags=new Array(PRACTICE.length).fill(false);

function normFormula(s){
  return s.trim().toUpperCase().replace(/\s+/g,'').replace(/;/g,',');
}
function scorePractice(){
  let total=0; lastPracticeDetail=[];
  const inputs=document.querySelectorAll('.practice-input');
  PRACTICE.forEach((item,idx)=&gt;{
    const raw=inputs[idx].value;
    let s=0;
    if(!practicePasteFlags[idx] &amp;&amp; raw.trim().length&gt;0){
      let norm=normFormula(raw);
      const normWithEq = norm.startsWith('=') ? norm : ('='+norm);
      const normNoEq = norm.startsWith('=') ? norm.slice(1) : norm;
      if(item.exact.test(normWithEq) || item.exact.test(normNoEq) || item.exact.test(norm)){
        s=100;
      } else {
        const funcOk = item.func ? norm.includes(item.func) : norm.includes('$');
        const refsOk = item.refs.every(r=&gt;norm.includes(r.toUpperCase().replace(/\s+/g,'')));
        if(funcOk &amp;&amp; refsOk) s=60;
        else if(funcOk || refsOk) s=30;
        else s=10;
      }
    }
    total+=s;
    lastPracticeDetail.push({
      no: idx+1,
      title: item.title,
      userFormula: practicePasteFlags[idx] ? '(terdeteksi tempel - bernilai 0)' : (raw.trim() || '(tidak diisi)'),
      contoh: item.contoh,
      skor: s
    });
  });
  return Math.round(total/PRACTICE.length);
}

// ===================== 5 SOAL ESAI (HOTS) =====================
const ESSAY = [
 {q:"Sebuah rumus pajak yang disalin ke banyak baris menghasilkan nilai salah karena sel tarif pajaknya ikut bergeser mengikuti baris tujuan. Jelaskan konsep referensi relatif dan absolut, serta bagaimana referensi absolut mengatasi masalah tersebut!",kw:["relatif","absolut","$","mengunci","referensi","bergeser"],min:60},
 {q:"Sebuah toko kelontong mencatat ratusan transaksi secara manual di buku dan sering salah menjumlahkan total harian. Jelaskan bagaimana spreadsheet dengan fungsi SUM dan format Currency dapat membantu mengatasi masalah tersebut!",kw:["sum","currency","otomatis","akurat","rumus","total"],min:60},
 {q:"Seorang guru ingin sistem otomatis menampilkan \"Lulus\" atau \"Tidak Lulus\" berdasarkan nilai siswa tanpa memeriksa satu per satu secara manual. Jelaskan cara kerja fungsi IF dan berikan contoh rumusnya untuk skenario ini!",kw:["if","syarat","kondisi","lulus","benar","salah"],min:60},
 {q:"Sebuah data penjualan memiliki 500 baris dan perlu diketahui berapa transaksi dengan nilai di atas 1 juta, serta total penjualan untuk kategori tertentu saja. Jelaskan mengapa COUNTIF dan SUMIF lebih efisien dibanding menghitung manual satu per satu pada data sebesar ini!",kw:["countif","sumif","kriteria","syarat","efisien","data besar"],min:60},
 {q:"Sebuah laporan penjualan berbentuk angka mentah sulit dipahami manajer dengan cepat saat rapat. Jelaskan manfaat conditional formatting dan chart (grafik) dalam membantu penyajian data spreadsheet agar lebih mudah dipahami!",kw:["conditional formatting","chart","grafik","visual","mudah dipahami","warna"],min:60}
];

essay_render();
const essayPasteFlags=new Array(ESSAY.length).fill(false);
function essay_render(){
  const ec=document.getElementById('essayContainer');
  ESSAY.forEach((item,idx)=&gt;{
    const card=document.createElement('div'); card.className='q-card';
    card.innerHTML=`&lt;div class="q-num"&gt;ESAI ${idx+1} / ${ESSAY.length}&lt;/div&gt;&lt;div class="q-text"&gt;${idx+1}. ${item.q}&lt;/div&gt;
      &lt;textarea class="essay-box" data-idx="${idx}" placeholder="Ketik jawabanmu di sini..."&gt;&lt;/textarea&gt;
      &lt;div class="editor-meta"&gt;&lt;span class="cc"&gt;0 karakter&lt;/span&gt;&lt;span class="flag"&gt;[PERINGATAN] Percobaan tempel terdeteksi - bernilai 0&lt;/span&gt;&lt;/div&gt;`;
    const box=card.querySelector('.essay-box'); const meta=card.querySelector('.cc'); const flag=card.querySelector('.flag');
    box.addEventListener('input',()=&gt;{meta.textContent=box.value.trim().length+' karakter';});
    box.addEventListener('paste',e=&gt;{e.preventDefault(); essayPasteFlags[idx]=true; flag.classList.add('show');});
    ec.appendChild(card);
  });
}
function normWords(t){return Array.from(new Set(t.toLowerCase().replace(/[^a-z0-9\s]/gi,' ').split(/\s+/).filter(w=&gt;w.length&gt;=3)));}
function scoreEssay(){
  let total=0; lastEssayDetail=[];
  const boxes=document.querySelectorAll('#essayContainer .essay-box');
  ESSAY.forEach((item,idx)=&gt;{
    const typed=boxes[idx].value.trim();
    let s=0;
    if(!essayPasteFlags[idx] &amp;&amp; typed.length&gt;0){
      const lengthRatio=Math.min(1,typed.length/item.min);
      const typedLower=typed.toLowerCase();
      let matched=0; item.kw.forEach(k=&gt;{if(typedLower.indexOf(k)!==-1)matched++;});
      const kwRatio=matched/item.kw.length;
      s=Math.min(100,Math.round(100*(0.3*lengthRatio+0.7*kwRatio)));
    }
    total+=s;
    lastEssayDetail.push({
      no: idx+1,
      q: item.q,
      answer: essayPasteFlags[idx] ? '(terdeteksi tempel - bernilai 0)' : (typed || '(tidak diisi)'),
      skor: s
    });
  });
  return Math.round(total/ESSAY.length);
}

// ===================== SUBMIT =====================
document.getElementById('btnHitung').addEventListener('click', ()=&gt;{
  const noAbsen=document.getElementById('noAbsen').value.trim();
  const nama=document.getElementById('nama').value.trim();
  const kelas=document.getElementById('kelas').value.trim();
  const msg=document.getElementById('uploadMsg');
  if(!noAbsen||!nama||!kelas){ msg.textContent='Lengkapi Kelas, No. Absen, dan Nama terlebih dahulu.'; return; }

  const pg=scorePG(); const practice=scorePractice(); const essay=scoreEssay();
  const finalScore=Math.round(pg.score*0.35 + practice*0.40 + essay*0.25);

  lastSubmission={noAbsen,nama,kelas,pg,practice,essay,finalScore};
  document.getElementById('btnUnduhPDF').disabled=false;

  msg.textContent='';
  const panel=document.getElementById('resultPanel');
  const scoreEl=document.getElementById('scoreValue');
  const detailEl=document.getElementById('resultDetail');
  panel.style.display='block';
  scoreEl.textContent=finalScore;
  detailEl.textContent=`Pilihan Ganda: ${pg.correct}/${pg.total} benar (${pg.score}) | Praktik Rumus: ${practice} | Esai: ${essay} - Mengirim ke guru...`;

  fetch(GAS_ENDPOINT,{method:'POST',mode:'no-cors',headers:{'Content-Type':'application/json'},
    body:JSON.stringify({noAbsen,nama,kelas,skor:finalScore,judulMateri:JUDUL_MATERI})
  }).then(()=&gt;{
    detailEl.textContent=`Pilihan Ganda: ${pg.correct}/${pg.total} benar (${pg.score}) | Praktik Rumus: ${practice} | Esai: ${essay} - Nilai sudah terkirim ke guru.`;
  }).catch(()=&gt;{
    detailEl.textContent=`Pilihan Ganda: ${pg.correct}/${pg.total} benar (${pg.score}) | Praktik Rumus: ${practice} | Esai: ${essay} - Gagal terkirim otomatis, tunjukkan skor ini ke guru.`;
  });
});

// ===================== UNDUH BUKTI MENGERJAKAN (PDF F4) =====================
document.getElementById('btnUnduhPDF').addEventListener('click', downloadBuktiPDF);

function downloadBuktiPDF(){
  if(!lastSubmission){ alert('Klik tombol "Hitung &amp; Kirim Nilai" terlebih dahulu sebelum mengunduh bukti.'); return; }
  if(!window.jspdf){ alert('Pustaka pembuat PDF gagal dimuat. Pastikan koneksi internet aktif lalu muat ulang halaman.'); return; }
  const { jsPDF } = window.jspdf;
  const doc = new jsPDF({ unit:'mm', format:[215,330] }); // Ukuran F4
  const pageW=215, pageH=330, marginX=16, marginTop=18, marginBottom=16, contentW=pageW-marginX*2;
  let y = marginTop;

  function ensureSpace(h){ if(y+h&gt;pageH-marginBottom){ doc.addPage([pageW,pageH]); y=marginTop; } }
  function divider(){ ensureSpace(4); doc.setDrawColor(190,200,195); doc.line(marginX,y,pageW-marginX,y); y+=6; }
  function text(str, opts={}){
    const size=opts.size||10; const bold=opts.bold||false; const color=opts.color||[20,30,25];
    doc.setFont('helvetica', bold?'bold':'normal'); doc.setFontSize(size); doc.setTextColor(color[0],color[1],color[2]);
    const lines = doc.splitTextToSize(String(str), opts.width||contentW);
    lines.forEach(line=&gt;{
      ensureSpace(size*0.55);
      doc.text(line, marginX, y);
      y += size*0.5;
    });
    y += (opts.gap!==undefined ? opts.gap : 2);
  }

  text('BUKTI MENGERJAKAN EVALUASI INDIVIDU', {size:14, bold:true, gap:1});
  text(JUDUL_MATERI, {size:11, bold:true, color:[21,128,61], gap:4});
  divider();

  text('IDENTITAS PESERTA', {size:10, bold:true, gap:3});
  text('Kelas       : ' + lastSubmission.kelas, {size:10});
  text('No. Absen   : ' + lastSubmission.noAbsen, {size:10});
  text('Nama        : ' + lastSubmission.nama, {size:10, gap:4});
  divider();

  text('RINGKASAN NILAI', {size:10, bold:true, gap:3});
  text(`Pilihan Ganda (bobot 35%)  : ${lastSubmission.pg.correct}/${lastSubmission.pg.total} benar  -&gt;  skor ${lastSubmission.pg.score}`, {size:10});
  text(`Praktik Rumus (bobot 40%)  : skor ${lastSubmission.practice}`, {size:10});
  text(`Esai (bobot 25%)           : skor ${lastSubmission.essay}`, {size:10, gap:2});
  text(`NILAI AKHIR                : ${lastSubmission.finalScore}`, {size:12, bold:true, color:[13,90,42], gap:4});
  divider();

  text('RINCIAN JAWABAN PILIHAN GANDA', {size:10, bold:true, gap:3});
  lastPGDetail.forEach(item=&gt;{
    text(`${item.no}. ${item.q}`, {size:9, gap:1});
    text(`   Jawaban dipilih : ${item.picked}`, {size:9});
    text(`   Jawaban benar   : ${item.correct}  [${item.isCorrect?'BENAR':'SALAH'}]`, {size:9, gap:3});
  });
  divider();

  text('RINCIAN JAWABAN PRAKTIK RUMUS', {size:10, bold:true, gap:3});
  lastPracticeDetail.forEach(item=&gt;{
    text(`${item.no}. ${item.title}`, {size:9, bold:true, gap:1});
    text(`   Rumus ditulis   : ${item.userFormula}`, {size:9});
    text(`   Contoh benar    : ${item.contoh}`, {size:9});
    text(`   Skor            : ${item.skor}`, {size:9, gap:3});
  });
  divider();

  text('RINCIAN JAWABAN ESAI', {size:10, bold:true, gap:3});
  lastEssayDetail.forEach(item=&gt;{
    text(`${item.no}. ${item.q}`, {size:9, bold:true, gap:1});
    text(`   Jawaban : ${item.answer}`, {size:9});
    text(`   Skor    : ${item.skor}`, {size:9, gap:3});
  });

  ensureSpace(40);
  y += 8;
  text('Dokumen ini dicetak otomatis oleh sistem sebagai bukti telah mengerjakan evaluasi.', {size:8, color:[90,100,95], gap:10});
  const todayStr = new Date().toLocaleDateString('id-ID',{day:'numeric',month:'long',year:'numeric'});
  text('......................, ' + todayStr, {size:10, gap:18});
  text('( ' + lastSubmission.nama + ' )', {size:10, gap:2});
  text('Siswa', {size:9, color:[90,100,95]});

  const safeNama = lastSubmission.nama.replace(/[^a-z0-9]+/gi,'_');
  doc.save('Bukti-Spreadsheet-' + safeNama + '.pdf');
}
&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;</description><link>http://kitab-investasi.blogspot.com/2026/10/pengenalan-aplikasi-pengolah-angka.html</link><thr:total>0</thr:total><author>nof_rizal07@yahoo.co.id (abang_cool)</author></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-9000860041661554971.post-5344647207214984129</guid><pubDate>Thu, 01 Oct 2026 02:38:15 +0000</pubDate><atom:updated>2026-10-01T09:38:15.125+07:00</atom:updated><title>Kaidah Kebahasaan Teks Ceramah (Bagian 1)</title><description>&lt;style&gt;
@import url('https://fonts.googleapis.com/css2?family=Oswald:wght@400;500;600;700&amp;family=Source+Sans+3:wght@400;500;600;700&amp;family=IBM+Plex+Mono:wght@400;500;600&amp;display=swap');
.epb{
  --blueprint:#0F2A3D;
  --blueprint-deep:#0A1E2C;
  --panel:#4A2E12;
  --paper:#F3F0E6;
  --ink:#132029;
  --amber:#F5A623;
  --amber-deep:#C97F12;
  --mint:#6EC6CA;
  --line:rgba(234,242,245,0.16);
  --off-white:#EAF2F5;
  --muted:#9FB4C2;
}
.epb *{box-sizing:border-box;}
.epb{scroll-behavior:smooth; background:#0A1F2E;}
.epb{
  margin:0;
  position:relative;
  overflow:hidden;
  background:var(--blueprint);
  color:var(--off-white);
  font-family:'Source Sans 3',sans-serif;
  line-height:1.65;
  background-image:
    linear-gradient(var(--line) 1px, transparent 1px),
    linear-gradient(90deg, var(--line) 1px, transparent 1px);
  background-size: 34px 34px;
}
.epb h1, .epb h2, .epb h3, .epb h4{font-family:'Oswald',sans-serif; text-transform:uppercase; letter-spacing:0.02em; margin:0 0 0.5em;}
.epb .mono{font-family:'IBM Plex Mono',monospace;}
.epb a{color:var(--amber);}
.epb .crop{position:absolute; width:22px; height:22px; z-index:5; opacity:.55; pointer-events:none;}
.epb .crop::before, .epb .crop::after{content:"";position:absolute;background:var(--mint);}
.epb .crop::before{width:100%;height:1px;top:50%;left:0;}
.epb .crop::after{width:1px;height:100%;left:50%;top:0;}
.epb .crop.tl{top:14px;left:14px;}
.epb .crop.tr{top:14px;right:14px;}
.epb .crop.bl{bottom:14px;left:14px;}
.epb .crop.br{bottom:14px;right:14px;}
.epb header.cover{
  position:relative;
  padding:40px 24px 36px;
  border-bottom:1px solid var(--line);
  overflow:hidden;
}
.epb .doc-code{font-family:'IBM Plex Mono',monospace; color:var(--amber); letter-spacing:0.15em; font-size:0.78rem; text-transform:uppercase; margin-bottom:18px; display:flex; gap:10px; align-items:center;}
.epb .doc-code::before{content:"◆"; color:var(--amber);}
.epb .cover h1{font-size:clamp(1.6rem,7vw,2.5rem); color:var(--off-white); max-width:16ch; line-height:1.05;}
.epb .cover .subtitle{color:var(--muted); font-size:1.05rem; max-width:60ch; margin-top:14px;}
.epb .meta-strip{
  margin-top:38px; display:grid; grid-template-columns:repeat(auto-fit,minmax(150px,1fr));
  border-top:1px dashed var(--line); border-bottom:1px dashed var(--line);
}
.epb .meta-strip div{padding:14px 16px; border-right:1px dashed var(--line);}
.epb .meta-strip div:last-child{border-right:none;}
.epb .meta-strip .k{font-family:'IBM Plex Mono',monospace; font-size:0.68rem; color:var(--amber); text-transform:uppercase; letter-spacing:0.1em;}
.epb .meta-strip .v{font-size:0.98rem; color:var(--off-white); margin-top:4px; font-weight:600;}
.epb .stamp{
  position:absolute; top:40px; right:20px; width:104px; height:104px;
  border:2.5px solid var(--amber); border-radius:50%;
  display:flex; align-items:center; justify-content:center;
  transform:rotate(-11deg);
  color:var(--amber); font-family:'IBM Plex Mono',monospace;
  text-align:center; font-size:0.62rem; letter-spacing:0.08em; text-transform:uppercase;
  opacity:0.9;
}
.epb .stamp .ring{position:absolute; inset:8px; border:1px dashed var(--amber); border-radius:50%;}
.epb .stamp b{display:block; font-family:'Oswald',sans-serif; font-size:1.05rem; letter-spacing:0.06em; margin-top:4px;}

@media (max-width:760px){.epb .stamp{display:none;}
.epb }


.epb main{max-width:920px; margin:0 auto; padding:0 20px 60px;}
.epb .section{padding-top:64px;}
.epb .eyebrow{font-family:'IBM Plex Mono',monospace; color:var(--amber); font-size:0.78rem; letter-spacing:0.14em; text-transform:uppercase; margin-bottom:10px; display:flex; align-items:center; gap:10px;}
.epb .eyebrow::after{content:""; flex:1; height:1px; background:var(--line);}
.epb h2.section-title{font-size:1.7rem; color:var(--off-white);}
.epb p{color:#DDE7EC;}
.epb .lead{color:var(--muted); font-size:1.02rem; max-width:72ch;}
.epb .panel{
  background:var(--panel); border:1px solid var(--line); border-radius:2px;
  padding:26px 28px; margin:22px 0;
}
.epb .panel.tp{border-left:4px solid var(--mint);}
.epb .panel.warn{border-left:4px solid var(--amber);}
.epb .tp-box{display:grid; gap:14px; margin-top:18px;}
.epb .tp-item{display:flex; gap:14px; align-items:flex-start;}
.epb .tp-item .idx{font-family:'IBM Plex Mono',monospace; color:var(--amber); font-weight:600; min-width:34px;}
.epb .flow{display:grid; grid-template-columns:repeat(auto-fit,minmax(220px,1fr)); gap:14px; margin-top:20px;}
.epb .flow .step{background:var(--blueprint-deep); border:1px solid var(--line); padding:18px; position:relative;}
.epb .flow .step .tag{font-family:'IBM Plex Mono',monospace; color:var(--amber); font-size:0.7rem; letter-spacing:0.1em; text-transform:uppercase;}
.epb .flow .step h4{font-size:1rem; margin-top:8px; color:var(--off-white);}
.epb .flow .step .time{position:absolute; top:16px; right:16px; font-family:'IBM Plex Mono',monospace; font-size:0.7rem; color:var(--amber);}
.epb .grid-3{display:grid; grid-template-columns:repeat(auto-fit,minmax(200px,1fr)); gap:14px; margin-top:16px;}
.epb .card{background:var(--blueprint-deep); border:1px solid var(--line); padding:18px;}
.epb .card h4{color:var(--amber); font-size:0.95rem;}
.epb .criteria{display:grid; gap:16px; margin-top:20px;}
.epb .crit{
  background:var(--blueprint-deep); border:1px solid var(--line);
  display:grid; grid-template-columns:64px 1fr; gap:0;
}
.epb .crit .num{
  background:var(--amber); color:var(--blueprint-deep); font-family:'IBM Plex Mono',monospace;
  font-weight:700; display:flex; align-items:center; justify-content:center; font-size:1.05rem;
}
.epb .crit .body{padding:18px 20px;}
.epb .crit h4{color:var(--off-white); font-size:1.02rem; margin-bottom:6px;}
.epb .crit .q{margin-top:10px; padding-top:10px; border-top:1px dashed var(--line); font-family:'IBM Plex Mono',monospace; font-size:0.86rem; color:var(--amber);}
.epb .timeline{margin-top:24px; position:relative; padding-left:34px;}
.epb .timeline::before{content:""; position:absolute; left:11px; top:6px; bottom:6px; width:2px; background:var(--line);}
.epb .tl-item{position:relative; padding-bottom:26px;}
.epb .tl-item:last-child{padding-bottom:0;}
.epb .tl-item::before{content:""; position:absolute; left:-34px; top:2px; width:22px; height:22px; border-radius:50%; background:var(--blueprint); border:2px solid var(--amber);}
.epb .tl-item h4{color:var(--off-white); font-size:1rem; margin-bottom:4px;}
.epb .doc-sample{
  background:var(--paper); color:var(--ink); border-radius:2px; padding:0; margin-top:22px;
  box-shadow:0 20px 45px rgba(0,0,0,0.35);
}
.epb .doc-sample .doc-head{background:var(--ink); color:var(--paper); padding:12px 22px; font-family:'IBM Plex Mono',monospace; font-size:0.75rem; letter-spacing:0.1em; text-transform:uppercase; display:flex; justify-content:space-between;}
.epb .doc-sample .doc-body{padding:26px 28px 30px;}
.epb .doc-sample h3{font-family:'Oswald',sans-serif; color:var(--ink); font-size:1.25rem; text-transform:none; letter-spacing:0;}
.epb .doc-sample ol{padding-left:22px;}
.epb .doc-sample li{margin-bottom:9px;}
.epb .flag{
  display:inline-block; font-family:'IBM Plex Mono',monospace; font-size:0.7rem; font-weight:600;
  background:#D94E2A; color:#fff; padding:1px 7px; border-radius:2px; margin-left:6px; vertical-align:middle;
}
.epb .doc-sample .note-margin{margin-top:6px; font-family:'IBM Plex Mono',monospace; font-size:0.78rem; color:#8A3A1F; padding-left:8px; border-left:2px solid #D94E2A;}
.epb .legend{display:flex; flex-wrap:wrap; gap:10px 20px; margin-top:16px;}
.epb .legend span{font-family:'IBM Plex Mono',monospace; font-size:0.78rem; color:var(--muted); display:flex; align-items:center; gap:8px;}
.epb .legend .dot{width:10px; height:10px; border-radius:50%; display:inline-block;}
.epb table{width:100%; border-collapse:collapse; margin-top:18px; font-size:0.94rem;}
.epb th, .epb td{border:1px solid var(--line); padding:10px 12px; text-align:left; vertical-align:top;}
.epb th{background:var(--blueprint-deep); font-family:'IBM Plex Mono',monospace; font-size:0.75rem; text-transform:uppercase; letter-spacing:0.06em; color:var(--amber);}
.epb .summary-box{
  border:1px solid var(--amber); background:linear-gradient(180deg, rgba(245,166,35,0.08), transparent);
  padding:24px 26px; margin-top:24px;
}
.epb .summary-box ul{margin:10px 0 0; padding-left:20px;}
.epb .summary-box li{margin-bottom:8px;}
.epb .task-header{
  background:var(--amber); color:var(--blueprint-deep); padding:22px 26px; margin-top:20px;
  display:flex; justify-content:space-between; align-items:center; flex-wrap:wrap; gap:10px;
}
.epb .task-header h2{color:var(--blueprint-deep); font-size:1.4rem; margin:0;}
.epb .task-header .badge{font-family:'IBM Plex Mono',monospace; font-size:0.8rem; background:var(--blueprint-deep); color:var(--amber); padding:6px 12px; border-radius:2px;}
.epb .steps-num{counter-reset:step; margin-top:18px; list-style:none; padding:0;}
.epb .steps-num li{counter-increment:step; position:relative; padding-left:44px; margin-bottom:16px;}
.epb .steps-num li::before{content:counter(step,decimal-leading-zero); position:absolute; left:0; top:0; font-family:'IBM Plex Mono',monospace; color:var(--amber); font-weight:600; font-size:0.95rem; border:1px solid var(--amber); width:30px; height:26px; display:flex; align-items:center; justify-content:center;}
.epb .rubric-scale{display:grid; grid-template-columns:repeat(4,1fr); gap:10px; margin-top:16px;}
.epb .rubric-scale div{background:var(--blueprint-deep); border:1px solid var(--line); padding:12px; text-align:center;}
.epb .rubric-scale .n{font-family:'IBM Plex Mono',monospace; color:var(--amber); font-size:1.3rem; font-weight:700;}
.epb .rubric-scale .l{font-size:0.78rem; color:var(--muted); text-transform:uppercase; letter-spacing:0.05em;}
.epb .notebook{
  background:repeating-linear-gradient(var(--paper), var(--paper) 33px, #D8D3C2 34px);
  color:var(--ink); border-radius:2px; padding:28px 30px; margin-top:20px; position:relative;
  box-shadow:0 20px 45px rgba(0,0,0,0.35);
}
.epb .notebook::before{content:""; position:absolute; left:46px; top:0; bottom:0; width:1.5px; background:#C0453A; opacity:0.5;}
.epb .notebook .content{padding-left:24px;}
.epb .notebook h3{color:var(--ink); font-family:'Oswald',sans-serif; letter-spacing:0.02em; margin-bottom:10px;}
.epb .notebook ul{padding-left:20px;}
.epb footer{border-top:1px solid var(--line); padding:24px 20px 40px; color:var(--muted); font-size:0.86rem;}
.epb footer .doc-code{margin-bottom:10px;}
.epb .divider-dash{border:none; border-top:1px dashed var(--line); margin:44px 0 0;}
.epb::selection{background:var(--amber); color:var(--blueprint-deep);}

&lt;/style&gt;
&lt;div class="epb"&gt;
&lt;div class="crop tl"&gt;&lt;/div&gt;&lt;div class="crop tr"&gt;&lt;/div&gt;&lt;div class="crop bl"&gt;&lt;/div&gt;&lt;div class="crop br"&gt;&lt;/div&gt;

&lt;header class="cover"&gt;
  &lt;div class="stamp"&gt;&lt;div class="ring"&gt;&lt;/div&gt;&lt;span&gt;Modul Ajar&lt;b&gt;Terverifikasi&lt;/b&gt;Fase F&lt;/span&gt;&lt;/div&gt;
  &lt;div class="doc-code"&gt;DOK/B.INDO/XI/CERAMAH-KAIDAH-1 — 3 JP · 1 Pertemuan&lt;/div&gt;
  &lt;h1&gt;Kaidah Kebahasaan Teks Ceramah (Bagian 1)&lt;/h1&gt;
  &lt;p class="subtitle"&gt;Materi Bahasa Indonesia Kelas XI SMK/MAK — melatih murid mengidentifikasi ciri kebahasaan teks ceramah: kata ganti orang, kata teknis, dan kata persuasif.&lt;/p&gt;

  &lt;div class="meta-strip"&gt;
    &lt;div&gt;&lt;div class="k"&gt;Mata Pelajaran&lt;/div&gt;&lt;div class="v"&gt;Bahasa Indonesia&lt;/div&gt;&lt;/div&gt;
    &lt;div&gt;&lt;div class="k"&gt;Jenjang&lt;/div&gt;&lt;div class="v"&gt;SMK/MAK — Kelas XI&lt;/div&gt;&lt;/div&gt;
    &lt;div&gt;&lt;div class="k"&gt;Elemen&lt;/div&gt;&lt;div class="v"&gt;Membaca &amp;amp; Memirsa&lt;/div&gt;&lt;/div&gt;
    &lt;div&gt;&lt;div class="k"&gt;Alokasi Waktu&lt;/div&gt;&lt;div class="v"&gt;3 JP (3 × 45 menit)&lt;/div&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/header&gt;

&lt;main&gt;

  &lt;!-- ============ TUJUAN PEMBELAJARAN ============ --&gt;
  &lt;section class="section" id="tujuan"&gt;
    &lt;div class="eyebrow"&gt;01 — Identitas Pembelajaran&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Capaian &amp;amp; Tujuan Pembelajaran&lt;/h2&gt;

    &lt;div class="panel tp"&gt;
      &lt;div class="eyebrow" style="margin-bottom:6px;"&gt;Capaian Pembelajaran (Elemen Membaca–Memirsa)&lt;/div&gt;
      &lt;p&gt;Murid mampu mengidentifikasi dan menganalisis ciri kebahasaan pada berbagai jenis teks, termasuk teks ceramah, untuk memahami bagaimana bahasa digunakan secara efektif dalam menyampaikan pesan kepada pendengar.&lt;/p&gt;
    &lt;/div&gt;

    &lt;div class="panel"&gt;
      &lt;div class="eyebrow" style="margin-bottom:6px;"&gt;Tujuan Pembelajaran&lt;/div&gt;
      &lt;p style="font-size:1.05rem; color:var(--off-white); font-weight:600;"&gt;Murid mampu mengidentifikasi ciri kebahasaan teks ceramah, seperti kata ganti orang, kata teknis, dan kata persuasif.&lt;/p&gt;

      &lt;div class="tp-box"&gt;
        &lt;div class="tp-item"&gt;&lt;span class="idx mono"&gt;TP.1&lt;/span&gt;&lt;p&gt;Murid dapat menjelaskan jenis dan fungsi kata ganti orang dalam teks ceramah.&lt;/p&gt;&lt;/div&gt;
        &lt;div class="tp-item"&gt;&lt;span class="idx mono"&gt;TP.2&lt;/span&gt;&lt;p&gt;Murid dapat menjelaskan pengertian dan fungsi kata teknis dalam teks ceramah.&lt;/p&gt;&lt;/div&gt;
        &lt;div class="tp-item"&gt;&lt;span class="idx mono"&gt;TP.3&lt;/span&gt;&lt;p&gt;Murid dapat menjelaskan pengertian dan fungsi kata persuasif dalam teks ceramah.&lt;/p&gt;&lt;/div&gt;
        &lt;div class="tp-item"&gt;&lt;span class="idx mono"&gt;TP.4&lt;/span&gt;&lt;p&gt;Murid dapat menemukan ketiga ciri kebahasaan tersebut dalam sebuah teks ceramah.&lt;/p&gt;&lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;

    &lt;div class="eyebrow" style="margin-top:26px; margin-bottom:6px;"&gt;8 Profil Lulusan yang Dikembangkan&lt;/div&gt;
    &lt;div class="grid-3"&gt;
      &lt;div class="card"&gt;&lt;h4&gt;Penalaran Kritis&lt;/h4&gt;&lt;p style="font-size:0.9rem;"&gt;Menganalisis fungsi kata ganti orang, kata teknis, dan kata persuasif dalam teks.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;h4&gt;Kemandirian&lt;/h4&gt;&lt;p style="font-size:0.9rem;"&gt;Menyelesaikan identifikasi dan reviu materi secara mandiri.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;h4&gt;Kolaborasi&lt;/h4&gt;&lt;p style="font-size:0.9rem;"&gt;Bekerja sama dalam kelompok saat menganalisis ciri kebahasaan teks ceramah.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;h4&gt;Komunikasi&lt;/h4&gt;&lt;p style="font-size:0.9rem;"&gt;Menyampaikan hasil identifikasi ciri kebahasaan secara jelas dan runtut.&lt;/p&gt;&lt;/div&gt;
    &lt;/div&gt;
  &lt;/section&gt;

  &lt;hr class="divider-dash"&gt;

  &lt;!-- ============ MATERI A: RECAP TEKS CERAMAH ============ --&gt;
  &lt;section class="section" id="materi-a"&gt;
    &lt;div class="eyebrow"&gt;02 — Materi Inti A&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Mengingat Kembali Teks Ceramah&lt;/h2&gt;
    &lt;p class="lead"&gt;Teks ceramah adalah teks berisi pidato seseorang di hadapan pendengar, bertujuan memberi nasihat, wejangan, atau pengetahuan tentang suatu hal, dengan struktur pembukaan, isi, dan penutup. Pada pertemuan ini, murid akan mempelajari tiga ciri kebahasaan utama teks ceramah.&lt;/p&gt;

    &lt;div class="grid-3"&gt;
      &lt;div class="card"&gt;&lt;h4&gt;1. Kata Ganti Orang&lt;/h4&gt;&lt;p style="font-size:0.92rem;"&gt;Menunjukkan posisi penceramah dan pendengar dalam teks.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;h4&gt;2. Kata Teknis&lt;/h4&gt;&lt;p style="font-size:0.92rem;"&gt;Istilah khusus sesuai tema ceramah yang memberi kedalaman isi.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;h4&gt;3. Kata Persuasif&lt;/h4&gt;&lt;p style="font-size:0.92rem;"&gt;Kata ajakan/anjuran yang mendorong pendengar bertindak.&lt;/p&gt;&lt;/div&gt;
    &lt;/div&gt;
  &lt;/section&gt;

  &lt;hr class="divider-dash"&gt;

  &lt;!-- ============ MATERI B: KATA GANTI ORANG ============ --&gt;
  &lt;section class="section" id="materi-b"&gt;
    &lt;div class="eyebrow"&gt;03 — Materi Inti B&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Kata Ganti Orang dalam Teks Ceramah&lt;/h2&gt;

    &lt;div class="panel"&gt;
      &lt;p&gt;&lt;b style="color:var(--off-white);"&gt;Kata ganti orang&lt;/b&gt; dalam teks ceramah digunakan untuk menunjukkan posisi penceramah dan pendengar, sekaligus membangun kedekatan di antara keduanya selama penyampaian pesan.&lt;/p&gt;
    &lt;/div&gt;

    &lt;div class="criteria"&gt;
      &lt;div class="crit"&gt;
        &lt;div class="num mono"&gt;1&lt;/div&gt;
        &lt;div class="body"&gt;
          &lt;h4&gt;Kata Ganti Orang Pertama Tunggal&lt;/h4&gt;
          &lt;p style="margin:0;"&gt;Merujuk pada diri penceramah sendiri.&lt;/p&gt;
          &lt;div class="q"&gt;Contoh: "Izinkan saya menyampaikan sedikit renungan."&lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;
      &lt;div class="crit"&gt;
        &lt;div class="num mono"&gt;2&lt;/div&gt;
        &lt;div class="body"&gt;
          &lt;h4&gt;Kata Ganti Orang Pertama Jamak&lt;/h4&gt;
          &lt;p style="margin:0;"&gt;Membangun kebersamaan antara penceramah dan pendengar.&lt;/p&gt;
          &lt;div class="q"&gt;Contoh: "Marilah kita renungkan bersama."&lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;
      &lt;div class="crit"&gt;
        &lt;div class="num mono"&gt;3&lt;/div&gt;
        &lt;div class="body"&gt;
          &lt;h4&gt;Kata Ganti/Sapaan Orang Kedua&lt;/h4&gt;
          &lt;p style="margin:0;"&gt;Menyapa pendengar secara langsung.&lt;/p&gt;
          &lt;div class="q"&gt;Contoh: "Hadirin yang saya hormati..."&lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/section&gt;

  &lt;hr class="divider-dash"&gt;

  &lt;!-- ============ MATERI C: KATA TEKNIS ============ --&gt;
  &lt;section class="section" id="materi-c"&gt;
    &lt;div class="eyebrow"&gt;04 — Materi Inti C&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Kata Teknis dalam Teks Ceramah&lt;/h2&gt;

    &lt;div class="panel"&gt;
      &lt;p&gt;&lt;b style="color:var(--off-white);"&gt;Kata teknis&lt;/b&gt; adalah istilah khusus sesuai tema ceramah yang memberikan kedalaman dan kredibilitas pada isi yang disampaikan.&lt;/p&gt;
    &lt;/div&gt;

    &lt;div class="grid-3"&gt;
      &lt;div class="card"&gt;&lt;h4&gt;Tema Keagamaan&lt;/h4&gt;&lt;p style="font-size:0.9rem;"&gt;ibadah, akhlak, syukur, taqwa&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;h4&gt;Tema Kesehatan&lt;/h4&gt;&lt;p style="font-size:0.9rem;"&gt;imunitas, gizi seimbang, imunisasi&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;h4&gt;Tema Pendidikan&lt;/h4&gt;&lt;p style="font-size:0.9rem;"&gt;kurikulum, literasi, karakter&lt;/p&gt;&lt;/div&gt;
    &lt;/div&gt;
    &lt;p class="lead" style="margin-top:14px;"&gt;&lt;b style="color:var(--off-white);"&gt;Fungsi:&lt;/b&gt; memperkuat kredibilitas penceramah dan membantu pendengar memahami isu secara lebih mendalam sesuai tema yang dibahas.&lt;/p&gt;
  &lt;/section&gt;

  &lt;hr class="divider-dash"&gt;

  &lt;!-- ============ MATERI D: KATA PERSUASIF ============ --&gt;
  &lt;section class="section" id="materi-d"&gt;
    &lt;div class="eyebrow"&gt;05 — Materi Inti D&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Kata Persuasif dalam Teks Ceramah&lt;/h2&gt;

    &lt;div class="panel"&gt;
      &lt;p&gt;&lt;b style="color:var(--off-white);"&gt;Kata persuasif&lt;/b&gt; adalah kata yang bertujuan mengajak atau menganjurkan pendengar agar bertindak sesuai pesan yang disampaikan dalam ceramah.&lt;/p&gt;
    &lt;/div&gt;

    &lt;div class="grid-3"&gt;
      &lt;div class="card"&gt;&lt;h4&gt;Kata Ajakan&lt;/h4&gt;&lt;p style="font-size:0.9rem;"&gt;mari, marilah, ayo&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;h4&gt;Kata Anjuran&lt;/h4&gt;&lt;p style="font-size:0.9rem;"&gt;hendaknya, sebaiknya, seyogyanya&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;h4&gt;Contoh Kalimat&lt;/h4&gt;&lt;p style="font-size:0.9rem;"&gt;"Marilah kita membiasakan pola hidup sehat."&lt;/p&gt;&lt;/div&gt;
    &lt;/div&gt;
  &lt;/section&gt;

  &lt;hr class="divider-dash"&gt;

  &lt;!-- ============ MATERI E: TABEL RANGKUMAN ============ --&gt;
  &lt;section class="section" id="materi-e"&gt;
    &lt;div class="eyebrow"&gt;06 — Materi Inti E&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Rangkuman Ciri Kebahasaan Teks Ceramah&lt;/h2&gt;

    &lt;table&gt;
      &lt;tr&gt;&lt;th style="width:22%;"&gt;Ciri Kebahasaan&lt;/th&gt;&lt;th style="width:34%;"&gt;Fungsi&lt;/th&gt;&lt;th&gt;Contoh&lt;/th&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Kata Ganti Orang&lt;/td&gt;&lt;td&gt;Menunjukkan posisi penceramah &amp;amp; pendengar, membangun kedekatan&lt;/td&gt;&lt;td&gt;"saya", "kita", "hadirin"&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Kata Teknis&lt;/td&gt;&lt;td&gt;Memberi kedalaman dan kredibilitas sesuai tema ceramah&lt;/td&gt;&lt;td&gt;"imunitas", "akhlak", "kurikulum"&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Kata Persuasif&lt;/td&gt;&lt;td&gt;Mengajak/menganjurkan pendengar bertindak sesuai pesan&lt;/td&gt;&lt;td&gt;"marilah", "hendaknya"&lt;/td&gt;&lt;/tr&gt;
    &lt;/table&gt;
  &lt;/section&gt;

  &lt;hr class="divider-dash"&gt;

  &lt;!-- ============ PEMODELAN ============ --&gt;
  &lt;section class="section" id="contoh"&gt;
    &lt;div class="eyebrow"&gt;07 — Pemodelan&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Contoh Penerapan: Mengidentifikasi Ciri Kebahasaan&lt;/h2&gt;
    &lt;p class="lead"&gt;Guru membacakan dan membahas bersama contoh berikut sebagai model identifikasi sebelum murid mengerjakan tugas kelompok.&lt;/p&gt;

    &lt;div class="doc-sample"&gt;
      &lt;div class="doc-head"&gt;&lt;span&gt;Lampiran · Teks Ceramah Contoh&lt;/span&gt;&lt;span&gt;Dokumen-01&lt;/span&gt;&lt;/div&gt;
      &lt;div class="doc-body"&gt;
        &lt;h3 style="color:#132029 !important;"&gt;Pentingnya Menjaga Kesehatan di Musim Pancaroba&lt;/h3&gt;
        &lt;p style="margin:10px 0; color:#132029 !important;"&gt;Assalamu'alaikum warahmatullahi wabarakatuh. Bapak/Ibu dan hadirin&lt;span class="flag"&gt;SAPAAN/ORG.2&lt;/span&gt; yang saya hormati, izinkan saya&lt;span class="flag"&gt;ORG.1 TUNGGAL&lt;/span&gt; menyampaikan sedikit pesan tentang pentingnya menjaga kesehatan di musim pancaroba. Musim pancaroba sering menyebabkan daya tahan tubuh menurun, sehingga kita&lt;span class="flag"&gt;ORG.1 JAMAK&lt;/span&gt; rentan terserang flu dan demam. Oleh karena itu, marilah kita&lt;span class="flag"&gt;PERSUASIF&lt;/span&gt; membiasakan pola hidup sehat dengan mengonsumsi makanan bergizi seimbang&lt;span class="flag"&gt;KATA TEKNIS&lt;/span&gt; dan cukup istirahat. Selain itu, hendaknya&lt;span class="flag"&gt;PERSUASIF&lt;/span&gt; kita juga rutin berolahraga agar imunitas&lt;span class="flag"&gt;KATA TEKNIS&lt;/span&gt; tubuh tetap terjaga. Demikian yang dapat saya sampaikan, semoga bermanfaat bagi kita semua. Wassalamu'alaikum warahmatullahi wabarakatuh.&lt;/p&gt;
      &lt;/div&gt;
    &lt;/div&gt;

    &lt;div class="panel" style="margin-top:22px;"&gt;
      &lt;p style="margin:0;"&gt;&lt;b style="color:var(--off-white);"&gt;Simpulan model identifikasi:&lt;/b&gt; Teks di atas memakai kata ganti orang kedua untuk menyapa ("hadirin"), orang pertama tunggal saat memperkenalkan diri ("saya"), dan orang pertama jamak untuk membangun kebersamaan ("kita"). Kata teknis bidang kesehatan ("gizi seimbang", "imunitas") memperkuat kredibilitas isi, sementara kata persuasif ("marilah", "hendaknya") mengajak pendengar menerapkan pola hidup sehat.&lt;/p&gt;
    &lt;/div&gt;
  &lt;/section&gt;

  &lt;hr class="divider-dash"&gt;

  &lt;!-- ============ RANGKUMAN ============ --&gt;
  &lt;section class="section" id="rangkuman"&gt;
    &lt;div class="eyebrow"&gt;08 — Ringkasan Materi&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Poin-Poin Penting&lt;/h2&gt;
    &lt;div class="summary-box"&gt;
      &lt;ul&gt;
        &lt;li&gt;Kata ganti orang dalam teks ceramah terdiri atas orang pertama tunggal ("saya"), orang pertama jamak ("kita/kami"), dan sapaan orang kedua ("hadirin", "Bapak/Ibu").&lt;/li&gt;
        &lt;li&gt;Kata teknis adalah istilah khusus sesuai tema ceramah yang memberi kedalaman dan kredibilitas pada isi.&lt;/li&gt;
        &lt;li&gt;Kata persuasif berupa kata ajakan ("marilah") dan anjuran ("hendaknya") yang mengajak pendengar bertindak sesuai pesan.&lt;/li&gt;
        &lt;li&gt;Ketiga ciri kebahasaan ini saling melengkapi untuk membuat ceramah lebih dekat, meyakinkan, dan mudah diterima pendengar.&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/div&gt;
  &lt;/section&gt;

  &lt;hr class="divider-dash"&gt;

  &lt;!-- ============ TUGAS KELOMPOK ============ --&gt;
  &lt;section class="section" id="tugas-kelompok"&gt;
    &lt;div class="eyebrow"&gt;09 — Lembar Kerja&lt;/div&gt;
    &lt;div class="task-header"&gt;
      &lt;h2&gt;Tugas Kelompok: Mengidentifikasi Ciri Kebahasaan Teks Ceramah&lt;/h2&gt;
      &lt;span class="badge"&gt;Durasi ± 60 menit&lt;/span&gt;
    &lt;/div&gt;

    &lt;p style="margin-top:18px;"&gt;&lt;b style="color:var(--off-white);"&gt;Tujuan tugas:&lt;/b&gt; Murid secara berkelompok mengidentifikasi kata ganti orang, kata teknis, dan kata persuasif pada teks ceramah berikut, lalu mempresentasikan hasil temuannya.&lt;/p&gt;

    &lt;div class="doc-sample" style="margin-top:20px;"&gt;
      &lt;div class="doc-head"&gt;&lt;span&gt;Lampiran · Teks Ceramah untuk Diidentifikasi&lt;/span&gt;&lt;span&gt;Dokumen-02&lt;/span&gt;&lt;/div&gt;
      &lt;div class="doc-body"&gt;
        &lt;h3 style="color:#132029 !important;"&gt;Pentingnya Pendidikan Karakter bagi Generasi Muda&lt;/h3&gt;
        &lt;p style="margin:10px 0; color:#132029 !important;"&gt;Assalamu'alaikum warahmatullahi wabarakatuh. Bapak/Ibu guru dan adik-adik yang saya banggakan, pada kesempatan ini saya ingin mengajak kita semua merenungkan pentingnya pendidikan karakter bagi generasi muda. Pendidikan karakter berperan penting dalam membentuk akhlak dan moral peserta didik, tidak hanya kecerdasan intelektual semata. Oleh karena itu, hendaknya sekolah dan keluarga bekerja sama menanamkan nilai-nilai kejujuran, tanggung jawab, dan kedisiplinan sejak dini. Marilah kita bersama-sama menjadi teladan yang baik bagi generasi penerus bangsa. Demikian yang dapat saya sampaikan. Wassalamu'alaikum warahmatullahi wabarakatuh.&lt;/p&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;p class="lead" style="margin-top:14px;"&gt;Teks di atas &lt;b style="color:var(--off-white);"&gt;belum ditandai&lt;/b&gt; — tugas kelompok adalah menemukan sendiri kata ganti orang, kata teknis, dan kata persuasif yang terdapat di dalamnya.&lt;/p&gt;

    &lt;h4 style="color:var(--off-white); margin-top:24px;"&gt;Petunjuk Pengerjaan&lt;/h4&gt;
    &lt;ol class="steps-num"&gt;
      &lt;li&gt;&lt;b&gt;Bentuk kelompok&lt;/b&gt; beranggotakan 4–5 orang sesuai pembagian dari guru.&lt;/li&gt;
      &lt;li&gt;&lt;b&gt;Baca teks ceramah&lt;/b&gt; di atas secara bersama-sama dalam kelompok.&lt;/li&gt;
      &lt;li&gt;&lt;b&gt;Tandai setiap kata/frasa&lt;/b&gt; sesuai jenisnya (kata ganti orang, kata teknis, atau kata persuasif).&lt;/li&gt;
      &lt;li&gt;&lt;b&gt;Isi Tabel Identifikasi&lt;/b&gt; di bawah ini untuk setiap ciri kebahasaan.&lt;/li&gt;
      &lt;li&gt;&lt;b&gt;Presentasikan hasil&lt;/b&gt; di depan kelas selama maksimal 5 menit per kelompok, dilanjutkan tanya jawab singkat.&lt;/li&gt;
    &lt;/ol&gt;

    &lt;h4 style="color:var(--off-white); margin-top:26px;"&gt;Format Tabel Identifikasi Kelompok&lt;/h4&gt;
    &lt;table&gt;
      &lt;tr&gt;&lt;th style="width:26%;"&gt;Ciri Kebahasaan&lt;/th&gt;&lt;th style="width:36%;"&gt;Contoh Kata/Frasa yang Ditemukan&lt;/th&gt;&lt;th style="width:12%;"&gt;Jumlah&lt;/th&gt;&lt;th&gt;Fungsi dalam Teks&lt;/th&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Kata Ganti Orang Pertama&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Kata Ganti/Sapaan Orang Kedua&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Kata Teknis&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Kata Persuasif&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;/table&gt;

    &lt;h4 style="color:var(--off-white); margin-top:26px;"&gt;Rubrik Penilaian Kelompok&lt;/h4&gt;
    &lt;table&gt;
      &lt;tr&gt;&lt;th style="width:26%;"&gt;Aspek Penilaian&lt;/th&gt;&lt;th&gt;Skor 4 (Sangat Baik)&lt;/th&gt;&lt;th&gt;Skor 3 (Baik)&lt;/th&gt;&lt;th&gt;Skor 2 (Cukup)&lt;/th&gt;&lt;th&gt;Skor 1 (Kurang)&lt;/th&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Ketepatan identifikasi kata ganti orang&lt;/td&gt;&lt;td&gt;Seluruh jenis teridentifikasi tepat&lt;/td&gt;&lt;td&gt;Sebagian besar tepat&lt;/td&gt;&lt;td&gt;Identifikasi dangkal, sebagian keliru&lt;/td&gt;&lt;td&gt;Identifikasi tidak sesuai&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Ketepatan identifikasi kata teknis &amp;amp; persuasif&lt;/td&gt;&lt;td&gt;Seluruh kata ditemukan dengan tepat&lt;/td&gt;&lt;td&gt;Sebagian besar tepat&lt;/td&gt;&lt;td&gt;Sebagian kata terlewat&lt;/td&gt;&lt;td&gt;Tidak ditemukan dengan tepat&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Kerja sama kelompok&lt;/td&gt;&lt;td&gt;Seluruh anggota aktif berkontribusi&lt;/td&gt;&lt;td&gt;Sebagian besar anggota aktif&lt;/td&gt;&lt;td&gt;Hanya sebagian kecil anggota aktif&lt;/td&gt;&lt;td&gt;Didominasi satu orang&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Presentasi&lt;/td&gt;&lt;td&gt;Jelas, percaya diri, menjawab pertanyaan dengan baik&lt;/td&gt;&lt;td&gt;Jelas namun kurang percaya diri&lt;/td&gt;&lt;td&gt;Kurang jelas/terbata-bata&lt;/td&gt;&lt;td&gt;Tidak dapat menjelaskan hasil&lt;/td&gt;&lt;/tr&gt;
    &lt;/table&gt;
  &lt;/section&gt;

  &lt;hr class="divider-dash"&gt;

  &lt;!-- ============ TUGAS INDIVIDU: KUIS 25 PERTANYAAN ============ --&gt;
  &lt;section class="section" id="tugas-individu"&gt;
    &lt;div class="eyebrow"&gt;10 — Penutup Pembelajaran&lt;/div&gt;
    &lt;div class="task-header"&gt;
      &lt;h2&gt;Tugas Individu: Menjawab 25 Pertanyaan tentang Materi&lt;/h2&gt;
      &lt;span class="badge"&gt;Dikerjakan Mandiri · Otomatis Bernilai&lt;/span&gt;
    &lt;/div&gt;

    &lt;p style="margin-top:18px;"&gt;&lt;b style="color:var(--off-white);"&gt;Petunjuk:&lt;/b&gt; Isi No. Absen dan Nama, lalu jawab 25 pertanyaan pilihan ganda (5 opsi) berikut. Soal-soal ini berbentuk &lt;b style="color:var(--off-white);"&gt;HOTS (Higher Order Thinking Skills)&lt;/b&gt; — menuntut analisis kutipan, perbandingan kalimat, dan penilaian efektivitas, bukan sekadar hafalan. Skor akan muncul otomatis setelah menekan tombol "Kirim Jawaban", dan hasilnya akan tercatat otomatis.&lt;/p&gt;

    &lt;div class="panel" style="margin-top:20px;"&gt;
      &lt;div style="display:grid; grid-template-columns:1fr 2fr; gap:14px; margin-bottom:22px;"&gt;
        &lt;div&gt;
          &lt;label class="mono" style="display:block; font-size:0.75rem; color:var(--amber); text-transform:uppercase; letter-spacing:0.08em; margin-bottom:6px;"&gt;No. Absen&lt;/label&gt;
          &lt;input id="kq-absen" type="text" inputmode="numeric" placeholder="Contoh: 12" style="width:100%; padding:10px 12px; border-radius:2px; border:1px solid var(--line); background:var(--blueprint-deep); color:var(--off-white); font-family:'Source Sans 3',sans-serif; font-size:0.95rem;"&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;label class="mono" style="display:block; font-size:0.75rem; color:var(--amber); text-transform:uppercase; letter-spacing:0.08em; margin-bottom:6px;"&gt;Nama Lengkap&lt;/label&gt;
          &lt;input id="kq-nama" type="text" placeholder="Tulis nama lengkap" style="width:100%; padding:10px 12px; border-radius:2px; border:1px solid var(--line); background:var(--blueprint-deep); color:var(--off-white); font-family:'Source Sans 3',sans-serif; font-size:0.95rem;"&gt;
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;div style="margin-bottom:20px; padding-bottom:16px; border-bottom:1px dashed rgba(234,242,245,0.16);"&gt;
        &lt;p style="color:#EAF2F5 !important; font-weight:600; margin:0 0 8px;"&gt;1. Perhatikan kutipan ceramah berikut: “Izinkan saya mengucapkan terima kasih atas kehadiran Bapak/Ibu sekalian. Pada kesempatan ini, marilah kita bersama-sama merenungkan arti pentingnya toleransi.” Perubahan kata ganti dari “saya” ke “kita” pada kutipan tersebut menunjukkan pergeseran fungsi dari...&lt;/p&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq0" value="0" style="margin-right:8px;"&gt;A. memperkenalkan diri ke mengajak keterlibatan bersama pendengar&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq0" value="1" style="margin-right:8px;"&gt;B. menyapa ke menyindir&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq0" value="2" style="margin-right:8px;"&gt;C. menjelaskan ke melarang&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq0" value="3" style="margin-right:8px;"&gt;D. bertanya ke menjawab&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq0" value="4" style="margin-right:8px;"&gt;E. mengeluh ke bersyukur&lt;/label&gt;
      &lt;/div&gt;
      &lt;div style="margin-bottom:20px; padding-bottom:16px; border-bottom:1px dashed rgba(234,242,245,0.16);"&gt;
        &lt;p style="color:#EAF2F5 !important; font-weight:600; margin:0 0 8px;"&gt;2. Seorang penceramah bertema kesehatan menyampaikan: “Pola makan yang buruk dapat meningkatkan risiko penyakit degeneratif.” Penggunaan istilah “penyakit degeneratif” dalam kutipan tersebut berfungsi untuk...&lt;/p&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq1" value="0" style="margin-right:8px;"&gt;A. membuat ceramah lebih sulit dipahami&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq1" value="1" style="margin-right:8px;"&gt;B. menunjukkan kedalaman wawasan dan kredibilitas penceramah terhadap tema yang dibahas&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq1" value="2" style="margin-right:8px;"&gt;C. mengganti fungsi kata ganti orang&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq1" value="3" style="margin-right:8px;"&gt;D. menghindari penggunaan kalimat persuasif&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq1" value="4" style="margin-right:8px;"&gt;E. menyingkat isi ceramah&lt;/label&gt;
      &lt;/div&gt;
      &lt;div style="margin-bottom:20px; padding-bottom:16px; border-bottom:1px dashed rgba(234,242,245,0.16);"&gt;
        &lt;p style="color:#EAF2F5 !important; font-weight:600; margin:0 0 8px;"&gt;3. Bandingkan dua kutipan berikut. Kutipan 1: “Anda harus mulai menabung sejak sekarang.” Kutipan 2: “Marilah kita mulai menabung sejak sekarang.” Perbedaan kesan yang ditimbulkan oleh kedua kutipan tersebut adalah...&lt;/p&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq2" value="0" style="margin-right:8px;"&gt;A. Kutipan 1 terkesan lebih menggurui/berjarak, kutipan 2 terkesan lebih mengajak dan melibatkan diri penceramah&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq2" value="1" style="margin-right:8px;"&gt;B. Kedua kutipan memberi kesan yang identik&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq2" value="2" style="margin-right:8px;"&gt;C. Kutipan 1 lebih persuasif daripada kutipan 2&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq2" value="3" style="margin-right:8px;"&gt;D. Kutipan 2 tidak termasuk kalimat persuasif&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq2" value="4" style="margin-right:8px;"&gt;E. Kutipan 1 menggunakan kata teknis, kutipan 2 tidak&lt;/label&gt;
      &lt;/div&gt;
      &lt;div style="margin-bottom:20px; padding-bottom:16px; border-bottom:1px dashed rgba(234,242,245,0.16);"&gt;
        &lt;p style="color:#EAF2F5 !important; font-weight:600; margin:0 0 8px;"&gt;4. “Hendaknya kita menjaga pola makan sehat demi imunitas tubuh yang optimal.” Jika kata “hendaknya” pada kalimat tersebut dihapus, dampak apa yang paling mungkin terjadi terhadap kalimat?&lt;/p&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq3" value="0" style="margin-right:8px;"&gt;A. Kalimat kehilangan unsur ajakan/anjuran dan berubah menjadi pernyataan biasa&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq3" value="1" style="margin-right:8px;"&gt;B. Kalimat kehilangan seluruh maknanya&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq3" value="2" style="margin-right:8px;"&gt;C. Kalimat menjadi kalimat tanya&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq3" value="3" style="margin-right:8px;"&gt;D. Kalimat berubah menjadi kalimat larangan&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq3" value="4" style="margin-right:8px;"&gt;E. Tidak ada perubahan apa pun&lt;/label&gt;
      &lt;/div&gt;
      &lt;div style="margin-bottom:20px; padding-bottom:16px; border-bottom:1px dashed rgba(234,242,245,0.16);"&gt;
        &lt;p style="color:#EAF2F5 !important; font-weight:600; margin:0 0 8px;"&gt;5. Seorang murid diminta menyusun potongan ceramah bertema lingkungan. Manakah susunan kalimat yang paling tepat menggabungkan kata ganti orang pertama jamak dan kata persuasif secara bersamaan?&lt;/p&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq4" value="0" style="margin-right:8px;"&gt;A. “Sampah plastik sulit terurai di alam.”&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq4" value="1" style="margin-right:8px;"&gt;B. “Marilah kita bersama-sama mengurangi penggunaan plastik sekali pakai.”&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq4" value="2" style="margin-right:8px;"&gt;C. “Data menunjukkan peningkatan sampah plastik setiap tahun.”&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq4" value="3" style="margin-right:8px;"&gt;D. “Plastik adalah bahan yang terbuat dari minyak bumi.”&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq4" value="4" style="margin-right:8px;"&gt;E. “Pencemaran laut disebabkan berbagai faktor.”&lt;/label&gt;
      &lt;/div&gt;
      &lt;div style="margin-bottom:20px; padding-bottom:16px; border-bottom:1px dashed rgba(234,242,245,0.16);"&gt;
        &lt;p style="color:#EAF2F5 !important; font-weight:600; margin:0 0 8px;"&gt;6. Perhatikan kutipan: “Bapak/Ibu dan hadirin yang saya hormati, pendidikan karakter berperan penting membentuk akhlak generasi muda.” Jika sapaan “Bapak/Ibu dan hadirin” diubah menjadi “kalian”, perubahan apa yang paling mungkin terjadi pada kesan ceramah tersebut?&lt;/p&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq5" value="0" style="margin-right:8px;"&gt;A. Kesan menjadi lebih formal dan menghormati pendengar&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq5" value="1" style="margin-right:8px;"&gt;B. Kesan menjadi lebih santai namun berpotensi kurang sopan dalam forum resmi&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq5" value="2" style="margin-right:8px;"&gt;C. Tidak ada perubahan kesan sama sekali&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq5" value="3" style="margin-right:8px;"&gt;D. Ceramah berubah menjadi teks prosedur&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq5" value="4" style="margin-right:8px;"&gt;E. Kalimat menjadi kalimat tanya&lt;/label&gt;
      &lt;/div&gt;
      &lt;div style="margin-bottom:20px; padding-bottom:16px; border-bottom:1px dashed rgba(234,242,245,0.16);"&gt;
        &lt;p style="color:#EAF2F5 !important; font-weight:600; margin:0 0 8px;"&gt;7. Mengapa penggunaan kata teknis yang berlebihan tanpa penjelasan dapat menjadi kelemahan dalam sebuah ceramah?&lt;/p&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq6" value="0" style="margin-right:8px;"&gt;A. Karena dapat membuat pendengar awam kesulitan memahami isi pesan&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq6" value="1" style="margin-right:8px;"&gt;B. Karena kata teknis selalu salah digunakan&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq6" value="2" style="margin-right:8px;"&gt;C. Karena kata teknis tidak diperbolehkan dalam ceramah&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq6" value="3" style="margin-right:8px;"&gt;D. Karena ceramah tidak boleh membahas tema spesifik&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq6" value="4" style="margin-right:8px;"&gt;E. Karena kata teknis mengubah struktur ceramah&lt;/label&gt;
      &lt;/div&gt;
      &lt;div style="margin-bottom:20px; padding-bottom:16px; border-bottom:1px dashed rgba(234,242,245,0.16);"&gt;
        &lt;p style="color:#EAF2F5 !important; font-weight:600; margin:0 0 8px;"&gt;8. Perhatikan dua kalimat berikut. (1) “Kita semua tahu bahwa membaca itu penting.” (2) “Konon membaca itu penting, entahlah.” Manakah kalimat yang lebih efektif membangun keyakinan pendengar, dan mengapa?&lt;/p&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq7" value="0" style="margin-right:8px;"&gt;A. Kalimat (1), karena menggunakan kata ganti “kita” yang melibatkan pendengar secara langsung&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq7" value="1" style="margin-right:8px;"&gt;B. Kalimat (2), karena terdengar lebih santai&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq7" value="2" style="margin-right:8px;"&gt;C. Keduanya sama efektifnya&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq7" value="3" style="margin-right:8px;"&gt;D. Kalimat (2), karena menggunakan kata “konon” sebagai penguat&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq7" value="4" style="margin-right:8px;"&gt;E. Tidak ada yang efektif karena keduanya tidak persuasif&lt;/label&gt;
      &lt;/div&gt;
      &lt;div style="margin-bottom:20px; padding-bottom:16px; border-bottom:1px dashed rgba(234,242,245,0.16);"&gt;
        &lt;p style="color:#EAF2F5 !important; font-weight:600; margin:0 0 8px;"&gt;9. Seorang penceramah ingin membahas tema “pentingnya olahraga” namun menghindari seluruh istilah kesehatan seperti “metabolisme” atau “kardiovaskular”. Apa kemungkinan konsekuensi dari pilihan tersebut?&lt;/p&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq8" value="0" style="margin-right:8px;"&gt;A. Ceramah akan lebih mudah dipahami pendengar awam, namun berpotensi kurang mendalam secara keilmuan&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq8" value="1" style="margin-right:8px;"&gt;B. Ceramah otomatis menjadi tidak persuasif&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq8" value="2" style="margin-right:8px;"&gt;C. Ceramah akan berubah menjadi teks prosedur&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq8" value="3" style="margin-right:8px;"&gt;D. Ceramah tidak dapat menggunakan kata ganti orang&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq8" value="4" style="margin-right:8px;"&gt;E. Tidak ada konsekuensi apa pun&lt;/label&gt;
      &lt;/div&gt;
      &lt;div style="margin-bottom:20px; padding-bottom:16px; border-bottom:1px dashed rgba(234,242,245,0.16);"&gt;
        &lt;p style="color:#EAF2F5 !important; font-weight:600; margin:0 0 8px;"&gt;10. Perhatikan kutipan: “Izinkan saya menutup ceramah ini dengan sebuah ajakan: marilah kita jadikan kejujuran sebagai kebiasaan sehari-hari.” Kombinasi kata ganti dan kata persuasif pada kalimat penutup tersebut berfungsi untuk...&lt;/p&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq9" value="0" style="margin-right:8px;"&gt;A. Menegaskan kembali kehadiran penceramah sekaligus mengajak pendengar bertindak bersama sebagai penutup yang berkesan&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq9" value="1" style="margin-right:8px;"&gt;B. Menyampaikan data statistik terakhir&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq9" value="2" style="margin-right:8px;"&gt;C. Menjelaskan proses ilmiah secara rinci&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq9" value="3" style="margin-right:8px;"&gt;D. Menyapa pendengar untuk pertama kalinya&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq9" value="4" style="margin-right:8px;"&gt;E. Menunjukkan urutan waktu kejadian&lt;/label&gt;
      &lt;/div&gt;
      &lt;div style="margin-bottom:20px; padding-bottom:16px; border-bottom:1px dashed rgba(234,242,245,0.16);"&gt;
        &lt;p style="color:#EAF2F5 !important; font-weight:600; margin:0 0 8px;"&gt;11. Dalam sebuah ceramah bertema pendidikan, penceramah berkata: “Kurikulum yang adaptif terhadap kebutuhan zaman akan mencetak generasi yang kompetitif.” Jika kalimat ini diucapkan di hadapan audiens awam tanpa latar belakang pendidikan, tantangan apa yang paling mungkin dihadapi penceramah?&lt;/p&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq10" value="0" style="margin-right:8px;"&gt;A. Audiens mungkin kesulitan memahami istilah “kurikulum adaptif” tanpa penjelasan tambahan&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq10" value="1" style="margin-right:8px;"&gt;B. Audiens akan langsung memahami tanpa kendala&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq10" value="2" style="margin-right:8px;"&gt;C. Kalimat tersebut tidak mengandung kata teknis sama sekali&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq10" value="3" style="margin-right:8px;"&gt;D. Audiens akan menganggap ceramah tersebut sebagai teks prosedur&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq10" value="4" style="margin-right:8px;"&gt;E. Tidak ada tantangan apa pun&lt;/label&gt;
      &lt;/div&gt;
      &lt;div style="margin-bottom:20px; padding-bottom:16px; border-bottom:1px dashed rgba(234,242,245,0.16);"&gt;
        &lt;p style="color:#EAF2F5 !important; font-weight:600; margin:0 0 8px;"&gt;12. Manakah revisi kalimat yang paling tepat mengubah kalimat formal “Anda diharapkan menjaga kebersihan lingkungan” menjadi kalimat ceramah yang lebih persuasif dan membangun kebersamaan?&lt;/p&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq11" value="0" style="margin-right:8px;"&gt;A. “Marilah kita bersama-sama menjaga kebersihan lingkungan demi kenyamanan bersama.”&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq11" value="1" style="margin-right:8px;"&gt;B. “Lingkungan harus bersih.”&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq11" value="2" style="margin-right:8px;"&gt;C. “Kebersihan lingkungan adalah tanggung jawab pemerintah.”&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq11" value="3" style="margin-right:8px;"&gt;D. “Sampah menyebabkan banjir.”&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq11" value="4" style="margin-right:8px;"&gt;E. “Lingkungan kotor tidak baik.”&lt;/label&gt;
      &lt;/div&gt;
      &lt;div style="margin-bottom:20px; padding-bottom:16px; border-bottom:1px dashed rgba(234,242,245,0.16);"&gt;
        &lt;p style="color:#EAF2F5 !important; font-weight:600; margin:0 0 8px;"&gt;13. Perhatikan kutipan: “Kita tentu sepakat bahwa generasi muda adalah penentu masa depan bangsa.” Kata “kita” dalam kalimat tersebut berfungsi untuk menciptakan kesan bahwa...&lt;/p&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq12" value="0" style="margin-right:8px;"&gt;A. Pendapat yang disampaikan adalah pendapat bersama, bukan sekadar opini pribadi penceramah&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq12" value="1" style="margin-right:8px;"&gt;B. Penceramah sedang bertanya kepada pendengar&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq12" value="2" style="margin-right:8px;"&gt;C. Penceramah sedang menyapa untuk pertama kali&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq12" value="3" style="margin-right:8px;"&gt;D. Kalimat tersebut adalah kalimat prosedur&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq12" value="4" style="margin-right:8px;"&gt;E. Kalimat tersebut tidak memiliki makna persuasif&lt;/label&gt;
      &lt;/div&gt;
      &lt;div style="margin-bottom:20px; padding-bottom:16px; border-bottom:1px dashed rgba(234,242,245,0.16);"&gt;
        &lt;p style="color:#EAF2F5 !important; font-weight:600; margin:0 0 8px;"&gt;14. Jika sebuah ceramah bertema keagamaan sama sekali tidak menggunakan istilah keagamaan (seperti “ibadah” atau “syukur”) dan hanya menggunakan bahasa umum, apa dampak paling mungkin terhadap kredibilitas ceramah tersebut di hadapan audiens yang memahami istilah tersebut?&lt;/p&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq13" value="0" style="margin-right:8px;"&gt;A. Kredibilitas dapat menurun karena ceramah terkesan kurang mendalam membahas tema keagamaan&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq13" value="1" style="margin-right:8px;"&gt;B. Kredibilitas pasti meningkat&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq13" value="2" style="margin-right:8px;"&gt;C. Tidak ada pengaruh terhadap kredibilitas&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq13" value="3" style="margin-right:8px;"&gt;D. Ceramah otomatis menjadi lebih persuasif&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq13" value="4" style="margin-right:8px;"&gt;E. Ceramah berubah menjadi artikel opini&lt;/label&gt;
      &lt;/div&gt;
      &lt;div style="margin-bottom:20px; padding-bottom:16px; border-bottom:1px dashed rgba(234,242,245,0.16);"&gt;
        &lt;p style="color:#EAF2F5 !important; font-weight:600; margin:0 0 8px;"&gt;15. Perhatikan kalimat: “Sebaiknya kita mulai membiasakan hidup hemat energi mulai dari rumah masing-masing.” Jika kata “sebaiknya” diganti dengan “wajib”, perubahan nuansa apa yang paling mungkin terjadi?&lt;/p&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq14" value="0" style="margin-right:8px;"&gt;A. Nuansa anjuran halus berubah menjadi kesan perintah yang lebih tegas/memaksa&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq14" value="1" style="margin-right:8px;"&gt;B. Tidak ada perubahan nuansa sama sekali&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq14" value="2" style="margin-right:8px;"&gt;C. Kalimat menjadi kalimat tanya&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq14" value="3" style="margin-right:8px;"&gt;D. Kalimat kehilangan makna persuasif sepenuhnya&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq14" value="4" style="margin-right:8px;"&gt;E. Kalimat berubah menjadi kalimat deklaratif netral&lt;/label&gt;
      &lt;/div&gt;
      &lt;div style="margin-bottom:20px; padding-bottom:16px; border-bottom:1px dashed rgba(234,242,245,0.16);"&gt;
        &lt;p style="color:#EAF2F5 !important; font-weight:600; margin:0 0 8px;"&gt;16. Seorang penceramah ingin ceramahnya terdengar lebih dekat secara emosional dengan audiens generasi muda. Manakah pilihan kata ganti yang paling sesuai untuk tujuan tersebut?&lt;/p&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq15" value="0" style="margin-right:8px;"&gt;A. “Kita”, karena melibatkan audiens sebagai bagian dari pembicaraan&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq15" value="1" style="margin-right:8px;"&gt;B. “Mereka”, karena lebih formal&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq15" value="2" style="margin-right:8px;"&gt;C. “Beliau”, karena lebih sopan&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq15" value="3" style="margin-right:8px;"&gt;D. “Ia”, karena lebih netral&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq15" value="4" style="margin-right:8px;"&gt;E. “Saya”, karena lebih fokus pada penceramah saja&lt;/label&gt;
      &lt;/div&gt;
      &lt;div style="margin-bottom:20px; padding-bottom:16px; border-bottom:1px dashed rgba(234,242,245,0.16);"&gt;
        &lt;p style="color:#EAF2F5 !important; font-weight:600; margin:0 0 8px;"&gt;17. Perhatikan dua kutipan berikut. Kutipan A: “Hadirin sekalian, marilah kita syukuri nikmat kesehatan ini.” Kutipan B: “Masyarakat diimbau untuk menjaga kesehatan.” Manakah kutipan yang lebih efektif membangun kedekatan emosional dengan pendengar, dan mengapa?&lt;/p&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq16" value="0" style="margin-right:8px;"&gt;A. Kutipan A, karena menggunakan sapaan langsung dan kata ganti “kita” yang melibatkan pendengar&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq16" value="1" style="margin-right:8px;"&gt;B. Kutipan B, karena lebih formal&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq16" value="2" style="margin-right:8px;"&gt;C. Keduanya sama efektifnya&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq16" value="3" style="margin-right:8px;"&gt;D. Kutipan B, karena menggunakan kata “diimbau”&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq16" value="4" style="margin-right:8px;"&gt;E. Tidak ada yang efektif&lt;/label&gt;
      &lt;/div&gt;
      &lt;div style="margin-bottom:20px; padding-bottom:16px; border-bottom:1px dashed rgba(234,242,245,0.16);"&gt;
        &lt;p style="color:#EAF2F5 !important; font-weight:600; margin:0 0 8px;"&gt;18. Mengapa kombinasi kata ganti orang pertama jamak dan kata persuasif sering muncul bersamaan pada bagian penutup ceramah?&lt;/p&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq17" value="0" style="margin-right:8px;"&gt;A. Untuk memperkuat ajakan bertindak bersama sebagai kesan terakhir yang ditinggalkan kepada pendengar&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq17" value="1" style="margin-right:8px;"&gt;B. Karena aturan tata bahasa baku mengharuskannya&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq17" value="2" style="margin-right:8px;"&gt;C. Karena bagian penutup tidak boleh mengandung kata ganti&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq17" value="3" style="margin-right:8px;"&gt;D. Agar ceramah terdengar lebih panjang&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq17" value="4" style="margin-right:8px;"&gt;E. Tidak ada alasan khusus&lt;/label&gt;
      &lt;/div&gt;
      &lt;div style="margin-bottom:20px; padding-bottom:16px; border-bottom:1px dashed rgba(234,242,245,0.16);"&gt;
        &lt;p style="color:#EAF2F5 !important; font-weight:600; margin:0 0 8px;"&gt;19. Sebuah ceramah menggunakan kalimat: “Riset menunjukkan bahwa remaja yang gemar membaca memiliki kemampuan berpikir kritis lebih baik.” Fungsi penyebutan “riset” dalam kalimat tersebut adalah untuk...&lt;/p&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq18" value="0" style="margin-right:8px;"&gt;A. Memperkuat kredibilitas pernyataan dengan merujuk pada bukti/fakta, mirip fungsi kata teknis dalam memperdalam isi&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq18" value="1" style="margin-right:8px;"&gt;B. Menyapa pendengar secara langsung&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq18" value="2" style="margin-right:8px;"&gt;C. Menunjukkan kata ganti orang pertama&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq18" value="3" style="margin-right:8px;"&gt;D. Mengganti fungsi kata persuasif&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq18" value="4" style="margin-right:8px;"&gt;E. Menandai urutan waktu&lt;/label&gt;
      &lt;/div&gt;
      &lt;div style="margin-bottom:20px; padding-bottom:16px; border-bottom:1px dashed rgba(234,242,245,0.16);"&gt;
        &lt;p style="color:#EAF2F5 !important; font-weight:600; margin:0 0 8px;"&gt;20. Perhatikan kutipan ceramah: “Izinkan saya mengajak Bapak/Ibu sekalian untuk turut merenungkan pentingnya gotong royong di tengah masyarakat yang kian individualis.” Manakah ciri kebahasaan yang TIDAK terdapat dalam kutipan tersebut?&lt;/p&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq19" value="0" style="margin-right:8px;"&gt;A. Kata ganti orang pertama tunggal&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq19" value="1" style="margin-right:8px;"&gt;B. Sapaan kepada pendengar&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq19" value="2" style="margin-right:8px;"&gt;C. Kata ajakan&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq19" value="3" style="margin-right:8px;"&gt;D. Konjungsi temporal urutan langkah seperti “kemudian”&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq19" value="4" style="margin-right:8px;"&gt;E. Kata persuasif&lt;/label&gt;
      &lt;/div&gt;
      &lt;div style="margin-bottom:20px; padding-bottom:16px; border-bottom:1px dashed rgba(234,242,245,0.16);"&gt;
        &lt;p style="color:#EAF2F5 !important; font-weight:600; margin:0 0 8px;"&gt;21. Dalam konteks ceramah bertema sosial, manakah fungsi paling tepat dari penggunaan kata teknis seperti “individualis” atau “gotong royong”?&lt;/p&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq20" value="0" style="margin-right:8px;"&gt;A. Memberi kerangka konsep yang memperjelas dan memperdalam gagasan yang disampaikan&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq20" value="1" style="margin-right:8px;"&gt;B. Membuat ceramah terdengar lebih santai&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq20" value="2" style="margin-right:8px;"&gt;C. Menghindari penggunaan kata persuasif&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq20" value="3" style="margin-right:8px;"&gt;D. Mengganti fungsi kata ganti orang&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq20" value="4" style="margin-right:8px;"&gt;E. Mempersingkat durasi ceramah&lt;/label&gt;
      &lt;/div&gt;
      &lt;div style="margin-bottom:20px; padding-bottom:16px; border-bottom:1px dashed rgba(234,242,245,0.16);"&gt;
        &lt;p style="color:#EAF2F5 !important; font-weight:600; margin:0 0 8px;"&gt;22. Seorang murid merevisi kalimat ceramah dari “Kalian harus peduli terhadap sesama” menjadi “Marilah kita peduli terhadap sesama”. Perubahan apa yang terjadi pada kalimat tersebut?&lt;/p&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq21" value="0" style="margin-right:8px;"&gt;A. Kata ganti berubah dari orang kedua menjadi orang pertama jamak, dan nuansa perintah berubah menjadi ajakan bersama&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq21" value="1" style="margin-right:8px;"&gt;B. Tidak ada perubahan makna maupun struktur&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq21" value="2" style="margin-right:8px;"&gt;C. Kalimat kehilangan unsur persuasif sepenuhnya&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq21" value="3" style="margin-right:8px;"&gt;D. Kalimat berubah menjadi kalimat tanya&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq21" value="4" style="margin-right:8px;"&gt;E. Kata teknis ditambahkan pada kalimat tersebut&lt;/label&gt;
      &lt;/div&gt;
      &lt;div style="margin-bottom:20px; padding-bottom:16px; border-bottom:1px dashed rgba(234,242,245,0.16);"&gt;
        &lt;p style="color:#EAF2F5 !important; font-weight:600; margin:0 0 8px;"&gt;23. Mengapa pemilihan kata ganti dan kata persuasif yang tepat penting diperhatikan saat menyusun teks ceramah untuk forum resmi dibandingkan forum santai?&lt;/p&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq22" value="0" style="margin-right:8px;"&gt;A. Karena tingkat formalitas memengaruhi kesan hormat dan efektivitas penyampaian pesan kepada audiens&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq22" value="1" style="margin-right:8px;"&gt;B. Karena forum resmi tidak boleh menggunakan kata ganti sama sekali&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq22" value="2" style="margin-right:8px;"&gt;C. Karena forum santai tidak membutuhkan kata persuasif&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq22" value="3" style="margin-right:8px;"&gt;D. Karena keduanya tidak memiliki perbedaan sama sekali&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq22" value="4" style="margin-right:8px;"&gt;E. Karena kata teknis hanya digunakan di forum santai&lt;/label&gt;
      &lt;/div&gt;
      &lt;div style="margin-bottom:20px; padding-bottom:16px; border-bottom:1px dashed rgba(234,242,245,0.16);"&gt;
        &lt;p style="color:#EAF2F5 !important; font-weight:600; margin:0 0 8px;"&gt;24. Perhatikan kutipan: “Kita sering mendengar pepatah ‘buah jatuh tidak jauh dari pohonnya’. Oleh karena itu, marilah kita menjadi teladan yang baik bagi anak-anak kita.” Apa hubungan logis antara dua kalimat tersebut dalam membangun argumen ceramah?&lt;/p&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq23" value="0" style="margin-right:8px;"&gt;A. Kalimat pertama menjadi dasar analogi yang memperkuat ajakan pada kalimat kedua&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq23" value="1" style="margin-right:8px;"&gt;B. Kedua kalimat tidak memiliki keterkaitan&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq23" value="2" style="margin-right:8px;"&gt;C. Kalimat kedua membantah kalimat pertama&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq23" value="3" style="margin-right:8px;"&gt;D. Kalimat pertama adalah kata teknis&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq23" value="4" style="margin-right:8px;"&gt;E. Kalimat kedua adalah sapaan&lt;/label&gt;
      &lt;/div&gt;
      &lt;div style="margin-bottom:20px; padding-bottom:16px; border-bottom:1px dashed rgba(234,242,245,0.16);"&gt;
        &lt;p style="color:#EAF2F5 !important; font-weight:600; margin:0 0 8px;"&gt;25. Jika Anda diminta menilai efektivitas sebuah teks ceramah, manakah kombinasi ciri kebahasaan yang paling menunjukkan ceramah tersebut disusun dengan baik?&lt;/p&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq24" value="0" style="margin-right:8px;"&gt;A. Penggunaan kata ganti yang membangun kedekatan, kata teknis yang memperdalam isi sesuai tema, dan kata persuasif yang mengajak secara halus&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq24" value="1" style="margin-right:8px;"&gt;B. Hanya menggunakan kalimat tanya di seluruh bagian&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq24" value="2" style="margin-right:8px;"&gt;C. Tidak menggunakan kata ganti maupun kata persuasif sama sekali&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq24" value="3" style="margin-right:8px;"&gt;D. Menggunakan bahasa asing tanpa terjemahan&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="kq24" value="4" style="margin-right:8px;"&gt;E. Mengulang kata yang sama di setiap kalimat&lt;/label&gt;
      &lt;/div&gt;

&lt;div style="margin-top:24px; display:flex; align-items:center; gap:16px; flex-wrap:wrap;"&gt;
        &lt;button id="kq-submit" type="button" style="background:var(--amber); color:var(--blueprint-deep); border:none; padding:12px 26px; font-family:'Oswald',sans-serif; text-transform:uppercase; letter-spacing:0.05em; font-weight:600; border-radius:2px; cursor:pointer; font-size:0.95rem;"&gt;Kirim Jawaban&lt;/button&gt;
        &lt;span id="kq-status" class="mono" style="font-size:0.85rem; color:var(--muted);"&gt;&lt;/span&gt;
      &lt;/div&gt;

      &lt;div id="kq-result" style="display:none; margin-top:20px; padding:18px 20px; border:1px solid var(--amber); background:rgba(245,166,35,0.08);"&gt;
        &lt;p style="margin:0; font-size:1.05rem;"&gt;Skor kamu: &lt;b id="kq-score" style="color:var(--amber); font-size:1.3rem;"&gt;&lt;/b&gt; / 100&lt;/p&gt;
        &lt;p id="kq-detail" style="margin:8px 0 0; font-size:0.9rem; color:var(--muted);"&gt;&lt;/p&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/section&gt;

&lt;/main&gt;

&lt;footer&gt;
  &lt;div class="doc-code"&gt;DOK/B.INDO/XI/CERAMAH-KAIDAH-1 — Fokus Tujuan Pembelajaran, Materi Inti, Tugas Kelompok &amp;amp; Tugas Individu, 1× pertemuan (3 JP)&lt;/div&gt;
  &lt;p style="margin:0;"&gt;Referensi: Kurikulum Merdeka — Capaian Pembelajaran Bahasa Indonesia Fase F (Elemen Membaca dan Memirsa); Buku Teks Bahasa Indonesia Kelas XI SMK/MAK Kemendikbudristek.&lt;/p&gt;
&lt;/footer&gt;

&lt;script&gt;
(function(){
  var KQ_ENDPOINT = "https://script.google.com/macros/s/AKfycbzM7t2qgAENzxQJXzSYJYL28R6nb3TxJVELLL3CopyEXb51t_gRtrkPOxTpI5mq6VCEKw/exec";
  var KQ_MATERI = "Kaidah Kebahasaan Teks Ceramah (Bagian 1)";
  var correctAnswers = [0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0];

  document.getElementById("kq-submit").addEventListener("click", function(){
    var absen = document.getElementById("kq-absen").value.trim();
    var nama = document.getElementById("kq-nama").value.trim();
    var statusEl = document.getElementById("kq-status");

    if(!absen || !nama){
      statusEl.textContent = "Isi No. Absen dan Nama terlebih dahulu.";
      statusEl.style.setProperty("color", "#F5A623", "important");
      return;
    }

    var belumDijawab = [];
    var benar = 0;
    correctAnswers.forEach(function(correct, idx){
      var checked = document.querySelector('input[name="kq' + idx + '"]:checked');
      if(!checked){
        belumDijawab.push(idx+1);
      } else if(parseInt(checked.value,10) === correct){
        benar++;
      }
    });

    if(belumDijawab.length &gt; 0){
      statusEl.textContent = "Masih ada " + belumDijawab.length + " soal yang belum dijawab (nomor " + belumDijawab.slice(0,5).join(", ") + (belumDijawab.length&gt;5? ", ...":"") + ").";
      statusEl.style.setProperty("color", "#F5A623", "important");
      return;
    }

    var skor = benar * 4;
    document.getElementById("kq-score").textContent = skor;
    document.getElementById("kq-detail").textContent = "Menjawab benar " + benar + " dari 25 pertanyaan.";
    document.getElementById("kq-result").style.display = "block";
    statusEl.textContent = "Mengirim hasil...";
    statusEl.style.setProperty("color", "#9FB4C2", "important");

    var payload = new URLSearchParams();
    payload.append("noAbsen", absen);
    payload.append("nama", nama);
    payload.append("skor", skor);
    payload.append("materi", KQ_MATERI);
    payload.append("waktu", new Date().toISOString());

    fetch(KQ_ENDPOINT, {
      method: "POST",
      mode: "no-cors",
      headers: {"Content-Type":"application/x-www-form-urlencoded"},
      body: payload.toString()
    }).then(function(){
      statusEl.textContent = "Hasil berhasil dikirim ke guru.";
      statusEl.style.setProperty("color", "#6EC6CA", "important");
    }).catch(function(){
      statusEl.textContent = "Skor tercatat di halaman ini, namun pengiriman gagal. Tunjukkan skor ini ke guru.";
      statusEl.style.setProperty("color", "#F5A623", "important");
    });
  });
})();
&lt;/script&gt;
&lt;/div&gt;</description><link>http://kitab-investasi.blogspot.com/2026/10/kaidah-kebahasaan-teks-ceramah-bagian-1.html</link><thr:total>0</thr:total><author>nof_rizal07@yahoo.co.id (abang_cool)</author></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-9000860041661554971.post-944626694112424463</guid><pubDate>Tue, 29 Sep 2026 01:52:49 +0000</pubDate><atom:updated>2026-10-15T08:03:10.568+07:00</atom:updated><title>Ujian Tengah Semester Informatika</title><description>&lt;!DOCTYPE html&gt;
&lt;html lang="id"&gt;
&lt;head&gt;
&lt;meta charset="UTF-8"&gt;
&lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&gt;
&lt;title&gt;Ujian Tengah Semester Informatika Kelas X SMK&lt;/title&gt;
&lt;link rel="preconnect" href="https://fonts.googleapis.com"&gt;
&lt;link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&amp;display=swap" rel="stylesheet"&gt;
&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"&gt;&lt;/script&gt;
&lt;style&gt;
  :root{
    --navy:#0b1b3a; --navy2:#1b3a8a; --blue:#1d4ed8; --blue-soft:#e8efff;
    --amber:#f59e0b; --amber-dark:#b45309; --amber-soft:#fff6de;
    --teal:#0f766e; --teal-soft:#dff5f1;
    --ink:#0f172a; --muted:#475569; --line:#d6deeb; --bg:#f1f5fb; --card:#ffffff;
    --ok:#15803d; --okbg:#e2f6e9; --bad:#b91c1c; --badbg:#fde8e8;
  }
  *{box-sizing:border-box;}
  body{margin:0; background:var(--bg); color:var(--ink); font-family:'Inter', system-ui, -apple-system, 'Segoe UI', Arial, sans-serif; line-height:1.55; padding-bottom:70px;}
  .hero{background:linear-gradient(135deg, var(--navy), var(--navy2)); color:#fff; padding:38px 20px 34px; text-align:center;}
  .hero .eyebrow{font-size:12.5px; letter-spacing:.09em; font-weight:700; color:#fbd38d;}
  .hero h1{margin:10px auto 8px; font-size:clamp(24px,4.4vw,36px); font-weight:800; line-height:1.2; max-width:780px;}
  .hero p{margin:0 auto; max-width:660px; color:#dbe6ff; font-size:15px;}
  .chips{display:flex; flex-wrap:wrap; justify-content:center; gap:8px; margin-top:20px;}
  .chip{background:rgba(255,255,255,.14); border:1px solid rgba(255,255,255,.28); padding:6px 14px; border-radius:999px; font-size:13px; font-weight:600;}
  .chip b{color:#fbd38d;}
  .wrap{max-width:920px; margin:0 auto; padding:0 18px;}
  .card{background:var(--card); border:1px solid var(--line); border-radius:14px; padding:24px 26px; margin-top:20px; box-shadow:0 2px 8px rgba(15,23,42,.05);}
  .card h2{margin:0 0 12px; font-size:19px; font-weight:800; color:var(--navy);}
  .card p, .card li{font-size:15px; color:#1e293b;}
  .card ul, .card ol{padding-left:20px; margin:8px 0;}
  table.tbl{width:100%; border-collapse:collapse; font-size:14.5px; margin-top:6px;}
  table.tbl th, table.tbl td{border:1px solid var(--line); padding:9px 12px; text-align:left;}
  table.tbl th{background:var(--blue-soft); color:var(--navy); font-weight:700;}
  table.tbl td.num, table.tbl th.num{text-align:center;}
  .notice{background:var(--amber-soft); border:1px solid #f3d68a; border-left:5px solid var(--amber); border-radius:10px; padding:14px 16px; font-size:14.5px; color:#5b3a06; margin-top:14px;}
  .notice b{color:#7a4a05;}
  .field-grid{display:grid; grid-template-columns:1.1fr 1fr 2fr 1.3fr; gap:14px;}
  @media (max-width:760px){ .field-grid{grid-template-columns:1fr 1fr;} .card{padding:20px 18px;} }
  @media (max-width:460px){ .field-grid{grid-template-columns:1fr;} }
  label.fl{display:block; font-size:13.5px; font-weight:700; margin-bottom:6px; color:var(--navy);}
  input[type=text], input[type=number], select, textarea{width:100%; padding:11px 12px; font-size:15px; border:1.5px solid #b6c2d6; border-radius:9px; font-family:inherit; background:#fff; color:var(--ink);}
  input:focus, select:focus, textarea:focus{outline:3px solid #bfd3ff; border-color:var(--blue);}
  input[readonly]{background:#f1f5f9; color:#334155; font-weight:600;}
  select:disabled{background:#f1f5f9; color:#94a3b8; cursor:not-allowed;}
  textarea{min-height:88px; resize:vertical; line-height:1.6;}
  .btn{display:inline-flex; align-items:center; justify-content:center; gap:8px; border:none; border-radius:10px; padding:13px 22px; font-size:15.5px; font-weight:700; cursor:pointer; font-family:inherit;}
  .btn.primary{background:var(--blue); color:#fff;}
  .btn.primary:hover{background:#1a43b8;}
  .btn.amber{background:var(--amber); color:#1c1300;}
  .btn.amber:hover{background:#e08d00;}
  .btn.ghost{background:#fff; color:var(--navy); border:1.5px solid #b6c2d6;}
  .btn.ghost:hover{background:var(--blue-soft);}
  .btn.block{width:100%;}
  .btn:disabled{opacity:.5; cursor:not-allowed;}
  .msg{padding:12px 14px; border-radius:10px; font-size:14.5px; margin-top:14px; display:none; font-weight:500;}
  .msg.show{display:block;}
  .msg.err{background:var(--badbg); color:var(--bad); border:1px solid #f1b8b8;}
  .msg.ok{background:var(--okbg); color:var(--ok); border:1px solid #a7dbb8;}
  .msg.info{background:var(--blue-soft); color:var(--navy); border:1px solid #bfd3ff;}
  .hidden{display:none !important;}

  .progress-bar{position:sticky; top:0; z-index:30; background:rgba(255,255,255,.97); border-bottom:1px solid var(--line); box-shadow:0 3px 10px rgba(15,23,42,.08); padding:10px 18px;}
  .progress-inner{max-width:920px; margin:0 auto; display:flex; align-items:center; gap:14px; flex-wrap:wrap;}
  .progress-inner .who{font-size:13px; font-weight:700; color:var(--navy);}
  .progress-inner .att{font-size:12.5px; font-weight:700; background:var(--amber-soft); color:var(--amber-dark); padding:3px 10px; border-radius:999px;}
  .pbar{flex:1; min-width:140px; height:10px; background:#e2e8f0; border-radius:999px; overflow:hidden;}
  .pbar &gt; div{height:100%; width:0; background:linear-gradient(90deg, var(--blue), #38bdf8); transition:width .25s;}
  .pcount{font-size:13px; font-weight:700; color:var(--navy); white-space:nowrap;}

  .sec-head{margin-top:26px; padding:16px 20px; border-radius:12px; color:#fff;}
  .sec-head h2{margin:0; font-size:18px; font-weight:800;}
  .sec-head p{margin:4px 0 0; font-size:13.5px; opacity:.95;}
  .sec-a{background:linear-gradient(135deg, #1d4ed8, #2563eb);}
  .sec-b{background:linear-gradient(135deg, #b45309, #d97706);}
  .sec-c{background:linear-gradient(135deg, #0f766e, #14958a);}

  .q{background:var(--card); border:1px solid var(--line); border-left:6px solid var(--blue); border-radius:12px; padding:18px 20px; margin-top:14px;}
  .q.b{border-left-color:var(--amber);}
  .q.c{border-left-color:var(--teal);}
  .q-top{display:flex; justify-content:space-between; align-items:center; gap:10px; margin-bottom:8px;}
  .q-no{font-weight:800; color:var(--navy); font-size:14px;}
  .q-tag{font-size:11.5px; font-weight:700; background:#eef2f9; color:var(--muted); padding:3px 10px; border-radius:999px;}
  .q-text{margin:0 0 12px; font-size:15.5px; font-weight:600; color:var(--ink);}
  .opt{display:flex; align-items:flex-start; gap:11px; padding:10px 12px; border:1.5px solid var(--line); border-radius:10px; margin-bottom:8px; cursor:pointer; font-size:14.8px; background:#fff;}
  .opt:hover{background:var(--blue-soft); border-color:#9db8f5;}
  .opt.sel{background:var(--blue-soft); border-color:var(--blue);}
  .opt input{margin-top:3px; accent-color:var(--blue);}
  .opt .lt{font-weight:800; color:var(--blue); min-width:18px;}
  .ref{background:var(--amber-soft); border:1.5px dashed #e0b34e; border-radius:10px; padding:14px 16px; font-size:15.5px; line-height:1.75; color:#3b2a05; margin-bottom:10px; user-select:none; -webkit-user-select:none; -moz-user-select:none; -ms-user-select:none; cursor:default; font-weight:500;}
  .ref-label{font-size:12px; font-weight:800; letter-spacing:.06em; color:var(--amber-dark); margin-bottom:4px;}
  .fmt-instr{font-size:13.5px; color:var(--amber-dark); font-weight:700; margin:0 0 10px; background:var(--amber-soft); padding:8px 11px; border-radius:8px; border:1px solid #f0d18f;}
  .fmt-toolbar{display:flex; flex-wrap:wrap; gap:10px; align-items:center; background:#0f172a; border-radius:12px; padding:10px 14px; margin-top:6px; position:sticky; top:54px; z-index:25; box-shadow:0 4px 12px rgba(15,23,42,.18);}
  .fmt-group{display:flex; gap:3px; background:rgba(255,255,255,.07); border-radius:8px; padding:4px;}
  .fmt-btn{background:transparent; border:none; color:#e2e8f0; padding:7px 11px; border-radius:6px; font-size:13.5px; font-weight:700; cursor:pointer; font-family:inherit;}
  .fmt-btn:hover{background:rgba(255,255,255,.16);}
  .fmt-select{background:#1e293b; color:#e2e8f0; border:1px solid #334155; border-radius:6px; padding:6px 8px; font-size:12.5px;}
  .fmt-hint{font-size:12px; color:#94a3b8; margin-left:auto;}
  .type-editable{min-height:78px; border:1.5px solid #b6c2d6; border-radius:9px; padding:11px 12px; font-size:15.5px; line-height:1.65; background:#fff; color:var(--ink); outline:none;}
  .type-editable:focus{border-color:var(--blue); outline:3px solid #bfd3ff;}
  .type-editable:empty:before{content:'Ketik di sini...'; color:#9aa5a1;}
  .type-editable ul, .type-editable ol{margin:6px 0; padding-left:24px;}
  .cnt{font-size:12.5px; color:var(--muted); margin-top:5px; display:flex; justify-content:space-between; gap:10px;}
  .cnt .warn{color:var(--bad); font-weight:700;}
  .missing{outline:3px solid #f5a3a3; outline-offset:2px;}

  .result-top{display:flex; gap:26px; align-items:center; flex-wrap:wrap;}
  .ring{--p:0; width:170px; height:170px; border-radius:50%; background:conic-gradient(var(--ringc,#1d4ed8) calc(var(--p) * 1%), #e2e8f0 0); display:flex; align-items:center; justify-content:center; flex:none;}
  .ring &gt; div{width:130px; height:130px; border-radius:50%; background:#fff; display:flex; flex-direction:column; align-items:center; justify-content:center;}
  .ring .val{font-size:44px; font-weight:800; color:var(--navy); line-height:1;}
  .ring .of{font-size:12.5px; color:var(--muted); font-weight:600; margin-top:2px;}
  .status-pill{display:inline-block; padding:6px 16px; border-radius:999px; font-weight:800; font-size:14px; margin-bottom:8px;}
  .status-pill.ok{background:var(--okbg); color:var(--ok);}
  .status-pill.no{background:var(--badbg); color:var(--bad);}
  .bars{margin-top:18px;}
  .bar-row{margin-bottom:12px;}
  .bar-row .lbl{display:flex; justify-content:space-between; font-size:13.5px; font-weight:700; color:var(--navy); margin-bottom:4px;}
  .bar-row .track{height:12px; background:#e2e8f0; border-radius:999px; overflow:hidden;}
  .bar-row .fill{height:100%; border-radius:999px;}
  .btn-row{display:flex; gap:12px; flex-wrap:wrap; margin-top:18px;}
  footer{max-width:920px; margin:38px auto 0; padding:0 18px; text-align:center; font-size:12.5px; color:#64748b;}

  .resetbox{margin-top:14px; border:1px dashed #b6c2d6; border-radius:10px; padding:10px 14px; background:#f8fafc;}
  .resetbox summary{cursor:pointer; font-size:14px; font-weight:600; color:var(--navy);}
  .resetbox .rrow{display:flex; gap:10px; flex-wrap:wrap; margin-top:10px; align-items:center;}
  .resetbox input[type=text]{flex:1; min-width:180px;}
  .guru-code{font-family:ui-monospace,Consolas,monospace; font-size:26px; font-weight:800; letter-spacing:.14em; color:var(--navy); background:var(--blue-soft); border-radius:10px; padding:10px 18px; display:inline-block; margin-top:6px;}
&lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;

&lt;div class="hero"&gt;
  &lt;div class="eyebrow"&gt;UJIAN TENGAH SEMESTER - INFORMATIKA - KELAS X SMK&lt;/div&gt;
  &lt;h1&gt;Ujian Tengah Semester Informatika&lt;/h1&gt;
  &lt;p&gt;Mencakup delapan materi: pengantar informatika, sistem komputer, sistem operasi, jaringan, pencarian informasi, dan pengolah kata.&lt;/p&gt;
  &lt;div class="chips"&gt;
    &lt;span class="chip"&gt;&lt;b&gt;35&lt;/b&gt; Pilihan Ganda&lt;/span&gt;
    &lt;span class="chip"&gt;&lt;b&gt;10&lt;/b&gt; Praktik Mengetik&lt;/span&gt;
    &lt;span class="chip"&gt;&lt;b&gt;5&lt;/b&gt; Esai&lt;/span&gt;
    &lt;span class="chip"&gt;KKM &lt;b&gt;75&lt;/b&gt;&lt;/span&gt;
    &lt;span class="chip"&gt;&lt;b&gt;3x&lt;/b&gt; Kesempatan&lt;/span&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;!-- ============ LAYAR 1: ATURAN &amp; IDENTITAS ============ --&gt;
&lt;div id="screenStart" class="wrap"&gt;
  &lt;div class="card"&gt;
    &lt;h2&gt;Sebelum Mengerjakan&lt;/h2&gt;
    &lt;p&gt;Ujian terdiri atas &lt;b&gt;35 soal pilihan ganda (5 opsi)&lt;/b&gt;, &lt;b&gt;10 soal praktik mengetik&lt;/b&gt;, dan &lt;b&gt;5 soal esai&lt;/b&gt;. Semua dinilai &lt;b&gt;otomatis oleh sistem&lt;/b&gt;. Urutan soal dan urutan opsi jawaban diacak, jadi milikmu bisa berbeda dari teman sebangku.&lt;/p&gt;
    &lt;table class="tbl"&gt;
      &lt;tr&gt;&lt;th&gt;Bagian&lt;/th&gt;&lt;th class="num"&gt;Jumlah&lt;/th&gt;&lt;th class="num"&gt;Bobot per soal&lt;/th&gt;&lt;th class="num"&gt;Bobot total&lt;/th&gt;&lt;th&gt;Cara penilaian&lt;/th&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;A. Pilihan Ganda&lt;/td&gt;&lt;td class="num"&gt;35&lt;/td&gt;&lt;td class="num"&gt;~1,43&lt;/td&gt;&lt;td class="num"&gt;50&lt;/td&gt;&lt;td&gt;Jawaban benar mendapat skor penuh&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;B. Praktik Mengetik&lt;/td&gt;&lt;td class="num"&gt;10&lt;/td&gt;&lt;td class="num"&gt;2,5&lt;/td&gt;&lt;td class="num"&gt;25&lt;/td&gt;&lt;td&gt;Sesuai tingkat kesamaan ketikan dengan naskah&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;C. Esai&lt;/td&gt;&lt;td class="num"&gt;5&lt;/td&gt;&lt;td class="num"&gt;5&lt;/td&gt;&lt;td class="num"&gt;25&lt;/td&gt;&lt;td&gt;Sesuai konsep kunci yang tercakup dalam jawaban&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;&lt;b&gt;Total&lt;/b&gt;&lt;/td&gt;&lt;td class="num"&gt;&lt;b&gt;50&lt;/b&gt;&lt;/td&gt;&lt;td class="num"&gt;-&lt;/td&gt;&lt;td class="num"&gt;&lt;b&gt;100&lt;/b&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;/table&gt;
    &lt;div class="notice"&gt;
      &lt;b&gt;Aturan penting:&lt;/b&gt;
      &lt;ul style="margin:6px 0 0;"&gt;
        &lt;li&gt;&lt;b&gt;KKM = 75.&lt;/b&gt; Begitu nilai akhirmu mencapai atau melebihi KKM, nilai itu langsung terkirim ke guru.&lt;/li&gt;
        &lt;li&gt;Kamu punya &lt;b&gt;3 kali kesempatan&lt;/b&gt;. Jika sampai percobaan ke-3 belum mencapai KKM, sistem mengirim &lt;b&gt;nilai tertinggi&lt;/b&gt; dari ketiga percobaan.&lt;/li&gt;
        &lt;li&gt;Pilih &lt;b&gt;Kelas&lt;/b&gt;, lalu &lt;b&gt;No. Absen&lt;/b&gt; - namamu akan terisi otomatis dari data presensi. Pastikan No. Absen yang dipilih benar-benar milikmu.&lt;/li&gt;
        &lt;li&gt;Masukkan &lt;b&gt;Token Kelas&lt;/b&gt; yang diberikan guru sebelum bisa memulai ujian. Token berbeda untuk setiap kelas.&lt;/li&gt;
        &lt;li id="deadlineNotice"&gt;Ujian wajib diselesaikan dalam batas waktu yang ditentukan guru. &lt;b&gt;Jika belum mengerjakan sama sekali setelah batas waktu berakhir, nilai yang tercatat otomatis 0.&lt;/b&gt;&lt;/li&gt;
        &lt;li&gt;Naskah pada soal mengetik &lt;b&gt;tidak bisa disalin&lt;/b&gt;, dan kolom jawaban &lt;b&gt;menolak tempel (paste)&lt;/b&gt;, seret-lepas teks, serta klik kanan. Semua jawaban wajib diketik sendiri.&lt;/li&gt;
        &lt;li&gt;Setelah selesai, &lt;b&gt;unduh bukti mengerjakan (PDF F4)&lt;/b&gt;, cetak, lalu serahkan ke guru mata pelajaran.&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/div&gt;
  &lt;/div&gt;

  &lt;div class="card"&gt;
    &lt;h2&gt;Identitas Peserta&lt;/h2&gt;
    &lt;div class="field-grid"&gt;
      &lt;div&gt;&lt;label class="fl" for="fKelas"&gt;Kelas&lt;/label&gt;
        &lt;select id="fKelas"&gt;
          &lt;option value="" disabled selected&gt;- Pilih kelas -&lt;/option&gt;
          &lt;option value="X TB1"&gt;X TB1&lt;/option&gt;
          &lt;option value="X TB2"&gt;X TB2&lt;/option&gt;
          &lt;option value="X TO1"&gt;X TO1&lt;/option&gt;
          &lt;option value="X TO2"&gt;X TO2&lt;/option&gt;
          &lt;option value="X TJKT1"&gt;X TJKT1&lt;/option&gt;
          &lt;option value="X TJKT2"&gt;X TJKT2&lt;/option&gt;
        &lt;/select&gt;&lt;/div&gt;
      &lt;div&gt;&lt;label class="fl" for="fAbsen"&gt;No. Absen&lt;/label&gt;
        &lt;select id="fAbsen" disabled&gt;&lt;option value=""&gt;- Pilih kelas dulu -&lt;/option&gt;&lt;/select&gt;&lt;/div&gt;
      &lt;div&gt;&lt;label class="fl" for="fNama"&gt;Nama Lengkap&lt;/label&gt;&lt;input type="text" id="fNama" placeholder="Otomatis setelah No. Absen dipilih" readonly&gt;&lt;/div&gt;
      &lt;div&gt;&lt;label class="fl" for="fToken"&gt;Token Kelas&lt;/label&gt;&lt;input type="text" id="fToken" placeholder="Token dari guru" autocomplete="off"&gt;&lt;/div&gt;
    &lt;/div&gt;
    
    &lt;details class="resetbox" id="resetBox"&gt;
      &lt;summary&gt;Punya Kode Reset dari guru?&lt;/summary&gt;
      &lt;div class="rrow"&gt;
        &lt;input type="text" id="fResetCode" placeholder="Kode reset dari guru" autocomplete="off" maxlength="12"&gt;
        &lt;button class="btn ghost" id="btnUseReset" type="button"&gt;Gunakan Kode&lt;/button&gt;
      &lt;/div&gt;
      &lt;div class="msg" id="resetMsg"&gt;&lt;/div&gt;
    &lt;/details&gt;
    &lt;div class="msg err" id="startErr"&gt;&lt;/div&gt;
    &lt;div style="margin-top:18px;"&gt;&lt;button class="btn primary block" id="btnStart" type="button"&gt;Mulai Mengerjakan&lt;/button&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="card hidden" id="guruCard"&gt;
    &lt;h2&gt;Panel Guru - Reset Percobaan&lt;/h2&gt;
    &lt;div id="guruLogin"&gt;
      &lt;label class="fl" for="rsPin"&gt;PIN Guru&lt;/label&gt;
      &lt;div class="rrow" style="display:flex; gap:10px; flex-wrap:wrap;"&gt;
        &lt;input type="password" id="rsPin" placeholder="Masukkan PIN guru" autocomplete="off" style="flex:1; min-width:200px;"&gt;
        &lt;button class="btn primary" id="btnGuruLogin" type="button"&gt;Buka Panel&lt;/button&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div id="guruTools" class="hidden"&gt;
      &lt;div class="field-grid" style="grid-template-columns:1fr 2fr 1fr;"&gt;
        &lt;div&gt;&lt;label class="fl" for="rsKelas"&gt;Kelas&lt;/label&gt;
          &lt;select id="rsKelas"&gt;&lt;option value="" disabled selected&gt;- Pilih kelas -&lt;/option&gt;&lt;/select&gt;&lt;/div&gt;
        &lt;div&gt;&lt;label class="fl" for="rsAbsen"&gt;Siswa (No. Absen)&lt;/label&gt;
          &lt;select id="rsAbsen" disabled&gt;&lt;option value=""&gt;- Pilih kelas dulu -&lt;/option&gt;&lt;/select&gt;&lt;/div&gt;
        &lt;div&gt;&lt;label class="fl" for="rsNo"&gt;Reset ke-&lt;/label&gt;
          &lt;input type="number" id="rsNo" min="1" max="9" value="1"&gt;&lt;/div&gt;
      &lt;/div&gt;
      &lt;div class="btn-row"&gt;
        &lt;button class="btn primary" id="btnRsCode" type="button"&gt;Buat Kode Reset&lt;/button&gt;
        &lt;button class="btn amber" id="btnRsHere" type="button"&gt;Reset di Perangkat Ini&lt;/button&gt;
      &lt;/div&gt;
      &lt;div id="rsOut" style="margin-top:12px;"&gt;&lt;/div&gt;
      &lt;p style="font-size:13px; color:#64748b; margin:12px 0 0;"&gt;
        &lt;b&gt;Kode reset&lt;/b&gt;: berikan ke siswa, lalu siswa memilih Kelas &amp;amp; No. Absen dan memasukkannya di kotak "Punya Kode Reset". Kode hanya berlaku untuk siswa tersebut dan sekali pakai per perangkat.
        Untuk reset kedua siswa yang sama, naikkan "Reset ke-" menjadi 2, dan seterusnya.
        &lt;b&gt;Reset di Perangkat Ini&lt;/b&gt; dipakai bila siswa mengerjakan di perangkat yang sedang Anda pegang.
      &lt;/p&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;!-- ============ LAYAR 2: UJIAN ============ --&gt;
&lt;div id="screenExam" class="hidden"&gt;
  &lt;div class="progress-bar"&gt;
    &lt;div class="progress-inner"&gt;
      &lt;span class="who" id="whoLbl"&gt;&lt;/span&gt;
      &lt;span class="att" id="attLbl"&gt;&lt;/span&gt;
      &lt;div class="pbar"&gt;&lt;div id="pbarFill"&gt;&lt;/div&gt;&lt;/div&gt;
      &lt;span class="pcount" id="pcount"&gt;0 / 50 terjawab&lt;/span&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="wrap"&gt;
    &lt;div class="sec-head sec-a"&gt;&lt;h2&gt;A. Pilihan Ganda (35 soal - 50 poin)&lt;/h2&gt;&lt;p&gt;Pilih satu jawaban paling tepat dari lima opsi.&lt;/p&gt;&lt;/div&gt;
    &lt;div id="bodyA"&gt;&lt;/div&gt;

    &lt;div class="sec-head sec-b"&gt;&lt;h2&gt;B. Praktik Mengetik (10 soal - 25 poin)&lt;/h2&gt;&lt;p&gt;Ketik ulang naskah sesuai instruksi, lalu terapkan format yang diminta memakai toolbar di bawah ini. Tempel (paste) dinonaktifkan.&lt;/p&gt;&lt;/div&gt;
    &lt;div class="fmt-toolbar" id="fmtToolbar"&gt;
      &lt;div class="fmt-group"&gt;
        &lt;button type="button" class="fmt-btn" data-cmd="bold" title="Bold"&gt;&lt;b&gt;B&lt;/b&gt;&lt;/button&gt;
        &lt;button type="button" class="fmt-btn" data-cmd="italic" title="Italic"&gt;&lt;i&gt;I&lt;/i&gt;&lt;/button&gt;
        &lt;button type="button" class="fmt-btn" data-cmd="underline" title="Underline"&gt;&lt;u&gt;U&lt;/u&gt;&lt;/button&gt;
      &lt;/div&gt;
      &lt;div class="fmt-group"&gt;
        &lt;button type="button" class="fmt-btn" data-cmd="justifyLeft"&gt;Kiri&lt;/button&gt;
        &lt;button type="button" class="fmt-btn" data-cmd="justifyCenter"&gt;Tengah&lt;/button&gt;
        &lt;button type="button" class="fmt-btn" data-cmd="justifyRight"&gt;Kanan&lt;/button&gt;
        &lt;button type="button" class="fmt-btn" data-cmd="justifyFull"&gt;Rata&lt;/button&gt;
      &lt;/div&gt;
      &lt;div class="fmt-group"&gt;
        &lt;button type="button" class="fmt-btn" data-cmd="insertUnorderedList"&gt;List Bullet&lt;/button&gt;
        &lt;button type="button" class="fmt-btn" data-cmd="insertOrderedList"&gt;1. List&lt;/button&gt;
      &lt;/div&gt;
      &lt;div class="fmt-group"&gt;
        &lt;select id="fmtSize" class="fmt-select" title="Ukuran huruf (pt)"&gt;
          &lt;option value=""&gt;Ukuran Huruf&lt;/option&gt;
          &lt;option value="8"&gt;8&lt;/option&gt;&lt;option value="10"&gt;10&lt;/option&gt;&lt;option value="11"&gt;11&lt;/option&gt;
          &lt;option value="12"&gt;12&lt;/option&gt;&lt;option value="14"&gt;14&lt;/option&gt;&lt;option value="16"&gt;16&lt;/option&gt;
          &lt;option value="18"&gt;18&lt;/option&gt;&lt;option value="20"&gt;20&lt;/option&gt;&lt;option value="24"&gt;24&lt;/option&gt;
          &lt;option value="28"&gt;28&lt;/option&gt;&lt;option value="36"&gt;36&lt;/option&gt;
        &lt;/select&gt;
        &lt;select id="fmtFont" class="fmt-select" title="Jenis huruf"&gt;
          &lt;option value=""&gt;Jenis Huruf&lt;/option&gt;
          &lt;option value="Times New Roman"&gt;Times New Roman&lt;/option&gt;
          &lt;option value="Arial"&gt;Arial&lt;/option&gt;
          &lt;option value="Calibri"&gt;Calibri&lt;/option&gt;
          &lt;option value="Verdana"&gt;Verdana&lt;/option&gt;
          &lt;option value="Georgia"&gt;Georgia&lt;/option&gt;
          &lt;option value="Tahoma"&gt;Tahoma&lt;/option&gt;
          &lt;option value="Courier New"&gt;Courier New&lt;/option&gt;
          &lt;option value="Comic Sans MS"&gt;Comic Sans MS&lt;/option&gt;
        &lt;/select&gt;
      &lt;/div&gt;
      &lt;span class="fmt-hint"&gt;Klik di kotak jawaban dulu, lalu gunakan tombol ini&lt;/span&gt;
    &lt;/div&gt;
    &lt;div id="bodyB"&gt;&lt;/div&gt;

    &lt;div class="sec-head sec-c"&gt;&lt;h2&gt;C. Esai (5 soal - 25 poin)&lt;/h2&gt;&lt;p&gt;Jawab dengan kalimatmu sendiri (minimal 40 karakter). Jawaban dinilai dari konsep kunci pada materi. Tempel (paste) dinonaktifkan.&lt;/p&gt;&lt;/div&gt;
    &lt;div id="bodyC"&gt;&lt;/div&gt;

    &lt;div class="card"&gt;
      &lt;div class="msg err" id="examErr"&gt;&lt;/div&gt;
      &lt;button class="btn primary block" id="btnSubmit" type="button"&gt;Kirim Jawaban&lt;/button&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;!-- ============ LAYAR 3: HASIL ============ --&gt;
&lt;div id="screenResult" class="wrap hidden"&gt;
  &lt;div class="card"&gt;
    &lt;div class="result-top"&gt;
      &lt;div class="ring" id="ring"&gt;&lt;div&gt;&lt;span class="val" id="rVal"&gt;0&lt;/span&gt;&lt;span class="of"&gt;dari 100&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;
      &lt;div style="flex:1; min-width:240px;"&gt;
        &lt;span class="status-pill" id="rPill"&gt;&lt;/span&gt;
        &lt;h2 style="margin:0 0 6px;" id="rTitle"&gt;&lt;/h2&gt;
        &lt;p style="margin:0; color:#334155;" id="rDesc"&gt;&lt;/p&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="bars" id="rBars"&gt;&lt;/div&gt;
    &lt;div class="notice" id="rHist"&gt;&lt;/div&gt;
    &lt;div class="msg info" id="rSend"&gt;&lt;/div&gt;
    &lt;div class="btn-row"&gt;
      &lt;button class="btn amber" id="btnPdf" type="button"&gt;Unduh Bukti Mengerjakan (PDF F4)&lt;/button&gt;
      &lt;button class="btn primary hidden" id="btnRetry" type="button"&gt;Coba Lagi&lt;/button&gt;
      &lt;button class="btn ghost" id="btnHome" type="button"&gt;Kembali ke Awal&lt;/button&gt;
    &lt;/div&gt;
    &lt;p style="font-size:13px; color:#64748b; margin:14px 0 0;"&gt;&lt;b&gt;Wajib:&lt;/b&gt; setelah nilai tersimpan, unduh PDF, cetak pada kertas F4 (maks. 3 lembar), dan serahkan ke guru mata pelajaran sebagai bukti pengerjaan.&lt;/p&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;footer&gt;Ujian Tengah Semester Informatika Kelas X SMK - DOK/INFORMATIKA/X/UTS&lt;/footer&gt;

&lt;iframe name="hidden_iframe" id="hidden_iframe" style="display:none;"&gt;&lt;/iframe&gt;
&lt;form id="gform" action="https://script.google.com/macros/s/AKfycbwKp7DrBTALJMlw8crjK7RgXIO8LVcU4yVEd9WJNs_vgSXkVxfw7fwkGbOT2IBNOjg3uQ/exec" method="POST" target="hidden_iframe" style="display:none;"&gt;
  &lt;input type="hidden" name="no absen" id="gAbsen"&gt;
  &lt;input type="hidden" name="nama" id="gNama"&gt;
  &lt;input type="hidden" name="kelas" id="gKelas"&gt;
  &lt;input type="hidden" name="nilai evaluasi" id="gNilai"&gt;
  &lt;input type="hidden" name="skor" id="gSkor"&gt;
  &lt;input type="hidden" name="Nilai STS" id="gNilaiSTS"&gt;
  &lt;input type="hidden" name="judul materi" id="gJudul"&gt;
&lt;/form&gt;

&lt;script&gt;
(function(){
"use strict";

var KKM = 75, MAX_ATT = 3;
var JUDUL = "Ujian Tengah Semester Informatika Kelas X";
var DOC_CODE = "DOK/INFORMATIKA/X/UTS";

/* TODO GURU: sesuaikan tanggal &amp; jam ujian dibuka di sini (format ISO, zona waktu WIB +07:00) */
var EXAM_OPEN = new Date('2026-10-15T07:00:00+07:00');
var DEADLINE_DAYS = 7;
var EXAM_DEADLINE = new Date(EXAM_OPEN.getTime() + DEADLINE_DAYS*24*60*60*1000);
/* Versi ujian - diperbarui otomatis tiap kali EXAM_OPEN diubah, supaya percobaan (attempt) siswa dari periode ujian sebelumnya tidak ikut terhitung saat ujian dibuka ulang */
var EXAM_VERSION = 'v-' + EXAM_OPEN.toISOString().slice(0,10);

var ROSTER = {
  'X TB1': [[1,'ADHA MIRAHAYU NINGSIH'],[2,'ANGELINA AGNES NOVIOLA'],[3,'ANISSA VIRA FIRMANDA'],[4,'Awinda Rizqi Amru Anjani'],[5,'CITRA AULIA BAHARIZQI'],[6,'DHIRA CAHYA OKTAVIANINGRUM'],[7,'Ema Deny Setyaningrum'],[8,'EVITA APRILIANI'],[9,'FAIR ROCHMATUL ISHMAH'],[10,'FATMA NABILA'],[11,'FATMAWATI'],[12,'Fika Setya Wulandari'],[13,'Gelsi Zalika Thufaila'],[14,'HIDAYATUL HUSNA MAULIDA'],[15,'IZZATUL LUTHFA IMANDA'],[16,'MEISHA AYU BERLIA'],[17,'MEYLISA PUTRI MURDIANI'],[18,'MITA TRI OKTAVIA'],[19,'MUTIARA SYABILLA'],[20,'NABILA SASKIA'],[21,'NADYA VEGA RAHMADANI'],[22,'Nafisa Nailal Husna'],[23,'NAWA SYIFFA MARYAM'],[24,'NIRIN FADILLAH'],[25,'RENI RESTIA PRAMESTI'],[26,'RIZKIYA MAULIDA'],[27,'SHINTA AULIA MUKTI'],[28,'SHINTIA AMELIA PUTRI'],[29,'SUCI NUR AZAHRA'],[30,'SYAH UITTA JIHAN MAKAELA'],[31,'VARISCA INDRI ARIANI'],[32,'VILSA SAFA AZZAHRA'],[33,'YUANITA ROBBITOTUN NAJA'],[34,'ZUNI ARIFAH']],
  'X TB2': [[1,'ADINDA EKA NUR AINI'],[2,'Adinda Permata Sari'],[3,'AMANDA PUSPA MAHARANI'],[4,'ANA AMELLIYA'],[5,'AULIYA NATASYA DEWI'],[6,'AYUB MAULANA'],[7,'BILQIS NGIZZATUN NISA\''],[8,'CEYSA ELVINA AMANDA'],[9,'CHAUDLI MAULIDINA AZRA'],[10,'DESTA AURA AZALIA SANI'],[11,'DINDA NURUL AMALIA'],[12,'Dwi Mayangsari'],[13,'EFRIDA DEWI ANANDA'],[14,'Emi Rara Pramudita'],[15,'FIRMAN ARYA DINAIA'],[16,'KEISYA ALISYA PUTRI ALI'],[17,'Kusnul Kusuma Wardhani'],[18,'LIBY ARUMBIYA'],[19,'Lutfia Putri'],[20,'MARISKA NUR AIRA'],[21,'NADIA NUR AZIZAH IRYSATI'],[22,'NAHLA AULIA SALSABILLA'],[23,'NAURA IZA AZAHRA'],[24,'NAZWA AKAYLA SAPUTRI'],[25,'NOVITA ADHA RIZKI ANGGRAINI'],[26,'PEMBAYUN ANGGER WIDJAYA'],[27,'REVALIA NOVIANTI TAMARA'],[28,'SAHAL HANIF YUSUF'],[29,'SEKAR WANGI'],[30,'Silvi Dwi Noviyanti'],[31,'SIRVI KHUNAIFIYAH LINA AINI NISA'],[32,'VITO ADI CANDRA'],[33,'ZAHWA'],[34,'ZIDANNAJ MAROSAT']],
  'X TO1': [[1,'ACHMAT SAPTA ARYA'],[2,'ADE FASIYAN NANDO'],[3,'ALBERTUS ADELIO RONALD FAGUNDEZ'],[4,'ALLAN FADLI MUHAMMAD JIBRANNI'],[5,'ARGA SYARUL SETIYAWAN'],[6,'DEDDY SETIYAWAN'],[7,'DENNIZ PRADIVTA ALVIANDRA'],[8,'DIMAS PUTRA ERLANGGA'],[9,'DIYAS PRASETYO'],[10,'DZAKIE AZ ZAAHII'],[11,'FADHIL DIANTORO'],[12,'FAQIH UBAIDILLAH'],[13,'FAQIYUDDIN ASYRAF'],[14,'HANIF TAUFIQULHAQIM'],[15,'IQBAL HAIDAR ARIQ'],[16,'IRFAN BAGAS VEBYANTINO'],[17,'MARCELINO ADI SANTOSO'],[18,'MUHAMAD AFTAH FARKHAN NAKA'],[19,'MUHAMAD AMAR MA\'RUF'],[20,'MUHAMAD ILHAM PRASETYO'],[21,'MUHAMMAD AFWAN MAULANA AZIDAN'],[22,'MUHAMMAD KAFA BIHI FADLURROZAG'],[23,'MUHAMMAD SONY TAFRIKHAN'],[24,'MUHAMMAD SYAHID SYAHPUTRA'],[25,'MUHAMMAD ZAHRUL ULUM AL BUSTHOMI'],[26,'NANDO KURNIA EKA PUTRA'],[27,'NAUFAL ZAKY MUTTAQIN'],[28,'Nizham Zafir Hariz Saputra'],[29,'NUR FATHUR RAHMATULLAH'],[30,'RADITYA PUTRA PERDANA'],[31,'RAFKA MAULANA PUTRA'],[32,'RAKA RAFIF AZMI'],[33,'REYHAN YUNAZTA PUTRA HANY'],[34,'RIZKI IBADALLAH ALBAROYA'],[35,'SEPTIAN DANANG PRASETYO'],[36,'Yehuda Bayu Seno Abimanyu']],
  'X TO2': [[1,'ADHAM DZAKI IBRAHIM MUFID'],[2,'AFLAH RAPHAEL WINDRA RADITYA'],[3,'AHMAD DAVI PRIA UTAMA'],[4,'AHMAD MAULANA ABDUL MALIK'],[5,'Ahmad Shovi Maola'],[6,'ALBARASYA HERMAN'],[7,'ANDIK FEBRI FIRMANSYAH'],[8,'DIMAS SAPUTRA'],[9,'DISKA INDRA FATA WIDAKDO'],[10,'FAREL ANDRIAN PRATAMA'],[11,'Ferdita Fatma Kusuma'],[12,'GALIH GINANJAR SAPUTRO'],[13,'LEVI FASTABIKHUL KHOIR'],[14,'LIONEL NATHAN KURNIAWAN'],[15,'MUHAMAD FIRDIANSYAH'],[16,'MUHAMAD KHOIRUL ANWAR'],[17,'MUHAMAD RIJAL ALIF IBRAHIM'],[18,'MUHAMAD TANFEBRO PERMANA'],[19,'MUHAMMAD AKMAL FARIZKY'],[20,'MUHAMMAD ALWI SIHAB'],[21,'MUHAMMAD \'AQILA AZKA'],[22,'MUHAMMAD FATIH'],[23,'MUHAMMAD FAUZI NOVANTYO'],[24,'Muhammad Rafka Adi Pratama'],[25,'MUHAMMAD TONI SUPRASETYO'],[26,'NOVAN ANANDA RIZKY'],[27,'PRAKASA TEGAR ANDRIYANTO'],[28,'RAFAEL BAYU PRATAMA'],[29,'RANDI KHOIRUL AZZAM'],[30,'RIDHO AMRU BAIN'],[31,'SABRI RADHITYA GANESWARA'],[32,'SATRIA FIRMAN WIBOWO'],[33,'SYARIF HIDAYAD'],[34,'WILDAN RIZQI ARRUMMAN'],[35,'VICKY ADIKA CHANDRA']],
  'X TJKT1': [[1,'ADLY SURYA HERNAWAN'],[2,'ADRIANUS FERDINAND BARRA ARDIONA'],[3,'AISYAH KHOIRUN NISA'],[4,'ALIF EVAN SANJAYA'],[5,'Alif Maulana Ashidiqie'],[6,'Alif Rizqullah Ramadhan'],[7,'ANDIKA BILLIE FAUSTINO'],[8,'ARVIN ARYASETA ATMAJA'],[9,'BRYLIANA JIHAN AMIR'],[10,'DANDRY KORNELIUS ARISANDI'],[11,'DANIEL REVELINO FEIVEL WIDJANARKO'],[12,'DWI APRIELLA NUR RAHMA'],[13,'HANAR FAIRUS NADHIR AMRULLAH'],[14,'HANI DWI RAHMAWATI'],[15,'IKHSAN ABDUL ROZAK'],[16,'JAVIEN PUTRA MAHENDRA'],[17,'Linda Putri Darmawan'],[18,'LINGGA MAHARDIKA SUSATYO'],[19,'MUAZARAH FARRAS AMELIA'],[20,'MUHAMMAD FA\'DLIL ASYHARI'],[21,'MUHAMMAD FAQIH ANWARI'],[22,'MUHAMMAD SIDIQ FATHUL MU\'IZ'],[23,'NAILATUSSAKINAH'],[24,'NAJMA AULYA'],[25,'Nazila Karrolina Aishi Azzahra'],[26,'RAKHUL SURYA PERMANA'],[27,'RAYA GHANIA PUTRI'],[28,'REVALINA AULIA ZAHRA'],[29,'Salma Anggun Aurellia'],[30,'SANREZ REKSI KUSUMA'],[31,'SETIYA RIZKY MAULANA'],[32,'SHARA FATIKA ADDAHLANI'],[33,'SINTA PUSPA SARI'],[34,'ZULFA IBNUL KARIM']],
  'X TJKT2': [[1,'AKHMAD FAKHRI HIDAYAT'],[2,'ALIA NUR AISYAH'],[3,'ANDIKA MAULANA MUHAIMIN'],[4,'ANDRIANSYAH MAULANA'],[5,'ANUM MANURAGA'],[6,'BRIANDA OCTA PRATAMA'],[7,'DAVID LUQMAN'],[8,'DEVANDRI KUSUMA'],[9,'DIMAS SALMAN KHAFI'],[10,'DIVANI AULIA NAJMI'],[11,'DWI AYU SASKIYA'],[12,'DYLLAN DEEP YOSHAN'],[13,'DZIKRI MAULANA'],[14,'FAREL RADHITYA PRADANA'],[15,'GHIFARI SAHILA DZAKI'],[16,'INDAH NAZIFA'],[17,'JATI WEKO ADI'],[18,'JERIKO PRANATA'],[19,'KHOIRUL MUNA'],[20,'MAYLINDA QHONITA PUTRI'],[21,'MIFTAKHUL ADIYANSYAH'],[22,'MUHAMAD RESTU FAUZI'],[23,'MUHAMMAD ABADI'],[24,'MUHAMMAD FAIZ FIRMANSYAH'],[25,'MUHAMMAD IRFAN SAPUTRA'],[26,'MUHAMMAD REVA IBRAHIMMUVIQ'],[27,'NAJA ADKAR KHAIR'],[28,'NIZAM JATI WARDOYO'],[29,'NUR FIDYAH'],[30,'OKFAL NOVA PUJI SATRIAWAN'],[31,'QUINSHA VIROSYA PRICILLIA'],[32,'REZA HAFID ARIYANTO'],[33,'RICKY ARDIANSYAH'],[34,'SITI ERNAWATI'],[35,'SYAHRINA LAILA FARHANA'],[36,'WILDAN SETIO FIRMANSYAH']],
};
var CLASS_TOKENS = {
  'X TB1': 'TB1-4821',
  'X TB2': 'TB2-7093',
  'X TO1': 'TO1-2264',
  'X TO2': 'TO2-5518',
  'X TJKT1': 'TJKT1-3390',
  'X TJKT2': 'TJKT2-9147',
};
var PT_PG = 50/35, PT_TYPE = 2.5, PT_ESAI = 5;
var MAX_PG = 50, MAX_TYPE = 25, MAX_ESAI = 25;
var TOTAL_Q = 50;

/* ================= BANK SOAL ================= */

var PG = [
 {m:"Pengantar Informatika", q:"Seorang siswa diminta menyusun langkah-langkah menemukan lokasi kelas yang berpindah menjadi instruksi berurutan yang bisa diikuti siapa pun. Kemampuan yang paling tepat digunakan siswa tersebut adalah...", o:["Machine learning", "Computational thinking", "Cloud computing", "Big data", "Artificial intelligence"], a:1, lvl:"mudah"},
 {m:"Pengantar Informatika", q:"Sebuah perusahaan logistik memasang sensor pada truk untuk memantau lokasi real-time, menganalisis pola pengiriman dengan big data, lalu mengotomatisasi rute lewat AI. Transformasi ini paling tepat menggambarkan ciri Revolusi Industri...", o:["1.0", "2.0", "3.0", "4.0", "5.0"], a:3, lvl:"sedang"},
 {m:"Pengantar Informatika", q:"Seorang karyawan baru terbiasa bekerja manual dan menyimpan file hanya di komputer pribadi. Setelah pindah ke tim yang tersebar di berbagai kota dan bekerja jarak jauh, langkah paling mendesak yang perlu ia lakukan adalah...", o:["Tetap bekerja seperti sebelumnya karena sudah terbiasa", "Mengadopsi kolaborasi daring dan penyimpanan cloud sebagai bagian budaya kerja digital", "Meminta seluruh tim kembali bekerja manual", "Menolak menggunakan aplikasi apa pun", "Hanya mengandalkan komunikasi tatap muka"], a:1, lvl:"sedang"},
 {m:"Pengantar Informatika", q:"Sebuah sekolah ingin memakai software edukasi gratis, namun tim IT-nya juga berencana memodifikasi kode programnya agar sesuai kebutuhan lokal dan membagikannya kembali ke sekolah lain. Jenis lisensi yang paling sesuai adalah...", o:["Proprietary", "Freeware", "Shareware", "Open Source", "Trial"], a:3, lvl:"sulit"},
 {m:"Pengantar Informatika", q:"Sebuah instansi mengalami kebocoran data pelanggan akibat serangan siber, dan manajemen ingin merekrut seseorang untuk merancang sistem pertahanan serta menganalisis celah keamanan secara berkelanjutan. Profesi yang paling tepat direkrut adalah...", o:["UI/UX Designer", "Data Analyst", "Cyber Security Specialist", "Cloud Engineer", "Game Developer"], a:2, lvl:"sulit"},
 {m:"Sistem Komputer", q:"Saat sebuah kalkulator menjumlahkan dua angka, komponen CPU yang secara langsung memproses operasi hitung tersebut adalah...", o:["Control Unit", "ALU", "Register", "Memori Utama", "Bus data"], a:1, lvl:"mudah"},
 {m:"Sistem Komputer", q:"Seorang teknisi menjelaskan bahwa pada komputer modern, program dan data yang diolahnya sama-sama disimpan di lokasi memori yang sama sehingga CPU dapat mengaksesnya secara fleksibel. Prinsip yang dijelaskan teknisi tersebut adalah...", o:["Bottleneck", "Stored program concept", "Fetch cycle", "Cache memory", "Virtual memory"], a:1, lvl:"sedang"},
 {m:"Sistem Komputer", q:"Saat listrik padam mendadak tanpa sempat menyimpan pekerjaan, dokumen yang sedang dikerjakan di komputer hilang total. Jenis penyimpanan yang menjelaskan mengapa hal ini terjadi adalah...", o:["HDD", "SSD", "RAM", "Flashdisk", "CD-ROM"], a:2, lvl:"sedang"},
 {m:"Sistem Komputer", q:"Seorang siswa mengamati bahwa CPU selalu mengambil instruksi dari memori terlebih dahulu, menerjemahkannya, baru menjalankannya, secara berulang jutaan kali per detik. Urutan tahapan yang sedang diamati siswa tersebut adalah...", o:["Execute-Fetch-Decode", "Decode-Fetch-Execute", "Fetch-Decode-Execute", "Fetch-Execute-Decode", "Execute-Decode-Fetch"], a:2, lvl:"sulit"},
 {m:"Sistem Operasi &amp; File", q:"Ketika laptop menjalankan Word, browser, dan pemutar musik secara bersamaan tanpa saling mengganggu, fungsi sistem operasi yang sedang bekerja adalah...", o:["Manajemen memori", "Manajemen proses", "Manajemen file", "User interface", "Manajemen perangkat"], a:1, lvl:"mudah"},
 {m:"Sistem Operasi &amp; File", q:"Seorang siswa kehilangan laptopnya, namun tetap dapat membuka seluruh tugasnya dari HP karena filenya otomatis tersinkronisasi ke sebuah layanan. Layanan yang dimaksud adalah...", o:["Hard disk internal", "Flashdisk", "Cloud storage", "Memory card", "CD-ROM"], a:2, lvl:"sedang"},
 {m:"Sistem Operasi &amp; File", q:"Seorang guru meminta tugas dikumpulkan dalam format yang dapat dibuka dan diedit ulang di Microsoft Word versi terbaru tanpa kehilangan format aslinya. Ekstensi file yang paling tepat diminta adalah...", o:[".txt", ".pdf", ".docx", ".jpg", ".exe"], a:2, lvl:"sedang"},
 {m:"Sistem Operasi &amp; File", q:"Sebuah pabrik smartphone menginginkan sistem operasi yang bersifat open source, ringan, dan dapat dimodifikasi bebas oleh berbagai produsen di dunia. Sistem operasi yang paling sesuai kebutuhan tersebut adalah...", o:["iOS", "Windows", "Android", "Chrome OS", "macOS"], a:2, lvl:"sulit"},
 {m:"Jaringan &amp; Keamanan", q:"Sebuah laboratorium komputer sekolah menghubungkan 20 unit komputer dalam satu ruangan menggunakan satu switch. Jenis jaringan yang diterapkan adalah...", o:["WAN", "MAN", "LAN", "PAN", "Internet"], a:2, lvl:"mudah"},
 {m:"Jaringan &amp; Keamanan", q:"Saat mengetikkan alamat sebuah situs di peramban, komputer perlu mengetahui alamat IP server tujuan sebelum dapat terhubung. Sistem yang menerjemahkan nama domain menjadi alamat IP tersebut adalah...", o:["HTTP", "DNS", "FTP", "ISP", "TCP"], a:1, lvl:"sedang"},
 {m:"Jaringan &amp; Keamanan", q:"Seorang siswa menerima pesan yang mengaku dari bank, meminta segera mengklik tautan dan memasukkan PIN karena akunnya \"akan diblokir\". Tindakan siber yang sedang dialami siswa tersebut adalah...", o:["Malware", "DDoS", "Phishing", "Firewall", "Enkripsi"], a:2, lvl:"sedang"},
 {m:"Jaringan &amp; Keamanan", q:"Sebuah aplikasi perbankan mengubah seluruh data transaksi pengguna menjadi kode acak yang hanya bisa dibaca kembali dengan kunci tertentu sebelum dikirim melalui jaringan. Proses yang diterapkan aplikasi tersebut adalah...", o:["Kompresi", "Enkripsi", "Kalibrasi", "Sinkronisasi", "Virtualisasi"], a:1, lvl:"sulit"},
 {m:"Pencarian &amp; Kolaborasi", q:"Seorang siswa ingin hasil pencariannya hanya menampilkan artikel dari situs resmi kemdikbud.go.id. Operator pencarian yang paling tepat digunakan adalah...", o:["Tanda kutip", "Tanda minus", "site:", "filetype:", "OR"], a:2, lvl:"mudah"},
 {m:"Pencarian &amp; Kolaborasi", q:"Saat meminjam laptop teman untuk login akun pribadi sebentar, seorang siswa ingin memastikan riwayat pencarian dan kata sandinya tidak tersimpan di perangkat tersebut. Fitur peramban yang sebaiknya digunakan adalah...", o:["Mode offline", "Mode incognito", "Mode hemat data", "Mode baca", "Mode pengembang"], a:1, lvl:"sedang"},
 {m:"Pencarian &amp; Kolaborasi", q:"Sebuah kelompok mengerjakan proposal bersama di Google Docs, namun salah satu anggota tidak sengaja menghapus dua paragraf penting. Fitur yang paling tepat digunakan untuk mengembalikan paragraf tersebut adalah...", o:["Bookmark", "Version history", "Cache", "Mode incognito", "Filter pencarian"], a:1, lvl:"sedang"},
 {m:"Pencarian &amp; Kolaborasi", q:"Sebuah judul artikel yang sangat provokatif tersebar cepat di media sosial tanpa mencantumkan sumber data yang jelas, dan setelah ditelusuri ternyata isinya tidak sesuai fakta. Fenomena ini paling tepat disebut...", o:["Opini", "Hoaks", "Editorial", "Testimoni", "Riset ilmiah"], a:1, lvl:"sulit"},
 {m:"Pencarian &amp; Kolaborasi", q:"Tiga siswa ingin menyunting satu dokumen laporan secara bersamaan dari rumah masing-masing pada waktu yang sama. Aplikasi pengolah kata yang paling sesuai untuk kebutuhan tersebut adalah...", o:["Microsoft Word (offline)", "Google Docs", "Notepad", "WordPad", "Adobe Reader"], a:1, lvl:"mudah"},
 {m:"Pengolah Kata Dasar", q:"Sebuah dokumen resmi mengharuskan seluruh paragraf terlihat rapi dengan sisi kiri dan kanan sama-sama lurus, tidak bergerigi. Pengaturan perataan yang perlu diterapkan adalah...", o:["Align Left", "Center", "Align Right", "Justify", "Indent"], a:3, lvl:"sedang"},
 {m:"Pengolah Kata Dasar", q:"Dalam dokumen sepanjang 50 halaman, seorang siswa perlu segera menemukan seluruh kemunculan kata \"revisi\" tanpa membaca ulang seluruh dokumen. Cara tercepat adalah menggunakan...", o:["Ctrl+S", "Ctrl+P", "Ctrl+F", "Ctrl+Z", "Ctrl+Y"], a:2, lvl:"sedang"},
 {m:"Pengolah Kata Dasar", q:"Seorang penulis menyadari ia salah mengeja nama tokoh di 40 tempat berbeda sepanjang naskah novelnya, dan ingin memperbaikinya sekaligus tanpa mencari satu per satu secara manual. Fitur paling efisien untuk kebutuhan tersebut adalah...", o:["Copy-Paste", "Find &amp; Replace", "Cut-Paste", "Undo-Redo", "Spell Check"], a:1, lvl:"sulit"},
 {m:"Fitur Lanjut Pengolah Kata", q:"Agar seluruh judul bab pada laporan dapat langsung dikenali sistem dan disusun otomatis menjadi daftar isi, judul-judul tersebut perlu diberi format...", o:["Normal", "Heading", "Caption", "Watermark", "Footnote"], a:1, lvl:"mudah"},
 {m:"Fitur Lanjut Pengolah Kata", q:"Panitia sebuah acara perlu mengirim 200 undangan dengan nama dan alamat penerima berbeda-beda, namun format suratnya identik. Fitur paling efisien untuk kebutuhan ini adalah...", o:["Table of Contents", "Mail Merge", "Cross-reference", "Citation", "Track Changes"], a:1, lvl:"sedang"},
 {m:"Fitur Lanjut Pengolah Kata", q:"Setelah menambahkan tiga subbab baru di tengah laporan, seorang siswa ingin daftar isi dan nomor halamannya diperbarui otomatis tanpa mengetik ulang. Hal ini dimungkinkan karena daftar isi otomatis dibangun berdasarkan...", o:["Warna teks", "Style Heading", "Ukuran font", "Jenis huruf", "Nomor halaman manual"], a:1, lvl:"sedang"},
 {m:"Fitur Lanjut Pengolah Kata", q:"Sebuah laporan berisi banyak gambar dan tabel yang perlu diberi keterangan bernomor otomatis seperti \"Gambar 1.1\" agar mudah dirujuk di dalam teks. Fitur yang tepat digunakan adalah...", o:["Watermark", "Caption", "Header", "Footer", "Page Break"], a:1, lvl:"sulit"},
 {m:"Integrasi Dokumen", q:"Sebuah laporan PKL perlu memakai angka romawi (i, ii, iii) untuk halaman kata pengantar dan angka biasa (1, 2, 3) untuk bab isi, dalam satu dokumen yang sama. Fitur yang memungkinkan dua format nomor halaman berbeda ini adalah...", o:["Page Number saja", "Section Break", "Column Break", "Mail Merge", "Caption"], a:1, lvl:"mudah"},
 {m:"Fitur Lanjut Pengolah Kata", q:"Seorang siswa merancang formulir biodata (nama, NIS, kelas) yang perlu terlihat rapi dan sejajar, namun tidak boleh menampilkan garis kotak apa pun saat dicetak. Teknik paling efisien untuk kebutuhan ini adalah...", o:["Tab manual berulang", "Spasi berulang", "Tabel dengan border disembunyikan (No Border)", "Bullet list", "Drop cap"], a:2, lvl:"sedang"},
 {m:"Integrasi Dokumen", q:"Sekolah menetapkan seluruh Laporan PKL siswa harus dicetak menggunakan ukuran kertas yang sedikit lebih panjang dari A4 sesuai pedoman resmi laporan dinas. Ukuran kertas yang dimaksud adalah...", o:["A4", "Letter", "F4", "Legal", "B5"], a:2, lvl:"mudah"},
 {m:"Integrasi Dokumen", q:"Seorang siswa menyusun Laporan PKL dan bingung di bagian mana sebaiknya menuliskan kesimpulan hasil pelaksanaan serta saran untuk perusahaan. Berdasarkan sistematika umum laporan, bagian yang tepat adalah...", o:["BAB I", "BAB II", "BAB III", "BAB IV", "Bagian Akhir"], a:3, lvl:"sedang"},
 {m:"Fitur Lanjut Pengolah Kata", q:"Sebuah laporan organisasi perlu menampilkan hierarki jabatan dari Ketua hingga Anggota secara visual dan mudah dipahami tanpa harus menuliskan penjelasan panjang. Fitur yang paling tepat digunakan adalah...", o:["Grafik data penjualan", "SmartArt bagan struktur organisasi", "Daftar pustaka", "Nomor halaman", "Watermark"], a:1, lvl:"sulit"},
 {m:"Integrasi Dokumen", q:"Sebuah karya tulis mengutip lima orang penulis sekaligus dari satu sumber jurnal, dan siswa ingin menuliskan sitasinya secara ringkas sesuai kaidah tanpa menyebutkan seluruh nama. Format sitasi yang tepat adalah...", o:["Menuliskan nama lengkap seluruh penulis", "Nama penulis pertama diikuti \"dkk.\"", "Hanya mencantumkan tahun", "Nama penulis terakhir saja", "Tanpa nama, hanya judul"], a:1, lvl:"sulit"},
];

var TYPING = [
 {m:'Fitur Lanjut Pengolah Kata', t:'STYLE DAN HEADING', instr:'Ketik judul berikut, lalu jadikan Bold dan rata Tengah.', fmt:['bold','center']},
 {m:'Fitur Lanjut Pengolah Kata', t:'Heading menandai struktur dan hierarki dokumen secara konsisten.', instr:'Ketik kalimat berikut, lalu jadikan huruf miring (Italic).', fmt:['italic']},
 {m:'Fitur Lanjut Pengolah Kata', t:'Update Table memperbarui daftar isi otomatis tanpa mengetik ulang.', instr:'Ketik kalimat berikut, lalu garis bawahi (Underline) seluruhnya.', fmt:['underline']},
 {m:'Fitur Lanjut Pengolah Kata', t:'Menyisipkan tabel\nMengatur text wrapping gambar\nMenambahkan caption otomatis', instr:'Ketik ketiga baris berikut sebagai daftar bertitik (Bullet List).', fmt:['ul'], multiline:true},
 {m:'Fitur Lanjut Pengolah Kata', t:'Buat dokumen utama\nSiapkan sumber data\nGabungkan dengan mail merge', instr:'Ketik ketiga baris berikut sebagai daftar bernomor (Numbered List).', fmt:['ol'], multiline:true},
 {m:'Integrasi Dokumen', t:'Jakarta, 8 September 2026', instr:'Ketik naskah berikut, lalu buat rata kanan (Align Right), seperti penulisan tanggal surat.', fmt:['right']},
 {m:'Fitur Lanjut Pengolah Kata', t:'Daftar pustaka disusun otomatis dari seluruh sitasi yang sudah dimasukkan ke dalam dokumen.', instr:'Ketik kalimat berikut, lalu ratakan kiri-kanan (Justify).', fmt:['justify']},
 {m:'Fitur Lanjut Pengolah Kata', t:'DAFTAR PUSTAKA', instr:'Ketik judul berikut, blok seluruh teksnya, lalu jadikan Bold dan pilih ukuran huruf 16 pt pada menu Ukuran Huruf.', fmt:['bold','size:16']},
 {m:'Integrasi Dokumen', t:'Section break memisahkan format nomor halaman romawi dan angka arab.', instr:'Ketik kalimat berikut, blok seluruh teksnya, lalu pilih jenis huruf Times New Roman dan ukuran huruf 12 pt pada menu yang tersedia.', fmt:['font:Times New Roman','size:12']},
 {m:'Fitur Lanjut Pengolah Kata', t:'SPELLING DAN AUTOCORRECT', instr:'Ketik judul berikut, lalu jadikan Bold, Underline, dan rata Tengah sekaligus.', fmt:['bold','underline','center']}
];
var FMT_LABELS = {bold:'Bold', italic:'Italic', underline:'Underline', center:'Rata Tengah', right:'Rata Kanan', justify:'Rata Kiri-Kanan', ul:'Bullet List', ol:'Numbered List', big:'Ukuran Besar', times:'Times New Roman'};
function fmtLabel(arr){ return (arr||[]).map(function(k){
  if(k.indexOf('size:')===0){ return 'Ukuran huruf '+k.slice(5)+' pt'; }
  if(k.indexOf('font:')===0){ return 'Jenis huruf '+k.slice(5); }
  return FMT_LABELS[k]||k; }).join(', '); }

var ESAI = [
 {m:"Sistem Komputer",
  q:"Sebuah komputer lama terasa sangat lambat meski menjalankan instruksi sederhana, karena data dan instruksi harus bergantian melalui jalur yang sama menuju satu memori. Jelaskan konsep arsitektur Von Neumann yang menjelaskan situasi ini beserta komponen utamanya!",
  g:[["von neumann", "neumann"], ["stored program", "program tersimpan", "instruksi dan data", "satu memori", "memori yang sama"], ["bus", "jalur"], ["cpu", "prosesor", "alu", "control unit", "unit kendali"], ["memori", "ram", "memory"], ["bottleneck", "kemacetan", "bergantian", "hambatan", "lambat", "antre"]]},
 {m:"Jaringan &amp; Keamanan",
  q:"Akun media sosial seorang siswa diretas setelah ia mengklik tautan hadiah palsu dan memakai kata sandi yang sama di semua akunnya. Jelaskan tiga langkah keamanan digital dasar yang seharusnya diterapkan untuk mencegah kejadian tersebut!",
  g:[["kata sandi", "password", "sandi"], ["unik", "berbeda", "kuat", "kombinasi", "panjang", "tidak sama"], ["autentikasi dua faktor", "2fa", "dua faktor", "otp", "verifikasi dua langkah"], ["phishing", "tautan", "link", "mencurigakan", "waspada", "tidak mengklik", "jangan klik"], ["backup", "cadangan", "antivirus", "firewall", "perbarui", "update", "enkripsi"], ["akun", "diretas", "peretasan", "data pribadi", "keamanan digital"]]},
 {m:"Pencarian &amp; Kolaborasi",
  q:"Seorang siswa mencari informasi tentang \"dampak AI\" namun hasil pencariannya penuh iklan dan artikel yang tidak relevan. Jelaskan cara kerja mesin pencari dan strategi yang bisa dilakukan siswa tersebut agar hasil pencarian lebih relevan!",
  g:[["crawling", "menjelajah", "spider", "bot"], ["indexing", "indeks", "mengindeks"], ["ranking", "peringkat", "mengurutkan", "urutan", "algoritma"], ["operator", "site:", "filetype", "tanda kutip", "tanda minus", "intitle"], ["kata kunci", "keyword", "spesifik"], ["relevan", "sesuai", "tepat", "tepercaya", "kredibel", "filter"]]},
 {m:"Fitur Lanjut Pengolah Kata",
  q:"Sebuah laporan 60 halaman kehilangan struktur karena seluruh judul bab hanya diberi format Bold manual tanpa Heading. Jelaskan mengapa hal ini menyulitkan pembuatan daftar isi otomatis dan bagaimana solusinya!",
  g:[["heading", "style", "gaya judul"], ["daftar isi", "table of contents"], ["otomatis", "langsung dibuat", "dibuat sendiri"], ["bold", "tebal", "manual", "tidak dikenali", "tidak terdeteksi", "hanya tampilan"], ["struktur", "hierarki", "level", "bab"], ["nomor halaman", "diperbarui", "update", "memperbarui", "navigasi", "rapi", "konsisten"]]},
 {m:"Integrasi Dokumen",
  q:"Laporan PKL seorang siswa menampilkan angka romawi di seluruh halaman termasuk bab isi, karena hanya satu jenis format nomor halaman diterapkan ke seluruh dokumen. Jelaskan mengapa section break diperlukan dan bagaimana cara kerjanya untuk mengatasi masalah ini!",
  g:[["section break", "section", "pemisah bagian"], ["nomor halaman", "penomoran"], ["romawi"], ["arab", "angka biasa", "1, 2, 3"], ["bagian", "terpisah", "memisahkan", "berbeda", "independen", "mandiri"], ["link to previous", "tautan", "format", "pengaturan", "mulai dari", "mulai lagi"]]}
];

/* ================= UTIL ================= */

function $(id){ return document.getElementById(id); }
function esc(s){ var d=document.createElement('div'); d.textContent=String(s); return d.innerHTML; }
function range(n){ var a=[],i; for(i=0;i&lt;n;i++){a.push(i);} return a; }
function shuffle(a){ var b=a.slice(),i,j,t; for(i=b.length-1;i&gt;0;i--){ j=Math.floor(Math.random()*(i+1)); t=b[i]; b[i]=b[j]; b[j]=t; } return b; }
function norm(s){ return String(s).replace(/\r/g,'').replace(/\s+/g,' ').trim(); }
function r1(x){ return Math.round(x*10)/10; }
function r2(x){ return Math.round(x*100)/100; }
function fmt(x){ return String(r1(x)).replace('.',','); }
function lev(a,b){
  var m=a.length, n=b.length, i, j, prev, cur, t, cost;
  if(m===0){ return n; } if(n===0){ return m; }
  prev=new Array(n+1); cur=new Array(n+1);
  for(j=0;j&lt;=n;j++){ prev[j]=j; }
  for(i=1;i&lt;=m;i++){
    cur[0]=i;
    for(j=1;j&lt;=n;j++){
      cost = a.charAt(i-1)===b.charAt(j-1) ? 0 : 1;
      cur[j] = Math.min(prev[j]+1, cur[j-1]+1, prev[j-1]+cost);
    }
    t=prev; prev=cur; cur=t;
  }
  return prev[n];
}
function editableText(el){
  var clone=el.cloneNode(true), i;
  var brs=clone.querySelectorAll('br');
  for(i=0;i&lt;brs.length;i++){ brs[i].parentNode.replaceChild(document.createTextNode('\n'), brs[i]); }
  var blocks=clone.querySelectorAll('li,div,p');
  for(i=0;i&lt;blocks.length;i++){ blocks[i].appendChild(document.createTextNode('\n')); }
  return clone.textContent;
}
function detectFormats(html){
  var f={};
  f.bold = /&lt;b[\s&gt;]|&lt;strong[\s&gt;]|font-weight:\s*(bold|[6-9]00)/i.test(html);
  f.italic = /&lt;i[\s&gt;]|&lt;em[\s&gt;]|font-style:\s*italic/i.test(html);
  f.underline = /&lt;u[\s&gt;]|text-decoration[^;"]*underline/i.test(html);
  f.center = /text-align:\s*center/i.test(html);
  f.right = /text-align:\s*right/i.test(html);
  f.justify = /text-align:\s*justify/i.test(html);
  f.ul = /&lt;ul[\s&gt;]/i.test(html);
  f.ol = /&lt;ol[\s&gt;]/i.test(html);
  f.big = /size=["']?[5-7]["']?|font-size:\s*(1[8-9]|[2-9][0-9])px|font-size:\s*x-?large/i.test(html);
  f.times = /times new roman/i.test(html);
  return f;
}
function detectSizes(html){
  var out=[], m, re;
  re=/font-size:\s*([0-9.]+)\s*(pt|px)/ig;
  while((m=re.exec(html))){ out.push(m[2].toLowerCase()==='px' ? parseFloat(m[1])*0.75 : parseFloat(m[1])); }
  re=/&lt;font[^&gt;]*\ssize=["']?([1-7])["']?/ig;
  var map={1:8,2:10,3:12,4:14,5:18,6:24,7:36};
  while((m=re.exec(html))){ out.push(map[m[1]]); }
  return out;
}
function hasFontName(html, name){
  var n=name.replace(/[.*+?^${}()|[\]\\]/g,'\\$&amp;');
  return new RegExp('(face=["\']?|font-family:\\s*(&amp;quot;|["\'])?)'+n, 'i').test(html);
}
function formatScoreRatio(required, html){
  if(!required || !required.length){ return 1; }
  var det=detectFormats(html), sizes=detectSizes(html), hit=0, i, k, ok, j;
  for(i=0;i&lt;required.length;i++){
    k=required[i]; ok=false;
    if(k.indexOf('size:')===0){
      var want=parseFloat(k.slice(5));
      for(j=0;j&lt;sizes.length;j++){ if(Math.abs(sizes[j]-want)&lt;0.5){ ok=true; break; } }
    } else if(k.indexOf('font:')===0){
      ok=hasFontName(html, k.slice(5));
    } else { ok=!!det[k]; }
    if(ok){ hit++; }
  }
  return hit/required.length;
}
function placeCaretAtEnd(el){
  el.focus();
  if(window.getSelection &amp;&amp; document.createRange){
    var range=document.createRange();
    range.selectNodeContents(el);
    range.collapse(false);
    var sel=window.getSelection();
    sel.removeAllRanges();
    sel.addRange(range);
  }
}
function similarity(ref, typed){
  var r=norm(ref), t=norm(typed);
  if(r.length===0){ return 100; }
  var d=lev(r,t), mx=Math.max(r.length,t.length);
  return Math.max(0, Math.round((1 - d/mx)*1000)/10);
}
function kwMatch(text, k){
  if(k.length&lt;=4){
    var re=new RegExp('(^|[^a-z0-9])'+k.replace(/[.*+?^${}()|[\]\\]/g,'\\$&amp;')+'($|[^a-z0-9])');
    return re.test(text);
  }
  return text.indexOf(k)!==-1;
}
function scoreEssay(idx, answer){
  var t=norm(answer).toLowerCase();
  var groups=ESAI[idx].g, matched=0;
  if(t.length&lt;40){ return {matched:0,total:groups.length,score:0}; }
  groups.forEach(function(g){
    var hit=false, i;
    for(i=0;i&lt;g.length;i++){ if(kwMatch(t,g[i])){ hit=true; break; } }
    if(hit){ matched++; }
  });
  var need=Math.ceil(groups.length*0.7);
  var ratio=Math.min(1, matched/need);
  return {matched:matched,total:groups.length,score:r2(ratio*PT_ESAI)};
}

/* ================= PENYIMPANAN PERCOBAAN ================= */

var memStore={};
function keyOf(kelas, absen){ return 'uts_inf_x|'+EXAM_VERSION+'|'+kelas+'|'+absen; }
function loadState(key){
  var s=null;
  try{ s=localStorage.getItem(key); }catch(e){}
  if(s){ try{ return JSON.parse(s); }catch(e2){} }
  return memStore[key] || {attempts:[], best:null, sent:false, sentValue:null};
}
function saveState(key, st){
  memStore[key]=st;
  try{ localStorage.setItem(key, JSON.stringify(st)); }catch(e){}
}

/* ================= STATE SESI ================= */

var ID=null, STATE=null, CUR=null;

/* ================= TAMPILAN ================= */

function show(which){
  $('screenStart').classList.toggle('hidden', which!=='start');
  $('screenExam').classList.toggle('hidden', which!=='exam');
  $('screenResult').classList.toggle('hidden', which!=='result');
  window.scrollTo(0,0);
}
function setMsg(el, text){
  if(text){ el.textContent=text; el.classList.add('show'); } else { el.classList.remove('show'); el.textContent=''; }
}

function buildExam(){
  var pg = shuffle(range(PG.length)).map(function(i){ return {i:i, order:shuffle([0,1,2,3,4])}; });
  var ty = shuffle(range(TYPING.length));
  return {pg:pg, ty:ty};
}

function renderExam(){
  var A=$('bodyA'), B=$('bodyB'), C=$('bodyC'), html='';
  CUR.exam.pg.forEach(function(item, n){
    var q=PG[item.i];
    html += '&lt;div class="q" id="qa'+n+'"&gt;&lt;div class="q-top"&gt;&lt;span class="q-no"&gt;Soal '+(n+1)+' dari 35&lt;/span&gt;&lt;span class="q-tag"&gt;'+esc(q.m)+'&lt;/span&gt;&lt;/div&gt;';
    html += '&lt;p class="q-text"&gt;'+esc(q.q)+'&lt;/p&gt;';
    item.order.forEach(function(oi, pos){
      html += '&lt;label class="opt"&gt;&lt;input type="radio" name="pg'+n+'" value="'+oi+'"&gt;&lt;span class="lt"&gt;'+String.fromCharCode(65+pos)+'.&lt;/span&gt;&lt;span&gt;'+esc(q.o[oi])+'&lt;/span&gt;&lt;/label&gt;';
    });
    html += '&lt;/div&gt;';
  });
  A.innerHTML=html;

  html='';
  CUR.exam.ty.forEach(function(ti, n){
    var t=TYPING[ti];
    var refDisplay = t.multiline ? esc(t.t).replace(/\n/g,'&lt;br&gt;') : esc(t.t);
    var refLen = t.t.replace(/\n/g,' ').length;
    html += '&lt;div class="q b" id="qb'+n+'"&gt;&lt;div class="q-top"&gt;&lt;span class="q-no"&gt;Soal '+(n+1)+' dari 10&lt;/span&gt;&lt;span class="q-tag"&gt;'+esc(t.m)+'&lt;/span&gt;&lt;/div&gt;';
    html += '&lt;p class="fmt-instr"&gt;'+esc(t.instr)+'&lt;/p&gt;';
    html += '&lt;div class="ref-label"&gt;NASKAH (TIDAK BISA DISALIN)&lt;/div&gt;';
    html += '&lt;div class="ref" id="ref'+n+'"&gt;'+refDisplay+'&lt;/div&gt;';
    html += '&lt;div class="type-editable" id="ty'+n+'" data-n="'+n+'" contenteditable="true" spellcheck="false"&gt;&lt;/div&gt;';
    html += '&lt;div class="cnt"&gt;&lt;span id="tyc'+n+'"&gt;0 / '+refLen+' karakter - format wajib: '+esc(fmtLabel(t.fmt))+'&lt;/span&gt;&lt;span class="warn" id="tyw'+n+'"&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;';
  });
  B.innerHTML=html;

  html='';
  ESAI.forEach(function(e, n){
    html += '&lt;div class="q c" id="qc'+n+'"&gt;&lt;div class="q-top"&gt;&lt;span class="q-no"&gt;Soal '+(n+1)+' dari 5&lt;/span&gt;&lt;span class="q-tag"&gt;'+esc(e.m)+'&lt;/span&gt;&lt;/div&gt;';
    html += '&lt;p class="q-text"&gt;'+esc(e.q)+'&lt;/p&gt;';
    html += '&lt;textarea id="es'+n+'" data-n="'+n+'" style="min-height:130px;" placeholder="Ketik jawabanmu di sini (minimal 40 karakter)..." autocomplete="off" spellcheck="false"&gt;&lt;/textarea&gt;';
    html += '&lt;div class="cnt"&gt;&lt;span id="esc'+n+'"&gt;0 karakter&lt;/span&gt;&lt;span class="warn" id="esw'+n+'"&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;';
  });
  C.innerHTML=html;

  bindExamEvents();
  updateProgress();
}

function flashWarn(id, text){
  var el=$(id); if(!el){ return; }
  el.textContent=text;
  setTimeout(function(){ if(el.textContent===text){ el.textContent=''; } }, 2600);
}

function guardTextarea(ta, warnId){
  var last='';
  var block=function(e){ e.preventDefault(); CUR.paste++; flashWarn(warnId, 'Tempel (paste) dinonaktifkan - ketik manual.'); };
  ta.addEventListener('paste', block);
  ta.addEventListener('drop', block);
  ta.addEventListener('contextmenu', function(e){ e.preventDefault(); });
  ta.addEventListener('beforeinput', function(e){
    var t=e.inputType||'';
    if(t==='insertFromPaste' || t==='insertFromDrop' || t==='insertFromPasteAsQuotation' || t==='insertFromYank'){ block(e); }
  });
  ta.addEventListener('input', function(){
    var v=ta.value;
    if(v.length - last.length &gt; 30){
      ta.value=last; CUR.paste++;
      flashWarn(warnId, 'Teks yang masuk sekaligus ditolak - ketik manual.');
    } else { last=v; }
  });
}

var activeEditable=null;
function guardEditable(el, warnId){
  el.__lastHtml='';
  var lastLen=0;
  el.addEventListener('paste', function(e){ e.preventDefault(); CUR.paste++; flashWarn(warnId, 'Tempel (paste) dinonaktifkan - ketik manual.'); });
  el.addEventListener('drop', function(e){ e.preventDefault(); CUR.paste++; flashWarn(warnId, 'Seret-lepas teks dinonaktifkan - ketik manual.'); });
  el.addEventListener('contextmenu', function(e){ e.preventDefault(); });
  el.addEventListener('focus', function(){ activeEditable=el; });
  el.addEventListener('input', function(){
    var len=el.textContent.length;
    if(len - lastLen &gt; 30){
      el.innerHTML = el.__lastHtml || '';
      CUR.paste++;
      flashWarn(warnId, 'Teks yang masuk sekaligus ditolak - ketik manual.');
      placeCaretAtEnd(el);
    } else {
      el.__lastHtml = el.innerHTML;
    }
    lastLen = el.textContent.length;
  });
}
var savedRange=null;
function trackSelection(){
  document.addEventListener('selectionchange', function(){
    if(!activeEditable){ return; }
    var sel=window.getSelection();
    if(sel &amp;&amp; sel.rangeCount&gt;0){
      var r=sel.getRangeAt(0);
      if(activeEditable.contains(r.commonAncestorContainer)){ savedRange=r.cloneRange(); }
    }
  });
}
function restoreSelection(){
  if(!activeEditable){ return false; }
  activeEditable.focus();
  if(savedRange &amp;&amp; activeEditable.contains(savedRange.commonAncestorContainer)){
    var sel=window.getSelection();
    sel.removeAllRanges();
    sel.addRange(savedRange);
  }
  return true;
}
function applyFontSizePt(pt){
  if(!restoreSelection()){ return; }
  try{ document.execCommand('styleWithCSS', false, false); }catch(e0){}
  try{ document.execCommand('fontSize', false, '7'); }catch(e){}
  var fonts=activeEditable.querySelectorAll('font[size="7"]'), i, sp;
  for(i=0;i&lt;fonts.length;i++){
    sp=document.createElement('span');
    sp.style.fontSize=pt+'pt';
    while(fonts[i].firstChild){ sp.appendChild(fonts[i].firstChild); }
    fonts[i].parentNode.replaceChild(sp, fonts[i]);
  }
  var spans=activeEditable.querySelectorAll('span[style*="xxx-large"]');
  for(i=0;i&lt;spans.length;i++){ spans[i].style.fontSize=pt+'pt'; }
}
function bindFormatToolbar(){
  var toolbar=$('fmtToolbar');
  if(!toolbar || toolbar.__bound){ return; }
  toolbar.__bound=true;
  trackSelection();
  var btns=toolbar.querySelectorAll('.fmt-btn'), i;
  for(i=0;i&lt;btns.length;i++){
    btns[i].addEventListener('mousedown', function(e){ e.preventDefault(); });
    btns[i].addEventListener('click', function(){
      if(!activeEditable){ return; }
      restoreSelection();
      try{ document.execCommand(this.getAttribute('data-cmd'), false, null); }catch(e){}
      activeEditable.dispatchEvent(new Event('input', {bubbles:true}));
    });
  }
  /* Dropdown TIDAK boleh memakai preventDefault pada mousedown (menyebabkan daftar tidak bisa dibuka). */
  $('fmtSize').addEventListener('change', function(){
    var v=parseFloat(this.value);
    if(!activeEditable){ alert('Klik di dalam kotak jawaban dulu, blok teks yang ingin diubah, lalu pilih ukuran huruf.'); this.value=''; return; }
    if(v&gt;0){ applyFontSizePt(v); activeEditable.dispatchEvent(new Event('input', {bubbles:true})); }
    this.value='';
  });
  $('fmtFont').addEventListener('change', function(){
    var v=this.value;
    if(!activeEditable){ alert('Klik di dalam kotak jawaban dulu, blok teks yang ingin diubah, lalu pilih jenis huruf.'); this.value=''; return; }
    if(v){
      restoreSelection();
      try{ document.execCommand('styleWithCSS', false, false); }catch(e0){}
      try{ document.execCommand('fontName', false, v); }catch(e){}
      activeEditable.dispatchEvent(new Event('input', {bubbles:true}));
    }
    this.value='';
  });
}

function bindExamEvents(){
  var n;
  CUR.exam.pg.forEach(function(_, i){
    var radios=document.getElementsByName('pg'+i), k;
    for(k=0;k&lt;radios.length;k++){
      radios[k].addEventListener('change', function(){
        var group=document.getElementsByName(this.name), z;
        for(z=0;z&lt;group.length;z++){ group[z].parentNode.classList.remove('sel'); }
        this.parentNode.classList.add('sel');
        $('qa'+i).classList.remove('missing');
        updateProgress();
      });
    }
  });
  CUR.exam.ty.forEach(function(ti, i){
    var el=$('ty'+i);
    guardEditable(el, 'tyw'+i);
    el.addEventListener('input', function(){
      var len=editableText(el).replace(/\n/g,' ').trim().length;
      var refLen=TYPING[ti].t.replace(/\n/g,' ').length;
      $('tyc'+i).textContent = len+' / '+refLen+' karakter - format wajib: '+fmtLabel(TYPING[ti].fmt);
      $('qb'+i).classList.remove('missing');
      updateProgress();
    });
    var ref=$('ref'+i);
    ['copy','cut','contextmenu','dragstart','selectstart'].forEach(function(ev){
      ref.addEventListener(ev, function(e){ e.preventDefault(); });
    });
  });
  bindFormatToolbar();
  ESAI.forEach(function(_, i){
    var ta=$('es'+i);
    guardTextarea(ta, 'esw'+i);
    ta.addEventListener('input', function(){
      $('esc'+i).textContent = ta.value.length+' karakter';
      $('qc'+i).classList.remove('missing');
      updateProgress();
    });
  });
}

function countAnswered(){
  var a=0, b=0, c=0, i;
  for(i=0;i&lt;PG.length;i++){ if(document.querySelector('input[name="pg'+i+'"]:checked')){ a++; } }
  for(i=0;i&lt;TYPING.length;i++){ if(editableText($('ty'+i)).replace(/\n/g,' ').trim().length&gt;=5){ b++; } }
  for(i=0;i&lt;ESAI.length;i++){ if($('es'+i).value.trim().length&gt;=40){ c++; } }
  return {a:a,b:b,c:c,all:a+b+c};
}
function updateProgress(){
  var c=countAnswered();
  $('pcount').textContent = c.all+' / '+TOTAL_Q+' terjawab';
  $('pbarFill').style.width = (c.all/TOTAL_Q*100)+'%';
}

/* ================= ALUR UJIAN ================= */

function attemptsLabel(){ return 'Percobaan ke-'+(STATE.attempts.length+1)+' dari '+MAX_ATT; }

function populateAbsenOptions(){
  var kelas=$('fKelas').value;
  var sel=$('fAbsen');
  sel.innerHTML='';
  $('fNama').value='';
  if(!kelas || !ROSTER[kelas]){
    sel.disabled=true;
    sel.innerHTML='&lt;option value=""&gt;- Pilih kelas dulu -&lt;/option&gt;';
    return;
  }
  sel.disabled=false;
  var opt0=document.createElement('option');
  opt0.value=''; opt0.textContent='- Pilih No. Absen -'; opt0.disabled=true; opt0.selected=true;
  sel.appendChild(opt0);
  ROSTER[kelas].forEach(function(pair){
    var o=document.createElement('option');
    o.value=String(pair[0]); o.textContent=pair[0]+' - '+pair[1];
    sel.appendChild(o);
  });
}
function populateNamaFromRoster(){
  var kelas=$('fKelas').value, absen=$('fAbsen').value, nama='', i, list;
  if(kelas &amp;&amp; absen &amp;&amp; ROSTER[kelas]){
    list=ROSTER[kelas];
    for(i=0;i&lt;list.length;i++){ if(String(list[i][0])===String(absen)){ nama=list[i][1]; break; } }
  }
  $('fNama').value=nama;
}
function initDeadlineNotice(){
  var opts={day:'numeric', month:'long', year:'numeric', hour:'2-digit', minute:'2-digit'};
  var openStr=EXAM_OPEN.toLocaleString('id-ID', opts);
  var closeStr=EXAM_DEADLINE.toLocaleString('id-ID', opts);
  var el=$('deadlineNotice');
  if(el){ el.innerHTML='Ujian dibuka mulai &lt;b&gt;'+openStr+'&lt;/b&gt; dan wajib diselesaikan sebelum &lt;b&gt;'+closeStr+'&lt;/b&gt; ('+DEADLINE_DAYS+' hari sejak dibuka). &lt;b&gt;Jika belum mengerjakan sama sekali setelah batas waktu berakhir, nilai yang tercatat otomatis 0.&lt;/b&gt;'; }
}

function startAttempt(){
  CUR={exam:buildExam(), paste:0, start:Date.now()};
  $('whoLbl').textContent = ID.nama+' - '+ID.kelas+' / No. '+ID.absen;
  $('attLbl').textContent = attemptsLabel();
  setMsg($('examErr'), '');
  $('btnSubmit').disabled=false;
  $('btnSubmit').textContent='Kirim Jawaban';
  renderExam();
  show('exam');
}

function onStart(){
  var kelas=$('fKelas').value, absen=$('fAbsen').value, nama=$('fNama').value.trim(), token=$('fToken').value.trim();
  setMsg($('startErr'), '');
  if(!kelas){ setMsg($('startErr'), 'Pilih Kelas terlebih dahulu.'); return; }
  if(!absen){ setMsg($('startErr'), 'Pilih No. Absen terlebih dahulu.'); return; }
  if(!nama){ setMsg($('startErr'), 'Nama tidak ditemukan untuk No. Absen ini. Hubungi guru.'); return; }
  if(!token){ setMsg($('startErr'), 'Masukkan Token Kelas yang diberikan guru.'); return; }
  if(!CLASS_TOKENS[kelas] || token.toUpperCase()!==CLASS_TOKENS[kelas].toUpperCase()){
    setMsg($('startErr'), 'Token Kelas salah. Minta token yang benar kepada guru.');
    return;
  }
  ID={absen:String(parseInt(absen,10)), nama:nama, kelas:kelas};
  ID.key=keyOf(ID.kelas, ID.absen);
  STATE=loadState(ID.key);
  STATE.nama=nama;

  if(!STATE.sent &amp;&amp; Date.now()&gt;EXAM_DEADLINE.getTime()){
    var val = STATE.best ? STATE.best.total : 0;
    if(!STATE.best){
      STATE.best={total:0, pg:0, type:0, esai:0, waktu:new Date().toISOString(), paste:0, no:0, detail:{pg:[],ty:[],es:[]}};
    }
    STATE.sent=true; STATE.sentValue=val;
    saveState(ID.key, STATE);
    sendScore(val);
    showResult(true, true);
    return;
  }

  if(STATE.sent || STATE.attempts.length&gt;=MAX_ATT){
    saveState(ID.key, STATE);
    showResult(false);
    return;
  }
  saveState(ID.key, STATE);
  startAttempt();
}

function collect(){
  var pg=[], ty=[], es=[], i, sPG=0, sTY=0, sES=0;
  CUR.exam.pg.forEach(function(item, n){
    var q=PG[item.i];
    var chosen=document.querySelector('input[name="pg'+n+'"]:checked');
    var val=parseInt(chosen.value,10);
    var ok=(val===q.a);
    if(ok){ sPG+=PT_PG; }
    pg.push({n:n+1, chosen:q.o[val], ok:ok});
  });
  CUR.exam.ty.forEach(function(ti, n){
    var el=$('ty'+n);
    var html=el.innerHTML;
    var typedText=editableText(el).replace(/\n/g,' ');
    var refText=TYPING[ti].t.replace(/\n/g,' ');
    var sim=similarity(refText, typedText);
    var fmtRatio=formatScoreRatio(TYPING[ti].fmt, html);
    var sc=r2((sim/100*0.7 + fmtRatio*0.3) * PT_TYPE);
    sTY+=sc;
    ty.push({n:n+1, typed:norm(typedText), sim:sim, fmtRatio:Math.round(fmtRatio*100), fmtLabel:fmtLabel(TYPING[ti].fmt), instr:TYPING[ti].instr, score:sc});
  });
  ESAI.forEach(function(e, n){
    var ans=$('es'+n).value;
    var r=scoreEssay(n, ans);
    sES+=r.score;
    es.push({n:n+1, q:e.q, answer:norm(ans), score:r.score, matched:r.matched, total:r.total});
  });
  sPG=r2(sPG); sTY=r2(sTY); sES=r2(sES);
  var total=Math.round(Math.min(100, sPG+sTY+sES));
  return {pg:sPG, type:sTY, esai:sES, total:total, waktu:new Date().toISOString(), paste:CUR.paste, detail:{pg:pg, ty:ty, es:es}};
}

function onSubmit(){
  setMsg($('examErr'), '');
  var c=countAnswered(), i, first=null, miss=[];
  for(i=0;i&lt;PG.length;i++){ if(!document.querySelector('input[name="pg'+i+'"]:checked')){ miss.push('A'+(i+1)); if(!first){first=$('qa'+i);} $('qa'+i).classList.add('missing'); } }
  for(i=0;i&lt;TYPING.length;i++){ if(editableText($('ty'+i)).replace(/\n/g,' ').trim().length&lt;5){ miss.push('B'+(i+1)); if(!first){first=$('qb'+i);} $('qb'+i).classList.add('missing'); } }
  for(i=0;i&lt;ESAI.length;i++){ if($('es'+i).value.trim().length&lt;40){ miss.push('C'+(i+1)); if(!first){first=$('qc'+i);} $('qc'+i).classList.add('missing'); } }
  if(miss.length){
    setMsg($('examErr'), 'Masih ada '+miss.length+' soal yang belum lengkap ('+miss.slice(0,12).join(', ')+(miss.length&gt;12?', ...':'')+'). Pilihan ganda wajib dijawab, soal mengetik wajib diisi dan diformat sesuai instruksi, esai minimal 40 karakter.');
    if(first){ first.scrollIntoView({behavior:'smooth', block:'center'}); }
    return;
  }
  $('btnSubmit').disabled=true;
  $('btnSubmit').textContent='Memproses...';

  var res=collect();
  res.no=STATE.attempts.length+1;
  STATE.attempts.push({no:res.no, total:res.total, pg:res.pg, type:res.type, esai:res.esai, waktu:res.waktu});
  if(!STATE.best || res.total&gt;STATE.best.total){ STATE.best=res; }

  var justSent=false;
  if(res.total&gt;=KKM){
    STATE.sent=true; STATE.sentValue=res.total; justSent=true;
  } else if(STATE.attempts.length&gt;=MAX_ATT){
    STATE.sent=true; STATE.sentValue=STATE.best.total; justSent=true;
  }
  saveState(ID.key, STATE);
  if(justSent){ sendScore(STATE.sentValue); }
  showResult(justSent);
}

function sendScore(value){
  $('gAbsen').value=ID.absen;
  $('gNama').value=ID.nama;
  $('gKelas').value=ID.kelas;
  $('gNilai').value=value;
  $('gSkor').value=value;
  $('gNilaiSTS').value=value;
  $('gJudul').value=JUDUL;
  $('gform').submit();
}

function showResult(justSent, isLate){
  var best=STATE.best;
  var att=STATE.attempts.length;
  var left=MAX_ATT-att;
  var last=STATE.attempts[att-1];
  var shown=best ? best.total : 0;
  var reached = best &amp;&amp; best.total&gt;=KKM;

  $('rVal').textContent = shown;
  $('ring').style.setProperty('--p', shown);
  $('ring').style.setProperty('--ringc', reached ? '#15803d' : '#d97706');

  var pill=$('rPill');
  if(isLate){
    pill.textContent='WAKTU HABIS - NILAI OTOMATIS TERCATAT';
    pill.className='status-pill no';
  } else if(STATE.sent){
    pill.textContent = reached ? 'TUNTAS - KKM TERCAPAI' : 'BELUM TUNTAS - NILAI TERTINGGI DIKIRIM';
    pill.className='status-pill '+(reached?'ok':'no');
  } else {
    pill.textContent='BELUM MENCAPAI KKM ('+KKM+')';
    pill.className='status-pill no';
  }

  if(isLate){
    $('rTitle').textContent = att===0 ? 'Batas waktu ujian sudah berakhir' : 'Batas waktu berakhir - nilai terakhir dikirim';
    $('rDesc').textContent = att===0
      ? 'Kamu tidak mengerjakan ujian ini sebelum batas waktu berakhir, sehingga nilai yang tercatat dan dikirim ke guru adalah 0.'
      : 'Batas waktu ujian sudah berakhir. Nilai tertinggi yang sempat kamu capai ('+STATE.sentValue+') telah dikirim ke guru.';
  } else if(att===0 || !best){
    $('rTitle').textContent='Belum ada data';
    $('rDesc').textContent='';
  } else if(STATE.sent &amp;&amp; !justSent){
    $('rTitle').textContent='Nilai kamu sudah tercatat';
    $('rDesc').textContent='Kesempatan mengerjakan sudah selesai untuk No. Absen ini. Nilai yang tercatat: '+STATE.sentValue+'.';
  } else if(STATE.sent){
    $('rTitle').textContent = reached ? 'Selamat, kamu mencapai KKM!' : 'Kesempatan ketiga selesai';
    $('rDesc').textContent = reached ? 'Nilai akhirmu '+best.total+' dan sudah dikirim ke guru.' : 'KKM belum tercapai. Nilai tertinggi dari '+att+' percobaan ('+best.total+') dikirim ke guru.';
  } else {
    $('rTitle').textContent='Nilaimu belum mencapai KKM';
    $('rDesc').textContent='Nilai percobaan ini '+last.total+' (tertinggi sementara '+best.total+'). Kamu masih punya '+left+' kesempatan. Nilai akan dikirim setelah KKM tercapai atau setelah percobaan ke-'+MAX_ATT+'.';
  }

  var bars='';
  if(best){
    bars += barRow('A. Pilihan Ganda', best.pg, MAX_PG, '#1d4ed8');
    bars += barRow('B. Praktik Mengetik', best.type, MAX_TYPE, '#d97706');
    bars += barRow('C. Esai', best.esai, MAX_ESAI, '#0f766e');
  }
  $('rBars').innerHTML=bars;

  var hist='&lt;b&gt;Riwayat percobaan:&lt;/b&gt; ';
  if(att===0){ hist+='-'; } else {
    hist += STATE.attempts.map(function(a){ return 'Ke-'+a.no+': &lt;b&gt;'+a.total+'&lt;/b&gt;'; }).join(' &amp;nbsp;|&amp;nbsp; ');
    hist += ' &amp;nbsp;-&amp;nbsp; Kesempatan tersisa: &lt;b&gt;'+(STATE.sent?0:left)+'&lt;/b&gt;';
  }
  $('rHist').innerHTML=hist;

  var sendEl=$('rSend');
  if(STATE.sent){
    sendEl.textContent='Nilai '+STATE.sentValue+' tercatat dan dikirim ke guru'+(justSent?'':' (pada sesi sebelumnya)')+'.';
    sendEl.className='msg info show';
  } else {
    sendEl.textContent='Nilai belum dikirim ke guru. Nilai dikirim otomatis begitu KKM tercapai atau setelah percobaan ke-'+MAX_ATT+'.';
    sendEl.className='msg info show';
  }

  $('btnRetry').classList.toggle('hidden', STATE.sent || left&lt;=0);
  $('btnPdf').disabled = !best;
  show('result');
}
function barRow(label, val, max, color){
  var pct=Math.max(0, Math.min(100, val/max*100));
  return '&lt;div class="bar-row"&gt;&lt;div class="lbl"&gt;&lt;span&gt;'+label+'&lt;/span&gt;&lt;span&gt;'+fmt(val)+' / '+max+'&lt;/span&gt;&lt;/div&gt;&lt;div class="track"&gt;&lt;div class="fill" style="width:'+pct+'%; background:'+color+';"&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;';
}

/* ================= PDF F4 ================= */

function pdfClean(s){ return String(s==null?'':s).replace(/[^\x20-\x7E\xA0-\xFF\n]/g,'?'); }

function downloadPdf(){
  if(!STATE || !STATE.best){ return; }
  if(!window.jspdf){ alert('Pustaka PDF belum termuat. Periksa koneksi internet lalu coba lagi.'); return; }
  var best=STATE.best;
  var doc=new window.jspdf.jsPDF({unit:'mm', format:[215,330]});
  var W=215, H=330, ML=15, MR=15, CW=W-ML-MR, YMAX=H-18, y=20;

  function need(h){ if(y+h&gt;YMAX){ doc.addPage([215,330]); y=22; } }
  function txt(s,x,yy,o){ doc.text(pdfClean(s), x, yy, o); }
  function bar(title, r,g,b){
    need(34);
    doc.setFillColor(r,g,b); doc.rect(ML,y,CW,7,'F');
    doc.setTextColor(255,255,255); doc.setFont('helvetica','bold'); doc.setFontSize(10);
    txt(title, ML+3, y+4.9);
    doc.setTextColor(0,0,0); y+=10;
  }

  doc.setFont('helvetica','bold'); doc.setFontSize(15);
  txt('BUKTI MENGERJAKAN UJIAN TENGAH SEMESTER', W/2, y, {align:'center'}); y+=6.5;
  doc.setFontSize(11); txt('Informatika Kelas X SMK', W/2, y, {align:'center'}); y+=5.2;
  doc.setFont('helvetica','normal'); doc.setFontSize(9);
  txt(DOC_CODE+' - 35 Pilihan Ganda, 10 Praktik Mengetik, 5 Esai - KKM '+KKM, W/2, y, {align:'center'}); y+=4;
  doc.setLineWidth(0.6); doc.line(ML,y,W-MR,y); y+=7;

  var rows=[
    ['No. Absen', ID.absen],
    ['Nama Lengkap', ID.nama],
    ['Kelas', ID.kelas],
    ['Waktu Pengerjaan', new Date(best.waktu).toLocaleString('id-ID')+' (percobaan ke-'+best.no+')']
  ];
  doc.setFontSize(10.5);
  rows.forEach(function(r){
    doc.setFont('helvetica','bold'); txt(r[0], ML, y);
    doc.setFont('helvetica','normal'); txt(': '+r[1], ML+38, y);
    y+=6;
  });
  y+=2;

  var reached=best.total&gt;=KKM;
  doc.setDrawColor(29,78,216); doc.setLineWidth(0.5); doc.rect(ML,y,CW,30);
  doc.setFont('helvetica','bold'); doc.setFontSize(9); txt('NILAI AKHIR', ML+5, y+7);
  doc.setFontSize(30); txt(String(best.total), ML+5, y+21);
  doc.setFontSize(10); txt('/ 100', ML+30, y+21);
  doc.setFontSize(9.5);
  txt('Pilihan Ganda   : '+fmt(best.pg)+' / '+MAX_PG, ML+62, y+8);
  txt('Praktik Mengetik: '+fmt(best.type)+' / '+MAX_TYPE, ML+62, y+14);
  txt('Esai            : '+fmt(best.esai)+' / '+MAX_ESAI, ML+62, y+20);
  if(reached){ doc.setTextColor(21,128,61); } else { doc.setTextColor(185,28,28); }
  doc.setFontSize(10.5); txt(reached?'TUNTAS (KKM '+KKM+' tercapai)':'BELUM TUNTAS (KKM '+KKM+')', ML+62, y+27);
  doc.setTextColor(0,0,0);
  y+=36;

  doc.setFont('helvetica','normal'); doc.setFontSize(9);
  var hist='Riwayat percobaan: '+STATE.attempts.map(function(a){ return 'Ke-'+a.no+' = '+a.total; }).join('  |  ');
  var hl=doc.splitTextToSize(pdfClean(hist), CW); doc.text(hl, ML, y); y+=hl.length*4;
  var sendTxt = STATE.sent ? 'Status: nilai '+STATE.sentValue+' telah dikirim ke guru.' : 'Status: nilai belum dikirim (masih ada kesempatan mengulang).';
  txt(sendTxt+'   Percobaan tempel yang ditolak sistem pada pengerjaan ini: '+(best.paste||0)+'.', ML, y); y+=8;

  /* A. PG */
  bar('A. PILIHAN GANDA - jawaban peserta', 29,78,216);
  doc.setFontSize(8.5);
  best.detail.pg.forEach(function(p){
    var lines=doc.splitTextToSize(pdfClean(p.n+'. '+p.chosen), CW-24);
    var h=lines.length*3.9+1.6;
    need(h);
    doc.setFont('helvetica','normal'); doc.setTextColor(0,0,0);
    doc.text(lines, ML, y+3);
    doc.setFont('helvetica','bold');
    if(p.ok){ doc.setTextColor(21,128,61); txt('BENAR', W-MR, y+3, {align:'right'}); }
    else { doc.setTextColor(185,28,28); txt('SALAH', W-MR, y+3, {align:'right'}); }
    doc.setTextColor(0,0,0);
    doc.setDrawColor(220,226,236); doc.setLineWidth(0.15); doc.line(ML, y+h-0.6, W-MR, y+h-0.6);
    y+=h;
  });
  y+=4;

  /* B. Mengetik */
  bar('B. PRAKTIK MENGETIK - ketikan peserta', 180,83,9);
  best.detail.ty.forEach(function(t){
    doc.setFontSize(8);
    var il=doc.splitTextToSize(pdfClean('Instruksi: '+t.instr), CW-4);
    var lines=doc.splitTextToSize(pdfClean(t.typed), CW-4);
    var h=il.length*3.6+lines.length*3.6+11;
    need(h);
    doc.setFont('helvetica','bold'); doc.setFontSize(8.5);
    txt('No. '+t.n+'  |  Kesamaan teks: '+String(t.sim).replace('.',',')+'%  |  Format diminta: '+t.fmtLabel+'  |  Format terpenuhi: '+t.fmtRatio+'%  |  Skor: '+fmt(t.score)+' / '+PT_TYPE, ML, y+3);
    doc.setFont('helvetica','italic'); doc.setFontSize(7.8);
    doc.text(il, ML+2, y+7);
    doc.setFont('helvetica','normal'); doc.setFontSize(8);
    doc.text(lines, ML+2, y+7+il.length*3.6);
    y+=h;
  });
  y+=4;

  /* C. Esai */
  bar('C. ESAI - jawaban peserta', 15,118,110);
  best.detail.es.forEach(function(e){
    doc.setFontSize(8.5);
    var ql=doc.splitTextToSize(pdfClean('Soal '+e.n+': '+e.q), CW);
    var al=doc.splitTextToSize(pdfClean('Jawaban: '+(e.answer||'-')), CW-4);
    var h=ql.length*3.9+al.length*3.7+11;
    need(h);
    doc.setFont('helvetica','bold'); doc.text(ql, ML, y+3);
    var yy=y+3+ql.length*3.9;
    doc.setFont('helvetica','normal'); doc.setFontSize(8.2); doc.text(al, ML+2, yy+1);
    yy+=al.length*3.7+2.5;
    doc.setFont('helvetica','bold'); doc.setFontSize(8.5);
    txt('Skor: '+fmt(e.score)+' / '+PT_ESAI, ML, yy+1);
    y+=h;
  });
  y+=6;

  /* Penutup */
  need(48);
  doc.setFont('helvetica','normal'); doc.setFontSize(9);
  var note='Dokumen ini adalah bukti otomatis bahwa peserta telah mengerjakan Ujian Tengah Semester Informatika Kelas X. Cetak pada kertas F4 dan serahkan kepada guru mata pelajaran sebagai bukti fisik pengerjaan.';
  var nl=doc.splitTextToSize(pdfClean(note), CW); doc.text(nl, ML, y); y+=nl.length*4.2+8;
  txt('Peserta,', ML+8, y); txt('Guru Mata Pelajaran,', W-MR-52, y);
  y+=22;
  txt('( '+ID.nama+' )', ML+8, y); txt('( ................................ )', W-MR-52, y);

  var total=doc.getNumberOfPages(), p;
  for(p=1;p&lt;=total;p++){
    doc.setPage(p);
    doc.setFont('helvetica','normal'); doc.setFontSize(8); doc.setTextColor(110,110,110);
    if(p&gt;1){ txt('UTS Informatika X - '+ID.nama+' ('+ID.kelas+' / No. '+ID.absen+')', ML, 12); }
    txt(DOC_CODE, ML, H-8);
    txt('Halaman '+p+' dari '+total, W-MR, H-8, {align:'right'});
  }
  doc.setTextColor(0,0,0);
  var safe=ID.nama.replace(/[^a-zA-Z0-9]+/g,'_');
  doc.save('Bukti_UTS_Informatika_X_'+safe+'_'+ID.absen+'.pdf');
}


/* ================= RESET PERCOBAAN OLEH GURU ================= */
/* TODO GURU: ganti PIN di bawah ini sebelum ujian dibagikan. Panel guru dibuka dengan menambahkan #guru di akhir alamat halaman. */
var GURU_PIN = 'GURU-UTS-X';

function resetCode(kelas, absen, n){
  var s=GURU_PIN+'|'+kelas+'|'+String(parseInt(absen,10))+'|reset|'+n, h=5381, i;
  for(i=0;i&lt;s.length;i++){ h=((h*33)^s.charCodeAt(i))&gt;&gt;&gt;0; }
  return ('000000'+h.toString(36).toUpperCase()).slice(-6);
}
function getUsedCodes(){
  try{ return JSON.parse(localStorage.getItem('uts_inf_x_used|'+EXAM_VERSION)||'[]'); }catch(e){ return memStore.__used||[]; }
}
function addUsedCode(c){
  var u=getUsedCodes(); u.push(c); memStore.__used=u;
  try{ localStorage.setItem('uts_inf_x_used|'+EXAM_VERSION, JSON.stringify(u)); }catch(e){}
}
function clearAttempts(kelas, absen){
  var key=keyOf(kelas, String(parseInt(absen,10)));
  delete memStore[key];
  try{ localStorage.removeItem(key); }catch(e){}
}
function onUseResetCode(){
  var kelas=$('fKelas').value, absen=$('fAbsen').value, code=$('fResetCode').value.trim().toUpperCase(), msg=$('resetMsg'), n, ok=false;
  msg.className='msg';
  function say(t, cls){ msg.textContent=t; msg.className='msg show '+cls; }
  if(!kelas || !absen){ say('Pilih Kelas dan No. Absen terlebih dahulu, lalu masukkan kode.', 'err'); return; }
  if(!code){ say('Masukkan kode reset dari guru.', 'err'); return; }
  if(getUsedCodes().indexOf(kelas+'|'+absen+'|'+code)!==-1){ say('Kode ini sudah pernah dipakai. Minta kode baru kepada guru.', 'err'); return; }
  for(n=1;n&lt;=9;n++){ if(resetCode(kelas, absen, n)===code){ ok=true; break; } }
  if(!ok){ say('Kode reset tidak cocok untuk Kelas dan No. Absen ini.', 'err'); return; }
  addUsedCode(kelas+'|'+absen+'|'+code);
  clearAttempts(kelas, absen);
  $('fResetCode').value='';
  say('Percobaan berhasil direset. Klik "Mulai Mengerjakan" untuk memulai lagi (3 kesempatan baru).', 'ok');
}
function fillGuruKelas(){
  var sel=$('rsKelas'), k;
  if(sel.options.length&gt;1){ return; }
  for(k in ROSTER){ if(Object.prototype.hasOwnProperty.call(ROSTER,k)){ var o=document.createElement('option'); o.value=k; o.textContent=k; sel.appendChild(o); } }
}
function fillGuruAbsen(){
  var kelas=$('rsKelas').value, sel=$('rsAbsen');
  sel.innerHTML='';
  if(!kelas || !ROSTER[kelas]){ sel.disabled=true; sel.innerHTML='&lt;option value=""&gt;- Pilih kelas dulu -&lt;/option&gt;'; return; }
  sel.disabled=false;
  var o0=document.createElement('option'); o0.value=''; o0.textContent='- Pilih siswa -'; o0.disabled=true; o0.selected=true; sel.appendChild(o0);
  ROSTER[kelas].forEach(function(p){ var o=document.createElement('option'); o.value=String(p[0]); o.textContent=p[0]+' - '+p[1]; sel.appendChild(o); });
}
function guruPick(){
  var kelas=$('rsKelas').value, absen=$('rsAbsen').value;
  if(!kelas || !absen){ $('rsOut').innerHTML='&lt;div class="msg err show"&gt;Pilih Kelas dan siswa terlebih dahulu.&lt;/div&gt;'; return null; }
  return {kelas:kelas, absen:absen};
}
function onGuruLogin(){
  if($('rsPin').value===GURU_PIN){
    $('guruLogin').classList.add('hidden'); $('guruTools').classList.remove('hidden'); fillGuruKelas();
  } else {
    alert('PIN guru salah.');
  }
}
function onGuruCode(){
  var p=guruPick(); if(!p){ return; }
  var n=parseInt($('rsNo').value,10); if(!(n&gt;=1 &amp;&amp; n&lt;=9)){ n=1; $('rsNo').value=1; }
  $('rsOut').innerHTML='&lt;div&gt;Kode reset untuk &lt;b&gt;'+esc(p.kelas)+' / No. '+esc(p.absen)+'&lt;/b&gt; (reset ke-'+n+'):&lt;/div&gt;&lt;div class="guru-code"&gt;'+resetCode(p.kelas,p.absen,n)+'&lt;/div&gt;';
}
function onGuruHere(){
  var p=guruPick(); if(!p){ return; }
  clearAttempts(p.kelas, p.absen);
  $('rsOut').innerHTML='&lt;div class="msg ok show"&gt;Percobaan '+esc(p.kelas)+' / No. '+esc(p.absen)+' pada perangkat ini sudah direset.&lt;/div&gt;';
}
function syncGuruCard(){
  $('guruCard').classList.toggle('hidden', window.location.hash!=='#guru');
}

/* ================= EVENT ================= */

$('btnStart').addEventListener('click', onStart);
$('fKelas').addEventListener('change', populateAbsenOptions);
$('fAbsen').addEventListener('change', populateNamaFromRoster);
initDeadlineNotice();
$('btnSubmit').addEventListener('click', onSubmit);
$('btnPdf').addEventListener('click', downloadPdf);
$('btnRetry').addEventListener('click', function(){ startAttempt(); });
$('btnHome').addEventListener('click', function(){ show('start'); });

$('btnUseReset').addEventListener('click', onUseResetCode);
$('btnGuruLogin').addEventListener('click', onGuruLogin);
$('rsKelas').addEventListener('change', fillGuruAbsen);
$('btnRsCode').addEventListener('click', onGuruCode);
$('btnRsHere').addEventListener('click', onGuruHere);
window.addEventListener('hashchange', syncGuruCard);
syncGuruCard();

/* Hook uji (tidak mengganggu pemakaian normal) */
window.__uts = {formatScoreRatio:formatScoreRatio, fmtLabel:fmtLabel, resetCode:resetCode, similarity:similarity, scoreEssay:scoreEssay, PG:PG, TYPING:TYPING, ESAI:ESAI, ROSTER:ROSTER, CLASS_TOKENS:CLASS_TOKENS, EXAM_OPEN:EXAM_OPEN, EXAM_DEADLINE:EXAM_DEADLINE};

})();
&lt;/script&gt;

&lt;/body&gt;
&lt;/html&gt;</description><link>http://kitab-investasi.blogspot.com/2026/09/ujian-tengah-semester-informatika.html</link><thr:total>0</thr:total><author>nof_rizal07@yahoo.co.id (abang_cool)</author></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-9000860041661554971.post-4838622872826116034</guid><pubDate>Tue, 29 Sep 2026 01:01:34 +0000</pubDate><atom:updated>2026-09-29T08:57:01.877+07:00</atom:updated><title>SERTIFIKAT KOMBEL</title><description>&lt;!DOCTYPE html&gt;
&lt;html lang="id"&gt;
&lt;head&gt;
&lt;meta charset="UTF-8"&gt;
&lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&gt;
&lt;title&gt;Generator Sertifikat&lt;/title&gt;

&lt;link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@700&amp;display=swap" rel="stylesheet"&gt;

&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"&gt;&lt;/script&gt;

&lt;style&gt;

body{
    font-family:Arial,sans-serif;
    background:#eef2f7;
    padding:20px;
    max-width:700px;
    margin:auto;
}

.card{
    background:white;
    padding:24px;
    border-radius:20px;
    box-shadow:0 10px 20px rgba(0,0,0,.1);
}

h2{
    text-align:center;
    color:#1e4668;
}

.confirm-box{
    background:#f0f6ff;
    border-left:5px solid #2c7da0;
    padding:16px;
    border-radius:16px;
    margin-bottom:20px;
    text-align:center;
}

.confirm-box p{
    margin-top:0;
    font-weight:bold;
    color:#1e4668;
}

.confirm-buttons{
    display:flex;
    gap:10px;
    margin-top:10px;
}

.confirm-buttons button{
    flex:1;
}

.yes-btn{
    background:#1f8a4c;
}

.yes-btn:hover{
    background:#166638;
}

.no-btn{
    background:#c0392b;
}

.no-btn:hover{
    background:#962d22;
}

input,select,button{
    width:100%;
    padding:12px;
    margin-top:10px;
    border-radius:12px;
    border:1px solid #ccc;
    font-size:16px;
}

button{
    background:#2c7da0;
    color:white;
    border:none;
    cursor:pointer;
    font-weight:bold;
}

button:hover{
    background:#1f5e7a;
}

button:disabled{
    background:#94a3b8;
    cursor:not-allowed;
}

input:disabled,
select:disabled{
    background:#f1f5f9;
}

#preview{
    width:100%;
    border-radius:12px;
    margin-top:10px;
}

.loading{
    display:none;
    margin-top:15px;
    color:#1e4668;
    font-weight:bold;
    text-align:center;
}

.status{
    margin-top:12px;
    font-weight:bold;
}

.success{
    color:#1f8a4c;
}

.error{
    color:#c0392b;
}

&lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;

&lt;div class="card"&gt;

&lt;h2&gt;&#128220; Generator Sertifikat&lt;/h2&gt;

&lt;!-- ================= KONFIRMASI ================= --&gt;

&lt;div class="confirm-box"&gt;

&lt;p&gt;&#128269; Apakah Anda mengikuti pelatihan?&lt;/p&gt;

&lt;div class="confirm-buttons"&gt;

&lt;button class="yes-btn" onclick="confirmIkut()"&gt;
✅ YA, IKUT
&lt;/button&gt;

&lt;button class="no-btn" onclick="confirmTidakIkut()"&gt;
❌ TIDAK
&lt;/button&gt;

&lt;/div&gt;

&lt;div id="statusKonfirmasi" class="status"&gt;&lt;/div&gt;

&lt;/div&gt;

&lt;!-- ================= FORM ================= --&gt;

&lt;label&gt;Nama Lengkap&lt;/label&gt;

&lt;input
type="text"
id="nama"
placeholder="Contoh: Ahmad Fauzi"
disabled&gt;

&lt;label&gt;Peran&lt;/label&gt;

&lt;select id="peran" disabled&gt;
    &lt;option&gt;Peserta&lt;/option&gt;
    &lt;option&gt;Narasumber&lt;/option&gt;
&lt;/select&gt;

&lt;img
id="preview"
src="https://lh3.googleusercontent.com/d/18EtT4MIeCpdBOvq7KWwjtm9ucFXmVGbj"
alt="Template"&gt;

&lt;button
id="downloadBtn"
onclick="generatePDF()"
disabled&gt;

⬇️ UNDUH PDF

&lt;/button&gt;

&lt;div class="loading" id="loading"&gt;
Memproses PDF...
&lt;/div&gt;

&lt;/div&gt;

&lt;script&gt;

// ================= TEMPLATE (DIUBAH) =================

const FILE_ID =
'18EtT4MIeCpdBOvq7KWwjtm9ucFXmVGbj';  // &lt;-- ID baru

const TEMPLATE_URL =
`https://lh3.googleusercontent.com/d/${FILE_ID}`;

// ================= UTIL =================

function showLoading(show){

    document.getElementById('loading').style.display =
        show ? 'block' : 'none';

}

function getRomanMonth(monthIndex){

    const romawi = [
        "I","II","III","IV","V","VI",
        "VII","VIII","IX","X","XI","XII"
    ];

    return romawi[monthIndex];

}

function capitalizeEachWord(text){

    return text
        .toLowerCase()
        .replace(/\b\w/g,c=&gt;c.toUpperCase());

}

// ================= KONFIRMASI =================

function confirmIkut(){

    document.getElementById('nama').disabled = false;

    document.getElementById('peran').disabled = false;

    document.getElementById('downloadBtn').disabled = false;

    document.getElementById('statusKonfirmasi').innerHTML =
        '&lt;span class="success"&gt;✅ Konfirmasi diterima. Anda dapat mengunduh sertifikat.&lt;/span&gt;';

}

function confirmTidakIkut(){

    document.getElementById('nama').disabled = true;

    document.getElementById('peran').disabled = true;

    document.getElementById('downloadBtn').disabled = true;

    document.getElementById('statusKonfirmasi').innerHTML =
        '&lt;span class="error"&gt;❌ Anda tidak dapat mengunduh sertifikat.&lt;/span&gt;';

}

// ================= LOAD IMAGE =================

function loadImage(url){

    return new Promise((resolve,reject)=&gt;{

        const img = new Image();

        img.crossOrigin = "anonymous";

        img.onload = ()=&gt;resolve(img);

        img.onerror = ()=&gt;{

            reject(
                new Error(
                    'Template Google Drive gagal dimuat'
                )
            );

        };

        img.src = url + '?t=' + Date.now();

    });

}

// ================= NOMOR =================

async function generateNomor(){

    const now = new Date();

    const bulan =
        getRomanMonth(now.getMonth());

    const tahun =
        now.getFullYear();

    const nomor =
        Math.floor(Math.random()*900)+100;

    return `${nomor}/K/${bulan}/${tahun}`;

}

// ================= PDF =================

async function generatePDF(){

    const namaInput =
        document.getElementById('nama');

    const peranSelect =
        document.getElementById('peran');

    let nama =
        namaInput.value.trim();

    const peran =
        peranSelect.value;

    if(!nama){

        alert('Nama wajib diisi');

        return;

    }

    nama =
        capitalizeEachWord(nama);

    showLoading(true);

    try{

        await document.fonts.ready;

        const img =
            await loadImage(TEMPLATE_URL);

        const canvas =
            document.createElement('canvas');

        canvas.width = img.width;
        canvas.height = img.height;

        const ctx =
            canvas.getContext('2d');

        ctx.drawImage(
            img,
            0,
            0,
            canvas.width,
            canvas.height
        );

        // ================= POSISI =================

        const nomorY =
            canvas.height * 0.235;

        const namaY =
            canvas.height * 0.3990;

        const peranY =
            canvas.height * 0.5420;

        // ================= STYLE =================

        ctx.textAlign = 'center';

        ctx.textBaseline = 'middle';

        ctx.fillStyle = '#000';

        // nomor
        const nomorSertifikat =
            await generateNomor();

        ctx.font =
            `bold ${canvas.width*0.0125}px Montserrat`;

        ctx.fillText(
            nomorSertifikat,
            canvas.width/2,
            nomorY
        );

        // nama auto shrink
        let fontSize =
            canvas.width * 0.031;

        ctx.font =
            `700 ${fontSize}px Montserrat`;

        let textWidth =
            ctx.measureText(nama).width;

        const maxWidth =
            canvas.width - 180;

        while(
            textWidth &gt; maxWidth &amp;&amp;
            fontSize &gt; 20
        ){

            fontSize -= 2;

            ctx.font =
                `700 ${fontSize}px Montserrat`;

            textWidth =
                ctx.measureText(nama).width;

        }

        ctx.fillText(
            nama,
            canvas.width/2,
            namaY
        );

        // peran
        ctx.font =
            `bold ${canvas.width*0.024}px Montserrat`;

        ctx.fillText(
            peran,
            canvas.width/2,
            peranY
        );

        // ================= PDF =================

        const imageData =
            canvas.toDataURL(
                'image/jpeg',
                1.0
            );

        const { jsPDF } =
            window.jspdf;

        const pdf =
            new jsPDF({

                orientation:
                    canvas.width &gt; canvas.height
                    ? 'landscape'
                    : 'portrait',

                unit:'px',

                format:[
                    canvas.width,
                    canvas.height
                ]

            });

        pdf.addImage(
            imageData,
            'JPEG',
            0,
            0,
            canvas.width,
            canvas.height
        );

        const safeName =
            nama.replace(/[^a-z0-9]/gi,'_');

        pdf.save(
            `Sertifikat_${safeName}.pdf`
        );

    }catch(error){

        console.error(error);

        alert(
            '❌ Gagal membuat PDF\n\n' +
            error.message +
            '\n\nPastikan file Google Drive bersifat PUBLIC.'
        );

    }finally{

        showLoading(false);

    }

}

&lt;/script&gt;

&lt;/body&gt;
&lt;/html&gt;</description><link>http://kitab-investasi.blogspot.com/2026/09/sertifikat-kombel_0210708163.html</link><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://lh3.googleusercontent.com/d/18EtT4MIeCpdBOvq7KWwjtm9ucFXmVGbj=s72-c" width="72"/><thr:total>0</thr:total><author>nof_rizal07@yahoo.co.id (abang_cool)</author></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-9000860041661554971.post-8866540713710335007</guid><pubDate>Wed, 23 Sep 2026 06:03:35 +0000</pubDate><atom:updated>2026-09-23T13:03:35.896+07:00</atom:updated><title>Membandingkan Isi Teks Ceramah dengan Teks Lain</title><description>&lt;style&gt;
@import url('https://fonts.googleapis.com/css2?family=Oswald:wght@400;500;600;700&amp;family=Source+Sans+3:wght@400;500;600;700&amp;family=IBM+Plex+Mono:wght@400;500;600&amp;display=swap');
.epb{
  --blueprint:#0F2A3D;
  --blueprint-deep:#0A1E2C;
  --panel:#4A2E12;
  --paper:#F3F0E6;
  --ink:#132029;
  --amber:#F5A623;
  --amber-deep:#C97F12;
  --mint:#6EC6CA;
  --line:rgba(234,242,245,0.16);
  --off-white:#EAF2F5;
  --muted:#9FB4C2;
}
.epb *{box-sizing:border-box;}
.epb{scroll-behavior:smooth; background:#0A1F2E;}
.epb{
  margin:0;
  position:relative;
  overflow:hidden;
  background:var(--blueprint);
  color:var(--off-white);
  font-family:'Source Sans 3',sans-serif;
  line-height:1.65;
  background-image:
    linear-gradient(var(--line) 1px, transparent 1px),
    linear-gradient(90deg, var(--line) 1px, transparent 1px);
  background-size: 34px 34px;
}
.epb h1, .epb h2, .epb h3, .epb h4{font-family:'Oswald',sans-serif; text-transform:uppercase; letter-spacing:0.02em; margin:0 0 0.5em;}
.epb .mono{font-family:'IBM Plex Mono',monospace;}
.epb a{color:var(--amber);}
.epb .crop{position:absolute; width:22px; height:22px; z-index:5; opacity:.55; pointer-events:none;}
.epb .crop::before, .epb .crop::after{content:"";position:absolute;background:var(--mint);}
.epb .crop::before{width:100%;height:1px;top:50%;left:0;}
.epb .crop::after{width:1px;height:100%;left:50%;top:0;}
.epb .crop.tl{top:14px;left:14px;}
.epb .crop.tr{top:14px;right:14px;}
.epb .crop.bl{bottom:14px;left:14px;}
.epb .crop.br{bottom:14px;right:14px;}
.epb header.cover{
  position:relative;
  padding:40px 24px 36px;
  border-bottom:1px solid var(--line);
  overflow:hidden;
}
.epb .doc-code{font-family:'IBM Plex Mono',monospace; color:var(--amber); letter-spacing:0.15em; font-size:0.78rem; text-transform:uppercase; margin-bottom:18px; display:flex; gap:10px; align-items:center;}
.epb .doc-code::before{content:"◆"; color:var(--amber);}
.epb .cover h1{font-size:clamp(1.6rem,7vw,2.5rem); color:var(--off-white); max-width:16ch; line-height:1.05;}
.epb .cover .subtitle{color:var(--muted); font-size:1.05rem; max-width:60ch; margin-top:14px;}
.epb .meta-strip{
  margin-top:38px; display:grid; grid-template-columns:repeat(auto-fit,minmax(150px,1fr));
  border-top:1px dashed var(--line); border-bottom:1px dashed var(--line);
}
.epb .meta-strip div{padding:14px 16px; border-right:1px dashed var(--line);}
.epb .meta-strip div:last-child{border-right:none;}
.epb .meta-strip .k{font-family:'IBM Plex Mono',monospace; font-size:0.68rem; color:var(--amber); text-transform:uppercase; letter-spacing:0.1em;}
.epb .meta-strip .v{font-size:0.98rem; color:var(--off-white); margin-top:4px; font-weight:600;}
.epb .stamp{
  position:absolute; top:40px; right:20px; width:104px; height:104px;
  border:2.5px solid var(--amber); border-radius:50%;
  display:flex; align-items:center; justify-content:center;
  transform:rotate(-11deg);
  color:var(--amber); font-family:'IBM Plex Mono',monospace;
  text-align:center; font-size:0.62rem; letter-spacing:0.08em; text-transform:uppercase;
  opacity:0.9;
}
.epb .stamp .ring{position:absolute; inset:8px; border:1px dashed var(--amber); border-radius:50%;}
.epb .stamp b{display:block; font-family:'Oswald',sans-serif; font-size:1.05rem; letter-spacing:0.06em; margin-top:4px;}

@media (max-width:760px){.epb .stamp{display:none;}
.epb }


.epb main{max-width:920px; margin:0 auto; padding:0 20px 60px;}
.epb .section{padding-top:64px;}
.epb .eyebrow{font-family:'IBM Plex Mono',monospace; color:var(--amber); font-size:0.78rem; letter-spacing:0.14em; text-transform:uppercase; margin-bottom:10px; display:flex; align-items:center; gap:10px;}
.epb .eyebrow::after{content:""; flex:1; height:1px; background:var(--line);}
.epb h2.section-title{font-size:1.7rem; color:var(--off-white);}
.epb p{color:#DDE7EC;}
.epb .lead{color:var(--muted); font-size:1.02rem; max-width:72ch;}
.epb .panel{
  background:var(--panel); border:1px solid var(--line); border-radius:2px;
  padding:26px 28px; margin:22px 0;
}
.epb .panel.tp{border-left:4px solid var(--mint);}
.epb .panel.warn{border-left:4px solid var(--amber);}
.epb .tp-box{display:grid; gap:14px; margin-top:18px;}
.epb .tp-item{display:flex; gap:14px; align-items:flex-start;}
.epb .tp-item .idx{font-family:'IBM Plex Mono',monospace; color:var(--amber); font-weight:600; min-width:34px;}
.epb .flow{display:grid; grid-template-columns:repeat(auto-fit,minmax(220px,1fr)); gap:14px; margin-top:20px;}
.epb .flow .step{background:var(--blueprint-deep); border:1px solid var(--line); padding:18px; position:relative;}
.epb .flow .step .tag{font-family:'IBM Plex Mono',monospace; color:var(--amber); font-size:0.7rem; letter-spacing:0.1em; text-transform:uppercase;}
.epb .flow .step h4{font-size:1rem; margin-top:8px; color:var(--off-white);}
.epb .flow .step .time{position:absolute; top:16px; right:16px; font-family:'IBM Plex Mono',monospace; font-size:0.7rem; color:var(--amber);}
.epb .grid-3{display:grid; grid-template-columns:repeat(auto-fit,minmax(200px,1fr)); gap:14px; margin-top:16px;}
.epb .card{background:var(--blueprint-deep); border:1px solid var(--line); padding:18px;}
.epb .card h4{color:var(--amber); font-size:0.95rem;}
.epb .criteria{display:grid; gap:16px; margin-top:20px;}
.epb .crit{
  background:var(--blueprint-deep); border:1px solid var(--line);
  display:grid; grid-template-columns:64px 1fr; gap:0;
}
.epb .crit .num{
  background:var(--amber); color:var(--blueprint-deep); font-family:'IBM Plex Mono',monospace;
  font-weight:700; display:flex; align-items:center; justify-content:center; font-size:1.05rem;
}
.epb .crit .body{padding:18px 20px;}
.epb .crit h4{color:var(--off-white); font-size:1.02rem; margin-bottom:6px;}
.epb .crit .q{margin-top:10px; padding-top:10px; border-top:1px dashed var(--line); font-family:'IBM Plex Mono',monospace; font-size:0.86rem; color:var(--amber);}
.epb .timeline{margin-top:24px; position:relative; padding-left:34px;}
.epb .timeline::before{content:""; position:absolute; left:11px; top:6px; bottom:6px; width:2px; background:var(--line);}
.epb .tl-item{position:relative; padding-bottom:26px;}
.epb .tl-item:last-child{padding-bottom:0;}
.epb .tl-item::before{content:""; position:absolute; left:-34px; top:2px; width:22px; height:22px; border-radius:50%; background:var(--blueprint); border:2px solid var(--amber);}
.epb .tl-item h4{color:var(--off-white); font-size:1rem; margin-bottom:4px;}
.epb .doc-sample{
  background:var(--paper); color:var(--ink); border-radius:2px; padding:0; margin-top:22px;
  box-shadow:0 20px 45px rgba(0,0,0,0.35);
}
.epb .doc-sample .doc-head{background:var(--ink); color:var(--paper); padding:12px 22px; font-family:'IBM Plex Mono',monospace; font-size:0.75rem; letter-spacing:0.1em; text-transform:uppercase; display:flex; justify-content:space-between;}
.epb .doc-sample .doc-body{padding:26px 28px 30px;}
.epb .doc-sample h3{font-family:'Oswald',sans-serif; color:var(--ink); font-size:1.25rem; text-transform:none; letter-spacing:0;}
.epb .doc-sample ol{padding-left:22px;}
.epb .doc-sample li{margin-bottom:9px;}
.epb .flag{
  display:inline-block; font-family:'IBM Plex Mono',monospace; font-size:0.7rem; font-weight:600;
  background:#D94E2A; color:#fff; padding:1px 7px; border-radius:2px; margin-left:6px; vertical-align:middle;
}
.epb .doc-sample .note-margin{margin-top:6px; font-family:'IBM Plex Mono',monospace; font-size:0.78rem; color:#8A3A1F; padding-left:8px; border-left:2px solid #D94E2A;}
.epb .legend{display:flex; flex-wrap:wrap; gap:10px 20px; margin-top:16px;}
.epb .legend span{font-family:'IBM Plex Mono',monospace; font-size:0.78rem; color:var(--muted); display:flex; align-items:center; gap:8px;}
.epb .legend .dot{width:10px; height:10px; border-radius:50%; display:inline-block;}
.epb table{width:100%; border-collapse:collapse; margin-top:18px; font-size:0.94rem;}
.epb th, .epb td{border:1px solid var(--line); padding:10px 12px; text-align:left; vertical-align:top;}
.epb th{background:var(--blueprint-deep); font-family:'IBM Plex Mono',monospace; font-size:0.75rem; text-transform:uppercase; letter-spacing:0.06em; color:var(--amber);}
.epb .summary-box{
  border:1px solid var(--amber); background:linear-gradient(180deg, rgba(245,166,35,0.08), transparent);
  padding:24px 26px; margin-top:24px;
}
.epb .summary-box ul{margin:10px 0 0; padding-left:20px;}
.epb .summary-box li{margin-bottom:8px;}
.epb .task-header{
  background:var(--amber); color:var(--blueprint-deep); padding:22px 26px; margin-top:20px;
  display:flex; justify-content:space-between; align-items:center; flex-wrap:wrap; gap:10px;
}
.epb .task-header h2{color:var(--blueprint-deep); font-size:1.4rem; margin:0;}
.epb .task-header .badge{font-family:'IBM Plex Mono',monospace; font-size:0.8rem; background:var(--blueprint-deep); color:var(--amber); padding:6px 12px; border-radius:2px;}
.epb .steps-num{counter-reset:step; margin-top:18px; list-style:none; padding:0;}
.epb .steps-num li{counter-increment:step; position:relative; padding-left:44px; margin-bottom:16px;}
.epb .steps-num li::before{content:counter(step,decimal-leading-zero); position:absolute; left:0; top:0; font-family:'IBM Plex Mono',monospace; color:var(--amber); font-weight:600; font-size:0.95rem; border:1px solid var(--amber); width:30px; height:26px; display:flex; align-items:center; justify-content:center;}
.epb .rubric-scale{display:grid; grid-template-columns:repeat(4,1fr); gap:10px; margin-top:16px;}
.epb .rubric-scale div{background:var(--blueprint-deep); border:1px solid var(--line); padding:12px; text-align:center;}
.epb .rubric-scale .n{font-family:'IBM Plex Mono',monospace; color:var(--amber); font-size:1.3rem; font-weight:700;}
.epb .rubric-scale .l{font-size:0.78rem; color:var(--muted); text-transform:uppercase; letter-spacing:0.05em;}
.epb .notebook{
  background:repeating-linear-gradient(var(--paper), var(--paper) 33px, #D8D3C2 34px);
  color:var(--ink); border-radius:2px; padding:28px 30px; margin-top:20px; position:relative;
  box-shadow:0 20px 45px rgba(0,0,0,0.35);
}
.epb .notebook::before{content:""; position:absolute; left:46px; top:0; bottom:0; width:1.5px; background:#C0453A; opacity:0.5;}
.epb .notebook .content{padding-left:24px;}
.epb .notebook h3{color:var(--ink); font-family:'Oswald',sans-serif; letter-spacing:0.02em; margin-bottom:10px;}
.epb .notebook ul{padding-left:20px;}
.epb footer{border-top:1px solid var(--line); padding:24px 20px 40px; color:var(--muted); font-size:0.86rem;}
.epb footer .doc-code{margin-bottom:10px;}
.epb .divider-dash{border:none; border-top:1px dashed var(--line); margin:44px 0 0;}
.epb::selection{background:var(--amber); color:var(--blueprint-deep);}

&lt;/style&gt;
&lt;div class="epb"&gt;
&lt;div class="crop tl"&gt;&lt;/div&gt;&lt;div class="crop tr"&gt;&lt;/div&gt;&lt;div class="crop bl"&gt;&lt;/div&gt;&lt;div class="crop br"&gt;&lt;/div&gt;

&lt;header class="cover"&gt;
  &lt;div class="stamp"&gt;&lt;div class="ring"&gt;&lt;/div&gt;&lt;span&gt;Modul Ajar&lt;b&gt;Terverifikasi&lt;/b&gt;Fase F&lt;/span&gt;&lt;/div&gt;
  &lt;div class="doc-code"&gt;DOK/B.INDO/XI/CERAMAH-BANDING — 3 JP · 1 Pertemuan&lt;/div&gt;
  &lt;h1&gt;Membandingkan Isi Teks Ceramah dengan Teks Lain&lt;/h1&gt;
  &lt;p class="subtitle"&gt;Materi Bahasa Indonesia Kelas XI SMK/MAK — melatih murid membandingkan isi teks ceramah dengan teks artikel opini serta menemukan kelebihan dan kekurangan masing-masing.&lt;/p&gt;

  &lt;div class="meta-strip"&gt;
    &lt;div&gt;&lt;div class="k"&gt;Mata Pelajaran&lt;/div&gt;&lt;div class="v"&gt;Bahasa Indonesia&lt;/div&gt;&lt;/div&gt;
    &lt;div&gt;&lt;div class="k"&gt;Jenjang&lt;/div&gt;&lt;div class="v"&gt;SMK/MAK — Kelas XI&lt;/div&gt;&lt;/div&gt;
    &lt;div&gt;&lt;div class="k"&gt;Elemen&lt;/div&gt;&lt;div class="v"&gt;Membaca &amp;amp; Memirsa&lt;/div&gt;&lt;/div&gt;
    &lt;div&gt;&lt;div class="k"&gt;Alokasi Waktu&lt;/div&gt;&lt;div class="v"&gt;3 JP (3 × 45 menit)&lt;/div&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/header&gt;

&lt;main&gt;

  &lt;!-- ============ TUJUAN PEMBELAJARAN ============ --&gt;
  &lt;section class="section" id="tujuan"&gt;
    &lt;div class="eyebrow"&gt;01 — Identitas Pembelajaran&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Capaian &amp;amp; Tujuan Pembelajaran&lt;/h2&gt;

    &lt;div class="panel tp"&gt;
      &lt;div class="eyebrow" style="margin-bottom:6px;"&gt;Capaian Pembelajaran (Elemen Membaca–Memirsa)&lt;/div&gt;
      &lt;p&gt;Murid mampu mengevaluasi informasi dari berbagai jenis teks, termasuk teks ceramah, serta membandingkannya dengan teks lain untuk menemukan persamaan, perbedaan, kelebihan, dan kekurangan masing-masing secara kritis.&lt;/p&gt;
    &lt;/div&gt;

    &lt;div class="panel"&gt;
      &lt;div class="eyebrow" style="margin-bottom:6px;"&gt;Tujuan Pembelajaran&lt;/div&gt;
      &lt;p style="font-size:1.05rem; color:var(--off-white); font-weight:600;"&gt;Murid mampu membandingkan isi teks ceramah dengan teks lainnya serta menemukan kelebihan dan kekurangan masing-masing.&lt;/p&gt;

      &lt;div class="tp-box"&gt;
        &lt;div class="tp-item"&gt;&lt;span class="idx mono"&gt;TP.1&lt;/span&gt;&lt;p&gt;Murid dapat menjelaskan struktur dan ciri kebahasaan teks ceramah.&lt;/p&gt;&lt;/div&gt;
        &lt;div class="tp-item"&gt;&lt;span class="idx mono"&gt;TP.2&lt;/span&gt;&lt;p&gt;Murid dapat menjelaskan struktur dan ciri kebahasaan teks artikel opini sebagai teks pembanding.&lt;/p&gt;&lt;/div&gt;
        &lt;div class="tp-item"&gt;&lt;span class="idx mono"&gt;TP.3&lt;/span&gt;&lt;p&gt;Murid dapat menemukan persamaan dan perbedaan antara teks ceramah dan teks artikel opini.&lt;/p&gt;&lt;/div&gt;
        &lt;div class="tp-item"&gt;&lt;span class="idx mono"&gt;TP.4&lt;/span&gt;&lt;p&gt;Murid dapat menemukan kelebihan dan kekurangan teks ceramah maupun teks artikel opini berdasarkan bukti dari kedua teks.&lt;/p&gt;&lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;

    &lt;div class="eyebrow" style="margin-top:26px; margin-bottom:6px;"&gt;8 Profil Lulusan yang Dikembangkan&lt;/div&gt;
    &lt;div class="grid-3"&gt;
      &lt;div class="card"&gt;&lt;h4&gt;Penalaran Kritis&lt;/h4&gt;&lt;p style="font-size:0.9rem;"&gt;Menganalisis kelebihan dan kekurangan dua jenis teks berdasarkan bukti tekstual.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;h4&gt;Kemandirian&lt;/h4&gt;&lt;p style="font-size:0.9rem;"&gt;Menyelesaikan reviu dan simpulan perbandingan secara mandiri.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;h4&gt;Kolaborasi&lt;/h4&gt;&lt;p style="font-size:0.9rem;"&gt;Bekerja sama dalam kelompok saat membandingkan dua teks.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;h4&gt;Komunikasi&lt;/h4&gt;&lt;p style="font-size:0.9rem;"&gt;Menyampaikan hasil perbandingan teks secara jelas dan runtut.&lt;/p&gt;&lt;/div&gt;
    &lt;/div&gt;
  &lt;/section&gt;

  &lt;hr class="divider-dash"&gt;

  &lt;!-- ============ MATERI A: TEKS CERAMAH ============ --&gt;
  &lt;section class="section" id="materi-a"&gt;
    &lt;div class="eyebrow"&gt;02 — Materi Inti A&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Mengenal Teks Ceramah&lt;/h2&gt;
    &lt;p class="lead"&gt;Teks ceramah dipelajari kembali sebagai salah satu teks yang akan dibandingkan pada pertemuan ini.&lt;/p&gt;

    &lt;div class="panel"&gt;
      &lt;p&gt;&lt;b style="color:var(--off-white);"&gt;Teks ceramah&lt;/b&gt; adalah teks berisi pidato seseorang di hadapan pendengar, bertujuan memberi nasihat, wejangan, atau pengetahuan tentang suatu hal, biasanya bertema moral, agama, atau sosial, dan disampaikan secara lisan.&lt;/p&gt;
    &lt;/div&gt;

    &lt;div class="grid-3"&gt;
      &lt;div class="card"&gt;&lt;h4&gt;Struktur&lt;/h4&gt;&lt;p style="font-size:0.92rem;"&gt;Pembukaan (salam &amp;amp; sapaan) → isi (paparan gagasan) → penutup (simpulan &amp;amp; salam).&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;h4&gt;Kata Ganti &amp;amp; Sapaan&lt;/h4&gt;&lt;p style="font-size:0.92rem;"&gt;"Kita", "kami", serta sapaan seperti "hadirin", "saudara-saudara".&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;h4&gt;Ciri Kebahasaan Lain&lt;/h4&gt;&lt;p style="font-size:0.92rem;"&gt;Kalimat persuasif, konjungsi kausalitas (karena, oleh karena itu), kalimat ajakan ("mari", "marilah").&lt;/p&gt;&lt;/div&gt;
    &lt;/div&gt;
  &lt;/section&gt;

  &lt;hr class="divider-dash"&gt;

  &lt;!-- ============ MATERI B: ARTIKEL OPINI ============ --&gt;
  &lt;section class="section" id="materi-b"&gt;
    &lt;div class="eyebrow"&gt;03 — Materi Inti B&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Mengenal Teks Artikel Opini sebagai Teks Pembanding&lt;/h2&gt;
    &lt;p class="lead"&gt;Teks artikel opini dipilih sebagai teks pembanding karena sama-sama bersifat persuasif, namun disampaikan melalui tulisan.&lt;/p&gt;

    &lt;div class="panel"&gt;
      &lt;p&gt;&lt;b style="color:var(--off-white);"&gt;Teks artikel opini&lt;/b&gt; adalah teks tulisan yang berisi pandangan atau pendapat penulis terhadap suatu isu, didukung fakta dan data, bertujuan meyakinkan pembaca terhadap sudut pandang tertentu.&lt;/p&gt;
    &lt;/div&gt;

    &lt;div class="grid-3"&gt;
      &lt;div class="card"&gt;&lt;h4&gt;Struktur&lt;/h4&gt;&lt;p style="font-size:0.92rem;"&gt;Pengantar/tesis (isu diangkat) → argumentasi (alasan &amp;amp; bukti) → penegasan ulang/simpulan.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;h4&gt;Sifat Penulisan&lt;/h4&gt;&lt;p style="font-size:0.92rem;"&gt;Lebih objektif, jarang memakai sapaan langsung, didukung data/fakta.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;h4&gt;Ciri Kebahasaan Lain&lt;/h4&gt;&lt;p style="font-size:0.92rem;"&gt;Kalimat argumentatif, konjungsi kausalitas &amp;amp; pertentangan, rujukan pendapat ahli/data.&lt;/p&gt;&lt;/div&gt;
    &lt;/div&gt;
  &lt;/section&gt;

  &lt;hr class="divider-dash"&gt;

  &lt;!-- ============ MATERI C: PERSAMAAN ============ --&gt;
  &lt;section class="section" id="materi-c"&gt;
    &lt;div class="eyebrow"&gt;04 — Materi Inti C&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Persamaan Teks Ceramah dan Artikel Opini&lt;/h2&gt;

    &lt;div class="criteria"&gt;
      &lt;div class="crit"&gt;
        &lt;div class="num mono"&gt;1&lt;/div&gt;
        &lt;div class="body"&gt;
          &lt;h4&gt;Sama-Sama Bersifat Persuasif&lt;/h4&gt;
          &lt;p style="margin:0;"&gt;Keduanya berusaha memengaruhi atau meyakinkan pembaca/pendengar terhadap suatu pandangan.&lt;/p&gt;
        &lt;/div&gt;
      &lt;/div&gt;
      &lt;div class="crit"&gt;
        &lt;div class="num mono"&gt;2&lt;/div&gt;
        &lt;div class="body"&gt;
          &lt;h4&gt;Menyajikan Argumen Berdasarkan Fakta&lt;/h4&gt;
          &lt;p style="margin:0;"&gt;Keduanya mendukung gagasan dengan alasan, contoh, atau data agar lebih meyakinkan.&lt;/p&gt;
        &lt;/div&gt;
      &lt;/div&gt;
      &lt;div class="crit"&gt;
        &lt;div class="num mono"&gt;3&lt;/div&gt;
        &lt;div class="body"&gt;
          &lt;h4&gt;Memiliki Struktur Pembuka-Isi-Penutup&lt;/h4&gt;
          &lt;p style="margin:0;"&gt;Keduanya tersusun dari bagian pembuka, pemaparan gagasan, dan penutup/simpulan.&lt;/p&gt;
        &lt;/div&gt;
      &lt;/div&gt;
      &lt;div class="crit"&gt;
        &lt;div class="num mono"&gt;4&lt;/div&gt;
        &lt;div class="body"&gt;
          &lt;h4&gt;Membahas Suatu Isu secara Mendalam&lt;/h4&gt;
          &lt;p style="margin:0;"&gt;Keduanya mengangkat satu topik tertentu dan membahasnya secara terfokus.&lt;/p&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/section&gt;

  &lt;hr class="divider-dash"&gt;

  &lt;!-- ============ MATERI D: PERBEDAAN ============ --&gt;
  &lt;section class="section" id="materi-d"&gt;
    &lt;div class="eyebrow"&gt;05 — Materi Inti D&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Perbedaan Teks Ceramah dan Artikel Opini&lt;/h2&gt;

    &lt;table&gt;
      &lt;tr&gt;&lt;th style="width:22%;"&gt;Aspek&lt;/th&gt;&lt;th&gt;Teks Ceramah&lt;/th&gt;&lt;th&gt;Teks Artikel Opini&lt;/th&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Media&lt;/td&gt;&lt;td&gt;Disampaikan secara lisan&lt;/td&gt;&lt;td&gt;Disampaikan secara tulisan&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Sifat Interaksi&lt;/td&gt;&lt;td&gt;Interaktif, ada kontak langsung dengan pendengar&lt;/td&gt;&lt;td&gt;Satu arah, dibaca sendiri oleh pembaca&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Kata Ganti/Sapaan&lt;/td&gt;&lt;td&gt;Sering memakai "kita/kami" dan sapaan "hadirin"&lt;/td&gt;&lt;td&gt;Lebih objektif, jarang memakai sapaan langsung&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Tema Umum&lt;/td&gt;&lt;td&gt;Sering bertema moral, agama, atau sosial&lt;/td&gt;&lt;td&gt;Lintas tema: politik, ekonomi, sosial, dan lainnya&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Cara Penyampaian&lt;/td&gt;&lt;td&gt;Intonasi, ekspresi, dan bahasa tubuh&lt;/td&gt;&lt;td&gt;Pilihan kata dan struktur kalimat tertulis&lt;/td&gt;&lt;/tr&gt;
    &lt;/table&gt;
  &lt;/section&gt;

  &lt;hr class="divider-dash"&gt;

  &lt;!-- ============ MATERI E: KELEBIHAN &amp; KEKURANGAN ============ --&gt;
  &lt;section class="section" id="materi-e"&gt;
    &lt;div class="eyebrow"&gt;06 — Materi Inti E&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Kelebihan dan Kekurangan Masing-Masing Teks&lt;/h2&gt;

    &lt;table&gt;
      &lt;tr&gt;&lt;th style="width:22%;"&gt;Jenis Teks&lt;/th&gt;&lt;th&gt;Kelebihan&lt;/th&gt;&lt;th&gt;Kekurangan&lt;/th&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Teks Ceramah&lt;/td&gt;&lt;td&gt;Dapat menyentuh emosi pendengar secara langsung melalui intonasi dan ekspresi; ada interaksi langsung (tanya jawab)&lt;/td&gt;&lt;td&gt;Sulit diulang kecuali direkam; pesan mudah terlupakan jika tidak dicatat&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Teks Artikel Opini&lt;/td&gt;&lt;td&gt;Dapat dibaca ulang kapan saja; dapat disebarluaskan lebih luas dan cepat melalui media cetak/daring&lt;/td&gt;&lt;td&gt;Tidak ada interaksi langsung dengan pembaca; kurang menyentuh emosi secara langsung&lt;/td&gt;&lt;/tr&gt;
    &lt;/table&gt;
  &lt;/section&gt;

  &lt;hr class="divider-dash"&gt;

  &lt;!-- ============ MATERI F: LANGKAH MEMBANDINGKAN ============ --&gt;
  &lt;section class="section" id="materi-f"&gt;
    &lt;div class="eyebrow"&gt;07 — Materi Inti F&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Langkah-Langkah Membandingkan Isi Dua Teks&lt;/h2&gt;

    &lt;div class="timeline"&gt;
      &lt;div class="tl-item"&gt;&lt;h4 class="mono"&gt;01 · Membaca Kedua Teks&lt;/h4&gt;&lt;p&gt;Baca teks ceramah dan artikel opini secara menyeluruh untuk memahami isi masing-masing.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="tl-item"&gt;&lt;h4 class="mono"&gt;02 · Mengidentifikasi Topik/Isu&lt;/h4&gt;&lt;p&gt;Tentukan isu atau topik yang dibahas pada masing-masing teks.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="tl-item"&gt;&lt;h4 class="mono"&gt;03 · Membandingkan Struktur &amp;amp; Cara Penyampaian&lt;/h4&gt;&lt;p&gt;Bandingkan bagian-bagian pembangun teks serta gaya penyampaian argumennya.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="tl-item"&gt;&lt;h4 class="mono"&gt;04 · Menganalisis Kelebihan &amp;amp; Kekurangan&lt;/h4&gt;&lt;p&gt;Tentukan sisi unggul dan sisi lemah masing-masing teks berdasarkan bukti dari teks.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="tl-item"&gt;&lt;h4 class="mono"&gt;05 · Menyusun Simpulan Perbandingan&lt;/h4&gt;&lt;p&gt;Tuliskan simpulan perbandingan secara ringkas dan berdasarkan bukti dari kedua teks.&lt;/p&gt;&lt;/div&gt;
    &lt;/div&gt;
  &lt;/section&gt;

  &lt;hr class="divider-dash"&gt;

  &lt;!-- ============ PEMODELAN ============ --&gt;
  &lt;section class="section" id="contoh"&gt;
    &lt;div class="eyebrow"&gt;08 — Pemodelan&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Contoh Penerapan: Membandingkan Dua Teks&lt;/h2&gt;
    &lt;p class="lead"&gt;Guru membacakan dan membahas bersama sepasang teks berikut sebagai model penerapan sebelum murid mengerjakan tugas kelompok.&lt;/p&gt;

    &lt;div class="doc-sample"&gt;
      &lt;div class="doc-head"&gt;&lt;span&gt;Lampiran · Teks Ceramah Contoh&lt;/span&gt;&lt;span&gt;Dokumen-01&lt;/span&gt;&lt;/div&gt;
      &lt;div class="doc-body"&gt;
        &lt;h3 style="color:#132029 !important;"&gt;Pentingnya Menjaga Lingkungan&lt;/h3&gt;
        &lt;p style="margin:10px 0; color:#132029 !important;"&gt;Assalamu'alaikum warahmatullahi wabarakatuh. Hadirin yang berbahagia, pada kesempatan ini marilah kita bersama-sama merenungkan pentingnya menjaga lingkungan. Kita sering melihat sampah berserakan di sekitar kita. Oleh karena itu, mari kita mulai membiasakan diri membuang sampah pada tempatnya. Dengan menjaga lingkungan, kita turut menjaga kesehatan diri dan generasi mendatang. Demikian yang dapat saya sampaikan, semoga bermanfaat. Wassalamu'alaikum warahmatullahi wabarakatuh.&lt;/p&gt;
      &lt;/div&gt;
    &lt;/div&gt;

    &lt;div class="doc-sample" style="margin-top:22px;"&gt;
      &lt;div class="doc-head"&gt;&lt;span&gt;Lampiran · Teks Artikel Opini Contoh&lt;/span&gt;&lt;span&gt;Dokumen-02&lt;/span&gt;&lt;/div&gt;
      &lt;div class="doc-body"&gt;
        &lt;h3 style="color:#132029 !important;"&gt;Pentingnya Menjaga Lingkungan bagi Generasi Mendatang&lt;/h3&gt;
        &lt;p style="margin:10px 0; color:#132029 !important;"&gt;Masalah sampah masih menjadi persoalan serius di berbagai daerah. Berdasarkan data Kementerian Lingkungan Hidup, volume sampah nasional terus meningkat setiap tahun. Kondisi ini menunjukkan bahwa kesadaran masyarakat dalam mengelola sampah masih rendah. Oleh sebab itu, diperlukan edukasi berkelanjutan mengenai pengelolaan sampah sejak dini agar generasi mendatang dapat hidup di lingkungan yang lebih bersih dan sehat.&lt;/p&gt;
      &lt;/div&gt;
    &lt;/div&gt;

    &lt;div class="panel" style="margin-top:22px;"&gt;
      &lt;p style="margin:0;"&gt;&lt;b style="color:var(--off-white);"&gt;Simpulan model perbandingan:&lt;/b&gt; Kedua teks membahas isu yang sama, yaitu menjaga lingkungan. Teks ceramah menggunakan sapaan religius dan kalimat ajakan langsung ("mari kita..."), sedangkan artikel opini menggunakan data resmi sebagai penguat argumen dengan bahasa yang lebih formal dan objektif. Kelebihan ceramah terletak pada kedekatan emosional melalui sapaan langsung, sementara kelebihan artikel opini terletak pada kekuatan argumen berbasis data yang dapat diverifikasi.&lt;/p&gt;
    &lt;/div&gt;
  &lt;/section&gt;

  &lt;hr class="divider-dash"&gt;

  &lt;!-- ============ RANGKUMAN ============ --&gt;
  &lt;section class="section" id="rangkuman"&gt;
    &lt;div class="eyebrow"&gt;09 — Ringkasan Materi&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Poin-Poin Penting&lt;/h2&gt;
    &lt;div class="summary-box"&gt;
      &lt;ul&gt;
        &lt;li&gt;Teks ceramah disampaikan secara lisan dan interaktif, sedangkan artikel opini disampaikan secara tulisan dan satu arah.&lt;/li&gt;
        &lt;li&gt;Persamaan keduanya: bersifat persuasif, menyajikan argumen berdasarkan fakta, dan memiliki struktur pembuka-isi-penutup.&lt;/li&gt;
        &lt;li&gt;Kelebihan ceramah adalah kedekatan emosional langsung; kekurangannya sulit diulang. Kelebihan artikel opini adalah dapat dibaca ulang dan disebarluaskan luas; kekurangannya tidak ada interaksi langsung.&lt;/li&gt;
        &lt;li&gt;Membandingkan dilakukan bertahap: membaca kedua teks → mengidentifikasi topik → membandingkan struktur → menganalisis kelebihan-kekurangan → menyusun simpulan.&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/div&gt;
  &lt;/section&gt;

  &lt;hr class="divider-dash"&gt;

  &lt;!-- ============ TUGAS KELOMPOK ============ --&gt;
  &lt;section class="section" id="tugas-kelompok"&gt;
    &lt;div class="eyebrow"&gt;10 — Lembar Kerja&lt;/div&gt;
    &lt;div class="task-header"&gt;
      &lt;h2&gt;Tugas Kelompok: Membandingkan Teks Ceramah dan Artikel Opini&lt;/h2&gt;
      &lt;span class="badge"&gt;Durasi ± 60 menit&lt;/span&gt;
    &lt;/div&gt;

    &lt;p style="margin-top:18px;"&gt;&lt;b style="color:var(--off-white);"&gt;Tujuan tugas:&lt;/b&gt; Murid secara berkelompok membandingkan sepasang teks bertema sama berikut, lalu menemukan persamaan, perbedaan, kelebihan, dan kekurangan masing-masing.&lt;/p&gt;

    &lt;div class="doc-sample" style="margin-top:20px;"&gt;
      &lt;div class="doc-head"&gt;&lt;span&gt;Lampiran · Teks Ceramah untuk Dibandingkan&lt;/span&gt;&lt;span&gt;Dokumen-03&lt;/span&gt;&lt;/div&gt;
      &lt;div class="doc-body"&gt;
        &lt;h3 style="color:#132029 !important;"&gt;Pentingnya Membaca Buku&lt;/h3&gt;
        &lt;p style="margin:10px 0; color:#132029 !important;"&gt;Assalamu'alaikum warahmatullahi wabarakatuh. Bapak/Ibu dan saudara sekalian yang saya hormati, pada hari ini izinkan saya menyampaikan sedikit renungan tentang pentingnya membaca buku. Di era digital ini, banyak dari kita lebih memilih menghabiskan waktu dengan gawai dibandingkan membaca buku. Padahal, buku adalah jendela ilmu yang dapat membuka wawasan kita seluas-luasnya. Oleh karena itu, marilah kita mulai membiasakan diri membaca buku minimal beberapa menit setiap hari. Dengan membiasakan membaca, kita akan menjadi pribadi yang lebih bijaksana dalam bertindak. Demikian yang dapat saya sampaikan. Wassalamu'alaikum warahmatullahi wabarakatuh.&lt;/p&gt;
      &lt;/div&gt;
    &lt;/div&gt;

    &lt;div class="doc-sample" style="margin-top:20px;"&gt;
      &lt;div class="doc-head"&gt;&lt;span&gt;Lampiran · Teks Artikel Opini untuk Dibandingkan&lt;/span&gt;&lt;span&gt;Dokumen-04&lt;/span&gt;&lt;/div&gt;
      &lt;div class="doc-body"&gt;
        &lt;h3 style="color:#132029 !important;"&gt;Minat Baca Rendah, Tantangan Generasi Digital&lt;/h3&gt;
        &lt;p style="margin:10px 0; color:#132029 !important;"&gt;Data dari sebuah survei literasi menunjukkan bahwa minat baca masyarakat Indonesia masih tergolong rendah dibandingkan negara lain. Fenomena ini erat kaitannya dengan maraknya penggunaan gawai untuk hiburan singkat seperti media sosial. Akibatnya, kemampuan berpikir kritis dan mendalam masyarakat berpotensi menurun. Oleh sebab itu, diperlukan upaya bersama, mulai dari keluarga hingga sekolah, untuk membangun kembali kebiasaan membaca buku sejak usia dini.&lt;/p&gt;
      &lt;/div&gt;
    &lt;/div&gt;

    &lt;h4 style="color:var(--off-white); margin-top:26px;"&gt;Petunjuk Pengerjaan&lt;/h4&gt;
    &lt;ol class="steps-num"&gt;
      &lt;li&gt;&lt;b&gt;Bentuk kelompok&lt;/b&gt; beranggotakan 4–5 orang sesuai pembagian dari guru.&lt;/li&gt;
      &lt;li&gt;&lt;b&gt;Baca kedua teks&lt;/b&gt; di atas secara bersama-sama dalam kelompok.&lt;/li&gt;
      &lt;li&gt;&lt;b&gt;Identifikasi persamaan dan perbedaan&lt;/b&gt; kedua teks berdasarkan struktur, kata ganti/sapaan, dan cara penyampaian.&lt;/li&gt;
      &lt;li&gt;&lt;b&gt;Isi Tabel Kelebihan dan Kekurangan&lt;/b&gt; di bawah ini untuk masing-masing teks.&lt;/li&gt;
      &lt;li&gt;&lt;b&gt;Presentasikan hasil&lt;/b&gt; di depan kelas selama maksimal 5 menit per kelompok, dilanjutkan tanya jawab singkat.&lt;/li&gt;
    &lt;/ol&gt;

    &lt;h4 style="color:var(--off-white); margin-top:26px;"&gt;Format Tabel Kelebihan dan Kekurangan&lt;/h4&gt;
    &lt;table&gt;
      &lt;tr&gt;&lt;th style="width:22%;"&gt;Jenis Teks&lt;/th&gt;&lt;th&gt;Kelebihan&lt;/th&gt;&lt;th&gt;Kekurangan&lt;/th&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Teks Ceramah&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Teks Artikel Opini&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;/table&gt;

    &lt;h4 style="color:var(--off-white); margin-top:26px;"&gt;Rubrik Penilaian Kelompok&lt;/h4&gt;
    &lt;table&gt;
      &lt;tr&gt;&lt;th style="width:26%;"&gt;Aspek Penilaian&lt;/th&gt;&lt;th&gt;Skor 4 (Sangat Baik)&lt;/th&gt;&lt;th&gt;Skor 3 (Baik)&lt;/th&gt;&lt;th&gt;Skor 2 (Cukup)&lt;/th&gt;&lt;th&gt;Skor 1 (Kurang)&lt;/th&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Ketepatan identifikasi persamaan &amp;amp; perbedaan&lt;/td&gt;&lt;td&gt;Seluruh aspek teridentifikasi tepat dengan bukti jelas&lt;/td&gt;&lt;td&gt;Sebagian besar tepat&lt;/td&gt;&lt;td&gt;Identifikasi dangkal&lt;/td&gt;&lt;td&gt;Tidak sesuai&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Ketepatan analisis kelebihan &amp;amp; kekurangan&lt;/td&gt;&lt;td&gt;Analisis tepat dan didukung bukti dari teks&lt;/td&gt;&lt;td&gt;Sebagian besar tepat&lt;/td&gt;&lt;td&gt;Analisis kurang didukung bukti&lt;/td&gt;&lt;td&gt;Tidak tepat&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Kerja sama kelompok&lt;/td&gt;&lt;td&gt;Seluruh anggota aktif berkontribusi&lt;/td&gt;&lt;td&gt;Sebagian besar anggota aktif&lt;/td&gt;&lt;td&gt;Hanya sebagian kecil anggota aktif&lt;/td&gt;&lt;td&gt;Didominasi satu orang&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Presentasi&lt;/td&gt;&lt;td&gt;Jelas, percaya diri, menjawab pertanyaan dengan baik&lt;/td&gt;&lt;td&gt;Jelas namun kurang percaya diri&lt;/td&gt;&lt;td&gt;Kurang jelas/terbata-bata&lt;/td&gt;&lt;td&gt;Tidak dapat menjelaskan hasil&lt;/td&gt;&lt;/tr&gt;
    &lt;/table&gt;
  &lt;/section&gt;

  &lt;hr class="divider-dash"&gt;

  &lt;!-- ============ TUGAS INDIVIDU: KUIS 25 PERTANYAAN ============ --&gt;
  &lt;section class="section" id="tugas-individu"&gt;
    &lt;div class="eyebrow"&gt;11 — Penutup Pembelajaran&lt;/div&gt;
    &lt;div class="task-header"&gt;
      &lt;h2&gt;Tugas Individu: Menjawab 25 Pertanyaan tentang Materi&lt;/h2&gt;
      &lt;span class="badge"&gt;Dikerjakan Mandiri · Otomatis Bernilai&lt;/span&gt;
    &lt;/div&gt;

    &lt;p style="margin-top:18px;"&gt;&lt;b style="color:var(--off-white);"&gt;Petunjuk:&lt;/b&gt; Isi No. Absen dan Nama, lalu jawab 25 pertanyaan pilihan ganda (5 opsi) berikut berdasarkan materi yang telah dipelajari hari ini — terdiri atas 10 soal mudah, 10 soal sedang, dan 5 soal sulit. Skor akan muncul otomatis setelah menekan tombol "Kirim Jawaban", dan hasilnya akan tercatat otomatis.&lt;/p&gt;

    &lt;div class="panel" style="margin-top:20px;"&gt;
      &lt;div style="display:grid; grid-template-columns:1fr 2fr; gap:14px; margin-bottom:22px;"&gt;
        &lt;div&gt;
          &lt;label class="mono" style="display:block; font-size:0.75rem; color:var(--amber); text-transform:uppercase; letter-spacing:0.08em; margin-bottom:6px;"&gt;No. Absen&lt;/label&gt;
          &lt;input id="cq-absen" type="text" inputmode="numeric" placeholder="Contoh: 12" style="width:100%; padding:10px 12px; border-radius:2px; border:1px solid var(--line); background:var(--blueprint-deep); color:var(--off-white); font-family:'Source Sans 3',sans-serif; font-size:0.95rem;"&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;label class="mono" style="display:block; font-size:0.75rem; color:var(--amber); text-transform:uppercase; letter-spacing:0.08em; margin-bottom:6px;"&gt;Nama Lengkap&lt;/label&gt;
          &lt;input id="cq-nama" type="text" placeholder="Tulis nama lengkap" style="width:100%; padding:10px 12px; border-radius:2px; border:1px solid var(--line); background:var(--blueprint-deep); color:var(--off-white); font-family:'Source Sans 3',sans-serif; font-size:0.95rem;"&gt;
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;div style="margin-bottom:20px; padding-bottom:16px; border-bottom:1px dashed rgba(234,242,245,0.16);"&gt;
        &lt;span class="mono" style="display:inline-block; font-size:0.68rem; letter-spacing:0.08em; text-transform:uppercase; color:#6EC6CA !important; border:1px solid #6EC6CA; padding:2px 8px; margin-bottom:6px;"&gt;Mudah&lt;/span&gt;
        &lt;p style="color:#EAF2F5 !important; font-weight:600; margin:6px 0 8px;"&gt;1. Teks yang berisi pidato bertujuan memberi nasihat atau wejangan kepada pendengar disebut teks...&lt;/p&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq0" value="0" style="margin-right:8px;"&gt;A. Artikel&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq0" value="1" style="margin-right:8px;"&gt;B. Ceramah&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq0" value="2" style="margin-right:8px;"&gt;C. Prosedur&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq0" value="3" style="margin-right:8px;"&gt;D. Eksplanasi&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq0" value="4" style="margin-right:8px;"&gt;E. Anekdot&lt;/label&gt;
      &lt;/div&gt;
      &lt;div style="margin-bottom:20px; padding-bottom:16px; border-bottom:1px dashed rgba(234,242,245,0.16);"&gt;
        &lt;span class="mono" style="display:inline-block; font-size:0.68rem; letter-spacing:0.08em; text-transform:uppercase; color:#6EC6CA !important; border:1px solid #6EC6CA; padding:2px 8px; margin-bottom:6px;"&gt;Mudah&lt;/span&gt;
        &lt;p style="color:#EAF2F5 !important; font-weight:600; margin:6px 0 8px;"&gt;2. Bagian struktur teks ceramah yang berisi salam dan sapaan disebut...&lt;/p&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq1" value="0" style="margin-right:8px;"&gt;A. Isi&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq1" value="1" style="margin-right:8px;"&gt;B. Penutup&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq1" value="2" style="margin-right:8px;"&gt;C. Pembukaan&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq1" value="3" style="margin-right:8px;"&gt;D. Simpulan&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq1" value="4" style="margin-right:8px;"&gt;E. Argumen&lt;/label&gt;
      &lt;/div&gt;
      &lt;div style="margin-bottom:20px; padding-bottom:16px; border-bottom:1px dashed rgba(234,242,245,0.16);"&gt;
        &lt;span class="mono" style="display:inline-block; font-size:0.68rem; letter-spacing:0.08em; text-transform:uppercase; color:#6EC6CA !important; border:1px solid #6EC6CA; padding:2px 8px; margin-bottom:6px;"&gt;Mudah&lt;/span&gt;
        &lt;p style="color:#EAF2F5 !important; font-weight:600; margin:6px 0 8px;"&gt;3. Kata ganti yang sering digunakan dalam teks ceramah untuk menyapa pendengar adalah...&lt;/p&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq2" value="0" style="margin-right:8px;"&gt;A. Saya&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq2" value="1" style="margin-right:8px;"&gt;B. Kalian&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq2" value="2" style="margin-right:8px;"&gt;C. Hadirin&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq2" value="3" style="margin-right:8px;"&gt;D. Mereka&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq2" value="4" style="margin-right:8px;"&gt;E. Dia&lt;/label&gt;
      &lt;/div&gt;
      &lt;div style="margin-bottom:20px; padding-bottom:16px; border-bottom:1px dashed rgba(234,242,245,0.16);"&gt;
        &lt;span class="mono" style="display:inline-block; font-size:0.68rem; letter-spacing:0.08em; text-transform:uppercase; color:#6EC6CA !important; border:1px solid #6EC6CA; padding:2px 8px; margin-bottom:6px;"&gt;Mudah&lt;/span&gt;
        &lt;p style="color:#EAF2F5 !important; font-weight:600; margin:6px 0 8px;"&gt;4. Teks tulisan yang berisi pendapat penulis terhadap suatu isu disebut teks...&lt;/p&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq3" value="0" style="margin-right:8px;"&gt;A. Ceramah&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq3" value="1" style="margin-right:8px;"&gt;B. Artikel opini&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq3" value="2" style="margin-right:8px;"&gt;C. Prosedur&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq3" value="3" style="margin-right:8px;"&gt;D. Deskripsi&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq3" value="4" style="margin-right:8px;"&gt;E. Anekdot&lt;/label&gt;
      &lt;/div&gt;
      &lt;div style="margin-bottom:20px; padding-bottom:16px; border-bottom:1px dashed rgba(234,242,245,0.16);"&gt;
        &lt;span class="mono" style="display:inline-block; font-size:0.68rem; letter-spacing:0.08em; text-transform:uppercase; color:#6EC6CA !important; border:1px solid #6EC6CA; padding:2px 8px; margin-bottom:6px;"&gt;Mudah&lt;/span&gt;
        &lt;p style="color:#EAF2F5 !important; font-weight:600; margin:6px 0 8px;"&gt;5. Bagian struktur artikel opini yang berisi isu yang diangkat disebut...&lt;/p&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq4" value="0" style="margin-right:8px;"&gt;A. Argumentasi&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq4" value="1" style="margin-right:8px;"&gt;B. Pengantar/tesis&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq4" value="2" style="margin-right:8px;"&gt;C. Penutup&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq4" value="3" style="margin-right:8px;"&gt;D. Interpretasi&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq4" value="4" style="margin-right:8px;"&gt;E. Orientasi&lt;/label&gt;
      &lt;/div&gt;
      &lt;div style="margin-bottom:20px; padding-bottom:16px; border-bottom:1px dashed rgba(234,242,245,0.16);"&gt;
        &lt;span class="mono" style="display:inline-block; font-size:0.68rem; letter-spacing:0.08em; text-transform:uppercase; color:#6EC6CA !important; border:1px solid #6EC6CA; padding:2px 8px; margin-bottom:6px;"&gt;Mudah&lt;/span&gt;
        &lt;p style="color:#EAF2F5 !important; font-weight:600; margin:6px 0 8px;"&gt;6. Manakah media penyampaian teks ceramah?&lt;/p&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq5" value="0" style="margin-right:8px;"&gt;A. Tulisan&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq5" value="1" style="margin-right:8px;"&gt;B. Lisan&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq5" value="2" style="margin-right:8px;"&gt;C. Gambar&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq5" value="3" style="margin-right:8px;"&gt;D. Video tanpa suara&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq5" value="4" style="margin-right:8px;"&gt;E. Simbol&lt;/label&gt;
      &lt;/div&gt;
      &lt;div style="margin-bottom:20px; padding-bottom:16px; border-bottom:1px dashed rgba(234,242,245,0.16);"&gt;
        &lt;span class="mono" style="display:inline-block; font-size:0.68rem; letter-spacing:0.08em; text-transform:uppercase; color:#6EC6CA !important; border:1px solid #6EC6CA; padding:2px 8px; margin-bottom:6px;"&gt;Mudah&lt;/span&gt;
        &lt;p style="color:#EAF2F5 !important; font-weight:600; margin:6px 0 8px;"&gt;7. Manakah media penyampaian teks artikel opini?&lt;/p&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq6" value="0" style="margin-right:8px;"&gt;A. Lisan&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq6" value="1" style="margin-right:8px;"&gt;B. Tulisan&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq6" value="2" style="margin-right:8px;"&gt;C. Gerakan tubuh&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq6" value="3" style="margin-right:8px;"&gt;D. Suara tanpa kata&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq6" value="4" style="margin-right:8px;"&gt;E. Simbol&lt;/label&gt;
      &lt;/div&gt;
      &lt;div style="margin-bottom:20px; padding-bottom:16px; border-bottom:1px dashed rgba(234,242,245,0.16);"&gt;
        &lt;span class="mono" style="display:inline-block; font-size:0.68rem; letter-spacing:0.08em; text-transform:uppercase; color:#6EC6CA !important; border:1px solid #6EC6CA; padding:2px 8px; margin-bottom:6px;"&gt;Mudah&lt;/span&gt;
        &lt;p style="color:#EAF2F5 !important; font-weight:600; margin:6px 0 8px;"&gt;8. Kalimat “Marilah kita menjaga lingkungan bersama-sama” termasuk kalimat...&lt;/p&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq7" value="0" style="margin-right:8px;"&gt;A. Deklaratif&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq7" value="1" style="margin-right:8px;"&gt;B. Interogatif&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq7" value="2" style="margin-right:8px;"&gt;C. Persuasif&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq7" value="3" style="margin-right:8px;"&gt;D. Naratif&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq7" value="4" style="margin-right:8px;"&gt;E. Deskriptif&lt;/label&gt;
      &lt;/div&gt;
      &lt;div style="margin-bottom:20px; padding-bottom:16px; border-bottom:1px dashed rgba(234,242,245,0.16);"&gt;
        &lt;span class="mono" style="display:inline-block; font-size:0.68rem; letter-spacing:0.08em; text-transform:uppercase; color:#6EC6CA !important; border:1px solid #6EC6CA; padding:2px 8px; margin-bottom:6px;"&gt;Mudah&lt;/span&gt;
        &lt;p style="color:#EAF2F5 !important; font-weight:600; margin:6px 0 8px;"&gt;9. Konjungsi yang menunjukkan sebab-akibat disebut konjungsi...&lt;/p&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq8" value="0" style="margin-right:8px;"&gt;A. Temporal&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq8" value="1" style="margin-right:8px;"&gt;B. Kausalitas&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq8" value="2" style="margin-right:8px;"&gt;C. Pertentangan&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq8" value="3" style="margin-right:8px;"&gt;D. Pilihan&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq8" value="4" style="margin-right:8px;"&gt;E. Penjumlahan&lt;/label&gt;
      &lt;/div&gt;
      &lt;div style="margin-bottom:20px; padding-bottom:16px; border-bottom:1px dashed rgba(234,242,245,0.16);"&gt;
        &lt;span class="mono" style="display:inline-block; font-size:0.68rem; letter-spacing:0.08em; text-transform:uppercase; color:#6EC6CA !important; border:1px solid #6EC6CA; padding:2px 8px; margin-bottom:6px;"&gt;Mudah&lt;/span&gt;
        &lt;p style="color:#EAF2F5 !important; font-weight:600; margin:6px 0 8px;"&gt;10. Apa tujuan utama dari kedua teks ceramah dan artikel opini?&lt;/p&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq9" value="0" style="margin-right:8px;"&gt;A. Menghibur pembaca&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq9" value="1" style="margin-right:8px;"&gt;B. Memengaruhi/meyakinkan pembaca atau pendengar&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq9" value="2" style="margin-right:8px;"&gt;C. Menceritakan pengalaman pribadi&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq9" value="3" style="margin-right:8px;"&gt;D. Menjelaskan langkah kerja&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq9" value="4" style="margin-right:8px;"&gt;E. Menjual produk&lt;/label&gt;
      &lt;/div&gt;
      &lt;div style="margin-bottom:20px; padding-bottom:16px; border-bottom:1px dashed rgba(234,242,245,0.16);"&gt;
        &lt;span class="mono" style="display:inline-block; font-size:0.68rem; letter-spacing:0.08em; text-transform:uppercase; color:#F5A623 !important; border:1px solid #F5A623; padding:2px 8px; margin-bottom:6px;"&gt;Sedang&lt;/span&gt;
        &lt;p style="color:#EAF2F5 !important; font-weight:600; margin:6px 0 8px;"&gt;11. Manakah persamaan antara teks ceramah dan artikel opini?&lt;/p&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq10" value="0" style="margin-right:8px;"&gt;A. Keduanya bersifat naratif&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq10" value="1" style="margin-right:8px;"&gt;B. Keduanya bersifat persuasif dan menyajikan argumen&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq10" value="2" style="margin-right:8px;"&gt;C. Keduanya tidak memiliki struktur&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq10" value="3" style="margin-right:8px;"&gt;D. Keduanya tidak menggunakan konjungsi&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq10" value="4" style="margin-right:8px;"&gt;E. Keduanya tidak membahas isu tertentu&lt;/label&gt;
      &lt;/div&gt;
      &lt;div style="margin-bottom:20px; padding-bottom:16px; border-bottom:1px dashed rgba(234,242,245,0.16);"&gt;
        &lt;span class="mono" style="display:inline-block; font-size:0.68rem; letter-spacing:0.08em; text-transform:uppercase; color:#F5A623 !important; border:1px solid #F5A623; padding:2px 8px; margin-bottom:6px;"&gt;Sedang&lt;/span&gt;
        &lt;p style="color:#EAF2F5 !important; font-weight:600; margin:6px 0 8px;"&gt;12. Perbedaan utama cara penyampaian pesan antara ceramah dan artikel opini adalah...&lt;/p&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq11" value="0" style="margin-right:8px;"&gt;A. Ceramah menggunakan intonasi dan ekspresi, artikel opini menggunakan pilihan kata tertulis&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq11" value="1" style="margin-right:8px;"&gt;B. Keduanya sama-sama menggunakan gambar&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq11" value="2" style="margin-right:8px;"&gt;C. Ceramah tidak memiliki pesan&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq11" value="3" style="margin-right:8px;"&gt;D. Artikel opini disampaikan secara lisan&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq11" value="4" style="margin-right:8px;"&gt;E. Keduanya tidak memiliki tujuan&lt;/label&gt;
      &lt;/div&gt;
      &lt;div style="margin-bottom:20px; padding-bottom:16px; border-bottom:1px dashed rgba(234,242,245,0.16);"&gt;
        &lt;span class="mono" style="display:inline-block; font-size:0.68rem; letter-spacing:0.08em; text-transform:uppercase; color:#F5A623 !important; border:1px solid #F5A623; padding:2px 8px; margin-bottom:6px;"&gt;Sedang&lt;/span&gt;
        &lt;p style="color:#EAF2F5 !important; font-weight:600; margin:6px 0 8px;"&gt;13. Salah satu kelebihan teks ceramah dibandingkan artikel opini adalah...&lt;/p&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq12" value="0" style="margin-right:8px;"&gt;A. Dapat dibaca ulang kapan saja&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq12" value="1" style="margin-right:8px;"&gt;B. Dapat menyentuh emosi pendengar secara langsung&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq12" value="2" style="margin-right:8px;"&gt;C. Lebih mudah disebarluaskan&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq12" value="3" style="margin-right:8px;"&gt;D. Lebih objektif&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq12" value="4" style="margin-right:8px;"&gt;E. Tidak memerlukan persiapan&lt;/label&gt;
      &lt;/div&gt;
      &lt;div style="margin-bottom:20px; padding-bottom:16px; border-bottom:1px dashed rgba(234,242,245,0.16);"&gt;
        &lt;span class="mono" style="display:inline-block; font-size:0.68rem; letter-spacing:0.08em; text-transform:uppercase; color:#F5A623 !important; border:1px solid #F5A623; padding:2px 8px; margin-bottom:6px;"&gt;Sedang&lt;/span&gt;
        &lt;p style="color:#EAF2F5 !important; font-weight:600; margin:6px 0 8px;"&gt;14. Salah satu kekurangan teks ceramah dibandingkan artikel opini adalah...&lt;/p&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq13" value="0" style="margin-right:8px;"&gt;A. Sulit diulang kecuali direkam&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq13" value="1" style="margin-right:8px;"&gt;B. Tidak dapat menyentuh emosi&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq13" value="2" style="margin-right:8px;"&gt;C. Tidak memiliki struktur&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq13" value="3" style="margin-right:8px;"&gt;D. Tidak bisa disampaikan di depan umum&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq13" value="4" style="margin-right:8px;"&gt;E. Tidak memiliki tujuan&lt;/label&gt;
      &lt;/div&gt;
      &lt;div style="margin-bottom:20px; padding-bottom:16px; border-bottom:1px dashed rgba(234,242,245,0.16);"&gt;
        &lt;span class="mono" style="display:inline-block; font-size:0.68rem; letter-spacing:0.08em; text-transform:uppercase; color:#F5A623 !important; border:1px solid #F5A623; padding:2px 8px; margin-bottom:6px;"&gt;Sedang&lt;/span&gt;
        &lt;p style="color:#EAF2F5 !important; font-weight:600; margin:6px 0 8px;"&gt;15. Salah satu kelebihan artikel opini dibandingkan ceramah adalah...&lt;/p&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq14" value="0" style="margin-right:8px;"&gt;A. Lebih menyentuh emosi secara langsung&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq14" value="1" style="margin-right:8px;"&gt;B. Dapat dibaca ulang dan disebarluaskan lebih luas&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq14" value="2" style="margin-right:8px;"&gt;C. Selalu lebih pendek&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq14" value="3" style="margin-right:8px;"&gt;D. Tidak memerlukan data&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq14" value="4" style="margin-right:8px;"&gt;E. Tidak memiliki penulis&lt;/label&gt;
      &lt;/div&gt;
      &lt;div style="margin-bottom:20px; padding-bottom:16px; border-bottom:1px dashed rgba(234,242,245,0.16);"&gt;
        &lt;span class="mono" style="display:inline-block; font-size:0.68rem; letter-spacing:0.08em; text-transform:uppercase; color:#F5A623 !important; border:1px solid #F5A623; padding:2px 8px; margin-bottom:6px;"&gt;Sedang&lt;/span&gt;
        &lt;p style="color:#EAF2F5 !important; font-weight:600; margin:6px 0 8px;"&gt;16. Mengapa teks ceramah sering menggunakan kata ganti “kita” atau “kami”?&lt;/p&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq15" value="0" style="margin-right:8px;"&gt;A. Untuk membangun kedekatan dengan pendengar&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq15" value="1" style="margin-right:8px;"&gt;B. Karena aturan tata bahasa baku&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq15" value="2" style="margin-right:8px;"&gt;C. Agar teks lebih panjang&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq15" value="3" style="margin-right:8px;"&gt;D. Untuk menghindari kesalahan tata bahasa&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq15" value="4" style="margin-right:8px;"&gt;E. Tidak ada alasan khusus&lt;/label&gt;
      &lt;/div&gt;
      &lt;div style="margin-bottom:20px; padding-bottom:16px; border-bottom:1px dashed rgba(234,242,245,0.16);"&gt;
        &lt;span class="mono" style="display:inline-block; font-size:0.68rem; letter-spacing:0.08em; text-transform:uppercase; color:#F5A623 !important; border:1px solid #F5A623; padding:2px 8px; margin-bottom:6px;"&gt;Sedang&lt;/span&gt;
        &lt;p style="color:#EAF2F5 !important; font-weight:600; margin:6px 0 8px;"&gt;17. Artikel opini cenderung lebih objektif dibanding ceramah karena...&lt;/p&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq16" value="0" style="margin-right:8px;"&gt;A. Menggunakan data dan fakta sebagai penguat argumen&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq16" value="1" style="margin-right:8px;"&gt;B. Tidak memiliki penulis&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq16" value="2" style="margin-right:8px;"&gt;C. Tidak membahas isu apa pun&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq16" value="3" style="margin-right:8px;"&gt;D. Selalu ditulis oleh banyak orang&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq16" value="4" style="margin-right:8px;"&gt;E. Tidak memiliki struktur&lt;/label&gt;
      &lt;/div&gt;
      &lt;div style="margin-bottom:20px; padding-bottom:16px; border-bottom:1px dashed rgba(234,242,245,0.16);"&gt;
        &lt;span class="mono" style="display:inline-block; font-size:0.68rem; letter-spacing:0.08em; text-transform:uppercase; color:#F5A623 !important; border:1px solid #F5A623; padding:2px 8px; margin-bottom:6px;"&gt;Sedang&lt;/span&gt;
        &lt;p style="color:#EAF2F5 !important; font-weight:600; margin:6px 0 8px;"&gt;18. Langkah pertama dalam membandingkan isi dua teks adalah...&lt;/p&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq17" value="0" style="margin-right:8px;"&gt;A. Menyusun simpulan langsung&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq17" value="1" style="margin-right:8px;"&gt;B. Membaca kedua teks secara menyeluruh&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq17" value="2" style="margin-right:8px;"&gt;C. Menilai kelebihan tanpa membaca&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq17" value="3" style="margin-right:8px;"&gt;D. Menghapus salah satu teks&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq17" value="4" style="margin-right:8px;"&gt;E. Menyajikan secara lisan&lt;/label&gt;
      &lt;/div&gt;
      &lt;div style="margin-bottom:20px; padding-bottom:16px; border-bottom:1px dashed rgba(234,242,245,0.16);"&gt;
        &lt;span class="mono" style="display:inline-block; font-size:0.68rem; letter-spacing:0.08em; text-transform:uppercase; color:#F5A623 !important; border:1px solid #F5A623; padding:2px 8px; margin-bottom:6px;"&gt;Sedang&lt;/span&gt;
        &lt;p style="color:#EAF2F5 !important; font-weight:600; margin:6px 0 8px;"&gt;19. Konjungsi “oleh karena itu” dalam teks ceramah maupun artikel opini umumnya berfungsi untuk...&lt;/p&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq18" value="0" style="margin-right:8px;"&gt;A. Menandai urutan waktu&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq18" value="1" style="margin-right:8px;"&gt;B. Menyimpulkan atau menegaskan alasan sebelumnya&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq18" value="2" style="margin-right:8px;"&gt;C. Menyatakan pertentangan&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq18" value="3" style="margin-right:8px;"&gt;D. Menyatakan pilihan&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq18" value="4" style="margin-right:8px;"&gt;E. Menambahkan informasi tanpa kaitan&lt;/label&gt;
      &lt;/div&gt;
      &lt;div style="margin-bottom:20px; padding-bottom:16px; border-bottom:1px dashed rgba(234,242,245,0.16);"&gt;
        &lt;span class="mono" style="display:inline-block; font-size:0.68rem; letter-spacing:0.08em; text-transform:uppercase; color:#F5A623 !important; border:1px solid #F5A623; padding:2px 8px; margin-bottom:6px;"&gt;Sedang&lt;/span&gt;
        &lt;p style="color:#EAF2F5 !important; font-weight:600; margin:6px 0 8px;"&gt;20. Manakah pernyataan yang tepat tentang struktur kedua teks?&lt;/p&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq19" value="0" style="margin-right:8px;"&gt;A. Ceramah tidak memiliki struktur&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq19" value="1" style="margin-right:8px;"&gt;B. Keduanya sama-sama memiliki bagian pembuka, isi, dan penutup meski istilahnya berbeda&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq19" value="2" style="margin-right:8px;"&gt;C. Artikel opini tidak memiliki penutup&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq19" value="3" style="margin-right:8px;"&gt;D. Keduanya identik tanpa perbedaan&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq19" value="4" style="margin-right:8px;"&gt;E. Ceramah tidak memiliki bagian isi&lt;/label&gt;
      &lt;/div&gt;
      &lt;div style="margin-bottom:20px; padding-bottom:16px; border-bottom:1px dashed rgba(234,242,245,0.16);"&gt;
        &lt;span class="mono" style="display:inline-block; font-size:0.68rem; letter-spacing:0.08em; text-transform:uppercase; color:#D94E2A !important; border:1px solid #D94E2A; padding:2px 8px; margin-bottom:6px;"&gt;Sulit&lt;/span&gt;
        &lt;p style="color:#EAF2F5 !important; font-weight:600; margin:6px 0 8px;"&gt;21. Sebuah ceramah dan artikel opini membahas isu yang sama, yaitu pentingnya menabung. Manakah simpulan yang paling tepat menggambarkan perbedaan pendekatan keduanya?&lt;/p&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq20" value="0" style="margin-right:8px;"&gt;A. Ceramah cenderung mengandalkan kedekatan emosional dan ajakan langsung, sedangkan artikel opini mengandalkan data dan argumentasi tertulis&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq20" value="1" style="margin-right:8px;"&gt;B. Keduanya menggunakan pendekatan yang sama persis&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq20" value="2" style="margin-right:8px;"&gt;C. Ceramah tidak memiliki pendekatan persuasif&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq20" value="3" style="margin-right:8px;"&gt;D. Artikel opini tidak membahas data&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq20" value="4" style="margin-right:8px;"&gt;E. Keduanya tidak dapat dibandingkan&lt;/label&gt;
      &lt;/div&gt;
      &lt;div style="margin-bottom:20px; padding-bottom:16px; border-bottom:1px dashed rgba(234,242,245,0.16);"&gt;
        &lt;span class="mono" style="display:inline-block; font-size:0.68rem; letter-spacing:0.08em; text-transform:uppercase; color:#D94E2A !important; border:1px solid #D94E2A; padding:2px 8px; margin-bottom:6px;"&gt;Sulit&lt;/span&gt;
        &lt;p style="color:#EAF2F5 !important; font-weight:600; margin:6px 0 8px;"&gt;22. Jika sebuah artikel opini ingin dijadikan bahan ceramah, penyesuaian apa yang paling penting dilakukan?&lt;/p&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq21" value="0" style="margin-right:8px;"&gt;A. Menambahkan sapaan, kata ganti “kita”, dan kalimat ajakan langsung yang sesuai penyampaian lisan&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq21" value="1" style="margin-right:8px;"&gt;B. Menghapus seluruh data pendukung&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq21" value="2" style="margin-right:8px;"&gt;C. Mengubahnya menjadi teks prosedur&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq21" value="3" style="margin-right:8px;"&gt;D. Menghapus argumen utama&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq21" value="4" style="margin-right:8px;"&gt;E. Tidak perlu penyesuaian apa pun&lt;/label&gt;
      &lt;/div&gt;
      &lt;div style="margin-bottom:20px; padding-bottom:16px; border-bottom:1px dashed rgba(234,242,245,0.16);"&gt;
        &lt;span class="mono" style="display:inline-block; font-size:0.68rem; letter-spacing:0.08em; text-transform:uppercase; color:#D94E2A !important; border:1px solid #D94E2A; padding:2px 8px; margin-bottom:6px;"&gt;Sulit&lt;/span&gt;
        &lt;p style="color:#EAF2F5 !important; font-weight:600; margin:6px 0 8px;"&gt;23. Manakah kondisi yang paling menunjukkan kekurangan teks ceramah dibandingkan artikel opini dalam konteks penyebaran informasi jangka panjang?&lt;/p&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq22" value="0" style="margin-right:8px;"&gt;A. Ceramah dapat langsung direkam otomatis&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq22" value="1" style="margin-right:8px;"&gt;B. Pesan ceramah berisiko hilang/terlupakan jika tidak didokumentasikan, sementara artikel opini tetap tersimpan sebagai teks&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq22" value="2" style="margin-right:8px;"&gt;C. Ceramah selalu lebih singkat&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq22" value="3" style="margin-right:8px;"&gt;D. Artikel opini tidak dapat disimpan&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq22" value="4" style="margin-right:8px;"&gt;E. Keduanya sama-sama tidak dapat didokumentasikan&lt;/label&gt;
      &lt;/div&gt;
      &lt;div style="margin-bottom:20px; padding-bottom:16px; border-bottom:1px dashed rgba(234,242,245,0.16);"&gt;
        &lt;span class="mono" style="display:inline-block; font-size:0.68rem; letter-spacing:0.08em; text-transform:uppercase; color:#D94E2A !important; border:1px solid #D94E2A; padding:2px 8px; margin-bottom:6px;"&gt;Sulit&lt;/span&gt;
        &lt;p style="color:#EAF2F5 !important; font-weight:600; margin:6px 0 8px;"&gt;24. Seorang penceramah menyampaikan argumen tanpa didukung data, sementara sebuah artikel opini pada topik yang sama menyertakan data resmi. Berdasarkan hal tersebut, manakah kelemahan yang paling menonjol dari ceramah tersebut?&lt;/p&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq23" value="0" style="margin-right:8px;"&gt;A. Kurangnya penguat argumen berupa fakta/data yang dapat diverifikasi&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq23" value="1" style="margin-right:8px;"&gt;B. Ceramah tersebut terlalu panjang&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq23" value="2" style="margin-right:8px;"&gt;C. Ceramah tersebut tidak memiliki penutup&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq23" value="3" style="margin-right:8px;"&gt;D. Ceramah tersebut tidak memiliki pembukaan&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq23" value="4" style="margin-right:8px;"&gt;E. Ceramah tersebut tidak disampaikan secara lisan&lt;/label&gt;
      &lt;/div&gt;
      &lt;div style="margin-bottom:20px; padding-bottom:16px; border-bottom:1px dashed rgba(234,242,245,0.16);"&gt;
        &lt;span class="mono" style="display:inline-block; font-size:0.68rem; letter-spacing:0.08em; text-transform:uppercase; color:#D94E2A !important; border:1px solid #D94E2A; padding:2px 8px; margin-bottom:6px;"&gt;Sulit&lt;/span&gt;
        &lt;p style="color:#EAF2F5 !important; font-weight:600; margin:6px 0 8px;"&gt;25. Manakah simpulan paling tepat tentang kapan sebaiknya menggunakan teks ceramah dibandingkan artikel opini untuk menyampaikan suatu pesan?&lt;/p&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq24" value="0" style="margin-right:8px;"&gt;A. Ceramah lebih tepat digunakan ketika ingin membangun kedekatan emosional secara langsung dengan audiens dalam suatu forum tertentu&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq24" value="1" style="margin-right:8px;"&gt;B. Artikel opini selalu lebih baik dalam segala situasi&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq24" value="2" style="margin-right:8px;"&gt;C. Ceramah tidak pernah digunakan untuk pesan penting&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq24" value="3" style="margin-right:8px;"&gt;D. Keduanya tidak memiliki perbedaan fungsi&lt;/label&gt;
        &lt;label style="display:block; color:#DDE7EC !important; font-size:0.92rem; margin:4px 0; cursor:pointer;"&gt;&lt;input type="radio" name="cq24" value="4" style="margin-right:8px;"&gt;E. Artikel opini tidak dapat memengaruhi pembaca&lt;/label&gt;
      &lt;/div&gt;

      &lt;div style="margin-top:24px; display:flex; align-items:center; gap:16px; flex-wrap:wrap;"&gt;
        &lt;button id="cq-submit" type="button" style="background:var(--amber); color:var(--blueprint-deep); border:none; padding:12px 26px; font-family:'Oswald',sans-serif; text-transform:uppercase; letter-spacing:0.05em; font-weight:600; border-radius:2px; cursor:pointer; font-size:0.95rem;"&gt;Kirim Jawaban&lt;/button&gt;
        &lt;span id="cq-status" class="mono" style="font-size:0.85rem; color:var(--muted);"&gt;&lt;/span&gt;
      &lt;/div&gt;

      &lt;div id="cq-result" style="display:none; margin-top:20px; padding:18px 20px; border:1px solid var(--amber); background:rgba(245,166,35,0.08);"&gt;
        &lt;p style="margin:0; font-size:1.05rem;"&gt;Skor kamu: &lt;b id="cq-score" style="color:var(--amber); font-size:1.3rem;"&gt;&lt;/b&gt; / 100&lt;/p&gt;
        &lt;p id="cq-detail" style="margin:8px 0 0; font-size:0.9rem; color:var(--muted);"&gt;&lt;/p&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/section&gt;

&lt;/main&gt;

&lt;footer&gt;
  &lt;div class="doc-code"&gt;DOK/B.INDO/XI/CERAMAH-BANDING — Fokus Tujuan Pembelajaran, Materi Inti, Tugas Kelompok &amp;amp; Tugas Individu, 1× pertemuan (3 JP)&lt;/div&gt;
  &lt;p style="margin:0;"&gt;Referensi: Kurikulum Merdeka — Capaian Pembelajaran Bahasa Indonesia Fase F (Elemen Membaca dan Memirsa); Buku Teks Bahasa Indonesia Kelas XI SMK/MAK Kemendikbudristek.&lt;/p&gt;
&lt;/footer&gt;

&lt;script&gt;
(function(){
  var CQ_ENDPOINT = "https://script.google.com/macros/s/AKfycbzM7t2qgAENzxQJXzSYJYL28R6nb3TxJVELLL3CopyEXb51t_gRtrkPOxTpI5mq6VCEKw/exec";
  var CQ_MATERI = "Membandingkan Isi Teks Ceramah dengan Teks Lain";
  var correctAnswers = [1, 2, 2, 1, 1, 1, 1, 2, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0];

  document.getElementById("cq-submit").addEventListener("click", function(){
    var absen = document.getElementById("cq-absen").value.trim();
    var nama = document.getElementById("cq-nama").value.trim();
    var statusEl = document.getElementById("cq-status");

    if(!absen || !nama){
      statusEl.textContent = "Isi No. Absen dan Nama terlebih dahulu.";
      statusEl.style.setProperty("color", "#F5A623", "important");
      return;
    }

    var belumDijawab = [];
    var benar = 0;
    correctAnswers.forEach(function(correct, idx){
      var checked = document.querySelector('input[name="cq' + idx + '"]:checked');
      if(!checked){
        belumDijawab.push(idx+1);
      } else if(parseInt(checked.value,10) === correct){
        benar++;
      }
    });

    if(belumDijawab.length &gt; 0){
      statusEl.textContent = "Masih ada " + belumDijawab.length + " soal yang belum dijawab (nomor " + belumDijawab.slice(0,5).join(", ") + (belumDijawab.length&gt;5? ", ...":"") + ").";
      statusEl.style.setProperty("color", "#F5A623", "important");
      return;
    }

    var skor = benar * 4;
    document.getElementById("cq-score").textContent = skor;
    document.getElementById("cq-detail").textContent = "Menjawab benar " + benar + " dari 25 pertanyaan.";
    document.getElementById("cq-result").style.display = "block";
    statusEl.textContent = "Mengirim hasil...";
    statusEl.style.setProperty("color", "#9FB4C2", "important");

    var payload = new URLSearchParams();
    payload.append("noAbsen", absen);
    payload.append("nama", nama);
    payload.append("skor", skor);
    payload.append("materi", CQ_MATERI);
    payload.append("waktu", new Date().toISOString());

    fetch(CQ_ENDPOINT, {
      method: "POST",
      mode: "no-cors",
      headers: {"Content-Type":"application/x-www-form-urlencoded"},
      body: payload.toString()
    }).then(function(){
      statusEl.textContent = "Hasil berhasil dikirim ke guru.";
      statusEl.style.setProperty("color", "#6EC6CA", "important");
    }).catch(function(){
      statusEl.textContent = "Skor tercatat di halaman ini, namun pengiriman gagal. Tunjukkan skor ini ke guru.";
      statusEl.style.setProperty("color", "#F5A623", "important");
    });
  });
})();
&lt;/script&gt;
&lt;/div&gt;</description><link>http://kitab-investasi.blogspot.com/2026/09/membandingkan-isi-teks-ceramah-dengan.html</link><thr:total>0</thr:total><author>nof_rizal07@yahoo.co.id (abang_cool)</author></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-9000860041661554971.post-8515984388765739015</guid><pubDate>Fri, 18 Sep 2026 06:32:06 +0000</pubDate><atom:updated>2026-09-18T13:32:06.488+07:00</atom:updated><title>SERTIFIKAT KOMBEL</title><description>&lt;!DOCTYPE html&gt;
&lt;html lang="id"&gt;
&lt;head&gt;
&lt;meta charset="UTF-8"&gt;
&lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&gt;
&lt;title&gt;Generator Sertifikat&lt;/title&gt;

&lt;link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@700&amp;display=swap" rel="stylesheet"&gt;

&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"&gt;&lt;/script&gt;

&lt;style&gt;

body{
    font-family:Arial,sans-serif;
    background:#eef2f7;
    padding:20px;
    max-width:700px;
    margin:auto;
}

.card{
    background:white;
    padding:24px;
    border-radius:20px;
    box-shadow:0 10px 20px rgba(0,0,0,.1);
}

h2{
    text-align:center;
    color:#1e4668;
}

.confirm-box{
    background:#f0f6ff;
    border-left:5px solid #2c7da0;
    padding:16px;
    border-radius:16px;
    margin-bottom:20px;
    text-align:center;
}

.confirm-box p{
    margin-top:0;
    font-weight:bold;
    color:#1e4668;
}

.confirm-buttons{
    display:flex;
    gap:10px;
    margin-top:10px;
}

.confirm-buttons button{
    flex:1;
}

.yes-btn{
    background:#1f8a4c;
}

.yes-btn:hover{
    background:#166638;
}

.no-btn{
    background:#c0392b;
}

.no-btn:hover{
    background:#962d22;
}

input,select,button{
    width:100%;
    padding:12px;
    margin-top:10px;
    border-radius:12px;
    border:1px solid #ccc;
    font-size:16px;
}

button{
    background:#2c7da0;
    color:white;
    border:none;
    cursor:pointer;
    font-weight:bold;
}

button:hover{
    background:#1f5e7a;
}

button:disabled{
    background:#94a3b8;
    cursor:not-allowed;
}

input:disabled,
select:disabled{
    background:#f1f5f9;
}

#preview{
    width:100%;
    border-radius:12px;
    margin-top:10px;
}

.loading{
    display:none;
    margin-top:15px;
    color:#1e4668;
    font-weight:bold;
    text-align:center;
}

.status{
    margin-top:12px;
    font-weight:bold;
}

.success{
    color:#1f8a4c;
}

.error{
    color:#c0392b;
}

&lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;

&lt;div class="card"&gt;

&lt;h2&gt;&#128220; Generator Sertifikat&lt;/h2&gt;

&lt;!-- ================= KONFIRMASI ================= --&gt;

&lt;div class="confirm-box"&gt;

&lt;p&gt;&#128269; Apakah Anda mengikuti pelatihan?&lt;/p&gt;

&lt;div class="confirm-buttons"&gt;

&lt;button class="yes-btn" onclick="confirmIkut()"&gt;
✅ YA, IKUT
&lt;/button&gt;

&lt;button class="no-btn" onclick="confirmTidakIkut()"&gt;
❌ TIDAK
&lt;/button&gt;

&lt;/div&gt;

&lt;div id="statusKonfirmasi" class="status"&gt;&lt;/div&gt;

&lt;/div&gt;

&lt;!-- ================= FORM ================= --&gt;

&lt;label&gt;Nama Lengkap&lt;/label&gt;

&lt;input
type="text"
id="nama"
placeholder="Contoh: Ahmad Fauzi"
disabled&gt;

&lt;label&gt;Peran&lt;/label&gt;

&lt;select id="peran" disabled&gt;
    &lt;option&gt;Peserta&lt;/option&gt;
    &lt;option&gt;Narasumber&lt;/option&gt;
&lt;/select&gt;

&lt;img
id="preview"
src="https://lh3.googleusercontent.com/d/1L7TuHgvpP30JNm5lwNSrqSLsTPDxdDbH"
alt="Template"&gt;

&lt;button
id="downloadBtn"
onclick="generatePDF()"
disabled&gt;

⬇️ UNDUH PDF

&lt;/button&gt;

&lt;div class="loading" id="loading"&gt;
Memproses PDF...
&lt;/div&gt;

&lt;/div&gt;

&lt;script&gt;

// ================= TEMPLATE (DIUBAH) =================

const FILE_ID =
'1L7TuHgvpP30JNm5lwNSrqSLsTPDxdDbH';  // &lt;-- ID baru

const TEMPLATE_URL =
`https://lh3.googleusercontent.com/d/${FILE_ID}`;

// ================= UTIL =================

function showLoading(show){

    document.getElementById('loading').style.display =
        show ? 'block' : 'none';

}

function getRomanMonth(monthIndex){

    const romawi = [
        "I","II","III","IV","V","VI",
        "VII","VIII","IX","X","XI","XII"
    ];

    return romawi[monthIndex];

}

function capitalizeEachWord(text){

    return text
        .toLowerCase()
        .replace(/\b\w/g,c=&gt;c.toUpperCase());

}

// ================= KONFIRMASI =================

function confirmIkut(){

    document.getElementById('nama').disabled = false;

    document.getElementById('peran').disabled = false;

    document.getElementById('downloadBtn').disabled = false;

    document.getElementById('statusKonfirmasi').innerHTML =
        '&lt;span class="success"&gt;✅ Konfirmasi diterima. Anda dapat mengunduh sertifikat.&lt;/span&gt;';

}

function confirmTidakIkut(){

    document.getElementById('nama').disabled = true;

    document.getElementById('peran').disabled = true;

    document.getElementById('downloadBtn').disabled = true;

    document.getElementById('statusKonfirmasi').innerHTML =
        '&lt;span class="error"&gt;❌ Anda tidak dapat mengunduh sertifikat.&lt;/span&gt;';

}

// ================= LOAD IMAGE =================

function loadImage(url){

    return new Promise((resolve,reject)=&gt;{

        const img = new Image();

        img.crossOrigin = "anonymous";

        img.onload = ()=&gt;resolve(img);

        img.onerror = ()=&gt;{

            reject(
                new Error(
                    'Template Google Drive gagal dimuat'
                )
            );

        };

        img.src = url + '?t=' + Date.now();

    });

}

// ================= NOMOR =================

async function generateNomor(){

    const now = new Date();

    const bulan =
        getRomanMonth(now.getMonth());

    const tahun =
        now.getFullYear();

    const nomor =
        Math.floor(Math.random()*900)+100;

    return `${nomor}/K/${bulan}/${tahun}`;

}

// ================= PDF =================

async function generatePDF(){

    const namaInput =
        document.getElementById('nama');

    const peranSelect =
        document.getElementById('peran');

    let nama =
        namaInput.value.trim();

    const peran =
        peranSelect.value;

    if(!nama){

        alert('Nama wajib diisi');

        return;

    }

    nama =
        capitalizeEachWord(nama);

    showLoading(true);

    try{

        await document.fonts.ready;

        const img =
            await loadImage(TEMPLATE_URL);

        const canvas =
            document.createElement('canvas');

        canvas.width = img.width;
        canvas.height = img.height;

        const ctx =
            canvas.getContext('2d');

        ctx.drawImage(
            img,
            0,
            0,
            canvas.width,
            canvas.height
        );

        // ================= POSISI =================

        const nomorY =
            canvas.height * 0.235;

        const namaY =
            canvas.height * 0.3990;

        const peranY =
            canvas.height * 0.5420;

        // ================= STYLE =================

        ctx.textAlign = 'center';

        ctx.textBaseline = 'middle';

        ctx.fillStyle = '#000';

        // nomor
        const nomorSertifikat =
            await generateNomor();

        ctx.font =
            `bold ${canvas.width*0.0125}px Montserrat`;

        ctx.fillText(
            nomorSertifikat,
            canvas.width/2,
            nomorY
        );

        // nama auto shrink
        let fontSize =
            canvas.width * 0.031;

        ctx.font =
            `700 ${fontSize}px Montserrat`;

        let textWidth =
            ctx.measureText(nama).width;

        const maxWidth =
            canvas.width - 180;

        while(
            textWidth &gt; maxWidth &amp;&amp;
            fontSize &gt; 20
        ){

            fontSize -= 2;

            ctx.font =
                `700 ${fontSize}px Montserrat`;

            textWidth =
                ctx.measureText(nama).width;

        }

        ctx.fillText(
            nama,
            canvas.width/2,
            namaY
        );

        // peran
        ctx.font =
            `bold ${canvas.width*0.024}px Montserrat`;

        ctx.fillText(
            peran,
            canvas.width/2,
            peranY
        );

        // ================= PDF =================

        const imageData =
            canvas.toDataURL(
                'image/jpeg',
                1.0
            );

        const { jsPDF } =
            window.jspdf;

        const pdf =
            new jsPDF({

                orientation:
                    canvas.width &gt; canvas.height
                    ? 'landscape'
                    : 'portrait',

                unit:'px',

                format:[
                    canvas.width,
                    canvas.height
                ]

            });

        pdf.addImage(
            imageData,
            'JPEG',
            0,
            0,
            canvas.width,
            canvas.height
        );

        const safeName =
            nama.replace(/[^a-z0-9]/gi,'_');

        pdf.save(
            `Sertifikat_${safeName}.pdf`
        );

    }catch(error){

        console.error(error);

        alert(
            '❌ Gagal membuat PDF\n\n' +
            error.message +
            '\n\nPastikan file Google Drive bersifat PUBLIC.'
        );

    }finally{

        showLoading(false);

    }

}

&lt;/script&gt;

&lt;/body&gt;
&lt;/html&gt;</description><link>http://kitab-investasi.blogspot.com/2026/09/sertifikat-kombel_01887761678.html</link><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://lh3.googleusercontent.com/d/1L7TuHgvpP30JNm5lwNSrqSLsTPDxdDbH=s72-c" width="72"/><thr:total>0</thr:total><author>nof_rizal07@yahoo.co.id (abang_cool)</author></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-9000860041661554971.post-1627330734637838139</guid><pubDate>Thu, 17 Sep 2026 03:15:22 +0000</pubDate><atom:updated>2026-09-17T10:25:44.751+07:00</atom:updated><title>Integrasi Dokumen dan Otomasi Pengolah Kata</title><description>&lt;!DOCTYPE html&gt;
&lt;html lang="id"&gt;
&lt;head&gt;
&lt;meta charset="UTF-8"&gt;
&lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&gt;
&lt;title&gt;Integrasi Dokumen dan Otomasi Pengolah Kata - Informatika Kelas X&lt;/title&gt;
&lt;link rel="preconnect" href="https://fonts.googleapis.com"&gt;
&lt;link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500;600;700&amp;family=IBM+Plex+Sans:wght@400;500;600;700&amp;family=Tinos:ital,wght@0,400;0,700;1,400&amp;display=swap" rel="stylesheet"&gt;
&lt;style&gt;
  :root{
    --word: #185ABD;
    --word-dark: #103F86;
    --ribbon: #F1F5FA;
    --paper: #FFFFFF;
    --ink: #1F2430;
    --ink-soft: #57606F;
    --line: #DDE1E6;
    --amber: #C08A1E;
    --green: #1E7A46;
    --red: #C43E2E;
    --radius: 6px;
  }
  *{box-sizing:border-box; margin:0; padding:0;}
  html{scroll-behavior:smooth;}
  body{ font-family:'IBM Plex Sans', sans-serif; background:#FFFFFF; color: var(--ink); line-height:1.6; }
  .mono{font-family:'IBM Plex Mono', monospace;}

  .page-shell{
    max-width: 1140px; margin: 16px auto; background:#FFFFFF; border-radius:14px;
    box-shadow: 0 8px 32px rgba(20,30,50,0.12), 0 1px 3px rgba(20,30,50,0.08); border: 1px solid var(--line);
  }

  /* ===== Hero ===== */
  .ribbon-hero{ background: var(--ribbon); border-bottom: 3px solid var(--word); border-radius:14px 14px 0 0; overflow:hidden; }
  .ribbon-strip{ display:flex; gap:6px; padding: 10px 5% 0; flex-wrap:wrap; }
  .ribbon-tab{ font-family:'IBM Plex Mono', monospace; font-size:0.7rem; padding:6px 12px; background:#FFFFFF; border:1px solid var(--line); border-bottom:none; border-radius:4px 4px 0 0; color: var(--ink-soft); }
  .ribbon-tab.active{ color: var(--word); font-weight:700; border-color: var(--word); }
  .hero-body{ padding: 28px 5% 40px; background:#FFFFFF; }
  .eyebrow{ font-family:'IBM Plex Mono', monospace; font-size:0.76rem; letter-spacing:0.14em; text-transform:uppercase; color: var(--word); display:flex; align-items:center; gap:10px; margin-bottom:18px; }
  .eyebrow::before{ content:""; width:10px; height:10px; border:1.5px solid var(--word); border-radius:2px; display:inline-block; }
  h1.title{ font-family:'IBM Plex Mono', monospace; font-weight:700; font-size: clamp(1.7rem, 4vw, 2.7rem); line-height:1.18; color: var(--word-dark); max-width:24ch; }
  .hero-sub{ margin-top:16px; max-width: 70ch; font-size:1.02rem; color: var(--ink-soft); }
  .meta-strip{ margin-top:30px; display:grid; grid-template-columns: repeat(auto-fit,minmax(160px,1fr)); gap:1px; background: var(--line); border:1px solid var(--line); }
  .meta-cell{ background: var(--ribbon); padding:12px 14px; }
  .meta-cell .k{ font-family:'IBM Plex Mono', monospace; font-size:0.64rem; letter-spacing:0.1em; text-transform:uppercase; color: var(--word); }
  .meta-cell .v{ margin-top:5px; font-size:0.9rem; font-weight:600; color: var(--ink); }

  /* ===== Content ===== */
  main{ background: var(--paper); }
  .section{ padding: 36px 5%; border-bottom:1px solid #ECEFF3; }
  .section:last-of-type{border-bottom:none;}
  .section-tag{ font-family:'IBM Plex Mono', monospace; font-size:0.7rem; letter-spacing:0.14em; text-transform:uppercase; color: var(--ink-soft); display:flex; align-items:center; gap:10px; margin-bottom:10px; }
  .section-tag .num{ color:#fff; background: linear-gradient(135deg, var(--word), var(--word-dark)); padding:3px 8px; border-radius:3px; font-weight:600; }
  h2.section-title{ font-family:'IBM Plex Mono', monospace; font-size: clamp(1.25rem, 2.2vw, 1.7rem); font-weight:700; color: var(--word-dark); margin-bottom: 18px; }
  h3.sub-title{ font-family:'IBM Plex Mono', monospace; font-size:1.02rem; font-weight:600; color: var(--word-dark); margin: 22px 0 10px; display:flex; align-items:center; gap:10px; }
  h3.sub-title::before{ content:""; width:8px;height:8px; background: var(--amber); display:inline-block; border-radius:1px; }
  p{ color:#33414F; max-width: 78ch; margin-bottom: 12px;}
  strong{color:var(--word-dark);}
  ul, ol{ margin: 6px 0 16px 1.3em; max-width: 78ch;}
  li{margin-bottom:7px; color:#33414F;}

  .callout{ border-left: 3px solid var(--word); background:#EBF2FB; padding: 14px 18px; border-radius: 0 6px 6px 0; margin: 16px 0; max-width: 78ch; }
  .callout .lbl{ font-family:'IBM Plex Mono', monospace; font-size:0.68rem; letter-spacing:0.1em; text-transform:uppercase; color: var(--word-dark); font-weight:700; margin-bottom:6px; }
  .callout.warn{ border-left-color: var(--red); background:#FBEAE7; }
  .callout.warn .lbl{ color:#9B3324; }
  .callout.ok{ border-left-color: var(--green); background:#EAF6EF; }
  .callout.ok .lbl{ color:#0F5C30; }

  .card-grid{ display:grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: 14px; margin: 16px 0 6px; }
  .card{ background: #FFFFFF; border: 1.5px solid var(--line); border-radius: var(--radius); padding: 16px 18px; box-shadow: 0 2px 8px rgba(20,30,50,0.05); }
  .card .tag{ font-family:'IBM Plex Mono', monospace; font-size:0.64rem; letter-spacing:0.1em; text-transform:uppercase; color:#fff; background: var(--word); padding:3px 8px; border-radius:3px; display:inline-block; margin-bottom:10px; }
  .card h4{ font-family:'IBM Plex Mono', monospace; font-size:0.94rem; margin-bottom:6px; color:var(--word-dark); }
  .card p{font-size:0.87rem; margin-bottom:0;}

  .table-scroll{ overflow-x:auto; margin:16px 0; }
  table.compare{ width:100%; border-collapse:collapse; font-size:0.88rem; min-width:480px; }
  table.compare th, table.compare td{ border:1px solid var(--line); padding:10px 12px; text-align:left; vertical-align:top; }
  table.compare th{ background: var(--word); color:#fff; font-family:'IBM Plex Mono', monospace; font-size:0.72rem; letter-spacing:0.04em; text-transform:uppercase; }
  table.compare tr:nth-child(even) td{ background: var(--ribbon); }

  .summary-box{ background: var(--word-dark); color: #fff; border-radius: 8px; padding: 22px 24px; margin-top: 8px; }
  .summary-box h4{ font-family:'IBM Plex Mono', monospace; color:#FCE29A; font-size:0.82rem; letter-spacing:0.08em; text-transform:uppercase; margin-bottom:12px; }
  .summary-box ul{ margin:0 0 0 1.1em; max-width:none; }
  .summary-box li{ color:#E6ECF7; margin-bottom:7px; }

  /* ===== Evaluasi ===== */
  #evaluasi{ background: linear-gradient(180deg, #EEF4FF 0%, #FFFFFF 55%); border-top:3px solid var(--word); }

  .submit-panel{ background: var(--ribbon); border:1px solid var(--line); border-radius:10px; padding:22px 20px; margin-bottom:22px; }
  .student-info{ display:grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap:14px; margin-top:12px; }
  .field label{ display:block; font-family:'IBM Plex Mono', monospace; font-size:0.66rem; letter-spacing:0.06em; text-transform:uppercase; color: var(--word-dark); margin-bottom:6px; font-weight:700; }
  .field input, .field select{ width:100%; padding:9px 11px; border-radius:5px; border:1px solid var(--line); background:#FFFFFF; color: var(--ink); font-family:'IBM Plex Sans', sans-serif; font-size:0.9rem; }
  .field select{cursor:pointer;}
  .field input:focus, .field select:focus{ outline:2px solid var(--word); }

  .primary-btn{
    font-family:'IBM Plex Mono', monospace; font-weight:700; font-size:0.88rem; padding:13px 24px; border-radius:8px; border:none; cursor:pointer;
    background: linear-gradient(135deg, var(--word), var(--word-dark)); color:#fff; box-shadow: 0 4px 14px rgba(16,63,134,0.3);
    transition: transform .15s, box-shadow .15s; margin-top:6px;
  }
  .primary-btn:hover{ transform: translateY(-2px); box-shadow: 0 6px 18px rgba(16,63,134,0.4); }
  .primary-btn.ghost{ background:#fff; color:var(--word-dark); border:1.5px solid var(--word); box-shadow:none; }
  .primary-btn.ghost:hover{ background:#EEF4FF; }
  .primary-btn:disabled{ opacity:0.55; cursor:not-allowed; transform:none; }
  #evalMsg, #praktikMsg{ font-family:'IBM Plex Mono', monospace; font-size:0.8rem; color:#8A6A1E; margin-left:10px; }

  .stage-head{ display:flex; align-items:center; gap:12px; flex-wrap:wrap; margin:26px 0 12px; }
  .stage-badge{ font-family:'IBM Plex Mono', monospace; font-size:0.66rem; letter-spacing:0.08em; text-transform:uppercase; color:#fff; background: var(--word-dark); padding:5px 12px; border-radius:20px; font-weight:700; }
  .stage-head h3{ font-family:'IBM Plex Mono', monospace; font-size:1.05rem; color: var(--word-dark); }

  .attempt-strip{ display:flex; gap:10px; flex-wrap:wrap; margin:14px 0; }
  .attempt-pill{
    font-family:'IBM Plex Mono', monospace; font-size:0.74rem; font-weight:600; padding:9px 16px; border-radius:20px;
    border:1.5px solid var(--line); background:#fff; color: var(--ink-soft); box-shadow: 0 1px 4px rgba(20,30,50,0.06);
  }
  .attempt-pill.pass{ border-color: var(--green); background:#DFF6E7; color:#0F5C30; }
  .attempt-pill.fail{ border-color: var(--red); background:#FBDEDA; color:#8A2A1C; }
  .attempt-pill.current{ box-shadow: 0 0 0 3px rgba(24,90,189,0.2); background:#EEF4FF; border-color:var(--word); color:var(--word-dark); }

  .game-panel{ background:#FFFFFF; border:1px solid var(--line); border-radius:10px; padding:22px; box-shadow: 0 2px 10px rgba(20,30,50,0.05); }
  .game-progress{ font-family:'IBM Plex Mono', monospace; font-size:0.72rem; color: var(--ink-soft); margin-bottom:14px; display:flex; justify-content:space-between; flex-wrap:wrap; gap:8px; }
  .q-instruksi{ font-family:'IBM Plex Mono', monospace; font-size:0.68rem; letter-spacing:0.1em; text-transform:uppercase; color: var(--word); font-weight:700; margin-bottom:8px; }
  .q-text{ font-size:1.05rem; font-weight:600; color: var(--ink); margin-bottom:18px; min-height:52px; }
  .drop-zone{
    border:3px dashed #9DBFE8; border-radius:10px; min-height:88px; display:flex; align-items:center; justify-content:center;
    background:#FAFCFF; color:#8A99AC; font-family:'IBM Plex Mono', monospace; font-size:0.82rem; margin-bottom:18px; transition: all .2s; padding:10px; text-align:center;
  }
  .drop-zone.drag-over{ background:#E2EDFB; border-color: var(--word); }
  .drop-zone.correct{ background:#E4F6EB; border-color: var(--green); border-style:solid; color:#0F5C30; font-weight:700; }
  .drop-zone.wrong{ background:#FBE7E4; border-color: var(--red); border-style:solid; color:#8A2A1C; font-weight:700; }
  .opt-pool{ display:flex; flex-wrap:wrap; gap:9px; justify-content:center; background:var(--ribbon); border:1px solid var(--line); border-radius:10px; padding:14px; }
  .opt-chip{
    font-family:'IBM Plex Mono', monospace; font-size:0.8rem; background: linear-gradient(135deg, var(--word), var(--word-dark)); color:#fff;
    padding:9px 15px; border-radius:7px; cursor:grab; box-shadow:0 2px 6px rgba(24,90,189,0.28); border:none;
  }
  .opt-chip:hover{ filter:brightness(1.1); }
  .opt-chip.dragging{ opacity:0.5; }

  /* ===== Editor dokumen F4 ===== */
  .doc-toolbar{
    position: sticky; top:10px; z-index:20; background:#FFFFFF; border:1.5px solid var(--word);
    border-radius:8px; padding:10px 12px; display:flex; flex-wrap:wrap; gap:6px; align-items:center;
    box-shadow: 0 6px 20px rgba(20,90,189,0.18); margin-bottom:16px;
  }
  .doc-toolbar button{ font-family:'IBM Plex Sans', sans-serif; font-size:0.83rem; background:#F3F5F8; border:1px solid var(--line); border-radius:4px; padding:6px 10px; cursor:pointer; color: var(--ink); }
  .doc-toolbar button:hover{ background:#E4EAF2; }
  .doc-toolbar button.b{font-weight:700;} .doc-toolbar button.i{font-style:italic;} .doc-toolbar button.u{text-decoration:underline;}
  .doc-toolbar select{ font-family:'IBM Plex Sans', sans-serif; font-size:0.8rem; padding:6px 8px; border-radius:4px; border:1px solid var(--line); background:#F3F5F8; }
  .doc-toolbar .sep{ width:1px; height:22px; background:var(--line); margin:0 4px; }
  .doc-toolbar .hint{ font-family:'IBM Plex Mono', monospace; font-size:0.68rem; color: var(--ink-soft); margin-left:auto; }

  .doc-stage{ background:#E7EBF0; border:1px solid var(--line); border-radius:10px; padding:18px; overflow-x:auto; }
  .f4-page{
    width: 215mm; min-height: 330mm; padding: 3cm 3cm 3cm 4cm;
    margin: 0 auto 22px; background:#fff; box-shadow: 0 4px 16px rgba(0,0,0,0.14);
    font-family:'Tinos','Times New Roman', serif; font-size: 12pt; line-height: 1.5; outline:none; position:relative;
  }
  .f4-page::after{
    content: attr(data-pagelabel); position:absolute; top:8px; right:14px;
    font-family:'IBM Plex Mono', monospace; font-size:8pt; color:#B6BDC6; letter-spacing:0.08em;
  }
  .f4-page:focus{ box-shadow: 0 0 0 3px rgba(24,90,189,0.25), 0 4px 16px rgba(0,0,0,0.14); }
  .placeholder-note{ color:#9AA3AE; font-style:italic; }
  .doc-meta{ font-family:'IBM Plex Mono', monospace; font-size:0.72rem; color: var(--ink-soft); margin-top:10px; display:flex; justify-content:space-between; flex-wrap:wrap; gap:10px; }
  .doc-meta .flag{ color: var(--red); font-weight:700; display:none; }
  .doc-meta .flag.show{ display:inline; }

  .checklist{ background:#fff; border:1px solid var(--line); border-radius:8px; padding:16px 18px; margin-top:14px; }
  .checklist h5{ font-family:'IBM Plex Mono', monospace; font-size:0.8rem; color:var(--word-dark); margin-bottom:10px; }
  .checklist ul{ margin:0 0 0 1.1em; }
  .checklist li{ font-size:0.86rem; margin-bottom:5px; }

  /* ===== Lampiran contoh laporan (proteksi salin) ===== */
  .lampiran-wrap{ background:#FBF9F2; border:1.5px solid var(--amber); border-radius:10px; padding:18px 20px; margin:18px 0; }
  .lampiran-head{ display:flex; justify-content:space-between; align-items:flex-start; gap:12px; flex-wrap:wrap; margin-bottom:8px; }
  .lampiran-eyebrow{ font-family:'IBM Plex Mono', monospace; font-size:0.64rem; letter-spacing:0.1em; text-transform:uppercase; color:#8A6A1E; font-weight:700; }
  .lampiran-head h4{ font-family:'IBM Plex Mono', monospace; font-size:1rem; color:#6B5210; margin-top:4px; }
  .lock-badge{ font-family:'IBM Plex Mono', monospace; font-size:0.64rem; letter-spacing:0.06em; text-transform:uppercase; background:#8A5A0A; color:#fff; padding:5px 11px; border-radius:20px; font-weight:700; white-space:nowrap; }
  .lampiran-note{ font-size:0.86rem; color:#5E5238; max-width:none; margin-bottom:14px; }
  .lampiran-list{ display:flex; flex-direction:column; gap:8px; }
  .lampiran-item{ background:#fff; border:1px solid #E2D9BE; border-radius:7px; overflow:hidden; }
  .lampiran-toggle{
    width:100%; text-align:left; background:#FFFDF6; border:none; cursor:pointer; padding:11px 15px;
    font-family:'IBM Plex Mono', monospace; font-size:0.85rem; color:#6B5210; font-weight:600;
    display:flex; justify-content:space-between; align-items:center; gap:10px;
  }
  .lampiran-toggle:hover{ background:#FBF3DF; }
  .lampiran-toggle .chev{ font-size:0.75rem; color:#A88A3E; }
  .lampiran-body{
    display:none; padding:14px 16px; border-top:1px dashed #E2D9BE; background:#fff;
    font-family:'Tinos','Times New Roman', serif; font-size:0.95rem; color:#332C1E; white-space:pre-wrap; line-height:1.55;
    user-select:none; -webkit-user-select:none; -moz-user-select:none; -ms-user-select:none;
    max-height:420px; overflow-y:auto;
  }
  .lampiran-body.open{ display:block; }

  .result-panel{ display:none; margin-top:18px; background:#FFFFFF; border:1.5px solid var(--green); border-radius:8px; padding:20px 22px; }
  .result-panel .score{ font-family:'IBM Plex Mono', monospace; font-size:2.2rem; font-weight:700; color: var(--green); }
  .result-panel .score-lbl{ font-family:'IBM Plex Mono', monospace; font-size:0.68rem; letter-spacing:0.1em; text-transform:uppercase; color: var(--ink-soft); }
  .result-panel p{ color:#33414F; font-size:0.87rem; margin-top:8px; }

  .closing-task{ background:#FFF6E6; border:1.5px solid var(--amber); border-radius:8px; padding:18px 20px; margin-bottom:14px; }
  .closing-task .lbl{ font-family:'IBM Plex Mono', monospace; font-size:0.68rem; letter-spacing:0.1em; text-transform:uppercase; color:#8A5A0A; font-weight:700; margin-bottom:8px; }

  footer{ background: var(--ribbon); color: var(--ink-soft); text-align:center; padding: 22px 5% 30px; font-family:'IBM Plex Mono', monospace; font-size:0.72rem; border-top:1px solid var(--line); border-radius:0 0 14px 14px; }

  /* ===== Area Cetak PDF F4 ===== */
  .print-area{ display:none; }
  .pd-kop{ text-align:center; border-bottom:3px double #000; padding-bottom:10px; margin-bottom:16px; }
  .pd-kop h1{ font-size:15pt; margin-bottom:4px; }
  .pd-kop p{ font-size:9.5pt; margin:0; max-width:none; }
  .pd-meta-table{ width:100%; border-collapse:collapse; margin-bottom:14px; font-size:10pt; }
  .pd-meta-table td{ padding:3px 6px; vertical-align:top; }
  .pd-meta-table td.lbl{ width:118px; font-weight:600; }
  .pd-section-title{ font-size:11pt; font-weight:700; margin:16px 0 8px; border-bottom:1.5px solid #000; padding-bottom:3px; }
  .pd-score-table{ width:100%; border-collapse:collapse; font-size:10pt; margin-bottom:10px; }
  .pd-score-table th, .pd-score-table td{ border:1px solid #000; padding:5px 8px; text-align:left; }
  .pd-score-table th{ background:#EEE; }
  .pd-answer-item{ border:1px solid #999; border-radius:3px; padding:8px 10px; margin-bottom:8px; page-break-inside: avoid; }
  .pd-answer-item .pd-anum{ font-size:9pt; font-weight:700; color:#222; }
  .pd-answer-item .pd-atext{ font-size:10pt; white-space:pre-wrap; margin-top:4px; font-family:'Tinos','Times New Roman', serif; }
  .pd-verdict{ display:inline-block; font-size:8pt; font-weight:700; padding:1px 7px; border-radius:3px; margin-left:8px; border:1px solid #000; }
  .pd-verdict.ok{ background:#E4F5E9; }
  .pd-verdict.no{ background:#FBE4E1; }
  .pd-eval-table{ width:100%; border-collapse:collapse; font-size:9pt; margin-bottom:14px; }
  .pd-eval-table th, .pd-eval-table td{ border:1px solid #999; padding:5px 7px; text-align:left; vertical-align:top; }
  .pd-eval-table th{ background:#EEE; font-size:8.5pt; }
  .pd-signature{ display:flex; justify-content:space-between; margin-top:36px; font-size:10pt; page-break-inside:avoid; }
  .pd-signature div{ text-align:center; width:45%; }
  .pd-signature .line{ margin-top:50px; border-top:1px solid #000; padding-top:4px; }
  .pd-footnote{ font-size:8.5pt; color:#444; margin-top:18px; text-align:center; }

  @media print{
    html, body{ height:auto !important; }
    body *{ visibility:hidden; }
    .print-area, .print-area *{ visibility:visible; }
    .print-area{
      display:block !important; visibility:visible; position:absolute; left:0; top:0; width:100%;
      color:#000; font-family:'IBM Plex Sans', sans-serif; background:#fff; z-index:99999;
    }
    @page{ size: 215mm 330mm; margin: 15mm; }
  }

  @media (max-width:700px){ .hero-body{padding:22px 5% 32px;} .section{padding:26px 5%;} .f4-page{ padding:2cm 1.5cm; } }
&lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;

&lt;div class="page-shell"&gt;
&lt;div class="ribbon-hero"&gt;
  &lt;div class="ribbon-strip"&gt;
    &lt;div class="ribbon-tab active"&gt;Beranda&lt;/div&gt;
    &lt;div class="ribbon-tab"&gt;Sisipkan&lt;/div&gt;
    &lt;div class="ribbon-tab"&gt;Tata Letak&lt;/div&gt;
    &lt;div class="ribbon-tab"&gt;Referensi&lt;/div&gt;
    &lt;div class="ribbon-tab"&gt;Surat&lt;/div&gt;
    &lt;div class="ribbon-tab"&gt;Tinjau&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="hero-body"&gt;
    &lt;div class="eyebrow"&gt;Informatika - Fase E - Kelas X SMK&lt;/div&gt;
    &lt;h1 class="title"&gt;Integrasi Dokumen dan Otomasi Pengolah Kata&lt;/h1&gt;
    &lt;p class="hero-sub"&gt;Materi ini membahas cara menggabungkan berbagai objek (tabel, gambar, bagan, grafik) ke dalam satu dokumen, memanfaatkan template dan formulir, serta menerapkan fitur otomatis pengolah kata untuk menyusun dokumen panjang secara efisien. Studi kasusnya: Laporan Praktik Kerja Lapangan (PKL) sesuai pedoman SMK Negeri 1 Tuntang Tahun 2025/2026.&lt;/p&gt;
    &lt;div class="meta-strip"&gt;
      &lt;div class="meta-cell"&gt;&lt;div class="k"&gt;Elemen CP&lt;/div&gt;&lt;div class="v"&gt;Integrasi &amp;amp; Otomasi Dokumen&lt;/div&gt;&lt;/div&gt;
      &lt;div class="meta-cell"&gt;&lt;div class="k"&gt;Jenjang&lt;/div&gt;&lt;div class="v"&gt;SMK Kelas X&lt;/div&gt;&lt;/div&gt;
      &lt;div class="meta-cell"&gt;&lt;div class="k"&gt;Alokasi Waktu&lt;/div&gt;&lt;div class="v"&gt;1 Pertemuan - 4 JP (180 menit)&lt;/div&gt;&lt;/div&gt;
      &lt;div class="meta-cell"&gt;&lt;div class="k"&gt;Produk&lt;/div&gt;&lt;div class="v"&gt;Draf Laporan PKL (F4)&lt;/div&gt;&lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;main&gt;

  &lt;!-- ===================== TUJUAN ===================== --&gt;
  &lt;section class="section" id="tujuan"&gt;
    &lt;div class="section-tag"&gt;&lt;span class="num"&gt;00&lt;/span&gt; Capaian &amp;amp; Tujuan Pembelajaran&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Ke Mana Materi Ini Menuju&lt;/h2&gt;
    &lt;h3 class="sub-title"&gt;Tujuan Pembelajaran&lt;/h3&gt;
    &lt;p&gt;Murid mampu membuat laporan kerja lapangan yang mengintegrasikan berbagai objek, menggunakan template, formulir, serta fitur otomatis untuk meningkatkan efisiensi pembuatan dokumen.&lt;/p&gt;

    &lt;h3 class="sub-title"&gt;Indikator Ketercapaian&lt;/h3&gt;
    &lt;ol&gt;
      &lt;li&gt;Menjelaskan konsep integrasi objek (tabel, gambar, bagan, grafik) dalam satu dokumen.&lt;/li&gt;
      &lt;li&gt;Menerapkan template dan style untuk menjaga konsistensi format dokumen panjang.&lt;/li&gt;
      &lt;li&gt;Membuat formulir/isian terstruktur (biodata, jurnal kegiatan, lembar konsultasi) dengan tabel.&lt;/li&gt;
      &lt;li&gt;Menggunakan fitur otomatis: daftar isi otomatis, penomoran halaman bertingkat, caption, sitasi, dan mail merge.&lt;/li&gt;
      &lt;li&gt;Menerapkan tata tulis dan sistematika Laporan PKL pada dokumen nyata.&lt;/li&gt;
    &lt;/ol&gt;

    &lt;h3 class="sub-title"&gt;Rincian Kegiatan (4 JP x 45 menit)&lt;/h3&gt;
    &lt;div class="table-scroll"&gt;
    &lt;table class="compare"&gt;
      &lt;tr&gt;&lt;th&gt;Tahap&lt;/th&gt;&lt;th&gt;Kegiatan&lt;/th&gt;&lt;th&gt;Waktu&lt;/th&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Pendahuluan&lt;/td&gt;&lt;td&gt;Apersepsi ("Bagaimana laporan 20 halaman bisa rapi tanpa mengetik ulang daftar isi berkali-kali?"), penyampaian tujuan&lt;/td&gt;&lt;td&gt;15 menit&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Inti - Eksplorasi Konsep&lt;/td&gt;&lt;td&gt;Penjelasan integrasi objek, template, formulir, dan fitur otomatis pengolah kata&lt;/td&gt;&lt;td&gt;55 menit&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Inti - Evaluasi Tahap 1&lt;/td&gt;&lt;td&gt;Kuis drag &amp;amp; drop Master Penyusun Laporan PKL (KKM 75, maksimal 3 percobaan)&lt;/td&gt;&lt;td&gt;35 menit&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Inti - Evaluasi Tahap 2&lt;/td&gt;&lt;td&gt;Latihan praktik mengetik dan memformat dokumen Laporan PKL pada lembar F4 digital&lt;/td&gt;&lt;td&gt;60 menit&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Penutup&lt;/td&gt;&lt;td&gt;Unduh bukti PDF F4, catat nilai evaluasi dan tulis resume di buku catatan&lt;/td&gt;&lt;td&gt;15 menit&lt;/td&gt;&lt;/tr&gt;
    &lt;/table&gt;
    &lt;/div&gt;
  &lt;/section&gt;

  &lt;!-- ===================== A. INTEGRASI OBJEK ===================== --&gt;
  &lt;section class="section" id="integrasi"&gt;
    &lt;div class="section-tag"&gt;&lt;span class="num"&gt;01&lt;/span&gt; Menggabungkan Objek&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Integrasi Objek dalam Dokumen&lt;/h2&gt;
    &lt;p&gt;&lt;strong&gt;Integrasi dokumen&lt;/strong&gt; adalah proses menggabungkan berbagai jenis objek ke dalam satu dokumen utuh, sehingga informasi tersaji lengkap: teks untuk penjelasan, tabel untuk data, gambar untuk bukti, dan bagan untuk struktur. Dalam Laporan PKL, keempatnya dipakai sekaligus.&lt;/p&gt;

    &lt;div class="card-grid"&gt;
      &lt;div class="card"&gt;&lt;span class="tag"&gt;Data&lt;/span&gt;&lt;h4&gt;Tabel&lt;/h4&gt;&lt;p&gt;Menyusun data baris-kolom. Dipakai untuk analisis SWOT, jurnal kegiatan harian, dan lembar konsultasi.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;span class="tag"&gt;Bukti&lt;/span&gt;&lt;h4&gt;Gambar / Foto&lt;/h4&gt;&lt;p&gt;Dokumentasi kegiatan dan denah lokasi. Atur &lt;em&gt;text wrapping&lt;/em&gt; agar teks mengalir rapi di sekitarnya.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;span class="tag"&gt;Struktur&lt;/span&gt;&lt;h4&gt;SmartArt / Shapes&lt;/h4&gt;&lt;p&gt;Menggambarkan struktur organisasi tempat PKL secara visual dan mudah diperbarui.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;span class="tag"&gt;Angka&lt;/span&gt;&lt;h4&gt;Grafik / Chart&lt;/h4&gt;&lt;p&gt;Menyajikan data kuantitatif (mis. jumlah produksi per minggu) dari tabel menjadi visual.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;span class="tag"&gt;Keterangan&lt;/span&gt;&lt;h4&gt;Caption&lt;/h4&gt;&lt;p&gt;Penomoran otomatis objek, mis. "Gambar 2.1" dan "Tabel 2.2", yang menyesuaikan urutan bab.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;span class="tag"&gt;Rujukan Silang&lt;/span&gt;&lt;h4&gt;Cross-Reference&lt;/h4&gt;&lt;p&gt;Merujuk objek dari teks ("lihat Tabel 2.2") yang nomornya ikut berubah bila urutan bergeser.&lt;/p&gt;&lt;/div&gt;
    &lt;/div&gt;

    &lt;div class="callout"&gt;
      &lt;div class="lbl"&gt;Praktik Baik&lt;/div&gt;
      &lt;p style="margin:0;"&gt;Setiap gambar dan tabel dalam Laporan PKL wajib diberi &lt;strong&gt;caption bernomor bab&lt;/strong&gt; (Gambar 2.1 berarti gambar pertama pada BAB II) dan dirujuk di dalam teks. Caption yang dibuat lewat fitur otomatis akan memudahkan pembuatan Daftar Gambar dan Daftar Tabel.&lt;/p&gt;
    &lt;/div&gt;
  &lt;/section&gt;

  &lt;!-- ===================== B. TEMPLATE &amp; STYLE ===================== --&gt;
  &lt;section class="section" id="template"&gt;
    &lt;div class="section-tag"&gt;&lt;span class="num"&gt;02&lt;/span&gt; Konsistensi Format&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Template, Style, dan Section&lt;/h2&gt;
    &lt;p&gt;&lt;strong&gt;Template&lt;/strong&gt; adalah dokumen cetakan awal yang sudah memuat pengaturan margin, jenis huruf, style, dan struktur bab. Dengan template, seluruh murid menghasilkan laporan dengan format seragam tanpa mengatur ulang satu per satu.&lt;/p&gt;

    &lt;h3 class="sub-title"&gt;Tata Tulis Laporan PKL (Wajib)&lt;/h3&gt;
    &lt;div class="table-scroll"&gt;
    &lt;table class="compare"&gt;
      &lt;tr&gt;&lt;th&gt;Unsur&lt;/th&gt;&lt;th&gt;Ketentuan&lt;/th&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Ukuran kertas&lt;/td&gt;&lt;td&gt;F4 (215 mm x 330 mm), berat 70 gsm&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Jenis dan ukuran huruf&lt;/td&gt;&lt;td&gt;Times New Roman, 12 pt&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Margin&lt;/td&gt;&lt;td&gt;Kiri 4 cm; atas, kanan, dan bawah masing-masing 3 cm&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Spasi isi laporan&lt;/td&gt;&lt;td&gt;1,5 spasi&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Spasi khusus&lt;/td&gt;&lt;td&gt;Kata pengantar, daftar isi, kutipan langsung, dan daftar pustaka: 1 spasi (single)&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Nomor halaman bagian awal&lt;/td&gt;&lt;td&gt;Angka romawi kecil (i, ii, iii), halaman judul tidak ditampilkan&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Nomor halaman bagian utama&lt;/td&gt;&lt;td&gt;Angka arab (1, 2, 3)&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Letak nomor halaman&lt;/td&gt;&lt;td&gt;Kanan atas (header); khusus halaman berjudul BAB: tengah bawah (footer)&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Jumlah halaman&lt;/td&gt;&lt;td&gt;Tidak kurang dari 20 halaman&lt;/td&gt;&lt;/tr&gt;
    &lt;/table&gt;
    &lt;/div&gt;

    &lt;div class="callout ok"&gt;
      &lt;div class="lbl"&gt;Kunci Otomasi&lt;/div&gt;
      &lt;p style="margin:0;"&gt;Perbedaan format nomor halaman (romawi lalu arab) dan perbedaan posisinya (kanan atas lalu tengah bawah) hanya mungkin dilakukan otomatis dengan &lt;strong&gt;Section Break&lt;/strong&gt;. Tanpa section break, seluruh dokumen terpaksa memakai satu format nomor halaman yang sama.&lt;/p&gt;
    &lt;/div&gt;

    &lt;h3 class="sub-title"&gt;Hierarki Penomoran Sub Bab&lt;/h3&gt;
    &lt;p&gt;Pedoman menetapkan urutan tingkatan penomoran sebagai berikut, dan dilarang menggunakan simbol gambar seperti panah atau bintang:&lt;/p&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;strong&gt;BAB&lt;/strong&gt; ditulis dengan angka romawi: BAB I&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Sub BAB&lt;/strong&gt; dengan huruf kapital: A. Latar Belakang&lt;/li&gt;
      &lt;li&gt;Tingkat berikutnya berurutan: 1. lalu 1.1 lalu a. lalu 1) lalu a)&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/section&gt;

  &lt;!-- ===================== C. FORMULIR ===================== --&gt;
  &lt;section class="section" id="formulir"&gt;
    &lt;div class="section-tag"&gt;&lt;span class="num"&gt;03&lt;/span&gt; Isian Terstruktur&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Formulir dan Dokumen Isian&lt;/h2&gt;
    &lt;p&gt;&lt;strong&gt;Formulir&lt;/strong&gt; adalah dokumen dengan bagian isian yang sudah ditentukan letaknya, sehingga pengisi hanya perlu melengkapi data. Dalam Laporan PKL, terdapat tiga formulir penting yang seluruhnya paling efisien dibuat dengan &lt;strong&gt;tabel&lt;/strong&gt; (bukan dengan spasi atau titik-titik manual yang mudah bergeser).&lt;/p&gt;
    &lt;div class="card-grid"&gt;
      &lt;div class="card"&gt;&lt;span class="tag"&gt;Identitas&lt;/span&gt;&lt;h4&gt;Biodata Peserta Didik&lt;/h4&gt;&lt;p&gt;Berisi nama, NIS, kelas, program keahlian, dan pas foto 3x4. Dirapikan dengan tabel tanpa garis.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;span class="tag"&gt;Harian&lt;/span&gt;&lt;h4&gt;Jurnal Kegiatan PKL&lt;/h4&gt;&lt;p&gt;Tabel berisi kolom No., Hari/Tanggal, Unit Kerja/Pekerjaan, dan Catatan pembimbing dunia kerja.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;span class="tag"&gt;Bimbingan&lt;/span&gt;&lt;h4&gt;Lembar Konsultasi&lt;/h4&gt;&lt;p&gt;Tabel bukti bimbingan dengan guru pembimbing, minimal 8 kali konsultasi.&lt;/p&gt;&lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="callout"&gt;
      &lt;div class="lbl"&gt;Tips Teknis&lt;/div&gt;
      &lt;p style="margin:0;"&gt;Agar titik dua pada formulir biodata sejajar sempurna, gunakan tabel 2 kolom lalu sembunyikan garisnya (&lt;em&gt;No Border&lt;/em&gt;) - jauh lebih rapi dan stabil dibanding menekan spasi atau tab berulang kali.&lt;/p&gt;
    &lt;/div&gt;
  &lt;/section&gt;

  &lt;!-- ===================== D. FITUR OTOMATIS ===================== --&gt;
  &lt;section class="section" id="otomasi"&gt;
    &lt;div class="section-tag"&gt;&lt;span class="num"&gt;04&lt;/span&gt; Efisiensi Kerja&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Fitur Otomasi Pengolah Kata&lt;/h2&gt;
    &lt;div class="table-scroll"&gt;
    &lt;table class="compare"&gt;
      &lt;tr&gt;&lt;th&gt;Fitur&lt;/th&gt;&lt;th&gt;Fungsi dalam Laporan PKL&lt;/th&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Heading Style&lt;/td&gt;&lt;td&gt;Menandai judul BAB dan sub bab agar dikenali fitur otomatis lain; fondasi seluruh otomasi.&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Table of Contents&lt;/td&gt;&lt;td&gt;Membuat Daftar Isi otomatis lengkap dengan nomor halaman; cukup klik Update Table bila ada perubahan.&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Page Number + Section Break&lt;/td&gt;&lt;td&gt;Penomoran halaman otomatis dengan format dan posisi berbeda antar bagian.&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Insert Caption&lt;/td&gt;&lt;td&gt;Memberi nomor otomatis pada gambar dan tabel, sekaligus bahan Daftar Gambar/Tabel.&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Citation &amp;amp; Bibliography&lt;/td&gt;&lt;td&gt;Menyimpan sumber kutipan dan menghasilkan Daftar Pustaka otomatis, terurut abjad.&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Mail Merge&lt;/td&gt;&lt;td&gt;Membuat surat pengantar PKL massal dari satu template dan satu daftar data murid.&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;SmartArt&lt;/td&gt;&lt;td&gt;Membuat bagan struktur organisasi tempat PKL secara cepat dan mudah diedit.&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Find &amp;amp; Replace&lt;/td&gt;&lt;td&gt;Mengganti istilah yang salah di seluruh dokumen sekaligus, mis. nama perusahaan.&lt;/td&gt;&lt;/tr&gt;
    &lt;/table&gt;
    &lt;/div&gt;

    &lt;h3 class="sub-title"&gt;Aturan Penulisan Sitasi&lt;/h3&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;strong&gt;Satu penulis&lt;/strong&gt;: Bowlby (1973) di awal kalimat, atau (Guiffrida, 2006) di akhir kalimat.&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Dua penulis&lt;/strong&gt;: gunakan kata "dan" di awal kalimat (Nagy dan Herman, 1987), gunakan simbol "&amp;amp;" di dalam kurung (Sills &amp;amp; Song, 2002).&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Tiga penulis atau lebih&lt;/strong&gt;: cukup nama penulis pertama diikuti "dkk." (West, dkk., 1993).&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Daftar Pustaka&lt;/strong&gt;: diurutkan abjad A-Z, spasi tunggal, nama jurnal dan judul buku dicetak miring.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/section&gt;

  &lt;!-- ===================== E. SISTEMATIKA ===================== --&gt;
  &lt;section class="section" id="sistematika"&gt;
    &lt;div class="section-tag"&gt;&lt;span class="num"&gt;05&lt;/span&gt; Struktur Laporan&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Sistematika Laporan PKL&lt;/h2&gt;
    &lt;div class="table-scroll"&gt;
    &lt;table class="compare"&gt;
      &lt;tr&gt;&lt;th&gt;Kelompok&lt;/th&gt;&lt;th&gt;Isi&lt;/th&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Bagian Awal&lt;/td&gt;&lt;td&gt;Halaman judul, biodata, lembar pengesahan, lembar persetujuan, kata pengantar, daftar isi, daftar gambar, daftar tabel&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;BAB I Pendahuluan&lt;/td&gt;&lt;td&gt;Latar belakang, tujuan, manfaat, tempat dan waktu PKL&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;BAB II Tinjauan Umum&lt;/td&gt;&lt;td&gt;Sejarah umum, visi misi dan slogan, kegiatan umum, tugas dan fungsi, analisis usaha (SWOT, 5W+1H)&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;BAB III Pelaksanaan PKL&lt;/td&gt;&lt;td&gt;Bidang kerja, pelaksanaan kerja, kendala yang dihadapi, cara mengatasi kendala&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;BAB IV Penutup&lt;/td&gt;&lt;td&gt;Kesimpulan dan saran&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Bagian Akhir&lt;/td&gt;&lt;td&gt;Daftar pustaka, lembar konsultasi, jadwal dinas, dokumentasi kegiatan&lt;/td&gt;&lt;/tr&gt;
    &lt;/table&gt;
    &lt;/div&gt;
  &lt;/section&gt;

  &lt;!-- ===================== RANGKUMAN ===================== --&gt;
  &lt;section class="section" id="rangkuman"&gt;
    &lt;div class="section-tag"&gt;&lt;span class="num"&gt;06&lt;/span&gt; Penguatan Konsep&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Rangkuman Materi&lt;/h2&gt;
    &lt;div class="summary-box"&gt;
      &lt;h4&gt;Poin-Poin Kunci&lt;/h4&gt;
      &lt;ul&gt;
        &lt;li&gt;Integrasi dokumen menggabungkan teks, tabel, gambar, bagan, dan grafik menjadi satu dokumen utuh.&lt;/li&gt;
        &lt;li&gt;Template dan style menjaga konsistensi format di seluruh dokumen panjang.&lt;/li&gt;
        &lt;li&gt;Laporan PKL memakai kertas F4, Times New Roman 12 pt, margin kiri 4 cm dan sisi lain 3 cm, spasi 1,5.&lt;/li&gt;
        &lt;li&gt;Section break memungkinkan format nomor halaman romawi lalu arab dalam satu dokumen.&lt;/li&gt;
        &lt;li&gt;Formulir (biodata, jurnal, lembar konsultasi) paling rapi dibuat menggunakan tabel.&lt;/li&gt;
        &lt;li&gt;Daftar isi, caption, sitasi, dan daftar pustaka dapat dibuat otomatis dari Heading dan data sumber.&lt;/li&gt;
        &lt;li&gt;Mail merge membuat banyak surat serupa dari satu template dan satu sumber data.&lt;/li&gt;
        &lt;li&gt;Sistematika laporan: bagian awal, BAB I sampai BAB IV, lalu bagian akhir.&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/div&gt;
  &lt;/section&gt;

  &lt;!-- ===================== EVALUASI ===================== --&gt;
  &lt;section class="section" id="evaluasi"&gt;
    &lt;div class="section-tag"&gt;&lt;span class="num"&gt;07&lt;/span&gt; Tugas Pribadi&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Evaluasi: Master Penyusun Laporan PKL&lt;/h2&gt;
    &lt;p&gt;Evaluasi ini terdiri atas &lt;strong&gt;dua tahap&lt;/strong&gt; yang saling melengkapi: &lt;strong&gt;Tahap 1&lt;/strong&gt; menguji pemahaman aturan lewat kuis drag &amp;amp; drop, dan &lt;strong&gt;Tahap 2&lt;/strong&gt; menguji keterampilan lewat latihan praktik mengetik dan memformat dokumen Laporan PKL langsung di lembar F4 digital. Nilai akhir digabung 50:50 dari kedua tahap.&lt;/p&gt;

    &lt;div class="submit-panel"&gt;
      &lt;h3 class="sub-title" style="margin-top:0;"&gt;Identitas Peserta&lt;/h3&gt;
      &lt;p style="font-size:0.86rem; margin-bottom:0;"&gt;Isi identitas terlebih dahulu agar nilai dapat tercatat dengan benar.&lt;/p&gt;
      &lt;div class="student-info"&gt;
        &lt;div class="field"&gt;&lt;label for="noAbsen"&gt;No. Absen&lt;/label&gt;&lt;input type="number" id="noAbsen" min="1" placeholder="mis. 12"&gt;&lt;/div&gt;
        &lt;div class="field"&gt;&lt;label for="nama"&gt;Nama Lengkap&lt;/label&gt;&lt;input type="text" id="nama" placeholder="Nama sesuai absensi"&gt;&lt;/div&gt;
        &lt;div class="field"&gt;&lt;label for="kelas"&gt;Kelas&lt;/label&gt;
          &lt;select id="kelas"&gt;
            &lt;option value=""&gt;-- Pilih Kelas --&lt;/option&gt;
            &lt;option value="X TB1"&gt;X TB1&lt;/option&gt;
            &lt;option value="X TB2"&gt;X TB2&lt;/option&gt;
            &lt;option value="X TO1"&gt;X TO1&lt;/option&gt;
            &lt;option value="X TO2"&gt;X TO2&lt;/option&gt;
            &lt;option value="X TJKT1"&gt;X TJKT1&lt;/option&gt;
            &lt;option value="X TJKT2"&gt;X TJKT2&lt;/option&gt;
          &lt;/select&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;

    &lt;!-- TAHAP 1 --&gt;
    &lt;div class="stage-head"&gt;
      &lt;span class="stage-badge"&gt;Tahap 1 - Bobot 50%&lt;/span&gt;
      &lt;h3&gt;Kuis Drag &amp;amp; Drop: Aturan Penyusunan Laporan&lt;/h3&gt;
    &lt;/div&gt;
    &lt;p&gt;Tarik jawaban yang tepat ke kotak dokumen sesuai instruksi pembimbing.&lt;/p&gt;

    &lt;div class="callout warn"&gt;
      &lt;div class="lbl"&gt;Aturan Bermain&lt;/div&gt;
      &lt;p style="margin:0;"&gt;&lt;strong&gt;Jika jawaban salah, soal langsung lanjut ke soal berikutnya dan tidak mendapat nilai&lt;/strong&gt; - tidak ada kesempatan mengulang soal yang sama. Nilai dikirim bila mencapai &lt;strong&gt;KKM = 75&lt;/strong&gt;. Bila belum, tersedia &lt;strong&gt;3 kali kesempatan&lt;/strong&gt;; setelah 3 kali, &lt;strong&gt;nilai tertinggi&lt;/strong&gt; dari ketiga percobaan yang dipakai.&lt;/p&gt;
    &lt;/div&gt;

    &lt;div class="attempt-strip" id="attemptStrip"&gt;&lt;/div&gt;

    &lt;div class="game-panel" id="gamePanel"&gt;
      &lt;button id="btnMulaiEvaluasi" class="primary-btn"&gt;Mulai Kuis Tahap 1&lt;/button&gt;
      &lt;span id="evalMsg"&gt;&lt;/span&gt;
    &lt;/div&gt;

    &lt;!-- TAHAP 2 --&gt;
    &lt;div class="stage-head"&gt;
      &lt;span class="stage-badge"&gt;Tahap 2 - Bobot 50%&lt;/span&gt;
      &lt;h3&gt;Latihan Praktik: Mengetik &amp;amp; Memformat Dokumen F4&lt;/h3&gt;
    &lt;/div&gt;
    &lt;p&gt;Lembar di bawah ini adalah &lt;strong&gt;area ketik langsung&lt;/strong&gt; seukuran kertas F4 dengan margin sesuai pedoman (kiri 4 cm, sisi lain 3 cm). Ganti seluruh teks dalam tanda kurung siku dengan tulisan kalian sendiri, lalu rapikan menggunakan toolbar. Area ini &lt;strong&gt;menolak aksi tempel (paste)&lt;/strong&gt;.&lt;/p&gt;

    &lt;div class="checklist"&gt;
      &lt;h5&gt;Daftar Periksa yang Dinilai&lt;/h5&gt;
      &lt;ul&gt;
        &lt;li&gt;Mengganti seluruh bagian bertanda kurung siku pada Cover, Lembar Pengesahan, dan BAB I.&lt;/li&gt;
        &lt;li&gt;Mengetik Latar Belakang, Tujuan, dan Manfaat PKL dengan kalimat sendiri (minimal 200 karakter tiap bagian).&lt;/li&gt;
        &lt;li&gt;Menerapkan format: judul rata tengah dan tebal, isi paragraf rata kiri-kanan (Justify).&lt;/li&gt;
        &lt;li&gt;Tidak melakukan salin-tempel dari sumber mana pun.&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/div&gt;

    &lt;!-- ===== LAMPIRAN CONTOH LAPORAN PKL (PANDUAN, TIDAK BISA DISALIN) ===== --&gt;
    &lt;div class="lampiran-wrap"&gt;
      &lt;div class="lampiran-head"&gt;
        &lt;div&gt;
          &lt;div class="lampiran-eyebrow"&gt;Panduan Praktik&lt;/div&gt;
          &lt;h4&gt;Lampiran: Contoh Laporan Praktik Kerja Lapangan (PKL) Tahun 2025/2026&lt;/h4&gt;
        &lt;/div&gt;
        &lt;span class="lock-badge"&gt;Tidak dapat disalin - wajib diketik&lt;/span&gt;
      &lt;/div&gt;
      &lt;p class="lampiran-note"&gt;Berikut contoh laporan resmi dari Buku Pedoman PKL SMK Negeri 1 Tuntang sebagai acuan kalian mengetik. Klik judul bagian untuk membuka isinya. Teks di dalamnya &lt;strong&gt;sengaja diproteksi&lt;/strong&gt; sehingga tidak dapat diblok, disalin, atau di-klik kanan - silakan baca lalu ketik ulang di lembar dokumen di bawah.&lt;/p&gt;

      &lt;div class="lampiran-list" id="lampiranList"&gt;&lt;/div&gt;
    &lt;/div&gt;

    &lt;div class="doc-toolbar" id="docToolbar"&gt;
      &lt;button class="b" data-cmd="bold" title="Tebal"&gt;B&lt;/button&gt;
      &lt;button class="i" data-cmd="italic" title="Miring"&gt;I&lt;/button&gt;
      &lt;button class="u" data-cmd="underline" title="Garis Bawah"&gt;U&lt;/button&gt;
      &lt;span class="sep"&gt;&lt;/span&gt;
      &lt;button data-cmd="justifyLeft" title="Rata Kiri"&gt;Kiri&lt;/button&gt;
      &lt;button data-cmd="justifyCenter" title="Rata Tengah"&gt;Tengah&lt;/button&gt;
      &lt;button data-cmd="justifyRight" title="Rata Kanan"&gt;Kanan&lt;/button&gt;
      &lt;button data-cmd="justifyFull" title="Rata Kiri-Kanan"&gt;Rata&lt;/button&gt;
      &lt;span class="sep"&gt;&lt;/span&gt;
      &lt;button data-cmd="insertUnorderedList" title="Daftar Butir"&gt;List Bullet&lt;/button&gt;
      &lt;button data-cmd="insertOrderedList" title="Daftar Nomor"&gt;List Nomor&lt;/button&gt;
      &lt;span class="sep"&gt;&lt;/span&gt;
      &lt;select id="fontSizeSelect" title="Ukuran Huruf"&gt;
        &lt;option value="3" selected&gt;12 pt (Isi)&lt;/option&gt;
        &lt;option value="4"&gt;14 pt (Sub Judul)&lt;/option&gt;
        &lt;option value="5"&gt;16 pt (Judul BAB)&lt;/option&gt;
      &lt;/select&gt;
      &lt;select id="fontFamilySelect" title="Jenis Huruf"&gt;
        &lt;option value="Times New Roman"&gt;Times New Roman&lt;/option&gt;
        &lt;option value="Arial"&gt;Arial&lt;/option&gt;
      &lt;/select&gt;
      &lt;span class="sep"&gt;&lt;/span&gt;
      &lt;button id="btnTambahHalaman" title="Tambah Halaman Kosong"&gt;+ Halaman&lt;/button&gt;
      &lt;span class="hint"&gt;Klik di lembar dokumen dulu, lalu gunakan tombol ini&lt;/span&gt;
    &lt;/div&gt;

    &lt;div class="doc-stage" id="docStage"&gt;

      &lt;div class="f4-page" contenteditable="true" data-pagelabel="Halaman 1 - Cover" id="page1" style="text-align:center;"&gt;
        &lt;br&gt;&lt;br&gt;
        &lt;div style="font-size:16pt; font-weight:bold;"&gt;
          LAPORAN PRAKTIK KERJA LAPANGAN (PKL)&lt;br&gt;
          TAHUN PELAJARAN 2025/2026&lt;br&gt;&lt;br&gt;
          DI [Ketik Nama Perusahaan Tempat PKL]
        &lt;/div&gt;
        &lt;br&gt;&lt;br&gt;
        &lt;div&gt;&lt;i&gt;Diajukan sebagai salah satu syarat untuk mengikuti&lt;br&gt;Ujian Kompetensi Keahlian&lt;/i&gt;&lt;/div&gt;
        &lt;br&gt;&lt;br&gt;
        &lt;div style="border:1px solid black; width:3cm; height:4cm; margin:0 auto; display:flex; align-items:center; justify-content:center; font-style:italic; color:gray;"&gt;Foto 3x4&lt;/div&gt;
        &lt;br&gt;&lt;br&gt;
        &lt;div style="font-weight:bold; font-size:14pt;"&gt;
          Disusun Oleh:&lt;br&gt;&lt;br&gt;
          NAMA: [Ketik Nama Anda]&lt;br&gt;
          NIS: [Ketik NIS Anda]&lt;br&gt;
          KELAS: [Ketik Kelas Anda]
        &lt;/div&gt;
        &lt;br&gt;&lt;br&gt;
        &lt;div style="font-weight:bold; font-size:16pt;"&gt;
          PEMERINTAH PROVINSI JAWA TENGAH&lt;br&gt;
          DINAS PENDIDIKAN DAN KEBUDAYAAN&lt;br&gt;
          SMK NEGERI 1 TUNTANG&lt;br&gt;
          2025
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;div class="f4-page" contenteditable="true" data-pagelabel="Halaman 2 - Lembar Pengesahan" id="page2"&gt;
        &lt;div style="text-align:center; font-weight:bold; font-size:14pt;"&gt;LEMBAR PENGESAHAN&lt;/div&gt;
        &lt;br&gt;&lt;br&gt;
        &lt;div style="text-align:justify;"&gt;
          Laporan Praktik Kerja Lapangan (PKL) yang disusun oleh:&lt;br&gt;&lt;br&gt;
          Nama&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;: [Ketik Nama Anda]&lt;br&gt;
          NIS&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;: [Ketik NIS Anda]&lt;br&gt;
          Program Keahlian&amp;nbsp;&amp;nbsp;: [Ketik Program Keahlian Anda]&lt;br&gt;
          Tempat PKL&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;: [Ketik Nama Perusahaan Tempat PKL]&lt;br&gt;&lt;br&gt;
          Telah diperiksa, disetujui, dan disahkan pada tanggal: [Ketik Tanggal Pengesahan]
        &lt;/div&gt;
        &lt;br&gt;&lt;br&gt;&lt;br&gt;
        &lt;div style="display:flex; justify-content:space-between; text-align:center;"&gt;
          &lt;div style="width:45%;"&gt;
            Pembimbing Industri,&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;
            &lt;b&gt;&lt;u&gt;[Ketik Nama Pembimbing Industri]&lt;/u&gt;&lt;/b&gt;
          &lt;/div&gt;
          &lt;div style="width:45%;"&gt;
            Guru Pembimbing Sekolah,&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;
            &lt;b&gt;&lt;u&gt;[Ketik Nama Guru Pembimbing]&lt;/u&gt;&lt;/b&gt;&lt;br&gt;
            NIP. .....................................
          &lt;/div&gt;
        &lt;/div&gt;
        &lt;br&gt;&lt;br&gt;
        &lt;div style="text-align:center;"&gt;
          Mengetahui,&lt;br&gt;
          Kepala SMK Negeri 1 Tuntang&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;
          &lt;b&gt;&lt;u&gt;Nanang Nurdiyanto, S.Pd, M.Eng&lt;/u&gt;&lt;/b&gt;&lt;br&gt;
          NIP. 19770402 200501 1 010
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;div class="f4-page" contenteditable="true" data-pagelabel="Halaman 3 - BAB I Pendahuluan" id="page3"&gt;
        &lt;div style="text-align:center; font-weight:bold; font-size:14pt;"&gt;BAB I&lt;br&gt;PENDAHULUAN&lt;/div&gt;
        &lt;br&gt;&lt;br&gt;
        &lt;b&gt;A. Latar Belakang&lt;/b&gt;
        &lt;div style="text-align:justify; text-indent:1.25cm;" class="placeholder-note"&gt;
          [Blok dan hapus teks ini, lalu ketik latar belakang pelaksanaan PKL dengan kalimat sendiri, minimal 200 karakter. Gunakan format Rata (Justify) dan awal paragraf menjorok ke dalam.]
        &lt;/div&gt;
        &lt;br&gt;
        &lt;b&gt;B. Tujuan Praktik Kerja Lapangan&lt;/b&gt;
        &lt;div style="text-align:justify; text-indent:1.25cm;" class="placeholder-note"&gt;
          [Blok dan hapus teks ini, lalu ketik tujuan dilaksanakannya PKL bagi peserta didik, minimal 200 karakter.]
        &lt;/div&gt;
        &lt;br&gt;
        &lt;b&gt;C. Manfaat Praktik Kerja Lapangan&lt;/b&gt;
        &lt;div style="text-align:justify; text-indent:1.25cm;" class="placeholder-note"&gt;
          [Blok dan hapus teks ini, lalu ketik manfaat PKL bagi peserta didik, sekolah, dan dunia kerja, minimal 200 karakter.]
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="doc-meta"&gt;
      &lt;span id="docCharCount"&gt;0 karakter diketik&lt;/span&gt;
      &lt;span class="flag" id="docPasteFlag"&gt;&lt;/span&gt;
    &lt;/div&gt;

    &lt;button id="btnHitungPraktik" class="primary-btn"&gt;Periksa &amp;amp; Hitung Nilai Latihan Praktik&lt;/button&gt;
    &lt;span id="praktikMsg"&gt;&lt;/span&gt;

    &lt;div class="result-panel" id="praktikResultPanel"&gt;
      &lt;div class="score-lbl"&gt;Nilai Latihan Praktik (bobot 50%)&lt;/div&gt;
      &lt;div class="score" id="praktikScoreValue"&gt;0&lt;/div&gt;
      &lt;p id="praktikResultDetail"&gt;&lt;/p&gt;
    &lt;/div&gt;

    &lt;!-- HASIL AKHIR --&gt;
    &lt;div class="result-panel" id="finalResultPanel"&gt;
      &lt;div class="score-lbl" id="finalResultLabel"&gt;Nilai Akhir Evaluasi&lt;/div&gt;
      &lt;div class="score" id="finalScoreValue"&gt;0&lt;/div&gt;
      &lt;p id="finalResultDetail"&gt;&lt;/p&gt;
      &lt;button id="btnCobaLagi" class="primary-btn" style="display:none;"&gt;Coba Lagi Kuis Tahap 1&lt;/button&gt;
      &lt;button id="btnUnduhPDF" class="primary-btn ghost" style="display:none;"&gt;Unduh Bukti Mengerjakan (PDF F4)&lt;/button&gt;
      &lt;p id="pdfHint" style="display:none; font-size:0.8rem; color:var(--ink-soft); margin-top:8px;"&gt;Setelah diunduh, cetak pada kertas F4 dan serahkan kepada guru sebagai bukti pengerjaan.&lt;/p&gt;
    &lt;/div&gt;
  &lt;/section&gt;

  &lt;!-- ===================== PENUTUP ===================== --&gt;
  &lt;section class="section" id="penutup"&gt;
    &lt;div class="section-tag"&gt;&lt;span class="num"&gt;08&lt;/span&gt; Penutup Pembelajaran&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Tugas Individu di Buku Catatan&lt;/h2&gt;
    &lt;div class="closing-task"&gt;
      &lt;div class="lbl"&gt;1. Catat Nilai Evaluasi&lt;/div&gt;
      &lt;p style="margin:0;"&gt;Salin &lt;strong&gt;Nilai Akhir Evaluasi&lt;/strong&gt; yang muncul di layar ke buku catatan pada kolom &lt;strong&gt;"Nilai Evaluasi"&lt;/strong&gt; (buat tabel: Tanggal | Materi | Nilai Evaluasi).&lt;/p&gt;
    &lt;/div&gt;
    &lt;div class="closing-task"&gt;
      &lt;div class="lbl"&gt;2. Tulis Resume Materi&lt;/div&gt;
      &lt;p style="margin:0;"&gt;Buat &lt;strong&gt;resume materi "Integrasi Dokumen dan Otomasi Pengolah Kata"&lt;/strong&gt; dengan bahasa sendiri, mencakup: integrasi objek, template dan style, formulir, fitur otomatis, serta sistematika dan tata tulis Laporan PKL.&lt;/p&gt;
    &lt;/div&gt;
  &lt;/section&gt;

&lt;/main&gt;

&lt;footer&gt;
  INFORMATIKA - INTEGRASI DOKUMEN DAN OTOMASI PENGOLAH KATA - FASE E KELAS X SMK
&lt;/footer&gt;
&lt;/div&gt;

&lt;div class="print-area" id="printArea"&gt;&lt;/div&gt;

&lt;script&gt;
  var GAS_ENDPOINT = "https://script.google.com/macros/s/AKfycbwKp7DrBTALJMlw8crjK7RgXIO8LVcU4yVEd9WJNs_vgSXkVxfw7fwkGbOT2IBNOjg3uQ/exec";
  var JUDUL_MATERI = "Integrasi Dokumen dan Otomasi Pengolah Kata";
  var KKM = 75;
  var MAX_ATTEMPTS = 3;
  var EVAL_SOAL_COUNT = 12;

  // ============================================================
  // TAHAP 1: KUIS DRAG &amp; DROP
  // ============================================================
  var allOptions = [
    { id:"opt_f4", text:"Kertas F4" },
    { id:"opt_a4", text:"Kertas A4" },
    { id:"opt_margin_kiri", text:"4 cm (Margin Kiri)" },
    { id:"opt_margin_lain", text:"3 cm (Atas, Kanan, Bawah)" },
    { id:"opt_tnr", text:"Times New Roman" },
    { id:"opt_arial", text:"Arial" },
    { id:"opt_size_12", text:"Ukuran 12 pt" },
    { id:"opt_size_14", text:"Ukuran 14 pt" },
    { id:"opt_spasi_1_5", text:"1,5 Spasi" },
    { id:"opt_spasi_1", text:"1 Spasi (Single)" },
    { id:"opt_bag_awal", text:"Bagian Awal" },
    { id:"opt_bag_utama", text:"Bagian Utama" },
    { id:"opt_bag_akhir", text:"Bagian Akhir" },
    { id:"opt_biodata", text:"Biodata Peserta Didik" },
    { id:"opt_pengesahan", text:"Lembar Pengesahan" },
    { id:"opt_toc", text:"Table of Contents" },
    { id:"opt_page_num", text:"Page Number" },
    { id:"opt_header_kanan", text:"Kanan Atas (Header)" },
    { id:"opt_footer_tengah", text:"Tengah Bawah (Footer)" },
    { id:"opt_romawi", text:"Angka Romawi Kecil (i, ii)" },
    { id:"opt_arab", text:"Angka Arab (1, 2, 3)" },
    { id:"opt_citation", text:"Citation / Bibliography" },
    { id:"opt_table", text:"Insert Table" },
    { id:"opt_mailmerge", text:"Mail Merge" },
    { id:"opt_smartart", text:"SmartArt / Shapes" },
    { id:"opt_picture", text:"Insert Picture" },
    { id:"opt_caption", text:"Insert Caption" },
    { id:"opt_section", text:"Section Break" },
    { id:"opt_bab_1", text:"BAB I Pendahuluan" },
    { id:"opt_bab_2", text:"BAB II Tinjauan Umum" },
    { id:"opt_bab_3", text:"BAB III Pelaksanaan PKL" },
    { id:"opt_bab_4", text:"BAB IV Penutup" },
    { id:"opt_jurnal", text:"Jurnal Kegiatan PKL" },
    { id:"opt_konsultasi", text:"Lembar Konsultasi" },
    { id:"opt_abjad", text:"Urut Abjad (A-Z)" },
    { id:"opt_kata_dan", text:"Kata 'dan'" },
    { id:"opt_simbol_dan", text:"Simbol '&amp;'" },
    { id:"opt_dkk", text:"Singkatan 'dkk.'" },
    { id:"opt_italic", text:"Cetak Miring (Italic)" },
    { id:"opt_heading", text:"Heading Style" }
  ];

  var questions = [
    { q:"Ukuran standar kertas yang diwajibkan untuk mencetak Laporan PKL adalah...", correctId:"opt_f4" },
    { q:"Agar teks tidak tertutup saat laporan dijilid, batas kertas sebelah kiri (Margin Kiri) diatur sebesar...", correctId:"opt_margin_kiri" },
    { q:"Berapa ukuran Margin Atas, Kanan, dan Bawah yang benar sesuai pedoman?", correctId:"opt_margin_lain" },
    { q:"Jenis huruf (Font) standar yang diwajibkan untuk seluruh teks laporan adalah...", correctId:"opt_tnr" },
    { q:"Untuk teks paragraf biasa, ukuran huruf yang digunakan adalah...", correctId:"opt_size_12" },
    { q:"Berapa jarak antar baris (Line Spacing) untuk bagian isi utama laporan?", correctId:"opt_spasi_1_5" },
    { q:"Khusus pengetikan Daftar Pustaka dan Kata Pengantar, jarak antar barisnya harus...", correctId:"opt_spasi_1" },
    { q:"Halaman Judul, Kata Pengantar, dan Daftar Isi termasuk kelompok...", correctId:"opt_bag_awal" },
    { q:"BAB I hingga BAB IV yang merupakan inti laporan disebut sebagai...", correctId:"opt_bag_utama" },
    { q:"Daftar Pustaka dan Lampiran-lampiran diletakkan pada...", correctId:"opt_bag_akhir" },
    { q:"Halaman setelah cover yang wajib dilengkapi pas foto 3x4 disebut...", correctId:"opt_biodata" },
    { q:"Lembar berisi tanda tangan pembimbing dan Kepala Sekolah sebagai bukti laporan sah adalah...", correctId:"opt_pengesahan" },
    { q:"Fitur otomatis agar judul BAB dan nomor halamannya terupdate tanpa mengetik manual adalah...", correctId:"opt_toc" },
    { q:"Fitur untuk memberikan nomor pada setiap lembar dokumen secara otomatis adalah...", correctId:"opt_page_num" },
    { q:"Untuk halaman isi biasa (bukan awal BAB), nomor halaman diletakkan di...", correctId:"opt_header_kanan" },
    { q:"Khusus halaman yang memuat Judul BAB baru, nomor halamannya diletakkan di...", correctId:"opt_footer_tengah" },
    { q:"Format nomor halaman untuk Bagian Awal (Kata Pengantar, Daftar Isi) menggunakan...", correctId:"opt_romawi" },
    { q:"Format nomor halaman untuk Bagian Utama (BAB I dst) menggunakan...", correctId:"opt_arab" },
    { q:"Fitur yang memungkinkan format nomor halaman berbeda antar bagian dalam satu dokumen adalah...", correctId:"opt_section" },
    { q:"Fitur otomatis untuk mengelola sumber kutipan dan membuat Daftar Pustaka instan adalah...", correctId:"opt_citation" },
    { q:"Untuk membuat layout formulir Biodata yang rapi dan sejajar, fitur paling efisien adalah...", correctId:"opt_table" },
    { q:"Jika panitia ingin membuat Surat Tugas massal dengan data dari Excel, fitur yang tepat adalah...", correctId:"opt_mailmerge" },
    { q:"Fitur yang cocok untuk membuat visualisasi Struktur Organisasi tempat PKL adalah...", correctId:"opt_smartart" },
    { q:"Untuk menambahkan bukti foto kegiatan di bagian lampiran, digunakan fitur...", correctId:"opt_picture" },
    { q:"Fitur untuk memberi keterangan bernomor otomatis pada gambar (Gambar 2.1) dan tabel adalah...", correctId:"opt_caption" },
    { q:"Fondasi seluruh otomasi dokumen, yang menandai judul bab agar dikenali fitur lain, adalah...", correctId:"opt_heading" },
    { q:"Latar Belakang, Tujuan, dan Manfaat PKL diketik pada bagian...", correctId:"opt_bab_1" },
    { q:"Sejarah Perusahaan, Visi Misi, dan Analisis SWOT dijabarkan pada...", correctId:"opt_bab_2" },
    { q:"Bagian berisi rincian pekerjaan dan kendala yang dihadapi ada di...", correctId:"opt_bab_3" },
    { q:"Kesimpulan hasil PKL dan Saran untuk sekolah/industri ditulis pada...", correctId:"opt_bab_4" },
    { q:"Dokumen lampiran berupa tabel yang wajib diisi setiap hari saat praktik di industri adalah...", correctId:"opt_jurnal" },
    { q:"Tabel lampiran yang membuktikan telah rutin bimbingan dengan guru pembimbing adalah...", correctId:"opt_konsultasi" },
    { q:"Urutan penulisan sumber dalam Daftar Pustaka disusun berdasarkan...", correctId:"opt_abjad" },
    { q:"Mengutip 2 penulis di awal kalimat: 'Nagy ... Herman (1987)'. Kata sambungnya adalah...", correctId:"opt_kata_dan" },
    { q:"Mengutip 2 penulis di dalam kurung: '(Sills ... Song, 2002)'. Simbol sambungnya adalah...", correctId:"opt_simbol_dan" },
    { q:"Jika sumber ditulis 3 orang atau lebih, setelah nama penulis pertama diikuti singkatan...", correctId:"opt_dkk" },
    { q:"Dalam Daftar Pustaka, pemformatan huruf untuk Judul Buku atau Nama Jurnal harus...", correctId:"opt_italic" }
  ];

  function shuffleArray(array){
    var a = array.slice();
    for (var i = a.length - 1; i &gt; 0; i--){
      var j = Math.floor(Math.random() * (i + 1));
      var t = a[i]; a[i] = a[j]; a[j] = t;
    }
    return a;
  }

  function getIdentitas(){
    return {
      noAbsen: document.getElementById('noAbsen').value.trim(),
      nama: document.getElementById('nama').value.trim(),
      kelas: document.getElementById('kelas').value.trim()
    };
  }

  var evalAttemptScores = [];
  var evalAttemptLogs = [];
  var currentLog = [];
  var evalFinalAttemptIndex = null;
  var evalFinalScore = null;
  var praktikScore = null;
  var combinedFinalScore = null;
  var currentSet = [];
  var qIndex = 0;
  var correctCount = 0;
  var draggedChip = null;

  function renderAttemptStrip(){
    var strip = document.getElementById('attemptStrip');
    strip.innerHTML = '';
    for (var i = 0; i &lt; MAX_ATTEMPTS; i++){
      var pill = document.createElement('div');
      pill.className = 'attempt-pill';
      if (i &lt; evalAttemptScores.length){
        pill.className += (evalAttemptScores[i] &gt;= KKM ? ' pass' : ' fail');
        pill.textContent = 'Percobaan ' + (i+1) + ': ' + evalAttemptScores[i];
      } else if (i === evalAttemptScores.length){
        pill.className += ' current';
        pill.textContent = 'Percobaan ' + (i+1) + ': belum dimulai';
      } else {
        pill.textContent = 'Percobaan ' + (i+1) + ': -';
      }
      strip.appendChild(pill);
    }
  }
  renderAttemptStrip();

  document.getElementById('btnMulaiEvaluasi').addEventListener('click', function(){
    var id = getIdentitas();
    if (!id.noAbsen || !id.nama || !id.kelas){
      document.getElementById('evalMsg').textContent = 'Lengkapi identitas terlebih dahulu.';
      return;
    }
    document.getElementById('evalMsg').textContent = '';
    startEvalAttempt();
  });
  document.getElementById('btnCobaLagi').addEventListener('click', function(){
    document.getElementById('finalResultPanel').style.display = 'none';
    startEvalAttempt();
  });

  function startEvalAttempt(){
    qIndex = 0; correctCount = 0; currentLog = [];
    currentSet = shuffleArray(questions).slice(0, EVAL_SOAL_COUNT);
    document.getElementById('finalResultPanel').style.display = 'none';
    renderQuestion();
  }

  function renderQuestion(){
    var panel = document.getElementById('gamePanel');
    if (qIndex &gt;= currentSet.length){ finishEvalAttempt(); return; }

    var q = currentSet[qIndex];
    panel.innerHTML =
      '&lt;div class="game-progress"&gt;&lt;span&gt;Soal ' + (qIndex+1) + ' / ' + EVAL_SOAL_COUNT + '&lt;/span&gt;&lt;span&gt;Benar: ' + correctCount + '&lt;/span&gt;&lt;/div&gt;' +
      '&lt;div class="q-instruksi"&gt;Instruksi Pembimbing&lt;/div&gt;' +
      '&lt;div class="q-text"&gt;' + q.q + '&lt;/div&gt;' +
      '&lt;div class="drop-zone" id="dropZone"&gt;Tarik (drag) jawaban ke sini, atau klik salah satu pilihan&lt;/div&gt;' +
      '&lt;div class="opt-pool" id="optPool"&gt;&lt;/div&gt;';

    var dropZone = document.getElementById('dropZone');
    var optPool = document.getElementById('optPool');

    var correctOpt = null;
    for (var i = 0; i &lt; allOptions.length; i++){ if (allOptions[i].id === q.correctId) correctOpt = allOptions[i]; }
    var distractors = shuffleArray(allOptions.filter(function(o){ return o.id !== q.correctId; })).slice(0, 3);
    var choices = shuffleArray([correctOpt].concat(distractors));

    choices.forEach(function(opt){
      var chip = document.createElement('div');
      chip.className = 'opt-chip';
      chip.draggable = true;
      chip.dataset.id = opt.id;
      chip.textContent = opt.text;
      chip.addEventListener('dragstart', function(){ draggedChip = chip; chip.classList.add('dragging'); });
      chip.addEventListener('dragend', function(){ chip.classList.remove('dragging'); });
      chip.addEventListener('click', function(){ handleAnswer(opt, q, dropZone); });
      optPool.appendChild(chip);
    });

    dropZone.addEventListener('dragover', function(e){ e.preventDefault(); dropZone.classList.add('drag-over'); });
    dropZone.addEventListener('dragleave', function(){ dropZone.classList.remove('drag-over'); });
    dropZone.addEventListener('drop', function(e){
      e.preventDefault();
      dropZone.classList.remove('drag-over');
      if (!draggedChip) return;
      var pickedId = draggedChip.dataset.id;
      var picked = null;
      for (var i = 0; i &lt; allOptions.length; i++){ if (allOptions[i].id === pickedId) picked = allOptions[i]; }
      draggedChip = null;
      handleAnswer(picked, q, dropZone);
    });
  }

  function handleAnswer(picked, q, dropZone){
    if (dropZone.dataset.answered === '1') return;
    dropZone.dataset.answered = '1';

    var correctOpt = null;
    for (var i = 0; i &lt; allOptions.length; i++){ if (allOptions[i].id === q.correctId) correctOpt = allOptions[i]; }
    var isCorrect = picked.id === q.correctId;

    currentLog.push({ q: q.q, userAns: picked.text, correctAns: correctOpt.text, isCorrect: isCorrect });

    if (isCorrect){
      correctCount++;
      dropZone.className = 'drop-zone correct';
      dropZone.textContent = '[BENAR] ' + correctOpt.text;
    } else {
      dropZone.className = 'drop-zone wrong';
      dropZone.textContent = '[SALAH] Jawabanmu: ' + picked.text + '. Yang benar: ' + correctOpt.text;
    }

    setTimeout(function(){ qIndex++; renderQuestion(); }, 1400);
  }

  function finishEvalAttempt(){
    var attemptScore = Math.round((correctCount / EVAL_SOAL_COUNT) * 100);
    evalAttemptScores.push(attemptScore);
    evalAttemptLogs.push(currentLog.slice());
    renderAttemptStrip();

    document.getElementById('gamePanel').innerHTML =
      '&lt;p style="text-align:center; margin:0;"&gt;Percobaan ke-' + evalAttemptScores.length + ' selesai. Benar ' + correctCount + ' dari ' + EVAL_SOAL_COUNT + ' soal. Skor Tahap 1: &lt;strong&gt;' + attemptScore + '&lt;/strong&gt; (KKM = ' + KKM + ')&lt;/p&gt;';

    var panel = document.getElementById('finalResultPanel');
    var label = document.getElementById('finalResultLabel');
    var scoreEl = document.getElementById('finalScoreValue');
    var detailEl = document.getElementById('finalResultDetail');
    var btnCoba = document.getElementById('btnCobaLagi');

    if (attemptScore &gt;= KKM){
      evalFinalScore = attemptScore;
      evalFinalAttemptIndex = evalAttemptScores.length - 1;
      label.textContent = 'Nilai Tahap 1 (Tercapai KKM)';
      scoreEl.textContent = evalFinalScore;
      detailEl.textContent = 'KKM tercapai pada percobaan ke-' + evalAttemptScores.length + '. Lanjutkan ke Tahap 2: Latihan Praktik.';
      btnCoba.style.display = 'none';
      panel.style.display = 'block';
      tryFinalize();
    } else if (evalAttemptScores.length &lt; MAX_ATTEMPTS){
      label.textContent = 'Belum Mencapai KKM';
      scoreEl.textContent = attemptScore;
      detailEl.textContent = 'Skor ' + attemptScore + ' belum mencapai KKM (' + KKM + '). Sisa kesempatan: ' + (MAX_ATTEMPTS - evalAttemptScores.length) + ' kali.';
      btnCoba.style.display = 'inline-block';
      panel.style.display = 'block';
    } else {
      evalFinalScore = Math.max.apply(null, evalAttemptScores);
      evalFinalAttemptIndex = evalAttemptScores.indexOf(evalFinalScore);
      label.textContent = 'Nilai Tahap 1 (Tertinggi dari 3 Percobaan)';
      scoreEl.textContent = evalFinalScore;
      detailEl.textContent = 'Sudah 3 kali percobaan. Nilai tertinggi (' + evalFinalScore + ') yang digunakan. Lanjutkan ke Tahap 2: Latihan Praktik.';
      btnCoba.style.display = 'none';
      panel.style.display = 'block';
      tryFinalize();
    }
  }

  // ============================================================
  // LAMPIRAN CONTOH LAPORAN PKL (panduan, diproteksi dari penyalinan)
  // ============================================================
  var LAMPIRAN = [
    { judul: "1. Halaman Judul (Cover)",
      isi: "LAPORAN\nPRAKTIK KERJA LAPANGAN\nDI PT UNGARAN SARI GARMEN KABUPATEN SEMARANG\n26 NOVEMBER 2025 - 13 MARET 2026\n\n(Logo sekolah, lebar 6 cm x tinggi 6 cm)\n\nDISUSUN OLEH : RIZWAN NADIF AL-HAKIM\n(NIS)\n\nPROGRAM KEAHLIAN TATA BUSANA\nSMK NEGERI 1 TUNTANG\n2025\n\nCatatan format: seluruh teks judul berukuran 14 pt, dicetak tebal, dan rata tengah." },

    { judul: "2. Biodata Peserta Didik",
      isi: "BIODATA PESERTA DIDIK\n\nNama                  : ------------\nNIS                   : -----------\nKelas                 : XII\nProgram Keahlian      : TATA BUSANA\n\n(Kotak PHOTO 3x4 diletakkan di sisi kanan)\n\nNomor halaman: ii\n\nCatatan format: agar titik dua sejajar sempurna, bagian ini dibuat dengan tabel 2 kolom tanpa garis (No Border)." },

    { judul: "3. Lembar Pengesahan",
      isi: "LEMBAR PENGESAHAN\n\nRIZWAN NADIF AL-HAKIM\n(NIS: 1874/215.067)\n\nDipertahankan di depan Tim Penguji PKL\nProgram Keahlian Tata Busana\nSMK Negeri 1 Tuntang\n\nTim Penguji\n\n............................ (Tanggal Pengesahan) (Tanda Tangan)\n(Pembimbing Sekolah)\n\n............................ (Tanggal Pengesahan) (Tanda Tangan)\n(Penguji)\n\nMengetahui,\nKepala SMKN 1 TUNTANG\n\n\nNanang Nurdiyanto, S.Pd, M.Eng\nNIP. 19770402 200501 1 010\n\nNomor halaman: iii" },

    { judul: "4. Lembar Persetujuan",
      isi: "LEMBAR PERSETUJUAN\n\nRIZWAN NADIF AL-HAKIM\n(NIS: 1874/215.067)\n\nLaporan ini ditulis untuk memenuhi sebagian persyaratan\ndalam mengikuti sidang PKL\nProgram Keahlian Tata Busana\n\nMenyetujui untuk diajukan pada ujian PKL:\n\nPembimbing DUDI                    Pembimbing Sekolah\n\n\n.............................      .............................\nNIP..                              NIP..\n\nMengetahui\nKetua Program Keahlian\n\n\n------------------------------------\nNIP.\n\nKepala SMKN 1 TUNTANG\n\n\nNanang Nurdiyanto, S.Pd, M.Eng\nNIP. 19770402 200501 1 010\n\nNomor halaman: iv" },

    { judul: "5. Kata Pengantar",
      isi: "KATA PENGANTAR\n\nPuji dan syukur penyusun panjatkan kepada Allah SWT, karena atas segala rahmat, berkah dan karunia-Nya sehingga penyusun dapat menyelesaikan Laporan Praktik Kerja Lapangan yang bertempat di Laboratorium Kesehatan Daerah Kabupaten Semarang Program Keahlian Teknik Laboratorium Medik. Penyusun menyadari sepenuhnya bahwa selesainya laporan ini berkat bantuan dari berbagai pihak. Pada kesempatan kali ini penyusun ingin menyampaikan terimakasih kepada:\n\n1. ............................ selaku Kepala SMK Negeri 1 Tuntang Kabupaten Semarang\n2. ............................ selaku Wakil Kepala Sekolah Bidang Humas SMK Negeri 1 Tuntang\n3. ............................ selaku Kepala Program Keahlian Tata Busana\n4. Bapak/Ibu ......................, selaku pembimbing Praktik Kerja Lapangan dari SMK Negeri 1 Tuntang\n5. ...........\n6. ...........\n7. Dst. (optional)\n\nPenyusun menyadari masih banyak kekurangan dalam penyusunan Laporan Praktik Kerja Lapangan ini, walaupun demikian semoga laporan ini dapat bermanfaat bagi para pembaca.\n\nKabupaten Semarang, 13 Maret 2026\nPenyusun\n\nNomor halaman: v\nCatatan format: kata pengantar diketik dengan spasi tunggal (single), bukan 1,5." },

    { judul: "6. Daftar Isi",
      isi: "DAFTAR ISI\n\nHalaman Judul ........................................................ i\nHalaman Biodata ..................................................... ii\nHalaman Pengesahan .................................................. iii\nHalaman Persetujuan ................................................. iv\nKata Pengantar ...................................................... v\nDaftar Isi .......................................................... vi\nDaftar Gambar ....................................................... vii\nDaftar Tabel ........................................................ viii\n\nBAB I PENDAHULUAN\nA. Latar Belakang PKL\nB. Tujuan PKL\nC. Manfaat PKL\nD. Tempat dan Waktu PKL\n\nBAB II TINJAUAN UMUM TEMPAT PKL\nA. Sejarah Umum\nB. Visi, Misi, dan Slogan\nC. Kegiatan Umum\nD. Tugas dan Fungsi\nE. Analisis Usaha\n\nBAB III PELAKSANAAN PKL\nA. Bidang Kerja\nB. Pelaksanaan Kerja\nC. Kendala yang Dihadapi\nD. Cara Mengatasi Masalah\n\nBAB IV PENUTUP\nA. Kesimpulan\nB. Saran\n\nDAFTAR PUSTAKA\nLAMPIRAN\n1. Lembar Konsultasi\n2. Jadwal Dinas/Jaga/Shift\n3. Dokumentasi Kegiatan\n\nNomor halaman: vi\nCatatan format: dibuat otomatis melalui References &gt; Table of Contents, bukan diketik manual." },

    { judul: "7. BAB I - Pendahuluan",
      isi: "BAB I\nPENDAHULUAN\n\nA. Latar Belakang Praktik Kerja Lapangan (PKL)\n    SMK Negeri 1 Tuntang Kabupaten Semarang merupakan salah satu Sekolah Menengah Kejuruan (SMK) yang berada di Kabupaten Semarang. dst\n\nB. Tujuan Praktik Kerja Lapangan (PKL)\n    Tujuan adanya PKL ini antara lain sebagai berikut;\n\nC. Manfaat Praktik Kerja Lapangan (PKL)\n    1. Manfaat Bagi Peserta Didik\n       a. Meningkatnya kompetensi keahlian yang telah diperoleh di sekolah.\n    2. Manfaat Bagi Sekolah\n       a. Terjalinnya hubungan kerja sama yang saling menguntungkan antara sekolah\n    3. Manfaat Bagi Dunia Kerja\n       a. Adanya masukan yang positif dan konstruktif dari SMK/MAK untuk perkembangan dunia kerja.\n\nD. Tempat dan Waktu Praktik Kerja Lapangan (PKL)\n    1. Tempat Praktik Kerja Lapangan (PKL)\n       Praktik Kerja Lapangan (PKL) ini dilaksanakan di ................ (Alamat lengkap disertai Kode Pos)\n    2. Waktu Praktik Kerja Lapangan (PKL)\n       Waktu Praktik Kerja Lapangan (PKL) dilaksanakan pada tanggal 26 November 2025 sampai dengan tanggal 13 Maret 2026, dengan jadwal kegiatan terlampir." },

    { judul: "8. BAB II - Tinjauan Umum Tempat PKL",
      isi: "BAB II\nTINJAUAN UMUM TEMPAT PKL\n\nA. Sejarah Umum\n    PT. Ungaran Sari Garmen berdiri sejak ..... dengan dst\n\n    Gambar 2.1 letak PT. Ungaran Sari Garmen Kabupaten Semarang\n    (googlemaps)\n\n    PT. Ungaran Sari Garmen Kabupaten Semarang merupakan .....dst.\n\nB. Visi, Misi dan Slogan\n    Adapun Visi dan Misi didirikannya PT. Ungaran Sari Garmen Kabupaten Semarang adalah sebagai berikut:\n    ..................................dst\n\nC. Kegiatan Umum\n    Tata Busana adalah sebuah program keahlian yang mempelajari dasar-dasar kemampuan dst ................ PT. Ungaran Sari Garmen Kabupaten Semarang seperti ............... dst.\n\nD. Tugas dan Fungsi\n    PT. Ungaran Sari Garmen memiliki tugas dan fungsi ............... dst.\n\nE. Analisis Usaha\n    Analisis usaha adalah proses evaluasi yang dilakukan terhadap suatu bisnis\n\n    1. Analisis SWOT\n       Analisis SWOT adalah teknik yang digunakan untuk mengidentifikasi\n\n       Tabel 2.2 Tabel Analisis SWOT PT. Ungaran Sari Garmen Kabupaten Semarang\n\n       Strength (Kekuatan)    | Weakness (Kelemahan)\n       1. PT. Ungaran Sari    | 1. Kurangnya dalam fasilitas\n          Garmen ...          |    persediaan alat ... dst\n\n       Opportunity (Peluang)  | Threat (Ancaman)\n       1. Peningkatan alat    | 1. Akan ada timbulnya persaingan\n          yang sesuai ...dst  |    dengan ... dst\n\n    2. Analisis Solusi\n       Strategi SO | Strategi WO\n       Strategi ST | Strategi WT\n\n    3. Analisis 5W + 1H\n       Analisis 5W+1H adalah sebuah metode yang digunakan untuk merinci dan memahami suatu peristiwa, situasi, atau masalah dengan cara mengajukan serangkaian pertanyaan yang mencakup lima unsur utama (What, Who, When, Where, Why) ditambah satu unsur tambahan (How)." },

    { judul: "9. BAB III - Pelaksanaan PKL",
      isi: "BAB III\nPELAKSANAAN PKL\n\nA. Bidang Kerja\n    Lokasi Praktikan melaksanakan Praktik Kerja Lapangan (PKL) yaitu di ....................... Praktikan ditempatkan di ........................., yang sifat pekerjaannya berfokus untuk ...............................dst.\n\nB. Pelaksanaan Kerja\n    Selama pelaksanaan Praktik Kerja Lapangan (PKL) Praktikan dibimbing adalah sebagai berikut:\n    ........\n\n    Catatan:\n    Uraian praktikum dikerjakan sesuai dengan tempat PKL.\n    Jabarkan kegiatan setiap poin kompetensi di atas bila dilaksanakan.\n\nC. Kendala yang Dihadapi\n    Dalam menyelesaikan tugas yang diberikan selama Praktik Kerja, yang menjadi kendala saat menyelesaikan tugas meliputi:\n    1. dst\n\nD. Cara Mengatasi Masalah\n    Berikut ini cara yang dilakukan Praktikan dalam mengatasi kendala untuk menyelesaikan tugas yang diberikan, yaitu:\n    1. dst" },

    { judul: "10. BAB IV - Penutup",
      isi: "BAB IV\nPENUTUP\n\nA. Kesimpulan\n    Dari penjelasan diatas kesimpulannya adalah :\n    1. dst\n\nB. Saran\n    Berikut ini adalah saran yang bisa Praktikan berikan dalam pelaksanaan Praktik Kerja Lapangan, yaitu:\n    ...... dst" },

    { judul: "11. Daftar Pustaka",
      isi: "DAFTAR PUSTAKA\n\nBillett, S. (2011). Vocational education: Purposes, traditions and prospects. Springer.\n\nCreswell, J. W. &amp; Poth, C. N. (2018). Qualitative inquiry &amp; research design (4th ed.). SAGE Publication.\n\nKemendikbud. (2014). Garis-garis besar program pembinaan SMK. Direktorat PSMK Kementerian Pendidikan dan Kebudayaan.\n\nKusumam, A., Mukhidin, M., &amp; Hasan, B. (2016). Pengembangan bahan ajar mata pelajaran dasar dan pengukuran listrik untuk sekolah menengah kejuruan. Jurnal Pendidikan Teknologi dan Kejuruan, 23(1), 28-39. http://doi.org/10.21831/jptk.v23i1.9352\n\nWahjusaputri, S., Marlina, E., &amp; Latifah, S. (2020). Developing the teaching factory learning media in a public vocational high school. Jurnal Pendidikan Vokasi, 10 (1), 69-79.\n\nCatatan format: ditulis spasi tunggal, jarak dua spasi antar sumber, diurutkan abjad A-Z, nama jurnal dan judul buku dicetak miring." },

    { judul: "12. Lampiran - Jurnal Kegiatan PKL",
      isi: "JURNAL KEGIATAN PKL\n\nNama Peserta Didik            : Fulan\nDunia Kerja Tempat PKL        : Apotek Seger Waras\nNama Instruktur               : Nama Pembimbing DUDI\nNama Guru Pembimbing          : Febrina/Amalia/Amil\n\nNo. | Hari/Tanggal            | Unit Kerja/Pekerjaan                  | Catatan dan Paraf Dunia Kerja\n1.  | Selasa / 2 Januari 2023 | Membersihkan ruangan                  |\n    |                         | Membaca SOP layanan klien             |\n    |                         | Bertemu dengan Kliyen                 |\n    |                         | Merancang pembuatan video             |\n    |                         | Membuat Skrip                         |\n    |                         | Dst..........                         |\n2.  | Rabu / 3 Januari 2023   | Membersihkan ruangan                  |\n    |                         | Membaca SOP layanan klien             |\n    |                         | Mempersiapkan shooting                |\n    |                         | Dst..........                         |\n\nJurnal kegiatan disusun oleh peserta didik sebagai dokumen pekerjaan yang dilaksanakan.\nCatatan diberikan oleh pembimbing dunia kerja pada setiap kegiatan atau waktu tertentu." },

    { judul: "13. Lampiran - Catatan Kegiatan PKL",
      isi: "CATATAN KEGIATAN PKL\n\nNama Peserta Didik            : Fulan\nDunia Kerja Tempat PKL        : PT. Ungaran Sari Garmen\nNama Instruktur               : Nama Pembimbing DUDI\nNama Guru Pembimbing          : Na'ilir/ Win Rizki/Bagus/Nila Rukmi\n\nA. Nama Pekerjaan\n   Pencatatan Skrip\n\nB. Perencanaan Kegiatan\n   (Jadwal Kegiatan/dokumen perencanaan)\n   Tanggal disepakati pada tanggal 25 Desember 2024\n   Persiapan alat dan bahan\n   Alat :\n   1. Kamera\n   2. Dst...\n   Bahan :\n   1. Kertas HVS\n   2. Dst...\n\nC. Pelaksanaan Kegiatan/Hasil\n   (Uraian proses kerja dan foto hasil)\n   1. Prosedur pencatatan skrip\n      a. Mengikuti prosedur Kesehatan, Keselamatan, dan Keamanan di Tempat Kerja\n      b. Menjaga continuity saat syuting\n      c. Dst.....\n   2. Hasil\n      Hasil pembuatan skrip dapat dilihat pada lampiran.\n\n   (Foto hasil dan Dokumentasi)\n\nD. Catatan Instruktur\n   (Catatan Instruktur)\n\n                                            Tanda Tangan Instruktur\n\n                                            (...........................)" },

    { judul: "14. Lampiran - Lembar Konsultasi Laporan",
      isi: "LEMBAR KONSULTASI LAPORAN\n\nNO. | TANGGAL    | MATERI YANG DIKONSULTASIKAN DAN URAIAN PEMBIMBING          | NAMA DAN TTD PEMBIMBING\n1.  | 23-12-2024 | Pengajuan topik/masalah: editor tidak mampu melakukan      |\n    |            | pengeditan menggunakan aplikasi yang belum diajarkan      |\n    |            | di sekolah ........                                       |\n2.  | .......... | ........................................................  |\n\nCatatan : Konsultasi dilakukan minimal sebanyak 8 kali." },

    { judul: "15. Format Margin dan Tata Tulis",
      isi: "FORMAT PENGGUNAAN MARGIN\n\nMenggunakan kertas ukuran F4 dengan batas pengetikan:\n- 4 cm dari sisi kiri kertas\n- 3 cm dari sisi kanan kertas\n- 3 cm dari sisi atas kertas\n- 3 cm dari sisi bawah kertas\n\nTATA TULIS:\n- Kertas F4 berat 70 gsm\n- Jenis huruf Times New Roman ukuran 12 pt\n- Isi laporan diketik dengan spasi 1,5\n- Kata pengantar, daftar isi, kutipan langsung, dan daftar pustaka: spasi single\n- Jumlah halaman tidak kurang dari 20 halaman\n\nPENULISAN BAB DAN SUB BAB:\n1. Penulisan Judul BAB dengan romawi, seperti BAB I\n2. Penulisan Sub BAB dengan huruf Abjad Kapital, seperti A. Latar Belakang\n3. Penulisan keterangan anak Sub BAB dengan tangga urutan sebagai berikut:\n   A. Latar Belakang\n   1. Sejarah\n   1.1 Bila Sejarah ada sub-sub lainnya dapat dilanjutkan dengan 1.1, 1.2, dst\n   a. Bila hanya penyebutan dapat menggunakan abjad kecil, a, b, c, d, dst.\n   1) Bila di dalam abjad kecil diperlukan keterangan lagi maka menggunakan simbol 1), 2), 3), dst.\n   a) Bila masih diperlukan keterangan tambahan lagi maka menggunakan simbol a), b), c), dst.\n\n   Tidak diperkenankan menggunakan simbol gambar seperti panah, bintang, dll.\n\n4. Nomor halaman bagian awal: romawi kecil (i, ii, iii, dst), kecuali halaman judul tidak ditampilkan.\n5. Nomor halaman bagian utama: angka (1, 2, 3, dst). Bagian akhir tidak diberi nomor halaman.\n6. Letak nomor halaman di kanan atas (header kanan), tetapi untuk halaman yang memuat judul BAB nomor halaman terletak di tengah bawah (footer tengah)." }
  ];

  var lampiranList = document.getElementById('lampiranList');
  LAMPIRAN.forEach(function(item, idx){
    var wrap = document.createElement('div');
    wrap.className = 'lampiran-item';

    var btn = document.createElement('button');
    btn.className = 'lampiran-toggle';
    btn.type = 'button';
    btn.innerHTML = '&lt;span&gt;' + item.judul + '&lt;/span&gt;&lt;span class="chev"&gt;[ buka ]&lt;/span&gt;';

    var body = document.createElement('div');
    body.className = 'lampiran-body';
    body.textContent = item.isi;

    // Proteksi penyalinan: blokir copy, cut, klik kanan, dan seleksi via keyboard
    body.addEventListener('copy', function(e){ e.preventDefault(); alert('Contoh laporan ini tidak dapat disalin. Silakan baca lalu ketik ulang di lembar dokumen.'); });
    body.addEventListener('cut', function(e){ e.preventDefault(); });
    body.addEventListener('contextmenu', function(e){ e.preventDefault(); });
    body.addEventListener('dragstart', function(e){ e.preventDefault(); });

    btn.addEventListener('click', function(){
      var isOpen = body.classList.toggle('open');
      btn.querySelector('.chev').textContent = isOpen ? '[ tutup ]' : '[ buka ]';
    });

    wrap.appendChild(btn);
    wrap.appendChild(body);
    lampiranList.appendChild(wrap);
  });

  // ============================================================
  // TAHAP 2: LATIHAN PRAKTIK DOKUMEN F4
  // ============================================================
  var docPasteDetected = false;
  var currentDocPage = null;
  var pageCounter = 3;

  var PRACTICE_TARGETS = [
    { label:"Nama perusahaan pada Cover", marker:"[Ketik Nama Perusahaan Tempat PKL]" },
    { label:"Nama pada Cover", marker:"[Ketik Nama Anda]" },
    { label:"NIS pada Cover", marker:"[Ketik NIS Anda]" },
    { label:"Kelas pada Cover", marker:"[Ketik Kelas Anda]" },
    { label:"Program Keahlian pada Lembar Pengesahan", marker:"[Ketik Program Keahlian Anda]" },
    { label:"Tanggal Pengesahan", marker:"[Ketik Tanggal Pengesahan]" },
    { label:"Nama Pembimbing Industri", marker:"[Ketik Nama Pembimbing Industri]" },
    { label:"Nama Guru Pembimbing", marker:"[Ketik Nama Guru Pembimbing]" }
  ];

  var PRACTICE_ESSAYS = [
    { label:"A. Latar Belakang", marker:"ketik latar belakang pelaksanaan PKL", minChars:200 },
    { label:"B. Tujuan PKL", marker:"ketik tujuan dilaksanakannya PKL", minChars:200 },
    { label:"C. Manfaat PKL", marker:"ketik manfaat PKL bagi peserta didik", minChars:200 }
  ];

  function getDocPages(){ return document.querySelectorAll('.f4-page'); }

  function getDocText(){
    var pages = getDocPages();
    var out = [];
    for (var i = 0; i &lt; pages.length; i++){ out.push(pages[i].innerText); }
    return out.join('\n');
  }

  function bindPage(page){
    page.addEventListener('focus', function(){ currentDocPage = page; });
    page.addEventListener('paste', function(e){
      e.preventDefault();
      docPasteDetected = true;
      var flag = document.getElementById('docPasteFlag');
      flag.classList.add('show');
      flag.textContent = '[PERINGATAN] Percobaan tempel terdeteksi - nilai latihan praktik dipotong 50%';
    });
    page.addEventListener('drop', function(e){ e.preventDefault(); });
    page.addEventListener('input', updateDocCount);
  }

  function updateDocCount(){
    document.getElementById('docCharCount').textContent = getDocText().trim().length + ' karakter diketik';
  }

  var initPages = getDocPages();
  for (var p = 0; p &lt; initPages.length; p++){ bindPage(initPages[p]); }
  updateDocCount();

  document.getElementById('docToolbar').addEventListener('mousedown', function(e){
    if (e.target.tagName === 'BUTTON') e.preventDefault();
  });
  var docBtns = document.querySelectorAll('#docToolbar button[data-cmd]');
  for (var db = 0; db &lt; docBtns.length; db++){
    (function(btn){
      btn.addEventListener('click', function(){
        if (!currentDocPage){ alert('Klik di dalam lembar dokumen terlebih dahulu.'); return; }
        currentDocPage.focus();
        document.execCommand(btn.dataset.cmd, false, null);
      });
    })(docBtns[db]);
  }
  document.getElementById('fontSizeSelect').addEventListener('change', function(e){
    if (!currentDocPage) return;
    currentDocPage.focus();
    document.execCommand('fontSize', false, e.target.value);
  });
  document.getElementById('fontFamilySelect').addEventListener('change', function(e){
    if (!currentDocPage) return;
    currentDocPage.focus();
    document.execCommand('fontName', false, e.target.value);
  });
  document.getElementById('btnTambahHalaman').addEventListener('click', function(){
    pageCounter++;
    var newPage = document.createElement('div');
    newPage.className = 'f4-page';
    newPage.contentEditable = 'true';
    newPage.setAttribute('data-pagelabel', 'Halaman ' + pageCounter + ' - Tambahan');
    newPage.innerHTML = '&lt;div style="text-align:center; font-weight:bold; font-size:14pt;"&gt;BAB ...&lt;br&gt;...&lt;/div&gt;&lt;br&gt;&lt;div style="text-align:justify; text-indent:1.25cm;"&gt;Ketik isi halaman tambahan di sini.&lt;/div&gt;';
    document.getElementById('docStage').appendChild(newPage);
    bindPage(newPage);
    newPage.scrollIntoView({ behavior:'smooth', block:'start' });
  });

  var practiceDetail = [];

  function hitungPraktik(){
    var docText = getDocText();
    practiceDetail = [];
    var poinIsian = 0;

    PRACTICE_TARGETS.forEach(function(t){
      var stillThere = docText.indexOf(t.marker) !== -1;
      practiceDetail.push({ label: t.label, ok: !stillThere, ket: stillThere ? 'Belum diganti' : 'Sudah diisi' });
      if (!stillThere) poinIsian++;
    });

    var poinEsai = 0;
    PRACTICE_ESSAYS.forEach(function(es){
      var markerGone = docText.indexOf(es.marker) === -1;
      var ok = false, ket = '';
      if (!markerGone){
        ket = 'Teks petunjuk belum dihapus/diganti';
      } else {
        ok = true; ket = 'Sudah ditulis dengan kalimat sendiri';
      }
      practiceDetail.push({ label: es.label, ok: ok, ket: ket });
      if (ok) poinEsai++;
    });

    var totalItem = PRACTICE_TARGETS.length + PRACTICE_ESSAYS.length;
    var base = ((poinIsian + poinEsai) / totalItem) * 100;

    // Bonus kelengkapan tulisan: dokumen yang digarap serius jauh lebih panjang
    var len = docText.trim().length;
    var lenFactor = Math.min(1, len / 2600);
    var score = Math.round(base * 0.75 + lenFactor * 25);
    if (docPasteDetected) score = Math.round(score * 0.5);
    if (score &gt; 100) score = 100;
    return score;
  }

  document.getElementById('btnHitungPraktik').addEventListener('click', function(){
    var id = getIdentitas();
    var msg = document.getElementById('praktikMsg');
    if (!id.noAbsen || !id.nama || !id.kelas){
      msg.textContent = 'Lengkapi identitas terlebih dahulu.';
      return;
    }
    msg.textContent = '';
    praktikScore = hitungPraktik();

    var sudah = 0;
    for (var i = 0; i &lt; practiceDetail.length; i++){ if (practiceDetail[i].ok) sudah++; }

    document.getElementById('praktikScoreValue').textContent = praktikScore;
    var detail = 'Terpenuhi ' + sudah + ' dari ' + practiceDetail.length + ' butir daftar periksa, ditambah penilaian kelengkapan isi dokumen.';
    if (docPasteDetected) detail = '[PERINGATAN] Terdeteksi percobaan tempel - nilai dipotong 50%. ' + detail;
    document.getElementById('praktikResultDetail').textContent = detail;
    document.getElementById('praktikResultPanel').style.display = 'block';

    tryFinalize();
  });

  // ============================================================
  // NILAI AKHIR &amp; PENGIRIMAN
  // ============================================================
  function tryFinalize(){
    if (evalFinalScore === null || praktikScore === null) return;

    combinedFinalScore = Math.round((evalFinalScore * 0.5) + (praktikScore * 0.5));
    var panel = document.getElementById('finalResultPanel');
    panel.style.display = 'block';
    document.getElementById('finalResultLabel').textContent = 'Nilai Akhir Evaluasi (Terkirim ke Guru)';
    document.getElementById('finalScoreValue').textContent = combinedFinalScore;
    document.getElementById('finalResultDetail').textContent =
      'Nilai akhir = 50% Kuis Tahap 1 (' + evalFinalScore + ') + 50% Latihan Praktik (' + praktikScore + ') = ' + combinedFinalScore + '. Mengirim ke guru...';

    document.getElementById('btnUnduhPDF').style.display = 'inline-block';
    document.getElementById('pdfHint').style.display = 'block';

    var id = getIdentitas();
    fetch(GAS_ENDPOINT, {
      method: 'POST',
      mode: 'no-cors',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ noAbsen: id.noAbsen, nama: id.nama, kelas: id.kelas, skor: combinedFinalScore, judulMateri: JUDUL_MATERI })
    }).then(function(){
      document.getElementById('finalResultDetail').textContent =
        'Nilai akhir = 50% Kuis Tahap 1 (' + evalFinalScore + ') + 50% Latihan Praktik (' + praktikScore + ') = ' + combinedFinalScore + '. Nilai sudah terkirim ke guru. Unduh bukti PDF di bawah, lalu catat nilainya di buku catatan.';
    }).catch(function(){
      document.getElementById('finalResultDetail').textContent =
        'Nilai akhir = ' + combinedFinalScore + ', tetapi gagal terkirim otomatis. Unduh bukti PDF di bawah sebagai bukti fisik dan tunjukkan kepada guru.';
    });
  }

  // ============================================================
  // BUKTI PDF F4
  // ============================================================
  function escapeHTML(str){
    return String(str).replace(/&amp;/g,'&amp;amp;').replace(/&lt;/g,'&amp;lt;').replace(/&gt;/g,'&amp;gt;');
  }

  function generatePrintArea(){
    var id = getIdentitas();
    var now = new Date();
    var tanggalCetak = now.toLocaleDateString('id-ID', { day:'numeric', month:'long', year:'numeric' }) +
      ', ' + now.toLocaleTimeString('id-ID', { hour:'2-digit', minute:'2-digit' });

    var html = '';
    html += '&lt;div class="pd-kop"&gt;&lt;h1&gt;BUKTI MENGERJAKAN EVALUASI&lt;/h1&gt;&lt;p&gt;' + escapeHTML(JUDUL_MATERI) + '&lt;/p&gt;&lt;p&gt;Master Penyusun Laporan PKL - Informatika Fase E Kelas X SMK&lt;/p&gt;&lt;/div&gt;';

    html += '&lt;table class="pd-meta-table"&gt;';
    html += '&lt;tr&gt;&lt;td class="lbl"&gt;No. Absen&lt;/td&gt;&lt;td&gt;: ' + escapeHTML(id.noAbsen) + '&lt;/td&gt;&lt;td class="lbl"&gt;Dicetak&lt;/td&gt;&lt;td&gt;: ' + tanggalCetak + '&lt;/td&gt;&lt;/tr&gt;';
    html += '&lt;tr&gt;&lt;td class="lbl"&gt;Nama&lt;/td&gt;&lt;td&gt;: ' + escapeHTML(id.nama) + '&lt;/td&gt;&lt;td class="lbl"&gt;Percobaan Kuis&lt;/td&gt;&lt;td&gt;: ' + evalAttemptScores.length + ' dari ' + MAX_ATTEMPTS + ' kali&lt;/td&gt;&lt;/tr&gt;';
    html += '&lt;tr&gt;&lt;td class="lbl"&gt;Kelas&lt;/td&gt;&lt;td&gt;: ' + escapeHTML(id.kelas) + '&lt;/td&gt;&lt;td class="lbl"&gt;KKM&lt;/td&gt;&lt;td&gt;: ' + KKM + '&lt;/td&gt;&lt;/tr&gt;';
    html += '&lt;/table&gt;';

    html += '&lt;div class="pd-section-title"&gt;Ringkasan Nilai&lt;/div&gt;';
    html += '&lt;table class="pd-score-table"&gt;&lt;tr&gt;&lt;th&gt;Komponen&lt;/th&gt;&lt;th&gt;Bobot&lt;/th&gt;&lt;th&gt;Skor&lt;/th&gt;&lt;/tr&gt;';
    html += '&lt;tr&gt;&lt;td&gt;Tahap 1 - Kuis Drag &amp;amp; Drop (' + EVAL_SOAL_COUNT + ' soal)&lt;/td&gt;&lt;td&gt;50%&lt;/td&gt;&lt;td&gt;' + (evalFinalScore !== null ? evalFinalScore : '-') + '&lt;/td&gt;&lt;/tr&gt;';
    html += '&lt;tr&gt;&lt;td&gt;Tahap 2 - Latihan Praktik Dokumen F4&lt;/td&gt;&lt;td&gt;50%&lt;/td&gt;&lt;td&gt;' + (praktikScore !== null ? praktikScore : '-') + '&lt;/td&gt;&lt;/tr&gt;';
    html += '&lt;tr&gt;&lt;th&gt;Nilai Akhir&lt;/th&gt;&lt;th&gt;&lt;/th&gt;&lt;th&gt;' + (combinedFinalScore !== null ? combinedFinalScore : '-') + '&lt;/th&gt;&lt;/tr&gt;&lt;/table&gt;';

    if (evalAttemptScores.length){
      var rincian = [];
      for (var i = 0; i &lt; evalAttemptScores.length; i++){ rincian.push('Percobaan ' + (i+1) + ' = ' + evalAttemptScores[i]); }
      html += '&lt;p style="font-size:9.5pt; margin-bottom:12px;"&gt;Rincian percobaan kuis: ' + rincian.join('; ') + '.&lt;/p&gt;';
    }

    if (evalFinalAttemptIndex !== null &amp;&amp; evalAttemptLogs[evalFinalAttemptIndex]){
      html += '&lt;div class="pd-section-title"&gt;Rincian Jawaban Kuis (Percobaan ke-' + (evalFinalAttemptIndex+1) + ')&lt;/div&gt;';
      html += '&lt;table class="pd-eval-table"&gt;&lt;tr&gt;&lt;th style="width:40%;"&gt;Pertanyaan&lt;/th&gt;&lt;th style="width:20%;"&gt;Jawaban Murid&lt;/th&gt;&lt;th style="width:20%;"&gt;Jawaban Benar&lt;/th&gt;&lt;th style="width:20%;"&gt;Status&lt;/th&gt;&lt;/tr&gt;';
      evalAttemptLogs[evalFinalAttemptIndex].forEach(function(r){
        html += '&lt;tr&gt;&lt;td&gt;' + escapeHTML(r.q) + '&lt;/td&gt;&lt;td&gt;' + escapeHTML(r.userAns) + '&lt;/td&gt;&lt;td&gt;' + escapeHTML(r.correctAns) + '&lt;/td&gt;&lt;td&gt;' +
          (r.isCorrect ? '&lt;span class="pd-verdict ok"&gt;BENAR&lt;/span&gt;' : '&lt;span class="pd-verdict no"&gt;SALAH&lt;/span&gt;') + '&lt;/td&gt;&lt;/tr&gt;';
      });
      html += '&lt;/table&gt;';
    }

    if (practiceDetail.length){
      html += '&lt;div class="pd-section-title"&gt;Daftar Periksa Latihan Praktik&lt;/div&gt;';
      html += '&lt;table class="pd-eval-table"&gt;&lt;tr&gt;&lt;th style="width:55%;"&gt;Butir yang Dinilai&lt;/th&gt;&lt;th style="width:25%;"&gt;Keterangan&lt;/th&gt;&lt;th style="width:20%;"&gt;Status&lt;/th&gt;&lt;/tr&gt;';
      practiceDetail.forEach(function(d){
        html += '&lt;tr&gt;&lt;td&gt;' + escapeHTML(d.label) + '&lt;/td&gt;&lt;td&gt;' + escapeHTML(d.ket) + '&lt;/td&gt;&lt;td&gt;' +
          (d.ok ? '&lt;span class="pd-verdict ok"&gt;TERPENUHI&lt;/span&gt;' : '&lt;span class="pd-verdict no"&gt;BELUM&lt;/span&gt;') + '&lt;/td&gt;&lt;/tr&gt;';
      });
      html += '&lt;/table&gt;';
    }

    html += '&lt;div class="pd-section-title"&gt;Hasil Ketikan Dokumen Laporan PKL&lt;/div&gt;';
    var pages = getDocPages();
    for (var pg = 0; pg &lt; pages.length; pg++){
      var label = pages[pg].getAttribute('data-pagelabel') || ('Halaman ' + (pg+1));
      var teks = pages[pg].innerText.trim();
      html += '&lt;div class="pd-answer-item"&gt;&lt;div class="pd-anum"&gt;' + escapeHTML(label) + '&lt;/div&gt;' +
        '&lt;div class="pd-atext"&gt;' + (teks ? escapeHTML(teks) : '(kosong)') + '&lt;/div&gt;&lt;/div&gt;';
    }

    html += '&lt;div class="pd-signature"&gt;' +
      '&lt;div&gt;Peserta Didik&lt;div class="line"&gt;' + escapeHTML(id.nama) + '&lt;/div&gt;&lt;/div&gt;' +
      '&lt;div&gt;Guru Mata Pelajaran&lt;div class="line"&gt;&amp;nbsp;&lt;/div&gt;&lt;/div&gt;' +
      '&lt;/div&gt;';

    html += '&lt;p class="pd-footnote"&gt;Dokumen ini dihasilkan otomatis sebagai bukti pengerjaan evaluasi. Cetak pada kertas F4 dan serahkan kepada guru mata pelajaran.&lt;/p&gt;';

    document.getElementById('printArea').innerHTML = html;
  }

  document.getElementById('btnUnduhPDF').addEventListener('click', function(){
    generatePrintArea();
    setTimeout(function(){ window.print(); }, 150);
  });
&lt;/script&gt;

&lt;/body&gt;
&lt;/html&gt;</description><link>http://kitab-investasi.blogspot.com/2026/09/integrasi-dokumen-dan-otomasi-pengolah.html</link><thr:total>0</thr:total><author>nof_rizal07@yahoo.co.id (abang_cool)</author></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-9000860041661554971.post-3348254440559995971</guid><pubDate>Tue, 15 Sep 2026 00:32:28 +0000</pubDate><atom:updated>2026-09-15T07:32:28.318+07:00</atom:updated><title>Evaluasi Informasi dalam Teks Ceramah</title><description>&lt;!DOCTYPE html&gt;
&lt;html lang="id"&gt;
&lt;head&gt;
&lt;meta charset="UTF-8"&gt;
&lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&gt;
&lt;title&gt;Evaluasi Informasi dalam Teks Ceramah - Kelas XI SMK&lt;/title&gt;
&lt;style&gt;
  :root{
    --ink:#1B2430;
    --ink-soft:#4A5568;
    --paper:#F7F5F0;
    --card:#FFFFFF;
    --line:#D8D2C4;
    --amber:#E8A33D;
    --amber-dark:#8A5A12;
    --green:#3F7D58;
    --green-bg:#E7F2EB;
    --red:#C1443B;
    --red-bg:#FBEAE8;
  }
  *{box-sizing:border-box;}
  body{margin:0;background:var(--paper);color:var(--ink);font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;line-height:1.6;}
  .wrap{max-width:800px;margin:0 auto;padding:28px 20px 90px;}
  header.top{border-bottom:3px solid var(--ink);padding-bottom:16px;margin-bottom:10px;}
  .kode{font-size:12px;letter-spacing:.04em;color:var(--ink-soft);}
  h1{font-size:23px;margin:6px 0 4px;font-weight:800;}
  .sub{font-size:14px;color:var(--ink-soft);margin:0;}
  .cpbox{background:#FFF6E6;border:1px solid var(--amber);border-left:4px solid var(--amber-dark);border-radius:6px;padding:12px 14px;margin-top:14px;font-size:13.5px;}
  nav.tabs{position:sticky;top:0;background:var(--paper);z-index:10;display:flex;gap:8px;padding:12px 0;border-bottom:1px solid var(--line);margin-bottom:20px;flex-wrap:wrap;}
  nav.tabs a{font-size:13px;font-weight:700;text-decoration:none;color:var(--ink);background:var(--card);border:1px solid var(--line);padding:8px 14px;border-radius:20px;}
  nav.tabs a:hover{background:#F1EFE7;}
  section{margin-bottom:10px;}
  .card{background:var(--card);border:1px solid var(--line);border-radius:8px;padding:22px;margin-bottom:20px;}
  h2.secTitle{font-size:19px;margin:0 0 16px;padding-bottom:10px;border-bottom:3px solid var(--ink);}
  h3{font-size:16px;color:var(--amber-dark);margin:22px 0 8px;}
  h3:first-of-type{margin-top:0;}
  p{font-size:14.5px;margin:8px 0;}
  ul,ol{font-size:14.5px;padding-left:22px;}
  li{margin-bottom:6px;}
  table.materi-table{width:100%;border-collapse:collapse;font-size:13.5px;margin:10px 0 16px;}
  table.materi-table th,table.materi-table td{border:1px solid var(--line);padding:8px 10px;text-align:left;vertical-align:top;}
  table.materi-table th{background:#F1EFE7;}
  .contoh-box{background:#FBF9F2;border:1px solid var(--line);border-left:4px solid var(--amber);padding:14px 16px;border-radius:4px;margin:12px 0;font-size:14px;white-space:pre-line;}
  .contoh-box .ct-label{font-weight:800;font-size:12.5px;color:var(--amber-dark);margin-bottom:6px;}
  .rangkuman{background:var(--green-bg);border:1px solid var(--green);border-radius:6px;padding:14px 16px;}
  .rangkuman li{margin-bottom:4px;}
  .taskbox{background:#FFF6E6;border:1px solid var(--amber);border-left:4px solid var(--amber-dark);border-radius:6px;padding:12px 14px;margin:12px 0;font-size:13.5px;}
  label{display:block;font-size:13px;color:var(--ink-soft);margin:12px 0 4px;}
  input[type=text],input[type=number]{width:100%;padding:10px 12px;border:1px solid var(--line);border-radius:6px;font-size:15px;background:#fff;color:var(--ink);}
  input:focus{outline:2px solid var(--amber);outline-offset:1px;}
  .btn{display:inline-block;border:none;border-radius:6px;padding:12px 20px;font-size:15px;font-weight:700;cursor:pointer;margin-top:16px;margin-right:8px;}
  .btn-primary{background:var(--ink);color:#fff;}
  .btn-primary:hover{background:#000;}
  .btn-secondary{background:var(--amber);color:#3A2400;}
  .btn-secondary:hover{background:#d6912e;}
  .btn:disabled{opacity:.5;cursor:not-allowed;}
  .err{color:var(--red);font-size:13px;margin-top:8px;display:none;}
  .stimulus{background:#FBF9F2;border:1px solid var(--line);border-left:4px solid var(--amber);padding:14px 16px;border-radius:4px;margin-bottom:14px;font-size:14.5px;white-space:pre-line;}
  .stimulus .st-title{font-weight:800;font-size:14px;margin-bottom:6px;color:var(--amber-dark);}
  .qgroup{margin-bottom:26px;}
  .q{margin-bottom:20px;padding-bottom:18px;border-bottom:1px solid var(--line);}
  .q:last-child{border-bottom:none;}
  .q-num{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px;color:var(--ink-soft);}
  .q-text{font-size:15px;font-weight:600;margin:4px 0 10px;}
  .opt{display:flex;gap:10px;align-items:flex-start;padding:8px 10px;border-radius:6px;cursor:pointer;border:1px solid transparent;font-size:14.5px;}
  .opt:hover{background:#F1EFE7;}
  .opt input{margin-top:3px;}
  .opt.selected{background:#FCEFDA;border-color:var(--amber);}
  #progressWrap{position:sticky;top:0;background:var(--paper);padding:10px 0;z-index:5;border-bottom:1px solid var(--line);margin-bottom:16px;}
  #progressBar{height:8px;background:var(--line);border-radius:4px;overflow:hidden;}
  #progressFill{height:100%;background:var(--amber);width:0%;transition:width .2s;}
  #progressText{font-size:12px;color:var(--ink-soft);margin-top:4px;}
  .result-score{font-size:48px;font-weight:800;margin:6px 0;}
  .pass{color:var(--green);}
  .fail{color:var(--red);}
  .result-box{border-radius:8px;padding:20px;text-align:center;}
  .result-box.pass-bg{background:var(--green-bg);border:1px solid var(--green);}
  .result-box.fail-bg{background:var(--red-bg);border:1px solid var(--red);}
  .hidden{display:none;}
  .essaySection{margin-top:10px;}
  .essayQ{margin-bottom:20px;padding-bottom:16px;border-bottom:1px solid var(--line);}
  .essayQ:last-child{border-bottom:none;}
  .essayQ-num{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px;color:var(--ink-soft);}
  .essayQ-text{font-size:15px;font-weight:600;margin:4px 0 8px;}
  textarea.essayInput{width:100%;min-height:80px;padding:10px 12px;border:1px solid var(--line);border-radius:6px;font-size:14.5px;font-family:inherit;resize:vertical;background:#fff;color:var(--ink);}
  textarea.essayInput:focus{outline:2px solid var(--amber);outline-offset:1px;}
  .charCount{font-size:12px;color:var(--ink-soft);text-align:right;margin-top:3px;}
  .charCount.over{color:var(--red);font-weight:700;}
  .pasteWarn{font-size:12.5px;color:var(--red);font-weight:700;margin-top:4px;display:none;}
  .pasteWarn.show{display:block;}
  .sectionLabel{font-size:13px;font-weight:800;letter-spacing:.02em;color:var(--amber-dark);margin:26px 0 4px;border-top:3px solid var(--ink);padding-top:14px;}
  #printArea{display:none;}
  @media print{
    body *{visibility:hidden;}
    #printArea, #printArea *{visibility:visible;}
    #printArea{display:block;position:absolute;left:0;top:0;width:100%;}
    @page{size:215mm 330mm;margin:14mm;}
    .pbreak{break-before:page;page-break-before:always;}
    .noBreak{break-inside:avoid;page-break-inside:avoid;}
  }
  .pf-kop{text-align:center;border-bottom:3px solid #000;padding-bottom:10px;margin-bottom:14px;}
  .pf-kop h2{margin:0;font-size:16px;}
  .pf-kop p{margin:2px 0 0;font-size:12px;}
  .pf-identitas{width:100%;border-collapse:collapse;font-size:13px;margin-bottom:14px;}
  .pf-identitas td{padding:3px 4px;vertical-align:top;}
  .pf-identitas td.lbl{width:150px;color:#333;}
  .pf-skorbox{border:2px solid #000;border-radius:4px;padding:10px 14px;margin-bottom:16px;display:flex;justify-content:space-between;gap:10px;flex-wrap:wrap;}
  .pf-skoritem{font-size:12px;}
  .pf-skoritem b{display:block;font-size:20px;}
  .pf-essay-q{font-size:13px;font-weight:700;margin-bottom:3px;}
  .pf-essay-a{font-size:12.5px;border:1px solid #999;border-radius:4px;padding:6px 8px;min-height:28px;white-space:pre-wrap;background:#FAFAF7;}
  .pf-ttd{display:flex;justify-content:space-between;margin-top:40px;font-size:12.5px;}
  .pf-ttd div{width:45%;text-align:center;}
  .pf-ttd .garis{margin-top:56px;border-top:1px solid #000;padding-top:4px;}
  .pf-note{font-size:11px;color:#555;margin-top:10px;}
  footer{margin-top:30px;font-size:12px;color:var(--ink-soft);text-align:center;}
&lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;div class="wrap"&gt;

  &lt;header class="top"&gt;
    &lt;div class="kode"&gt;DOK/B.INDO/XI/CERAMAH-01&lt;/div&gt;
    &lt;h1&gt;Evaluasi Informasi dalam Teks Ceramah&lt;/h1&gt;
    &lt;p class="sub"&gt;Bahasa Indonesia - Kelas XI SMK - Mengidentifikasi Gagasan Pokok dan Gagasan Pendukung serta Mengevaluasi Informasi dalam Teks Ceramah&lt;/p&gt;
    &lt;div class="cpbox"&gt;&lt;b&gt;Tujuan Pembelajaran:&lt;/b&gt; Murid mampu mengevaluasi informasi dalam teks ceramah serta mengidentifikasi gagasan pokok dan gagasan pendukung.&lt;/div&gt;
  &lt;/header&gt;

  &lt;nav class="tabs"&gt;
    &lt;a href="#materi"&gt;1. Materi&lt;/a&gt;
    &lt;a href="#kelompok"&gt;2. Tugas Kelompok&lt;/a&gt;
    &lt;a href="#individu"&gt;3. Tugas Individu&lt;/a&gt;
  &lt;/nav&gt;

  &lt;section id="materi"&gt;
  &lt;div class="card"&gt;
    &lt;h2 class="secTitle"&gt;Materi: Evaluasi Informasi dalam Teks Ceramah&lt;/h2&gt;

    &lt;h3&gt;A. Mengenal Teks Ceramah&lt;/h3&gt;
    &lt;p&gt;&lt;b&gt;Teks ceramah&lt;/b&gt; adalah teks yang berisi pemaparan gagasan, pengetahuan, atau informasi mengenai suatu topik tertentu yang disampaikan seseorang (penceramah) secara lisan di hadapan orang banyak, dengan tujuan memberi pengetahuan, menyadarkan, meyakinkan, atau mengajak pendengar untuk melakukan sesuatu. Ceramah biasa ditemukan dalam kegiatan keagamaan, upacara bendera, seminar, penyuluhan, hingga pengarahan kerja di dunia industri.&lt;/p&gt;
    &lt;p&gt;Ciri-ciri umum teks ceramah antara lain:&lt;/p&gt;
    &lt;ul&gt;
      &lt;li&gt;Disampaikan oleh satu orang penceramah kepada khalayak (bersifat satu arah, meskipun bisa diakhiri sesi tanya jawab).&lt;/li&gt;
      &lt;li&gt;Membahas satu topik tertentu secara sistematis dari pembukaan hingga penutup.&lt;/li&gt;
      &lt;li&gt;Bersifat persuasif, yaitu berusaha meyakinkan dan mengajak pendengar.&lt;/li&gt;
      &lt;li&gt;Didukung oleh data, fakta, atau contoh untuk memperkuat gagasan yang disampaikan.&lt;/li&gt;
    &lt;/ul&gt;

    &lt;h3&gt;B. Struktur Teks Ceramah&lt;/h3&gt;
    &lt;p&gt;Secara umum, teks ceramah disusun dalam tiga bagian struktur berikut.&lt;/p&gt;
    &lt;table class="materi-table"&gt;
      &lt;tr&gt;&lt;th&gt;Bagian&lt;/th&gt;&lt;th&gt;Isi&lt;/th&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;&lt;b&gt;Pembukaan&lt;/b&gt;&lt;/td&gt;&lt;td&gt;Berisi salam, sapaan kepada hadirin, ucapan syukur, dan pengantar topik yang akan dibahas.&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;&lt;b&gt;Isi&lt;/b&gt;&lt;/td&gt;&lt;td&gt;Berisi pemaparan gagasan pokok dan gagasan pendukung mengenai topik, disertai data, fakta, contoh, atau alasan logis, serta ajakan (persuasi) kepada pendengar.&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;&lt;b&gt;Penutup&lt;/b&gt;&lt;/td&gt;&lt;td&gt;Berisi simpulan, harapan penceramah, dan salam penutup.&lt;/td&gt;&lt;/tr&gt;
    &lt;/table&gt;

    &lt;h3&gt;C. Kaidah Kebahasaan Teks Ceramah&lt;/h3&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;b&gt;Kata ganti orang pertama jamak&lt;/b&gt; (kita, kami) untuk membangun kedekatan dengan pendengar. Contoh: "Marilah kita jaga kebersihan lingkungan sekolah."&lt;/li&gt;
      &lt;li&gt;&lt;b&gt;Kata sapaan&lt;/b&gt; untuk menyapa pendengar. Contoh: "Bapak/Ibu guru dan teman-teman yang saya hormati."&lt;/li&gt;
      &lt;li&gt;&lt;b&gt;Kata teknis/istilah&lt;/b&gt; sesuai topik yang dibahas. Contoh: "disiplin kerja", "Otoritas Jasa Keuangan".&lt;/li&gt;
      &lt;li&gt;&lt;b&gt;Konjungsi argumentatif&lt;/b&gt; seperti "oleh karena itu", "dengan demikian", "sebab" untuk menghubungkan alasan dan simpulan.&lt;/li&gt;
      &lt;li&gt;&lt;b&gt;Kata kerja mental&lt;/b&gt; yang menyatakan sikap/pandangan, seperti "menyimpulkan", "berpendapat", "meyakini".&lt;/li&gt;
      &lt;li&gt;&lt;b&gt;Kalimat persuasif&lt;/b&gt; berupa ajakan, seperti "marilah", "mari kita".&lt;/li&gt;
    &lt;/ul&gt;

    &lt;h3&gt;D. Gagasan Pokok dan Gagasan Pendukung&lt;/h3&gt;
    &lt;p&gt;&lt;b&gt;Gagasan pokok&lt;/b&gt; (ide pokok/ide utama) adalah inti persoalan yang dibahas dalam sebuah paragraf atau bagian teks. Gagasan pokok biasanya dituangkan dalam satu kalimat yang disebut kalimat utama.&lt;/p&gt;
    &lt;p&gt;&lt;b&gt;Gagasan pendukung&lt;/b&gt; (ide penjelas) adalah uraian, contoh, data, fakta, atau alasan yang berfungsi memperjelas, memperkuat, atau menjabarkan gagasan pokok. Gagasan pendukung dituangkan dalam kalimat-kalimat penjelas.&lt;/p&gt;
    &lt;p&gt;Berdasarkan letak gagasan pokoknya, paragraf dapat dibedakan menjadi tiga pola berikut.&lt;/p&gt;
    &lt;table class="materi-table"&gt;
      &lt;tr&gt;&lt;th&gt;Pola&lt;/th&gt;&lt;th&gt;Letak Gagasan Pokok&lt;/th&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;&lt;b&gt;Deduktif&lt;/b&gt;&lt;/td&gt;&lt;td&gt;Gagasan pokok terletak di awal paragraf, diikuti kalimat-kalimat penjelas.&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;&lt;b&gt;Induktif&lt;/b&gt;&lt;/td&gt;&lt;td&gt;Gagasan pokok terletak di akhir paragraf, didahului kalimat-kalimat penjelas.&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;&lt;b&gt;Campuran&lt;/b&gt;&lt;/td&gt;&lt;td&gt;Gagasan pokok muncul di awal, ditegaskan kembali di akhir paragraf.&lt;/td&gt;&lt;/tr&gt;
    &lt;/table&gt;
    &lt;p&gt;Langkah menemukan gagasan pokok dan gagasan pendukung:&lt;/p&gt;
    &lt;ol&gt;
      &lt;li&gt;Bacalah paragraf secara utuh untuk memahami keseluruhan isi.&lt;/li&gt;
      &lt;li&gt;Temukan kalimat yang memuat inti pembahasan (biasanya di awal atau akhir paragraf).&lt;/li&gt;
      &lt;li&gt;Tandai kalimat-kalimat lain sebagai gagasan pendukung jika berisi penjelasan, contoh, sebab-akibat, atau data yang mendukung gagasan pokok tersebut.&lt;/li&gt;
      &lt;li&gt;Rumuskan gagasan pokok dalam satu kalimat singkat menggunakan kata-katamu sendiri.&lt;/li&gt;
    &lt;/ol&gt;

    &lt;h3&gt;E. Evaluasi Informasi dalam Teks Ceramah&lt;/h3&gt;
    &lt;p&gt;&lt;b&gt;Mengevaluasi informasi&lt;/b&gt; berarti menilai kelayakan, kebenaran, dan kualitas suatu informasi berdasarkan kriteria tertentu, bukan sekadar menerima dan memahami informasi tersebut secara mentah-mentah. Kemampuan ini sangat penting bagi siswa SMK karena di dunia nyata kita sering menemukan ceramah, motivasi kerja, maupun informasi lisan lain yang isinya belum tentu benar, akurat, atau dapat dipertanggungjawabkan - termasuk potensi berita bohong (hoaks) dan opini yang dibungkus seolah-olah fakta.&lt;/p&gt;
    &lt;p&gt;Berikut enam kriteria yang digunakan untuk mengevaluasi informasi dalam teks ceramah.&lt;/p&gt;
    &lt;table class="materi-table"&gt;
      &lt;tr&gt;&lt;th&gt;Kriteria&lt;/th&gt;&lt;th&gt;Indikator&lt;/th&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;&lt;b&gt;1. Kredibilitas&lt;/b&gt;&lt;/td&gt;&lt;td&gt;Apakah penceramah/sumber informasi memiliki keahlian, pengalaman, atau otoritas yang relevan dengan topik yang dibahas?&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;&lt;b&gt;2. Keakuratan&lt;/b&gt;&lt;/td&gt;&lt;td&gt;Apakah data, fakta, dan angka yang disampaikan benar, dapat diverifikasi, dan berasal dari sumber yang jelas (bukan sekadar opini pribadi)?&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;&lt;b&gt;3. Kelogisan&lt;/b&gt;&lt;/td&gt;&lt;td&gt;Apakah alasan atau argumen yang dikemukakan masuk akal dan hubungan sebab-akibatnya wajar, bukan generalisasi berlebihan?&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;&lt;b&gt;4. Objektivitas&lt;/b&gt;&lt;/td&gt;&lt;td&gt;Apakah informasi disampaikan secara berimbang, tidak memihak secara berlebihan, dan minim bias pribadi?&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;&lt;b&gt;5. Kelengkapan&lt;/b&gt;&lt;/td&gt;&lt;td&gt;Apakah informasi yang disampaikan cukup lengkap sehingga tidak menyesatkan pendengar?&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;&lt;b&gt;6. Kesesuaian tujuan&lt;/b&gt;&lt;/td&gt;&lt;td&gt;Apakah isi ceramah relevan dan sesuai dengan topik serta tujuan ceramah yang disampaikan di awal?&lt;/td&gt;&lt;/tr&gt;
    &lt;/table&gt;
    &lt;p&gt;Langkah-langkah mengevaluasi informasi dalam teks ceramah:&lt;/p&gt;
    &lt;ol&gt;
      &lt;li&gt;Membaca/menyimak teks ceramah secara menyeluruh.&lt;/li&gt;
      &lt;li&gt;Mengidentifikasi struktur teks (pembukaan, isi, penutup).&lt;/li&gt;
      &lt;li&gt;Menemukan gagasan pokok dan gagasan pendukung pada bagian isi.&lt;/li&gt;
      &lt;li&gt;Menguji setiap informasi penting menggunakan keenam kriteria evaluasi di atas.&lt;/li&gt;
      &lt;li&gt;Mencatat temuan (informasi yang kuat maupun yang lemah/perlu diverifikasi).&lt;/li&gt;
      &lt;li&gt;Menyimpulkan dan memberi rekomendasi, misalnya perbaikan yang diperlukan agar informasi lebih dapat dipercaya.&lt;/li&gt;
    &lt;/ol&gt;

    &lt;h3&gt;F. Contoh Analisis Singkat&lt;/h3&gt;
    &lt;div class="contoh-box"&gt;
      &lt;div class="ct-label"&gt;CONTOH PENGGALAN CERAMAH&lt;/div&gt;"...Sayangnya, masih banyak siswa yang membuang sampah sembarangan. Menurut pengamatan pribadi saya, hampir separuh siswa di sekolah ini membuang sampah tidak pada tempatnya. Oleh karena itu, marilah kita membiasakan diri membuang sampah pada tempatnya..."&lt;/div&gt;
    &lt;table class="materi-table"&gt;
      &lt;tr&gt;&lt;th&gt;Aspek&lt;/th&gt;&lt;th&gt;Analisis&lt;/th&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Gagasan pokok&lt;/td&gt;&lt;td&gt;Ajakan untuk membiasakan diri membuang sampah pada tempatnya.&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Gagasan pendukung&lt;/td&gt;&lt;td&gt;Klaim bahwa hampir separuh siswa membuang sampah sembarangan.&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Evaluasi (Keakuratan)&lt;/td&gt;&lt;td&gt;Lemah - klaim "hampir separuh siswa" hanya berdasarkan pengamatan pribadi, bukan data resmi (misalnya survei atau catatan petugas kebersihan), sehingga akurasinya perlu dipertanyakan.&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Rekomendasi&lt;/td&gt;&lt;td&gt;Penceramah sebaiknya mencantumkan data resmi agar informasi lebih kredibel dan akurat.&lt;/td&gt;&lt;/tr&gt;
    &lt;/table&gt;

    &lt;h3&gt;G. Rangkuman&lt;/h3&gt;
    &lt;div class="rangkuman"&gt;
      &lt;ul&gt;
        &lt;li&gt;Teks ceramah terdiri atas struktur pembukaan, isi, dan penutup.&lt;/li&gt;
        &lt;li&gt;Gagasan pokok adalah inti pembahasan; gagasan pendukung memperjelas gagasan pokok.&lt;/li&gt;
        &lt;li&gt;Pola letak gagasan pokok: deduktif (awal), induktif (akhir), campuran (awal dan akhir).&lt;/li&gt;
        &lt;li&gt;Mengevaluasi informasi berarti menilai kredibilitas, keakuratan, kelogisan, objektivitas, kelengkapan, dan kesesuaian tujuan suatu informasi - bukan menerimanya begitu saja.&lt;/li&gt;
        &lt;li&gt;Kemampuan mengevaluasi informasi penting agar kita tidak mudah terpengaruh oleh informasi lisan yang belum tentu benar.&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;/section&gt;

  &lt;section id="kelompok"&gt;
  &lt;div class="card"&gt;
    &lt;h2 class="secTitle"&gt;Tugas Kelompok&lt;/h2&gt;
    &lt;p&gt;&lt;b&gt;Judul:&lt;/b&gt; Mengevaluasi Informasi dalam Teks Ceramah Secara Berkelompok&lt;/p&gt;
    &lt;div class="taskbox"&gt;&lt;b&gt;Ketentuan kelompok:&lt;/b&gt; 1 kelompok terdiri atas 4-5 siswa, dibagi oleh guru atau berdasarkan kesepakatan kelas.&lt;/div&gt;

    &lt;h3&gt;Langkah Pengerjaan&lt;/h3&gt;
    &lt;ol&gt;
      &lt;li&gt;Carilah atau gunakan satu teks/rekaman ceramah (transkrip pidato, ceramah keagamaan, motivasi kerja, atau video ceramah singkat dari sumber yang jelas). Teks/video boleh ditentukan guru atau dicari sendiri oleh kelompok.&lt;/li&gt;
      &lt;li&gt;Bacalah/simaklah teks ceramah tersebut secara menyeluruh bersama anggota kelompok.&lt;/li&gt;
      &lt;li&gt;Identifikasi struktur teks ceramah (pembukaan, isi, penutup).&lt;/li&gt;
      &lt;li&gt;Tentukan gagasan pokok pada setiap paragraf bagian isi.&lt;/li&gt;
      &lt;li&gt;Tentukan minimal dua gagasan pendukung untuk setiap gagasan pokok yang ditemukan.&lt;/li&gt;
      &lt;li&gt;Evaluasi informasi dalam ceramah tersebut menggunakan enam kriteria evaluasi (kredibilitas, keakuratan, kelogisan, objektivitas, kelengkapan, kesesuaian tujuan). Untuk tiap kriteria, berikan skor 1-4 beserta alasannya.&lt;/li&gt;
      &lt;li&gt;Simpulkan apakah ceramah tersebut layak dijadikan rujukan/dipercaya, disertai alasan dan rekomendasi perbaikan (jika ada).&lt;/li&gt;
      &lt;li&gt;Susun laporan tertulis, lalu presentasikan hasilnya di depan kelas (sekitar 10 menit per kelompok, termasuk sesi tanya jawab).&lt;/li&gt;
    &lt;/ol&gt;

    &lt;h3&gt;Format Laporan&lt;/h3&gt;
    &lt;ul&gt;
      &lt;li&gt;Halaman judul: judul tugas, nama kelompok, anggota, dan kelas.&lt;/li&gt;
      &lt;li&gt;Identitas teks ceramah yang dianalisis: judul/topik, sumber, nama penceramah (jika ada), tanggal/tautan.&lt;/li&gt;
      &lt;li&gt;Tabel gagasan pokok dan gagasan pendukung per paragraf isi.&lt;/li&gt;
      &lt;li&gt;Tabel hasil evaluasi enam kriteria beserta skor dan alasan.&lt;/li&gt;
      &lt;li&gt;Simpulan dan rekomendasi.&lt;/li&gt;
      &lt;li&gt;Lampiran: naskah/tautan teks ceramah yang dianalisis.&lt;/li&gt;
    &lt;/ul&gt;

    &lt;h3&gt;Rubrik Penilaian (skor 1-4 per aspek)&lt;/h3&gt;
    &lt;table class="materi-table"&gt;
      &lt;tr&gt;&lt;th&gt;Aspek&lt;/th&gt;&lt;th&gt;Deskripsi&lt;/th&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Ketepatan identifikasi struktur&lt;/td&gt;&lt;td&gt;Kesesuaian pembagian pembukaan, isi, dan penutup dengan teks yang dianalisis.&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Ketepatan gagasan pokok &amp;amp; pendukung&lt;/td&gt;&lt;td&gt;Kesesuaian dan kelengkapan gagasan pokok serta gagasan pendukung yang ditemukan.&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Kedalaman evaluasi&lt;/td&gt;&lt;td&gt;Ketajaman analisis pada keenam kriteria evaluasi beserta alasannya.&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Kualitas simpulan &amp;amp; rekomendasi&lt;/td&gt;&lt;td&gt;Kejelasan dan kelogisan simpulan serta rekomendasi yang diberikan.&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Kerja sama &amp;amp; presentasi&lt;/td&gt;&lt;td&gt;Pembagian tugas antaranggota serta kejelasan penyampaian saat presentasi.&lt;/td&gt;&lt;/tr&gt;
    &lt;/table&gt;
    &lt;p style="font-size:13px;color:var(--ink-soft);"&gt;Total skor maksimal 20, dikonversi ke skala 100 oleh guru. Batas waktu pengumpulan dan jadwal presentasi ditentukan oleh guru mata pelajaran.&lt;/p&gt;
  &lt;/div&gt;
  &lt;/section&gt;

  &lt;section id="individu"&gt;
  &lt;div class="card" id="screen-intro"&gt;
    &lt;h2 class="secTitle"&gt;Tugas Individu&lt;/h2&gt;
    &lt;p style="font-size:14px;"&gt;Tugas individu terdiri atas &lt;b&gt;25 soal pilihan ganda&lt;/b&gt; dan &lt;b&gt;5 soal esai&lt;/b&gt; dari materi Evaluasi Informasi dalam Teks Ceramah. Susunan soal dan urutan opsi jawaban diacak berbeda-beda untuk tiap peserta. Skor dihitung otomatis: &lt;b&gt;Skor PG x 70% + Skor Esai x 30%&lt;/b&gt;. Skor esai dihitung dari kesesuaian jawabanmu dengan konsep-konsep kunci pada tiap soal. &lt;b&gt;Jawaban esai wajib diketik sendiri&lt;/b&gt; - fitur tempel/paste (Ctrl+V, klik kanan, maupun tarik-lepas teks) dinonaktifkan pada kolom esai.&lt;/p&gt;
    &lt;div class="taskbox"&gt;
      &lt;b&gt;PENTING - wajib dilakukan setelah selesai mengerjakan:&lt;/b&gt;
      &lt;ol style="margin:6px 0 0;padding-left:18px;"&gt;
        &lt;li&gt;Jawaban dan skor akan &lt;b&gt;dikirim otomatis ke sistem sekolah&lt;/b&gt; begitu kamu menekan tombol Kirim.&lt;/li&gt;
        &lt;li&gt;&lt;b&gt;Unduh&lt;/b&gt; bukti mengerjakan (PDF, ukuran F4) lewat tombol "Unduh Bukti Mengerjakan (PDF)".&lt;/li&gt;
        &lt;li&gt;&lt;b&gt;Cetak&lt;/b&gt; dokumen tersebut (maksimal 3 lembar).&lt;/li&gt;
        &lt;li&gt;&lt;b&gt;Serahkan hasil cetak ke guru mata pelajaran&lt;/b&gt; sebagai bukti fisik pengerjaan tugas.&lt;/li&gt;
      &lt;/ol&gt;
    &lt;/div&gt;

    &lt;label for="absen"&gt;No. Absen&lt;/label&gt;
    &lt;input type="number" id="absen" placeholder="Contoh: 14" min="1"&gt;
    &lt;label for="nama"&gt;Nama Lengkap&lt;/label&gt;
    &lt;input type="text" id="nama" placeholder="Tulis nama lengkapmu"&gt;
    &lt;label for="kelas"&gt;Kelas&lt;/label&gt;
    &lt;input type="text" id="kelas" placeholder="Contoh: XI TKR 1"&gt;
    &lt;div class="err" id="introErr"&gt;Isi No. Absen, Nama Lengkap, dan Kelas terlebih dahulu.&lt;/div&gt;
    &lt;button class="btn btn-primary" id="btnCekStatus"&gt;Lanjutkan&lt;/button&gt;
  &lt;/div&gt;

  &lt;div id="screen-status" class="card hidden"&gt;
    &lt;h2 id="statusGreeting"&gt;&lt;/h2&gt;
    &lt;div id="statusBody"&gt;&lt;/div&gt;
    &lt;button class="btn btn-secondary" id="btnMulai"&gt;Mulai Mengerjakan&lt;/button&gt;
    &lt;button class="btn hidden" id="btnUnduhStatus" style="background:var(--green);color:#fff;"&gt;Unduh Bukti Mengerjakan (PDF)&lt;/button&gt;
    &lt;p class="hidden" id="instruksiStatus" style="font-size:12.5px;color:var(--ink-soft);margin-top:6px;"&gt;Cetak dokumen ini (maks. 3 lembar F4) dan &lt;b&gt;serahkan ke guru mata pelajaran&lt;/b&gt; sebagai bukti pengerjaan.&lt;/p&gt;
    &lt;button class="btn" id="btnGanti" style="background:transparent;border:1px solid var(--line);"&gt;Ganti No. Absen&lt;/button&gt;
  &lt;/div&gt;

  &lt;div id="screen-quiz" class="hidden"&gt;
    &lt;div id="progressWrap"&gt;
      &lt;div id="progressBar"&gt;&lt;div id="progressFill"&gt;&lt;/div&gt;&lt;/div&gt;
      &lt;div id="progressText"&gt;0 dari 30 soal terjawab&lt;/div&gt;
    &lt;/div&gt;
    &lt;div id="quizBody"&gt;&lt;/div&gt;
    &lt;div class="err" id="quizErr"&gt;Masih ada soal yang belum dijawab. Lengkapi seluruh soal sebelum mengirim.&lt;/div&gt;
    &lt;button class="btn btn-primary" id="btnKirim"&gt;Kirim Jawaban&lt;/button&gt;
  &lt;/div&gt;

  &lt;div id="screen-result" class="card hidden"&gt;
    &lt;div id="resultBoxOuter"&gt;&lt;/div&gt;
    &lt;button class="btn btn-secondary hidden" id="btnUnduhHasil" style="background:var(--green);color:#fff;"&gt;Unduh Bukti Mengerjakan (PDF)&lt;/button&gt;
    &lt;p id="instruksiHasil" style="font-size:12.5px;color:var(--ink-soft);margin-top:6px;"&gt;Cetak dokumen ini (maks. 3 lembar F4) dan &lt;b&gt;serahkan ke guru mata pelajaran&lt;/b&gt; sebagai bukti pengerjaan.&lt;/p&gt;
    &lt;button class="btn" id="btnSelesai" style="background:transparent;border:1px solid var(--line);"&gt;Kembali ke Awal&lt;/button&gt;
  &lt;/div&gt;
  &lt;/section&gt;

  &lt;footer&gt;DOK/B.INDO/XI/CERAMAH-01 - Evaluasi Informasi dalam Teks Ceramah - 25 Butir Pilihan Ganda + 5 Esai&lt;/footer&gt;
&lt;/div&gt;

&lt;div id="printArea"&gt;&lt;/div&gt;

&lt;script&gt;
const GAS_URL = "https://script.google.com/macros/s/AKfycbzM7t2qgAENzxQJXzSYJYL28R6nb3TxJVELLL3CopyEXb51t_gRtrkPOxTpI5mq6VCEKw/exec";

// ===== 25 SOAL PILIHAN GANDA =====
// Grup 0: konsep dasar (tanpa teks stimulus) - 10 soal
// Grup 1-3: masing-masing punya 1 teks ceramah stimulus - 5 soal per grup
const GROUPS = [
{
  title: "Konsep Dasar Teks Ceramah",
  stimulus: null,
  questions: [
    {q:"Teks ceramah adalah teks yang berisi...", opts:["Cerita fiksi tentang tokoh rekaan","Pemaparan gagasan atau informasi di hadapan orang banyak mengenai suatu topik tertentu","Kumpulan resep masakan","Petunjuk langkah kerja suatu alat","Data statistik dalam bentuk tabel"], correct:1},
    {q:"Struktur teks ceramah terdiri atas tiga bagian utama, yaitu...", opts:["Orientasi, komplikasi, resolusi","Pembukaan, isi, penutup","Abstrak, orientasi, koda","Pernyataan umum, deretan penjelas, interpretasi","Tesis, argumentasi, penegasan ulang pendapat"], correct:1},
    {q:"Bagian ceramah yang berisi salam, sapaan, dan pengantar topik termasuk struktur bagian...", opts:["Isi","Penutup","Pembukaan","Argumen","Simpulan"], correct:2},
    {q:"Gagasan pokok adalah...", opts:["Kalimat pembuka paragraf tanpa makna khusus","Ide utama yang menjadi inti pembahasan dalam sebuah paragraf atau teks","Kalimat tanya dalam paragraf","Kutipan langsung dari sumber lain","Judul dari keseluruhan teks"], correct:1},
    {q:"Gagasan pendukung berfungsi untuk...", opts:["Menggantikan gagasan pokok","Memperjelas, memperkuat, atau memberi contoh terhadap gagasan pokok","Menghilangkan gagasan pokok","Menjadi judul paragraf","Menutup keseluruhan teks"], correct:1},
    {q:"Paragraf yang gagasan pokoknya terletak di awal paragraf disebut paragraf berpola...", opts:["Induktif","Deduktif","Campuran","Naratif","Deskriptif"], correct:1},
    {q:"Paragraf yang gagasan pokoknya terletak di akhir paragraf, setelah dijabarkan dengan kalimat-kalimat penjelas terlebih dahulu, disebut paragraf berpola...", opts:["Deduktif","Induktif","Deskriptif","Naratif","Argumentatif"], correct:1},
    {q:"Berikut ini yang termasuk kaidah kebahasaan khas teks ceramah adalah...", opts:["Penggunaan kalimat imperatif untuk langkah kerja","Penggunaan kata ganti orang pertama jamak (kita, kami) untuk membangun kedekatan dengan pendengar","Penggunaan konjungsi kronologis semata","Penggunaan rumus matematika","Penggunaan dialog antartokoh"], correct:1},
    {q:"Mengevaluasi informasi dalam teks ceramah berarti...", opts:["Menghafalkan seluruh isi ceramah kata demi kata","Menilai kelayakan, kebenaran, dan kualitas informasi yang disampaikan penceramah berdasarkan kriteria tertentu","Menuliskan ulang ceramah dengan bahasa sendiri tanpa penilaian","Menerima seluruh isi ceramah tanpa mempertanyakan kebenarannya","Mencari kesalahan ejaan dalam naskah ceramah"], correct:1},
    {q:"Berikut ini yang BUKAN merupakan kriteria evaluasi informasi dalam teks ceramah adalah...", opts:["Kredibilitas penceramah/sumber informasi","Keakuratan data dan fakta yang disampaikan","Kelogisan alasan atau argumen yang dikemukakan","Keindahan rima dan irama kalimat seperti dalam puisi","Kelengkapan informasi yang disampaikan"], correct:3}
  ]
},
{
  title: "Ceramah 1 - Pentingnya Menjaga Kebersihan Lingkungan Sekolah",
  stimulus: "Assalamualaikum warahmatullahi wabarakatuh. Bapak/Ibu guru dan teman-teman yang saya hormati, pagi ini saya ingin mengajak kita semua untuk merenungkan pentingnya menjaga kebersihan lingkungan sekolah.\n\nLingkungan sekolah yang bersih memberikan banyak manfaat bagi warga sekolah. Pertama, lingkungan yang bersih membuat suasana belajar menjadi lebih nyaman sehingga konsentrasi belajar meningkat. Kedua, kebersihan lingkungan dapat mencegah munculnya berbagai penyakit yang disebabkan oleh sampah dan genangan air, seperti demam berdarah dan diare. Ketiga, sekolah yang bersih mencerminkan kedisiplinan dan karakter warga sekolahnya, sehingga dapat meningkatkan citra sekolah di mata masyarakat.\n\nSayangnya, masih banyak siswa yang membuang sampah sembarangan. Menurut pengamatan pribadi saya, hampir separuh siswa di sekolah ini membuang sampah tidak pada tempatnya. Oleh karena itu, marilah kita membiasakan diri membuang sampah pada tempatnya, memilah sampah organik dan anorganik, serta aktif dalam kegiatan Jumat bersih.\n\nDemikian yang dapat saya sampaikan. Semoga kita semua dapat menjadi warga sekolah yang peduli terhadap kebersihan lingkungan. Wassalamualaikum warahmatullahi wabarakatuh.",
  questions: [
    {q:"Apa gagasan pokok pada paragraf kedua ceramah tersebut?", opts:["Ajakan membuang sampah pada tempatnya","Manfaat menjaga kebersihan lingkungan sekolah","Data siswa yang membuang sampah sembarangan","Ucapan salam pembuka","Harapan penutup ceramah"], correct:1},
    {q:"Berikut yang termasuk gagasan pendukung dari gagasan pokok \"manfaat kebersihan lingkungan\" adalah...", opts:["Membiasakan memilah sampah","Lingkungan bersih mencegah penyakit seperti demam berdarah","Ajakan mengikuti Jumat bersih","Salam penutup ceramah","Sapaan kepada guru dan teman-teman"], correct:1},
    {q:"Kalimat \"menurut pengamatan pribadi saya, hampir separuh siswa di sekolah ini membuang sampah tidak pada tempatnya\" merupakan informasi yang lemah dari segi kriteria evaluasi berupa...", opts:["Kelogisan argumen","Objektivitas penceramah","Keakuratan data, karena hanya berdasarkan perkiraan pribadi tanpa data resmi","Kesesuaian dengan tujuan ceramah","Kelengkapan struktur teks"], correct:2},
    {q:"Bagian ceramah yang berisi ajakan \"membiasakan diri membuang sampah pada tempatnya...\" termasuk struktur teks ceramah bagian...", opts:["Pembukaan","Isi (rangkaian argumen dan ajakan)","Penutup","Salam pembuka","Simpulan akhir"], correct:1},
    {q:"Jika penceramah ingin memperkuat keakuratan informasi pada bagian data siswa yang membuang sampah sembarangan, langkah yang paling tepat dilakukan adalah...", opts:["Mengganti kalimat ajakan menjadi kalimat perintah","Menyertakan data resmi, misalnya hasil survei atau catatan petugas kebersihan sekolah","Menghilangkan seluruh bagian data tersebut","Mengubah topik ceramah","Menambahkan lebih banyak ucapan salam"], correct:1}
  ]
},
{
  title: "Ceramah 2 - Membangun Sikap Disiplin di Dunia Kerja",
  stimulus: "Selamat pagi, Bapak/Ibu guru serta adik-adik kelas XI yang saya banggakan. Hari ini saya akan berbicara tentang pentingnya membangun sikap disiplin sejak di bangku SMK, sebagai bekal memasuki dunia kerja.\n\nDisiplin adalah kunci utama keberhasilan seseorang di tempat kerja. Seorang pekerja yang disiplin akan selalu datang tepat waktu, menyelesaikan tugas sesuai target, dan mematuhi prosedur keselamatan kerja yang berlaku. Sebaliknya, pekerja yang tidak disiplin berisiko menimbulkan kerugian, baik bagi dirinya sendiri maupun perusahaan tempatnya bekerja.\n\nMenurut sebuah artikel yang pernah saya baca di internet, seratus persen perusahaan besar di dunia hanya mau merekrut karyawan yang disiplin tanpa terkecuali. Oleh karena itu, mari kita mulai membiasakan disiplin dari hal-hal kecil, seperti datang ke sekolah tepat waktu, mengumpulkan tugas sesuai tenggat, dan menaati tata tertib praktik kerja lapangan.\n\nSemoga dengan kebiasaan disiplin ini, kita semua siap menghadapi dunia kerja yang penuh tantangan. Terima kasih.",
  questions: [
    {q:"Topik utama ceramah tersebut adalah...", opts:["Pentingnya kebersihan lingkungan","Pentingnya sikap disiplin dalam dunia kerja","Cara mencari pekerjaan","Sejarah dunia kerja","Tata tertib sekolah"], correct:1},
    {q:"Gagasan pendukung yang menjelaskan ciri pekerja disiplin pada ceramah tersebut adalah...", opts:["Pekerja disiplin selalu datang tepat waktu, menyelesaikan tugas sesuai target, dan mematuhi prosedur keselamatan kerja","Pekerja disiplin selalu mendapat gaji tinggi","Pekerja disiplin tidak perlu mengikuti pelatihan","Pekerja disiplin bebas dari pengawasan atasan","Pekerja disiplin selalu bekerja lembur"], correct:0},
    {q:"Pernyataan \"seratus persen perusahaan besar di dunia hanya mau merekrut karyawan yang disiplin tanpa terkecuali\" lemah dari segi kriteria evaluasi...", opts:["Kelengkapan struktur teks","Kredibilitas sumber dan keakuratan data, karena bersifat generalisasi mutlak tanpa sumber yang jelas","Kesesuaian dengan tujuan ceramah","Penggunaan kalimat persuasif","Struktur bagian penutup"], correct:1},
    {q:"Frasa \"sebuah artikel yang pernah saya baca di internet\" pada ceramah tersebut menunjukkan kelemahan dari sisi...", opts:["Kelogisan argumen","Sumber informasi yang tidak disebutkan secara jelas dan tidak dapat ditelusuri","Struktur kalimat yang tidak baku","Penggunaan konjungsi","Ketepatan ejaan"], correct:1},
    {q:"Simpulan paling tepat mengenai kualitas informasi dalam ceramah tersebut adalah...", opts:["Seluruh informasi dalam ceramah tersebut sudah akurat dan dapat dipercaya sepenuhnya","Gagasan tentang pentingnya disiplin cukup logis, tetapi klaim persentase mutlak tentang perusahaan perlu diverifikasi lebih lanjut karena sumbernya tidak jelas","Ceramah tersebut tidak memiliki gagasan pokok sama sekali","Ceramah tersebut tidak layak didengarkan karena seluruhnya tidak logis","Ceramah tersebut hanya berisi salam tanpa isi"], correct:1}
  ]
},
{
  title: "Ceramah 3 - Waspada Pinjaman Online Ilegal",
  stimulus: "Assalamualaikum warahmatullahi wabarakatuh. Adik-adik yang saya sayangi, sebentar lagi kalian akan lulus dan memasuki dunia kerja dengan penghasilan sendiri. Oleh sebab itu, penting bagi kita untuk waspada terhadap pinjaman online ilegal.\n\nPinjaman online ilegal biasanya menawarkan proses pencairan dana yang sangat cepat tanpa syarat yang jelas, bunga yang sangat tinggi, serta melakukan penagihan dengan cara mengancam dan mengintimidasi peminjam. Berdasarkan data Otoritas Jasa Keuangan tahun 2023, ribuan aplikasi pinjaman online ilegal telah diblokir karena merugikan masyarakat.\n\nCiri-ciri pinjaman online ilegal antara lain tidak terdaftar di Otoritas Jasa Keuangan, meminta akses ke seluruh data pribadi di ponsel, serta tidak memiliki alamat kantor yang jelas. Untuk itu, sebelum meminjam, pastikan aplikasi tersebut sudah terdaftar dan diawasi oleh Otoritas Jasa Keuangan.\n\nMari kita bijak dalam mengelola keuangan dan menghindari jebakan pinjaman online ilegal, demi masa depan finansial yang lebih baik. Wassalamualaikum warahmatullahi wabarakatuh.",
  questions: [
    {q:"Topik utama ceramah tersebut adalah...", opts:["Pentingnya menabung","Bahaya pinjaman online ilegal","Cara melamar pekerjaan","Pentingnya kebersihan","Pentingnya disiplin kerja"], correct:1},
    {q:"Salah satu ciri pinjaman online ilegal yang disebutkan dalam ceramah adalah...", opts:["Terdaftar resmi di Otoritas Jasa Keuangan","Proses pencairan dana sangat cepat tanpa syarat jelas","Memiliki kantor dengan alamat yang jelas","Bunga pinjaman yang rendah dan wajar","Melakukan penagihan sesuai prosedur hukum"], correct:1},
    {q:"Kalimat \"Berdasarkan data Otoritas Jasa Keuangan tahun 2023, ribuan aplikasi pinjaman online ilegal telah diblokir\" menunjukkan bahwa informasi dalam ceramah tersebut memiliki keunggulan dari segi kriteria evaluasi...", opts:["Kelogisan semata","Kredibilitas sumber dan keakuratan data, karena merujuk pada lembaga resmi","Kesesuaian struktur teks","Penggunaan konjungsi temporal","Ketepatan salam pembuka"], correct:1},
    {q:"Dibandingkan dengan ceramah tentang disiplin kerja pada Teks 2, ceramah tentang pinjaman online ilegal ini lebih unggul dalam hal...", opts:["Panjang teks","Jumlah salam pembuka","Kejelasan dan ketertelusuran sumber informasi yang digunakan","Jumlah paragraf penutup","Penggunaan bahasa daerah"], correct:2},
    {q:"Berdasarkan perbandingan ketiga teks ceramah (kebersihan lingkungan, disiplin kerja, dan pinjaman online ilegal), simpulan yang paling tepat mengenai kualitas informasi adalah...", opts:["Ketiga ceramah memiliki kualitas informasi yang sama baiknya","Ceramah yang mencantumkan sumber data resmi dan jelas cenderung memiliki informasi yang lebih dapat dipertanggungjawabkan dibandingkan yang hanya mengandalkan opini atau sumber tidak jelas","Ceramah yang paling panjang selalu memiliki informasi paling akurat","Ceramah tanpa data sama sekali lebih meyakinkan karena lebih ringkas","Kualitas informasi ceramah tidak dapat dievaluasi"], correct:1}
  ]
}
];

// ===== 5 SOAL ESAI (skor otomatis berbasis konsep kunci) =====
const ESSAYS = [
  { q: "Jelaskan pengertian gagasan pokok dan gagasan pendukung, lalu jelaskan hubungan keduanya dalam sebuah paragraf ceramah!",
    concepts: [["gagasan pokok","ide utama","ide pokok"], ["gagasan pendukung","ide penjelas","ide pendukung"], ["memperjelas","memperkuat","contoh"], ["paragraf"]] },
  { q: "Sebutkan struktur teks ceramah (3 bagian) dan jelaskan secara singkat isi masing-masing bagian!",
    concepts: [["pembukaan"], ["isi"], ["penutup"], ["salam","sapaan"]] },
  { q: "Sebutkan minimal 4 dari 6 kriteria yang digunakan untuk mengevaluasi informasi dalam teks ceramah!",
    concepts: [["kredibilitas"], ["keakuratan","akurat"], ["kelogisan","logis"], ["objektivitas","bias"], ["kelengkapan","lengkap"], ["kesesuaian","relevan","tujuan"]] },
  { q: "Perhatikan kembali ceramah tentang \"disiplin di dunia kerja\" pada soal pilihan ganda. Menurut pendapatmu, mengapa klaim \"seratus persen perusahaan besar di dunia hanya mau merekrut karyawan yang disiplin\" perlu dipertanyakan kebenarannya? Jelaskan alasanmu berdasarkan kriteria evaluasi informasi!",
    concepts: [["sumber","tidak jelas"], ["generalisasi","mutlak","100%","seratus persen"], ["data","tidak ada","tanpa bukti"], ["keakuratan","kredibilitas"]] },
  { q: "Tuliskan satu gagasan pokok dan minimal dua gagasan pendukung dari sebuah ceramah singkat bertema bebas (sesuai bidang keahlianmu), lalu jelaskan secara singkat apakah informasi dalam ceramah buatanmu tersebut sudah memenuhi kriteria keakuratan dan kelogisan!",
    concepts: [["gagasan pokok"], ["gagasan pendukung"], ["akurat","keakuratan"], ["logis","kelogisan"]] }
];
const ESSAY_MAXLEN = 500;
const PG_WEIGHT = 0.7;
const ESSAY_WEIGHT = 0.3;

function scoreEssayAnswer(answerText, concepts){
  const norm = (answerText || '').toLowerCase();
  let found = 0;
  concepts.forEach(altGroup =&gt; {
    const hit = altGroup.some(alt =&gt; norm.includes(alt.toLowerCase()));
    if(hit) found++;
  });
  return {found: found, total: concepts.length, pct: Math.round((found/concepts.length)*100)};
}

const LETTERS = ["A","B","C","D","E"];
let currentAbsen = null, currentNama = null, currentKelas = null, currentRecord = null;
let quizGroups = null;
let answers = {};
let essayAnswers = {};

function shuffle(arr){
  const a = arr.slice();
  for(let i=a.length-1;i&gt;0;i--){
    const j = Math.floor(Math.random()*(i+1));
    [a[i],a[j]] = [a[j],a[i]];
  }
  return a;
}

function buildShuffledQuiz(){
  const groupOrder = shuffle(GROUPS);
  return groupOrder.map(g =&gt; ({
    title: g.title,
    stimulus: g.stimulus,
    questions: shuffle(g.questions).map(q =&gt; {
      const optIdx = shuffle(q.opts.map((_,i)=&gt;i));
      return {
        q: q.q,
        opts: optIdx.map(i =&gt; q.opts[i]),
        correctLetter: LETTERS[optIdx.indexOf(q.correct)]
      };
    })
  }));
}

async function loadRecord(absen){
  try{
    const r = await window.storage.get('ceramah-siswa:'+absen, true);
    return r ? JSON.parse(r.value) : null;
  }catch(e){
    return null;
  }
}
async function saveRecord(absen, record){
  try{
    await window.storage.set('ceramah-siswa:'+absen, JSON.stringify(record), true);
  }catch(e){
    console.error('Gagal menyimpan data', e);
  }
}

function submitToGoogleScript(payload){
  try{
    const params = new URLSearchParams();
    Object.keys(payload).forEach(k =&gt; params.append(k, payload[k] == null ? '' : String(payload[k])));
    fetch(GAS_URL, {method:'POST', mode:'no-cors', body: params}).catch(e =&gt; console.error('Gagal mengirim ke sistem sekolah', e));
  }catch(e){
    console.error('Gagal mengirim ke sistem sekolah', e);
  }
}

document.getElementById('btnCekStatus').addEventListener('click', async () =&gt; {
  const absenEl = document.getElementById('absen');
  const namaEl = document.getElementById('nama');
  const kelasEl = document.getElementById('kelas');
  const absen = absenEl.value.trim();
  const nama = namaEl.value.trim();
  const kelas = kelasEl.value.trim();
  const err = document.getElementById('introErr');
  if(!absen || !nama || !kelas){
    err.style.display = 'block';
    return;
  }
  err.style.display = 'none';
  currentAbsen = absen;
  currentNama = nama;
  currentKelas = kelas;
  currentRecord = await loadRecord(absen);
  if(!currentRecord){
    currentRecord = {absen, nama, kelas, done:false, result:null};
  } else {
    currentRecord.nama = nama;
    currentRecord.kelas = kelas;
  }
  showStatusScreen();
});

document.getElementById('btnGanti').addEventListener('click', () =&gt; {
  document.getElementById('screen-status').classList.add('hidden');
  document.getElementById('screen-intro').classList.remove('hidden');
});

function showStatusScreen(){
  document.getElementById('screen-intro').classList.add('hidden');
  const statusScreen = document.getElementById('screen-status');
  statusScreen.classList.remove('hidden');
  document.getElementById('statusGreeting').textContent = 'Halo, ' + currentNama + ' (No. Absen ' + currentAbsen + ')';
  const body = document.getElementById('statusBody');
  const btnMulai = document.getElementById('btnMulai');
  const btnUnduhStatus = document.getElementById('btnUnduhStatus');
  const instruksiStatus = document.getElementById('instruksiStatus');

  if(currentRecord.done &amp;&amp; currentRecord.result){
    const r = currentRecord.result;
    body.innerHTML =
      '&lt;p style="font-size:14px;"&gt;Tugas individu ini sudah kamu kerjakan dan skornya sudah tersimpan/terkirim.&lt;/p&gt;' +
      '&lt;div class="result-box ' + (r.score &gt;= 75 ? 'pass-bg' : 'fail-bg') + '" style="margin-top:10px;"&gt;' +
        '&lt;div style="font-size:13px;color:var(--ink-soft);"&gt;Nilai akhir&lt;/div&gt;' +
        '&lt;div class="result-score ' + (r.score &gt;= 75 ? 'pass' : 'fail') + '"&gt;' + r.score + '&lt;/div&gt;' +
        '&lt;div style="font-size:12px;color:var(--ink-soft);"&gt;Skor PG ' + r.pgScore + ' (bobot 70%) - Skor Esai ' + r.essayScorePct + ' (bobot 30%)&lt;/div&gt;' +
      '&lt;/div&gt;';
    btnMulai.classList.add('hidden');
    btnUnduhStatus.classList.remove('hidden');
    instruksiStatus.classList.remove('hidden');
  } else {
    body.innerHTML = '&lt;p style="font-size:14px;"&gt;Tugas ini hanya bisa dikerjakan &lt;b&gt;satu kali&lt;/b&gt;. Pastikan kamu sudah membaca materi sebelum mulai.&lt;/p&gt;';
    btnMulai.classList.remove('hidden');
    btnUnduhStatus.classList.add('hidden');
    instruksiStatus.classList.add('hidden');
  }
}

document.getElementById('btnMulai').addEventListener('click', startQuiz);

function startQuiz(){
  answers = {};
  essayAnswers = {};
  quizGroups = buildShuffledQuiz();
  document.getElementById('screen-status').classList.add('hidden');
  document.getElementById('screen-result').classList.add('hidden');
  document.getElementById('screen-quiz').classList.remove('hidden');
  renderQuiz();
  window.scrollTo({top:0, behavior:'smooth'});
}

function esc(s){
  const d = document.createElement('div');
  d.textContent = s;
  return d.innerHTML;
}

function renderQuiz(){
  const body = document.getElementById('quizBody');
  let html = '';
  let counter = 0;
  quizGroups.forEach((g, gi) =&gt; {
    html += '&lt;div class="qgroup"&gt;';
    if(g.stimulus){
      html += '&lt;div class="stimulus"&gt;&lt;div class="st-title"&gt;' + esc(g.title) + '&lt;/div&gt;' + esc(g.stimulus) + '&lt;/div&gt;';
    } else {
      html += '&lt;div class="stimulus" style="border-left-color:var(--ink);"&gt;&lt;div class="st-title"&gt;' + esc(g.title) + '&lt;/div&gt;Soal-soal berikut menguji pemahaman konsep dari materi, tanpa teks bacaan tambahan.&lt;/div&gt;';
    }
    g.questions.forEach((q, qi) =&gt; {
      counter++;
      const qKey = gi + '-' + qi;
      html += '&lt;div class="q" data-qkey="' + qKey + '"&gt;';
      html += '&lt;div class="q-num"&gt;Soal ' + counter + '&lt;/div&gt;';
      html += '&lt;div class="q-text"&gt;' + esc(q.q) + '&lt;/div&gt;';
      q.opts.forEach((opt, oi) =&gt; {
        const letter = LETTERS[oi];
        html += '&lt;label class="opt" data-qkey="' + qKey + '" data-letter="' + letter + '"&gt;' +
          '&lt;input type="radio" name="q-' + qKey + '" value="' + letter + '"&gt;' +
          '&lt;span&gt;&lt;b&gt;' + letter + '.&lt;/b&gt; ' + esc(opt) + '&lt;/span&gt;&lt;/label&gt;';
      });
      html += '&lt;/div&gt;';
    });
    html += '&lt;/div&gt;';
  });

  html += '&lt;div class="sectionLabel"&gt;Bagian II - Esai (5 soal, dinilai otomatis berdasarkan kesesuaian konsep kunci jawabanmu - bobot Esai 30% dari nilai akhir - maksimal ' + ESSAY_MAXLEN + ' karakter per soal - jawaban wajib diketik sendiri, tempel/paste dinonaktifkan)&lt;/div&gt;';
  html += '&lt;div class="essaySection"&gt;';
  ESSAYS.forEach((item, ei) =&gt; {
    html += '&lt;div class="essayQ" data-ekey="' + ei + '"&gt;';
    html += '&lt;div class="essayQ-num"&gt;Esai ' + (ei+1) + '&lt;/div&gt;';
    html += '&lt;div class="essayQ-text"&gt;' + esc(item.q) + '&lt;/div&gt;';
    html += '&lt;textarea class="essayInput" data-ekey="' + ei + '" maxlength="' + ESSAY_MAXLEN + '" placeholder="Ketik jawabanmu di sini (tempel/paste tidak diperbolehkan)..."&gt;&lt;/textarea&gt;';
    html += '&lt;div class="charCount" data-ekey="' + ei + '"&gt;0 / ' + ESSAY_MAXLEN + '&lt;/div&gt;';
    html += '&lt;div class="pasteWarn" data-ekey="' + ei + '"&gt;Menempel (paste) tidak diperbolehkan. Silakan ketik sendiri jawabanmu.&lt;/div&gt;';
    html += '&lt;/div&gt;';
  });
  html += '&lt;/div&gt;';

  body.innerHTML = html;

  body.querySelectorAll('.opt').forEach(optEl =&gt; {
    optEl.addEventListener('click', () =&gt; {
      const qKey = optEl.getAttribute('data-qkey');
      const letter = optEl.getAttribute('data-letter');
      answers[qKey] = letter;
      document.querySelectorAll('.opt[data-qkey="' + qKey + '"]').forEach(o =&gt; o.classList.remove('selected'));
      optEl.classList.add('selected');
      optEl.querySelector('input').checked = true;
      updateProgress();
    });
  });

  body.querySelectorAll('textarea.essayInput').forEach(ta =&gt; {
    ta.addEventListener('input', () =&gt; {
      const ekey = ta.getAttribute('data-ekey');
      essayAnswers[ekey] = ta.value;
      const counterEl = body.querySelector('.charCount[data-ekey="' + ekey + '"]');
      const len = ta.value.length;
      counterEl.textContent = len + ' / ' + ESSAY_MAXLEN;
      counterEl.classList.toggle('over', len &gt;= ESSAY_MAXLEN);
      updateProgress();
    });

    const showPasteWarn = () =&gt; {
      const ekey = ta.getAttribute('data-ekey');
      const warnEl = body.querySelector('.pasteWarn[data-ekey="' + ekey + '"]');
      if(!warnEl) return;
      warnEl.classList.add('show');
      clearTimeout(warnEl._hideTimer);
      warnEl._hideTimer = setTimeout(() =&gt; warnEl.classList.remove('show'), 3500);
    };
    ta.addEventListener('paste', (e) =&gt; { e.preventDefault(); showPasteWarn(); });
    ta.addEventListener('drop', (e) =&gt; { e.preventDefault(); showPasteWarn(); });
    ta.addEventListener('dragover', (e) =&gt; { e.preventDefault(); });
    ta.addEventListener('contextmenu', (e) =&gt; { e.preventDefault(); showPasteWarn(); });
    ta.addEventListener('keydown', (e) =&gt; {
      const key = (e.key || '').toLowerCase();
      const pasteCombo = (e.ctrlKey || e.metaKey) &amp;&amp; key === 'v';
      const shiftInsert = e.shiftKey &amp;&amp; key === 'insert';
      if(pasteCombo || shiftInsert){
        e.preventDefault();
        showPasteWarn();
      }
    });
  });

  updateProgress();
}

function totalPGQuestions(){
  return quizGroups.reduce((sum,g) =&gt; sum + g.questions.length, 0);
}
function totalQuestions(){
  return totalPGQuestions() + ESSAYS.length;
}
function essayAnsweredCount(){
  return ESSAYS.reduce((n,_,ei) =&gt; n + (essayAnswers[ei] &amp;&amp; essayAnswers[ei].trim() ? 1 : 0), 0);
}
function updateProgress(){
  const total = totalQuestions();
  const answered = Object.keys(answers).length + essayAnsweredCount();
  document.getElementById('progressFill').style.width = (answered/total*100) + '%';
  document.getElementById('progressText').textContent = answered + ' dari ' + total + ' soal terjawab (25 PG + 5 esai)';
}

document.getElementById('btnKirim').addEventListener('click', async () =&gt; {
  const total = totalQuestions();
  const answered = Object.keys(answers).length + essayAnsweredCount();
  const errEl = document.getElementById('quizErr');
  if(answered &lt; total){
    errEl.style.display = 'block';
    let target = null;
    const qEls = document.querySelectorAll('.q');
    for(let i=0;i&lt;qEls.length;i++){
      const qk = qEls[i].getAttribute('data-qkey');
      if(!answers[qk]){ target = qEls[i]; break; }
    }
    if(!target){
      const eEls = document.querySelectorAll('.essayQ');
      for(let i=0;i&lt;eEls.length;i++){
        const ek = eEls[i].getAttribute('data-ekey');
        if(!essayAnswers[ek] || !essayAnswers[ek].trim()){ target = eEls[i]; break; }
      }
    }
    if(target) target.scrollIntoView({behavior:'smooth', block:'center'});
    return;
  }
  errEl.style.display = 'none';

  let correctCount = 0;
  quizGroups.forEach((g, gi) =&gt; {
    g.questions.forEach((q, qi) =&gt; {
      const qKey = gi + '-' + qi;
      if(answers[qKey] === q.correctLetter) correctCount++;
    });
  });
  const pgScore = Math.round(correctCount * (100 / totalPGQuestions()));

  const essaySnapshot = ESSAYS.map((item, ei) =&gt; {
    const ans = (essayAnswers[ei] || '').trim();
    const result = scoreEssayAnswer(ans, item.concepts);
    return {q: item.q, a: ans, found: result.found, total: result.total, pct: result.pct};
  });
  const essayScorePct = Math.round(essaySnapshot.reduce((s,e) =&gt; s + e.pct, 0) / essaySnapshot.length);
  const score = Math.round(pgScore * PG_WEIGHT + essayScorePct * ESSAY_WEIGHT);

  const timestamp = new Date().toISOString();
  currentRecord.done = true;
  currentRecord.result = {score: score, pgScore: pgScore, essayScorePct: essayScorePct, correctCount: correctCount, essay: essaySnapshot, timestamp: timestamp};

  await saveRecord(currentAbsen, currentRecord);

  const gasPayload = {
    waktu: timestamp,
    nama: currentRecord.nama,
    kelas: currentRecord.kelas,
    absen: currentRecord.absen,
    materi: "Evaluasi Informasi dalam Teks Ceramah",
    skorPG: pgScore,
    skorEsai: essayScorePct,
    nilaiAkhir: score,
    benarPG: correctCount,
    totalPG: totalPGQuestions()
  };
  essaySnapshot.forEach((e, i) =&gt; { gasPayload['esai' + (i+1)] = e.a; });
  submitToGoogleScript(gasPayload);

  showResult(score, pgScore, essayScorePct);
});

function showResult(score, pgScore, essayScorePct){
  document.getElementById('screen-quiz').classList.add('hidden');
  const resultScreen = document.getElementById('screen-result');
  resultScreen.classList.remove('hidden');
  const passedNow = score &gt;= 75;
  const outer = document.getElementById('resultBoxOuter');

  outer.innerHTML =
    '&lt;div class="result-box ' + (passedNow ? 'pass-bg' : 'fail-bg') + '"&gt;' +
      '&lt;div style="font-size:13px;color:var(--ink-soft);"&gt;Nilai akhir tugas individu&lt;/div&gt;' +
      '&lt;div class="result-score ' + (passedNow ? 'pass' : 'fail') + '"&gt;' + score + ' / 100&lt;/div&gt;' +
      '&lt;div style="font-size:12px;color:var(--ink-soft);margin-bottom:6px;"&gt;Skor PG ' + pgScore + ' (bobot 70%) + Skor Esai ' + essayScorePct + ' (bobot 30%)&lt;/div&gt;' +
      '&lt;div style="font-size:14px;"&gt;Jawaban dan skor sudah dikirim ke sistem sekolah. Jangan lupa unduh, cetak, dan serahkan bukti ke guru.&lt;/div&gt;' +
    '&lt;/div&gt;';

  document.getElementById('btnUnduhHasil').classList.remove('hidden');
  window.scrollTo({top:0, behavior:'smooth'});
}

document.getElementById('btnSelesai').addEventListener('click', () =&gt; {
  document.getElementById('screen-result').classList.add('hidden');
  document.getElementById('screen-intro').classList.remove('hidden');
  document.getElementById('absen').value = '';
  document.getElementById('nama').value = '';
  document.getElementById('kelas').value = '';
});

function generatePrintArea(){
  const r = currentRecord.result;
  if(!r) return;
  const tgl = new Date(r.timestamp || Date.now()).toLocaleDateString('id-ID', {day:'numeric', month:'long', year:'numeric'});
  const statusTxt = r.score &gt;= 75 ? 'Mencapai KKM (75)' : 'Di bawah KKM (75)';

  let html = '';
  html += '&lt;div class="pf-kop noBreak"&gt;';
  html += '&lt;h2&gt;Bukti Mengerjakan Tugas Individu - Evaluasi Informasi dalam Teks Ceramah&lt;/h2&gt;';
  html += '&lt;p&gt;Mata Pelajaran Bahasa Indonesia - Kelas XI SMK - 25 Soal Pilihan Ganda + 5 Soal Esai&lt;/p&gt;';
  html += '&lt;/div&gt;';

  html += '&lt;table class="pf-identitas noBreak"&gt;';
  html += '&lt;tr&gt;&lt;td class="lbl"&gt;Nama Lengkap&lt;/td&gt;&lt;td&gt;: ' + esc(currentRecord.nama || '') + '&lt;/td&gt;' +
          '&lt;td class="lbl"&gt;No. Absen&lt;/td&gt;&lt;td&gt;: ' + esc(currentRecord.absen || '') + '&lt;/td&gt;&lt;/tr&gt;';
  html += '&lt;tr&gt;&lt;td class="lbl"&gt;Kelas&lt;/td&gt;&lt;td&gt;: ' + esc(currentRecord.kelas || '') + '&lt;/td&gt;' +
          '&lt;td class="lbl"&gt;Tanggal&lt;/td&gt;&lt;td&gt;: ' + tgl + '&lt;/td&gt;&lt;/tr&gt;';
  html += '&lt;/table&gt;';

  html += '&lt;div class="pf-skorbox noBreak"&gt;';
  html += '&lt;div class="pf-skoritem"&gt;Skor Pilihan Ganda (70%)&lt;b&gt;' + r.pgScore + ' / 100&lt;/b&gt;&lt;/div&gt;';
  html += '&lt;div class="pf-skoritem"&gt;Skor Esai Otomatis (30%)&lt;b&gt;' + r.essayScorePct + ' / 100&lt;/b&gt;&lt;/div&gt;';
  html += '&lt;div class="pf-skoritem"&gt;Nilai Akhir&lt;b&gt;' + r.score + ' / 100&lt;/b&gt;&lt;/div&gt;';
  html += '&lt;div class="pf-skoritem"&gt;Status&lt;b style="font-size:13px;"&gt;' + statusTxt + '&lt;/b&gt;&lt;/div&gt;';
  html += '&lt;/div&gt;';

  html += '&lt;div class="pf-kop noBreak" style="border-top:1px solid #000;border-bottom:none;padding-top:8px;margin-top:6px;"&gt;&lt;h2 style="font-size:14px;"&gt;Jawaban Esai (skor otomatis berdasarkan cakupan konsep kunci)&lt;/h2&gt;&lt;/div&gt;';

  r.essay.forEach((item, i) =&gt; {
    const breakClass = (i === 2) ? ' pbreak' : '';
    html += '&lt;div class="noBreak' + breakClass + '" style="margin-bottom:10px;"&gt;';
    html += '&lt;div class="pf-essay-q"&gt;' + (i+1) + '. ' + esc(item.q) + ' &lt;span style="font-weight:400;color:#555;"&gt;(cakupan konsep: ' + item.found + '/' + item.total + ' - skor ' + item.pct + ')&lt;/span&gt;&lt;/div&gt;';
    html += '&lt;div class="pf-essay-a"&gt;' + esc(item.a || '(tidak dijawab)') + '&lt;/div&gt;';
    html += '&lt;/div&gt;';
  });

  html += '&lt;div class="pf-ttd noBreak"&gt;';
  html += '&lt;div&gt;Peserta Didik&lt;div class="garis"&gt;' + esc(currentRecord.nama || '') + '&lt;/div&gt;&lt;/div&gt;';
  html += '&lt;div&gt;Guru Mata Pelajaran&lt;div class="garis"&gt;.............................&lt;/div&gt;&lt;/div&gt;';
  html += '&lt;/div&gt;';
  html += '&lt;p class="pf-note"&gt;&lt;b&gt;Dokumen ini wajib dicetak dan diserahkan kepada guru mata pelajaran Bahasa Indonesia&lt;/b&gt; sebagai bukti fisik pengerjaan tugas. Nilai akhir = (Skor Pilihan Ganda x 70%) + (Skor Esai Otomatis x 30%). Skor esai dihitung berdasarkan cakupan konsep kunci pada jawaban, sehingga guru tetap disarankan meninjau ulang jawaban esai untuk memastikan kualitas dan kejujuran akademik. Jawaban dan skor juga telah dikirim otomatis ke sistem sekolah.&lt;/p&gt;';

  document.getElementById('printArea').innerHTML = html;
}

function downloadProof(){
  if(!currentRecord.result){
    alert('Bukti PDF hanya tersedia setelah tugas dikerjakan dan dikirim.');
    return;
  }
  generatePrintArea();
  setTimeout(() =&gt; window.print(), 100);
}

document.getElementById('btnUnduhStatus').addEventListener('click', downloadProof);
document.getElementById('btnUnduhHasil').addEventListener('click', downloadProof);
&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;</description><link>http://kitab-investasi.blogspot.com/2026/09/evaluasi-informasi-dalam-teks-ceramah.html</link><thr:total>0</thr:total><author>nof_rizal07@yahoo.co.id (abang_cool)</author></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-9000860041661554971.post-8160615648339880190</guid><pubDate>Tue, 08 Sep 2026 00:52:38 +0000</pubDate><atom:updated>2026-09-21T08:13:54.497+07:00</atom:updated><title>Fitur Lanjut Pengolah Kata untuk Dokumen Profesional</title><description>&lt;!DOCTYPE html&gt;
&lt;html lang="id"&gt;
&lt;head&gt;
&lt;meta charset="UTF-8"&gt;
&lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&gt;
&lt;title&gt;Fitur Lanjut Pengolah Kata untuk Dokumen Profesional - Informatika Kelas X&lt;/title&gt;
&lt;link rel="preconnect" href="https://fonts.googleapis.com"&gt;
&lt;link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500;600;700&amp;family=IBM+Plex+Sans:wght@400;500;600;700&amp;family=Tinos:ital,wght@0,400;0,700;1,400&amp;display=swap" rel="stylesheet"&gt;
&lt;style&gt;
  :root{
    --word: #1660D6;
    --word-dark: #0E3E8F;
    --ribbon: #EFF3FA;
    --paper: #FFFFFF;
    --ink: #16202E;
    --ink-soft: #4C5A6B;
    --line: #D7DEE7;
    --amber: #D99A1B;
    --green: #17845A;
    --red: #D6412C;
    --radius: 6px;
  }
  *{box-sizing:border-box; margin:0; padding:0;}
  html{scroll-behavior:smooth;}
  body{ font-family:'IBM Plex Sans', sans-serif; background:#FFFFFF; color: var(--ink); line-height:1.6; }
  .mono{font-family:'IBM Plex Mono', monospace;}
  .serif{font-family:'Tinos', 'Times New Roman', serif;}

  .page-shell{
    max-width: 1140px; margin: 16px auto; background:#FFFFFF; border-radius:14px;
    box-shadow: 0 8px 32px rgba(20,30,50,0.12), 0 1px 3px rgba(20,30,50,0.08); border: 1px solid var(--line);
  }

  /* ===== Ribbon hero ===== */
  .ribbon-hero{ background: var(--ribbon); border-bottom: 3px solid var(--word); border-radius:14px 14px 0 0; overflow:hidden; }
  .ribbon-strip{ display:flex; gap:6px; padding: 10px 5% 0; }
  .ribbon-tab{ font-family:'IBM Plex Mono', monospace; font-size:0.7rem; padding:6px 12px; background:#FFFFFF; border:1px solid var(--line); border-bottom:none; border-radius:4px 4px 0 0; color: var(--ink-soft); }
  .ribbon-tab.active{ color: var(--word); font-weight:700; border-color: var(--word); }
  .hero-body{ padding: 28px 5% 40px; background:#FFFFFF; }
  .eyebrow{ font-family:'IBM Plex Mono', monospace; font-size:0.76rem; letter-spacing:0.14em; text-transform:uppercase; color: var(--word); display:flex; align-items:center; gap:10px; margin-bottom:18px; }
  .eyebrow::before{ content:""; width:10px; height:10px; border:1.5px solid var(--word); border-radius:2px; display:inline-block; }
  h1.title{ font-family:'IBM Plex Mono', monospace; font-weight:700; font-size: clamp(1.7rem, 4vw, 2.7rem); line-height:1.18; color: var(--word-dark); max-width:24ch; }
  .hero-sub{ margin-top:16px; max-width: 66ch; font-size:1.02rem; color: var(--ink-soft); }
  .meta-strip{ margin-top:30px; display:grid; grid-template-columns: repeat(auto-fit,minmax(160px,1fr)); gap:1px; background: var(--line); border:1px solid var(--line); }
  .meta-cell{ background: var(--ribbon); padding:12px 14px; }
  .meta-cell .k{ font-family:'IBM Plex Mono', monospace; font-size:0.64rem; letter-spacing:0.1em; text-transform:uppercase; color: var(--word); }
  .meta-cell .v{ margin-top:5px; font-size:0.9rem; font-weight:600; color: var(--ink); }

  /* ===== Content ===== */
  main{ background: var(--paper); }
  .section{ padding: 36px 5%; border-bottom:1px solid #ECEFF3; }
  .section:last-of-type{border-bottom:none;}
  .section-tag{ font-family:'IBM Plex Mono', monospace; font-size:0.7rem; letter-spacing:0.14em; text-transform:uppercase; color: var(--ink-soft); display:flex; align-items:center; gap:10px; margin-bottom:10px; }
  .section-tag .num{ color:#fff; background: var(--word); padding:3px 8px; border-radius:3px; font-weight:600; }
  h2.section-title{ font-family:'IBM Plex Mono', monospace; font-size: clamp(1.25rem, 2.2vw, 1.7rem); font-weight:700; color: var(--word-dark); margin-bottom: 18px; }
  h3.sub-title{ font-family:'IBM Plex Mono', monospace; font-size:1.02rem; font-weight:600; color: var(--word-dark); margin: 22px 0 10px; display:flex; align-items:center; gap:10px; }
  h3.sub-title::before{ content:""; width:8px;height:8px; background: var(--amber); display:inline-block; border-radius:1px; }
  p{ color:#33414F; max-width: 74ch; margin-bottom: 12px;}
  strong{color:var(--word-dark);}
  ul, ol{ margin: 6px 0 16px 1.3em; max-width: 74ch;}
  li{margin-bottom:7px; color:#33414F;}

  .callout{ border-left: 3px solid var(--word); background:#EBF2FB; padding: 14px 18px; border-radius: 0 6px 6px 0; margin: 16px 0; max-width: 74ch; }
  .callout .lbl{ font-family:'IBM Plex Mono', monospace; font-size:0.68rem; letter-spacing:0.1em; text-transform:uppercase; color: var(--word-dark); font-weight:700; margin-bottom:6px; }
  .callout.warn{ border-left-color: var(--red); background:#FBEAE7; }
  .callout.warn .lbl{ color:#9B3324; }

  .card-grid{ display:grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 14px; margin: 16px 0 6px; }
  .card{ background: #FFFFFF; border: 1.5px solid var(--line); border-radius: var(--radius); padding: 16px 18px; box-shadow: 0 2px 8px rgba(20,30,50,0.05); }
  .card .tag{ font-family:'IBM Plex Mono', monospace; font-size:0.64rem; letter-spacing:0.1em; text-transform:uppercase; color:#fff; background: var(--word); padding:3px 8px; border-radius:3px; display:inline-block; margin-bottom:10px; }
  .card h4{ font-family:'IBM Plex Mono', monospace; font-size:0.94rem; margin-bottom:6px; color:var(--word-dark); }
  .card p{font-size:0.87rem; margin-bottom:0;}

  .table-scroll{ overflow-x:auto; margin:16px 0; }
  table.compare{ width:100%; border-collapse:collapse; font-size:0.88rem; min-width:460px; }
  table.compare th, table.compare td{ border:1px solid var(--line); padding:10px 12px; text-align:left; }
  table.compare th{ background: var(--word); color:#fff; font-family:'IBM Plex Mono', monospace; font-size:0.72rem; letter-spacing:0.04em; text-transform:uppercase; }
  table.compare tr:nth-child(even) td{ background: var(--ribbon); }

  .summary-box{ background: var(--word-dark); color: #fff; border-radius: 8px; padding: 22px 24px; margin-top: 8px; }
  .summary-box h4{ font-family:'IBM Plex Mono', monospace; color:#FCE29A; font-size:0.82rem; letter-spacing:0.08em; text-transform:uppercase; margin-bottom:12px; }
  .summary-box ul{ margin:0 0 0 1.1em; max-width:none; }
  .summary-box li{ color:#E6ECF7; margin-bottom:7px; }

  /* ===== Praktik: toolbar &amp; editor ===== */
  #praktik, #evaluasi{ background: linear-gradient(180deg, #EEF4FF 0%, #FFFFFF 60%); border-top:3px solid var(--word); }
  #praktik .section-tag .num, #evaluasi .section-tag .num{ background: linear-gradient(135deg, var(--word), var(--word-dark)); }

  .toolbar{
    position: sticky; top:10px; z-index:20; background:#FFFFFF; border:1.5px solid var(--word);
    border-radius:8px; padding:10px 12px; display:flex; flex-wrap:wrap; gap:6px; align-items:center;
    box-shadow: 0 6px 20px rgba(20,90,189,0.18); margin-bottom:20px;
  }
  .toolbar button{
    font-family:'IBM Plex Sans', sans-serif; font-size:0.85rem; background:#F3F5F8; border:1px solid var(--line);
    border-radius:4px; padding:6px 10px; cursor:pointer; color: var(--ink);
  }
  .toolbar button:hover{ background:#E4EAF2; }
  .toolbar button.b{font-weight:700;} .toolbar button.i{font-style:italic;} .toolbar button.u{text-decoration:underline;}
  .toolbar select{ font-family:'IBM Plex Sans', sans-serif; font-size:0.82rem; padding:6px 8px; border-radius:4px; border:1px solid var(--line); background:#F3F5F8; }
  .toolbar .swatch{ width:22px; height:22px; border-radius:4px; border:1.5px solid var(--line); cursor:pointer; padding:0; }
  .toolbar .sep{ width:1px; height:22px; background:var(--line); margin:0 4px; }
  .toolbar .hint{ font-family:'IBM Plex Mono', monospace; font-size:0.7rem; color: var(--ink-soft); margin-left:auto; }

  .latihan-card{ background:#FFFFFF; border:1px solid var(--line); border-left:4px solid var(--word); border-radius:8px; margin-bottom:22px; overflow:hidden; box-shadow: 0 2px 10px rgba(20,30,50,0.05); }
  .latihan-head{ background: linear-gradient(90deg, #EEF4FF, var(--ribbon)); padding:14px 18px; border-bottom:1px solid var(--line); }
  .latihan-head .lnum{ font-family:'IBM Plex Mono', monospace; font-size:0.7rem; color: var(--word); letter-spacing:0.08em; }
  .latihan-head h4{ font-family:'IBM Plex Mono', monospace; font-size:1rem; color: var(--word-dark); margin-top:4px; }
  .latihan-body{ padding:16px 18px; }
  .latihan-instruksi{ font-size:0.88rem; color: var(--ink-soft); margin-bottom:12px; }
  .reference-box{
    background:#FBF9F2; border:1px dashed var(--amber); border-radius:6px; padding:12px 14px; margin-bottom:14px;
    font-family:'Tinos','Times New Roman', serif; font-size:0.95rem; color:#3A3226; white-space:pre-wrap;
    user-select:none; -webkit-user-select:none;
  }
  .reference-box .rlbl{ font-family:'IBM Plex Mono', monospace; font-size:0.64rem; letter-spacing:0.08em; text-transform:uppercase; color:#8A6A1E; margin-bottom:8px; display:block; }
  .editor-box{
    min-height:110px; background:#FFFFFF; border:1px solid var(--line); border-radius:6px; padding:14px 16px;
    font-family:'Tinos','Times New Roman', serif; font-size:1rem; color: var(--ink);
    box-shadow: inset 0 0 0 1px transparent; outline:none;
  }
  .editor-box:focus{ border-color: var(--word); box-shadow: 0 0 0 3px rgba(24,90,189,0.12); }
  .editor-box:empty::before{ content: attr(data-placeholder); color:#A6ADB8; }
  .editor-meta{ display:flex; justify-content:space-between; align-items:center; margin-top:8px; font-family:'IBM Plex Mono', monospace; font-size:0.72rem; color: var(--ink-soft); }
  .editor-meta .flag{ color: var(--red); font-weight:700; display:none; }
  .editor-meta .flag.show{ display:inline; }

  /* ===== Submit panel ===== */
  .submit-panel{ background: var(--ribbon); border:1px solid var(--line); border-radius:10px; padding:26px 24px; margin-top:8px; }
  .student-info{ display:grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap:14px; margin: 14px 0 22px; }
  .field label{ display:block; font-family:'IBM Plex Mono', monospace; font-size:0.68rem; letter-spacing:0.06em; text-transform:uppercase; color: var(--word-dark); margin-bottom:6px; }
  .field input, .field select{ width:100%; padding:9px 11px; border-radius:5px; border:1px solid var(--line); background:#FFFFFF; color: var(--ink); font-family:'IBM Plex Sans', sans-serif; font-size:0.9rem; }
  .field select{cursor:pointer;}
  .field input:focus, .field select:focus{ outline:2px solid var(--word); }
  #btnHitung, #btnKirim{ font-family:'IBM Plex Mono', monospace; font-weight:600; font-size:0.85rem; padding:12px 22px; border-radius:6px; border:none; cursor:pointer; }
  #btnHitung{ background: var(--word); color:#fff; }
  #btnKirim{ background: var(--green); color:#fff; display:none; }
  #btnKirim:disabled{ opacity:0.6; cursor:not-allowed; }
  #submitMsg{ font-family:'IBM Plex Mono', monospace; font-size:0.83rem; color:#8A6A1E; margin-left:12px; }
  .result-panel{ display:none; margin-top:18px; background:#FFFFFF; border:1.5px solid var(--green); border-radius:8px; padding:20px 22px; }
  .result-panel .score{ font-family:'IBM Plex Mono', monospace; font-size:2.2rem; font-weight:700; color: var(--green); }
  .result-panel .score-lbl{ font-family:'IBM Plex Mono', monospace; font-size:0.7rem; letter-spacing:0.1em; text-transform:uppercase; color: var(--ink-soft); }
  .result-panel p{ color:#33414F; font-size:0.88rem; margin-top:8px; }

  footer{ background: var(--ribbon); color: var(--ink-soft); text-align:center; padding: 22px 5% 30px; font-family:'IBM Plex Mono', monospace; font-size:0.72rem; border-top:1px solid var(--line); border-radius:0 0 14px 14px; overflow:hidden; }

  /* ===== Evaluasi: Dokumen Master (game gabungan) ===== */
  .primary-btn{
    font-family:'IBM Plex Mono', monospace; font-weight:700; font-size:0.9rem; padding:13px 26px; border-radius:8px; border:none; cursor:pointer;
    background: linear-gradient(135deg, var(--word), var(--word-dark)); color:#fff; box-shadow: 0 4px 14px rgba(16,63,134,0.3);
    transition: transform .15s, box-shadow .15s;
  }
  .primary-btn:hover{ transform: translateY(-2px); box-shadow: 0 6px 18px rgba(16,63,134,0.4); }
  .primary-btn.ghost{ background:#fff; color:var(--word-dark); border:1.5px solid var(--word); box-shadow:none; }
  .primary-btn.ghost:hover{ background:#EEF4FF; }

  .attempt-strip{ display:flex; gap:10px; flex-wrap:wrap; margin:16px 0; }
  .attempt-pill{
    font-family:'IBM Plex Mono', monospace; font-size:0.76rem; font-weight:600; padding:9px 16px; border-radius:20px;
    border:1.5px solid var(--line); background:#fff; color: var(--ink-soft); box-shadow: 0 1px 4px rgba(20,30,50,0.06);
  }
  .attempt-pill.done{ border-color: var(--word); color: var(--word-dark); }
  .attempt-pill.pass{ border-color: var(--green); background:#DFF6E7; color:#0F5C30; }
  .attempt-pill.fail{ border-color: var(--red); background:#FBDEDA; color:#8A2A1C; }
  .attempt-pill.current{ box-shadow: 0 0 0 3px rgba(24,90,189,0.2); background:#EEF4FF; }

  .game-panel{ background:#FFFFFF; border:1px solid var(--line); border-radius:10px; padding:22px; box-shadow: 0 2px 10px rgba(20,30,50,0.05); }
  .game-subtitle{ font-family:'IBM Plex Mono', monospace; font-size:0.85rem; color: var(--word-dark); font-weight:700; margin-bottom:14px; }
  .game-progress{ font-family:'IBM Plex Mono', monospace; font-size:0.74rem; color: var(--ink-soft); margin-bottom:16px; }
  .game-instruction{ background:#EBF2FB; border:1px solid #C7DAF2; border-radius:8px; padding:10px 14px; font-size:0.85rem; color: var(--word-dark); margin-bottom:16px; }

  .drop-grid{ display:grid; grid-template-columns: repeat(auto-fit, minmax(260px,1fr)); gap:12px; margin-bottom:18px; }
  .droppable{ background:#FBFBFB; border:2px dashed var(--line); border-radius:8px; padding:12px 14px; transition: all .2s; cursor:pointer; }
  .droppable:hover:not(.filled):not(.wrong){ border-color: var(--word); background:#F5F9FF; }
  .droppable.filled{ border-style:solid; border-color: var(--green); background:#F0FBF4; cursor:default; }
  .droppable.wrong{ border-style:solid; border-color: var(--red); background:#FDF1EF; animation: shakeX .4s; cursor:default; }
  @keyframes shakeX{ 0%,100%{transform:translateX(0);} 25%{transform:translateX(-4px);} 75%{transform:translateX(4px);} }
  .droppable .func-text{ font-size:0.86rem; color:#33414F; margin-bottom:10px; }
  .drop-target{ min-height:44px; background:#F3F5F8; border:1.5px dashed var(--line); border-radius:6px; display:flex; align-items:center; justify-content:center; padding:6px 10px; text-align:center; }
  .drop-target .placeholder-text{ font-family:'IBM Plex Mono', monospace; font-size:0.72rem; color:#A6ADB8; }
  .drop-target .correct-reveal{ font-family:'IBM Plex Mono', monospace; font-size:0.76rem; color:#9B3324; }

  .drag-pool{ background: var(--ribbon); border:1.5px solid var(--line); border-radius:10px; padding:16px; display:flex; flex-wrap:wrap; gap:10px; justify-content:center; }
  .draggable-chip{
    font-family:'IBM Plex Mono', monospace; font-size:0.85rem; background: var(--word); color:#fff;
    padding:10px 16px; border-radius:8px; cursor:pointer; box-shadow:0 2px 6px rgba(24,90,189,0.3);
    border:2px solid transparent; transition: transform .12s, box-shadow .12s; user-select:none; -webkit-tap-highlight-color: transparent;
  }
  .draggable-chip:active{ transform: scale(0.96); }
  .draggable-chip.selected{ background: var(--amber); border-color:#8A6A1E; box-shadow:0 0 0 4px rgba(192,154,62,0.28); transform: scale(1.05); }
  .draggable-chip.used{ display:none; }

  .type-box{ max-width:520px; margin:0 auto; text-align:center; }
  .type-question-text{ font-size:1.02rem; color: var(--ink); min-height:56px; display:flex; align-items:center; justify-content:center; margin-bottom:18px; }
  .type-input{ width:100%; text-align:center; font-size:1.1rem; padding:12px 14px; border:2px solid var(--line); border-radius:8px; font-family:'IBM Plex Mono', monospace; }
  .type-input:focus{ outline:none; border-color: var(--word); }
  .type-input.correct{ border-color: var(--green); background:#F0FBF4; }
  .type-input.wrong{ border-color: var(--red); background:#FDF1EF; }
  .type-feedback{ margin-top:10px; font-family:'IBM Plex Mono', monospace; font-size:0.84rem; min-height:20px; }
  .type-feedback.ok{ color: var(--green); }
  .type-feedback.no{ color:#9B3324; }

  .closing-task{ background:#FFF6E6; border:1.5px solid var(--amber); border-radius:8px; padding:18px 20px; }
  .closing-task .lbl{ font-family:'IBM Plex Mono', monospace; font-size:0.7rem; letter-spacing:0.1em; text-transform:uppercase; color:#8A5A0A; font-weight:700; margin-bottom:8px; }

  @media (max-width:700px){ .hero-body{padding:22px 5% 32px;} .section{padding:26px 5%;} }
&lt;/style&gt;
&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"&gt;&lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;

&lt;div class="page-shell"&gt;
&lt;div class="ribbon-hero"&gt;
  &lt;div class="ribbon-strip"&gt;
    &lt;div class="ribbon-tab active"&gt;Beranda&lt;/div&gt;
    &lt;div class="ribbon-tab"&gt;Sisipkan&lt;/div&gt;
    &lt;div class="ribbon-tab"&gt;Tata Letak&lt;/div&gt;
    &lt;div class="ribbon-tab"&gt;Referensi&lt;/div&gt;
    &lt;div class="ribbon-tab"&gt;Surat&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="hero-body"&gt;
    &lt;div class="eyebrow"&gt;Informatika - Fase E - Kelas X SMK&lt;/div&gt;
    &lt;h1 class="title"&gt;Fitur Lanjut Pengolah Kata untuk Dokumen Profesional&lt;/h1&gt;
    &lt;p class="hero-sub"&gt;Materi ini membahas fitur-fitur lanjutan pengolah kata  -  style &amp;amp; heading, daftar isi otomatis, tabel, gambar, mail merge, referensi/sitasi, serta berbagai fitur otomatis lain  -  agar kalian mampu menghasilkan dokumen yang rapi dan profesional.&lt;/p&gt;
    &lt;div class="meta-strip"&gt;
      &lt;div class="meta-cell"&gt;&lt;div class="k"&gt;Elemen CP&lt;/div&gt;&lt;div class="v"&gt;Pengolah Kata Lanjut&lt;/div&gt;&lt;/div&gt;
      &lt;div class="meta-cell"&gt;&lt;div class="k"&gt;Jenjang&lt;/div&gt;&lt;div class="v"&gt;SMK Kelas X&lt;/div&gt;&lt;/div&gt;
      &lt;div class="meta-cell"&gt;&lt;div class="k"&gt;Alokasi Waktu&lt;/div&gt;&lt;div class="v"&gt;1 Pertemuan - 4 JP (180 menit)&lt;/div&gt;&lt;/div&gt;
      &lt;div class="meta-cell"&gt;&lt;div class="k"&gt;Model&lt;/div&gt;&lt;div class="v"&gt;Penjelasan &amp; Praktik Langsung&lt;/div&gt;&lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;main&gt;

  &lt;!-- ===================== TUJUAN ===================== --&gt;
  &lt;section class="section" id="tujuan"&gt;
    &lt;div class="section-tag"&gt;&lt;span class="num"&gt;00&lt;/span&gt; Capaian &amp; Tujuan Pembelajaran&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Ke Mana Materi Ini Menuju&lt;/h2&gt;
    &lt;h3 class="sub-title"&gt;Tujuan Pembelajaran&lt;/h3&gt;
    &lt;p&gt;Murid mampu menggunakan style, heading, daftar isi otomatis, tabel, gambar, mail merge, referensi, dan fitur otomatis lainnya untuk menghasilkan dokumen profesional.&lt;/p&gt;

    &lt;h3 class="sub-title"&gt;Rincian Kegiatan (4 JP x 45 menit)&lt;/h3&gt;
    &lt;div class="table-scroll"&gt;
    &lt;table class="compare"&gt;
      &lt;tr&gt;&lt;th&gt;Tahap&lt;/th&gt;&lt;th&gt;Kegiatan&lt;/th&gt;&lt;th&gt;Waktu&lt;/th&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Pendahuluan&lt;/td&gt;&lt;td&gt;Apersepsi ("Bagaimana laporan/skripsi bisa punya daftar isi yang otomatis mengikuti nomor halaman?"), penyampaian tujuan&lt;/td&gt;&lt;td&gt;15 menit&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Inti  -  Eksplorasi Konsep&lt;/td&gt;&lt;td&gt;Penjelasan style/heading, daftar isi otomatis, tabel, gambar, mail merge, referensi, fitur otomatis lain&lt;/td&gt;&lt;td&gt;50 menit&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Inti  -  Praktik Langsung&lt;/td&gt;&lt;td&gt;Mengerjakan 19 latihan mengetik &amp;amp; memformat dokumen langsung di halaman ini (wajib diketik sendiri, tidak boleh tempel/paste)&lt;/td&gt;&lt;td&gt;95 menit&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Penutup&lt;/td&gt;&lt;td&gt;Refleksi, penguatan konsep, menulis kesimpulan ringkas di buku catatan&lt;/td&gt;&lt;td&gt;20 menit&lt;/td&gt;&lt;/tr&gt;
    &lt;/table&gt;
    &lt;/div&gt;
  &lt;/section&gt;

  &lt;!-- ===================== A. STYLE &amp; HEADING ===================== --&gt;
  &lt;section class="section" id="style-heading"&gt;
    &lt;div class="section-tag"&gt;&lt;span class="num"&gt;01&lt;/span&gt; Struktur Dokumen&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Style &amp; Heading&lt;/h2&gt;
    &lt;p&gt;&lt;strong&gt;Style&lt;/strong&gt; adalah kumpulan pengaturan format (jenis huruf, ukuran, warna, spasi) yang disimpan dengan satu nama, sehingga dapat diterapkan berulang kali secara konsisten. &lt;strong&gt;Heading&lt;/strong&gt; adalah style khusus untuk judul bab/subbab (Heading 1, Heading 2, Heading 3, dst.) yang menandai struktur/hierarki dokumen.&lt;/p&gt;
    &lt;div class="callout"&gt;
      &lt;div class="lbl"&gt;Mengapa Penting&lt;/div&gt;
      &lt;p style="margin:0;"&gt;Dokumen yang judul-judulnya diberi Heading (bukan sekadar huruf besar/tebal manual) dapat langsung dikenali oleh fitur otomatis lain, seperti Daftar Isi Otomatis dan Navigation Pane  -  inilah alasan utama style/heading menjadi fondasi dokumen profesional.&lt;/p&gt;
    &lt;/div&gt;
  &lt;/section&gt;

  &lt;!-- ===================== B. DAFTAR ISI OTOMATIS ===================== --&gt;
  &lt;section class="section" id="toc"&gt;
    &lt;div class="section-tag"&gt;&lt;span class="num"&gt;02&lt;/span&gt; Navigasi Dokumen&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Daftar Isi Otomatis&lt;/h2&gt;
    &lt;p&gt;&lt;strong&gt;Daftar isi otomatis (Table of Contents)&lt;/strong&gt; dibuat dari menu References &amp;gt; Table of Contents, dan secara otomatis mengambil seluruh teks yang diberi style Heading beserta nomor halamannya. Jika ada perubahan judul atau halaman, cukup klik &lt;strong&gt;Update Table&lt;/strong&gt;  -  tidak perlu mengetik ulang satu per satu seperti daftar isi manual.&lt;/p&gt;
  &lt;/section&gt;

  &lt;!-- ===================== C. TABEL &amp; GAMBAR ===================== --&gt;
  &lt;section class="section" id="tabel-gambar"&gt;
    &lt;div class="section-tag"&gt;&lt;span class="num"&gt;03&lt;/span&gt; Elemen Visual&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Tabel &amp; Gambar&lt;/h2&gt;
    &lt;div class="card-grid"&gt;
      &lt;div class="card"&gt;&lt;span class="tag"&gt;Data Terstruktur&lt;/span&gt;&lt;h4&gt;Tabel&lt;/h4&gt;&lt;p&gt;Menyusun data dalam baris &amp;amp; kolom; dapat digabung (merge cell), diberi Table Style, dan dihitung otomatis dengan rumus sederhana.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;span class="tag"&gt;Ilustrasi&lt;/span&gt;&lt;h4&gt;Gambar &amp; Text Wrapping&lt;/h4&gt;&lt;p&gt;Gambar dapat diatur agar teks mengalir di sekitarnya (Square, Tight) atau di belakang/depan teks (Behind/In Front of Text).&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;span class="tag"&gt;Penjelasan Gambar&lt;/span&gt;&lt;h4&gt;Caption&lt;/h4&gt;&lt;p&gt;Keterangan otomatis di bawah gambar/tabel (mis. "Gambar 1.1") yang bisa dirujuk ulang di teks (cross-reference).&lt;/p&gt;&lt;/div&gt;
    &lt;/div&gt;
  &lt;/section&gt;

  &lt;!-- ===================== D. MAIL MERGE ===================== --&gt;
  &lt;section class="section" id="mail-merge"&gt;
    &lt;div class="section-tag"&gt;&lt;span class="num"&gt;04&lt;/span&gt; Surat Massal&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Mail Merge&lt;/h2&gt;
    &lt;p&gt;&lt;strong&gt;Mail merge&lt;/strong&gt; adalah fitur untuk membuat banyak dokumen serupa (mis. surat undangan, sertifikat) secara otomatis, dengan menggabungkan satu &lt;strong&gt;dokumen utama&lt;/strong&gt; (format surat) dan satu &lt;strong&gt;sumber data&lt;/strong&gt; (mis. tabel Excel berisi daftar nama &amp;amp; alamat). Bagian yang berubah-ubah ditandai sebagai &lt;em&gt;merge field&lt;/em&gt;, misalnya &lt;span class="mono"&gt;&amp;lt;&amp;lt;Nama&amp;gt;&amp;gt;&lt;/span&gt; dan &lt;span class="mono"&gt;&amp;lt;&amp;lt;Alamat&amp;gt;&amp;gt;&lt;/span&gt;.&lt;/p&gt;
    &lt;div class="callout"&gt;
      &lt;div class="lbl"&gt;Contoh Penggunaan&lt;/div&gt;
      &lt;p style="margin:0;"&gt;Membuat 30 surat undangan wali murid dengan nama &amp;amp; kelas berbeda-beda, tanpa perlu mengetik ulang 30 kali  -  cukup satu template surat + satu daftar 30 nama.&lt;/p&gt;
    &lt;/div&gt;
  &lt;/section&gt;

  &lt;!-- ===================== E. REFERENSI ===================== --&gt;
  &lt;section class="section" id="referensi"&gt;
    &lt;div class="section-tag"&gt;&lt;span class="num"&gt;05&lt;/span&gt; Kutipan &amp; Rujukan&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Referensi &amp; Sitasi&lt;/h2&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;strong&gt;Citation/Sitasi&lt;/strong&gt;  -  menandai sumber kutipan dalam teks, mis. (Sugono, 2003).&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Daftar Pustaka (Bibliography)&lt;/strong&gt;  -  dibuat otomatis dari seluruh sitasi yang sudah dimasukkan, tersusun sesuai gaya penulisan (APA, MLA, dsb.).&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Footnote/Endnote&lt;/strong&gt;  -  catatan kaki/akhir untuk penjelasan tambahan tanpa mengganggu alur teks utama.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/section&gt;

  &lt;!-- ===================== F. FITUR OTOMATIS LAIN ===================== --&gt;
  &lt;section class="section" id="fitur-lain"&gt;
    &lt;div class="section-tag"&gt;&lt;span class="num"&gt;06&lt;/span&gt; Efisiensi Kerja&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Fitur Otomatis Lainnya&lt;/h2&gt;
    &lt;div class="card-grid"&gt;
      &lt;div class="card"&gt;&lt;span class="tag"&gt;Penomoran&lt;/span&gt;&lt;h4&gt;Page Number Otomatis&lt;/h4&gt;&lt;p&gt;Nomor halaman yang otomatis bertambah dan dapat diformat berbeda per bagian (section break).&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;span class="tag"&gt;Koreksi&lt;/span&gt;&lt;h4&gt;Spelling &amp; AutoCorrect&lt;/h4&gt;&lt;p&gt;Mendeteksi salah ketik dan otomatis memperbaiki kesalahan umum saat mengetik.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;span class="tag"&gt;Keamanan Isi&lt;/span&gt;&lt;h4&gt;Watermark &amp; Proteksi&lt;/h4&gt;&lt;p&gt;Menandai dokumen (mis. "DRAFT") atau membatasi siapa yang dapat mengedit bagian tertentu.&lt;/p&gt;&lt;/div&gt;
    &lt;/div&gt;
  &lt;/section&gt;

  &lt;!-- ===================== RANGKUMAN ===================== --&gt;
  &lt;section class="section" id="rangkuman"&gt;
    &lt;div class="section-tag"&gt;&lt;span class="num"&gt;07&lt;/span&gt; Penguatan Konsep&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Rangkuman Materi&lt;/h2&gt;
    &lt;div class="summary-box"&gt;
      &lt;h4&gt;Poin-Poin Kunci&lt;/h4&gt;
      &lt;ul&gt;
        &lt;li&gt;Style &amp;amp; Heading membangun struktur dokumen yang konsisten dan dapat dikenali fitur otomatis lain.&lt;/li&gt;
        &lt;li&gt;Daftar isi otomatis dibangun dari Heading, dapat diperbarui otomatis tanpa mengetik ulang.&lt;/li&gt;
        &lt;li&gt;Tabel menyusun data terstruktur; gambar dilengkapi text wrapping dan caption.&lt;/li&gt;
        &lt;li&gt;Mail merge menggabungkan dokumen utama + sumber data untuk membuat banyak surat sekaligus.&lt;/li&gt;
        &lt;li&gt;Referensi/sitasi dan daftar pustaka membantu menyusun karya tulis yang kredibel.&lt;/li&gt;
        &lt;li&gt;Fitur otomatis lain (nomor halaman, autocorrect, watermark) meningkatkan efisiensi dan profesionalitas dokumen.&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/div&gt;
  &lt;/section&gt;

  &lt;!-- ===================== TUGAS PRAKTIK ===================== --&gt;
  &lt;section class="section" id="praktik"&gt;
    &lt;div class="section-tag"&gt;&lt;span class="num"&gt;08&lt;/span&gt; Praktik Langsung&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Tugas Praktik: Latihan Mengetik 1-19&lt;/h2&gt;
    &lt;p&gt;Kerjakan seluruh 19 latihan berikut &lt;strong&gt;langsung di halaman ini&lt;/strong&gt;, dengan cara &lt;strong&gt;mengetik ulang sendiri&lt;/strong&gt;  -  bukan menyalin/tempel (paste). Setiap kotak jawaban akan &lt;strong&gt;menolak aksi tempel&lt;/strong&gt;; jika terdeteksi ada percobaan tempel, latihan tersebut otomatis bernilai 0. Gunakan toolbar pemformatan di atas untuk menerapkan Bold, Italic, Underline, warna huruf, perataan, dan daftar bertingkat/bernomor sesuai instruksi masing-masing latihan.&lt;/p&gt;

    &lt;div class="callout warn"&gt;
      &lt;div class="lbl"&gt;Aturan Pengerjaan&lt;/div&gt;
      &lt;p style="margin:0;"&gt;Dilarang menyalin-tempel teks dari mana pun (termasuk dari kotak naskah acuan di atas kolom jawaban). Ketik sendiri persis sesuai naskah, lalu format menggunakan toolbar. Kejujuran mengetik adalah bagian dari penilaian.&lt;/p&gt;
    &lt;/div&gt;

    &lt;div class="toolbar" id="toolbar"&gt;
      &lt;button class="b" data-cmd="bold" title="Bold"&gt;B&lt;/button&gt;
      &lt;button class="i" data-cmd="italic" title="Italic"&gt;I&lt;/button&gt;
      &lt;button class="u" data-cmd="underline" title="Underline"&gt;U&lt;/button&gt;
      &lt;span class="sep"&gt;&lt;/span&gt;
      &lt;button class="swatch" style="background:#000000" data-cmd="foreColor" data-val="#000000" title="Hitam"&gt;&lt;/button&gt;
      &lt;button class="swatch" style="background:#C43E2E" data-cmd="foreColor" data-val="#C43E2E" title="Merah"&gt;&lt;/button&gt;
      &lt;button class="swatch" style="background:#185ABD" data-cmd="foreColor" data-val="#185ABD" title="Biru"&gt;&lt;/button&gt;
      &lt;button class="swatch" style="background:#1E7A46" data-cmd="foreColor" data-val="#1E7A46" title="Hijau"&gt;&lt;/button&gt;
      &lt;span class="sep"&gt;&lt;/span&gt;
      &lt;button data-cmd="justifyLeft" title="Rata Kiri"&gt;Kiri&lt;/button&gt;
      &lt;button data-cmd="justifyCenter" title="Rata Tengah"&gt;Tengah&lt;/button&gt;
      &lt;button data-cmd="justifyRight" title="Rata Kanan"&gt;Kanan&lt;/button&gt;
      &lt;button data-cmd="justifyFull" title="Rata Kiri-Kanan"&gt;Rata&lt;/button&gt;
      &lt;span class="sep"&gt;&lt;/span&gt;
      &lt;button data-cmd="insertUnorderedList" title="Bullet List"&gt;List Bullet&lt;/button&gt;
      &lt;button data-cmd="insertOrderedList" title="Numbered List"&gt;1. List&lt;/button&gt;
      &lt;span class="sep"&gt;&lt;/span&gt;
      &lt;select id="fontSizeSelect" title="Ukuran Huruf"&gt;
        &lt;option value="2"&gt;Kecil&lt;/option&gt;
        &lt;option value="3" selected&gt;Normal&lt;/option&gt;
        &lt;option value="5"&gt;Besar&lt;/option&gt;
        &lt;option value="7"&gt;Sangat Besar&lt;/option&gt;
      &lt;/select&gt;
      &lt;select id="fontFamilySelect" title="Jenis Huruf"&gt;
        &lt;option value="Times New Roman"&gt;Times New Roman&lt;/option&gt;
        &lt;option value="Arial"&gt;Arial&lt;/option&gt;
        &lt;option value="Courier New"&gt;Courier New&lt;/option&gt;
        &lt;option value="Comic Sans MS"&gt;Comic Sans MS&lt;/option&gt;
      &lt;/select&gt;
      &lt;span class="hint"&gt;Klik di kotak jawaban dulu, lalu gunakan tombol ini&lt;/span&gt;
    &lt;/div&gt;

    &lt;div id="latihanContainer"&gt;&lt;/div&gt;

    &lt;div class="submit-panel"&gt;
      &lt;h3 class="sub-title"&gt;Identitas Peserta&lt;/h3&gt;
      &lt;div class="student-info"&gt;
        &lt;div class="field"&gt;&lt;label for="noAbsen"&gt;No. Absen&lt;/label&gt;&lt;input type="number" id="noAbsen" min="1" placeholder="mis. 12"&gt;&lt;/div&gt;
        &lt;div class="field"&gt;&lt;label for="nama"&gt;Nama Lengkap&lt;/label&gt;&lt;input type="text" id="nama" placeholder="Nama sesuai absensi"&gt;&lt;/div&gt;
        &lt;div class="field"&gt;&lt;label for="kelas"&gt;Kelas&lt;/label&gt;
          &lt;select id="kelas"&gt;
            &lt;option value=""&gt;-- Pilih Kelas --&lt;/option&gt;
            &lt;option value="X TB1"&gt;X TB1&lt;/option&gt;
            &lt;option value="X TB2"&gt;X TB2&lt;/option&gt;
            &lt;option value="X TO1"&gt;X TO1&lt;/option&gt;
            &lt;option value="X TO2"&gt;X TO2&lt;/option&gt;
            &lt;option value="X TJKT1"&gt;X TJKT1&lt;/option&gt;
            &lt;option value="X TJKT2"&gt;X TJKT2&lt;/option&gt;
          &lt;/select&gt;
        &lt;/div&gt;
      &lt;/div&gt;
      &lt;button id="btnHitungLatihan"&gt;Hitung Skor Latihan Mengetik&lt;/button&gt;
      &lt;span id="latihanMsg" class="mono" style="font-size:0.83rem; color:#8A6A1E; margin-left:12px;"&gt;&lt;/span&gt;

      &lt;div class="result-panel" id="latihanResultPanel"&gt;
        &lt;div class="score-lbl"&gt;Skor Latihan Mengetik (1-19)&lt;/div&gt;
        &lt;div class="score" id="latihanScoreValue"&gt;0&lt;/div&gt;
        &lt;p id="latihanResultDetail"&gt;&lt;/p&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/section&gt;

  &lt;!-- ===================== EVALUASI DOKUMEN MASTER (GAME) ===================== --&gt;
  &lt;section class="section" id="evaluasi"&gt;
    &lt;div class="section-tag"&gt;&lt;span class="num"&gt;09&lt;/span&gt; Evaluasi Pemahaman&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Evaluasi: Dokumen Master&lt;/h2&gt;
    &lt;p&gt;Bagian kedua dari Tugas Praktik ini adalah evaluasi pemahaman fitur pengolah kata dalam bentuk permainan singkat, terdiri dari &lt;strong&gt;Bagian A: Cocokkan Fitur (Drag &amp;amp; Drop)&lt;/strong&gt; dan &lt;strong&gt;Bagian B: Ketik Cepat&lt;/strong&gt;. Skor bagian ini akan digabung 50:50 dengan skor Latihan Mengetik di atas menjadi &lt;strong&gt;nilai akhir Tugas Praktik&lt;/strong&gt;.&lt;/p&gt;

    &lt;div class="callout warn"&gt;
      &lt;div class="lbl"&gt;Aturan Bermain&lt;/div&gt;
      &lt;p style="margin:0;"&gt;&lt;strong&gt;Jika jawaban salah, soal langsung lanjut ke soal berikutnya dan tidak mendapat nilai untuk soal itu&lt;/strong&gt;  -  tidak ada kesempatan mengulang jawaban pada soal yang sama. Nilai akhir dikirim ke guru otomatis jika mencapai &lt;strong&gt;KKM = 75&lt;/strong&gt;. Jika belum mencapai KKM, kalian punya &lt;strong&gt;3 kali kesempatan mengulang evaluasi ini&lt;/strong&gt; (skor Latihan Mengetik tidak perlu diulang); jika setelah 3 kali masih belum mencapai KKM, &lt;strong&gt;nilai tertinggi dari 3 percobaan itulah yang dikirim ke guru&lt;/strong&gt;.&lt;/p&gt;
    &lt;/div&gt;

    &lt;div class="attempt-strip" id="attemptStrip"&gt;&lt;/div&gt;

    &lt;div class="game-panel" id="gamePanel"&gt;
      &lt;button id="btnMulaiEvaluasi" class="primary-btn"&gt;Mulai Evaluasi Dokumen Master&lt;/button&gt;
    &lt;/div&gt;

    &lt;div class="result-panel" id="finalResultPanel"&gt;
      &lt;div class="score-lbl" id="finalResultLabel"&gt;Nilai Akhir Tugas Praktik&lt;/div&gt;
      &lt;div class="score" id="finalScoreValue"&gt;0&lt;/div&gt;
      &lt;p id="finalResultDetail"&gt;&lt;/p&gt;
      &lt;button id="btnCobaLagi" class="primary-btn" style="display:none; margin-top:14px;"&gt;Coba Lagi Evaluasi&lt;/button&gt;
      &lt;button id="btnUnduhPDF" class="primary-btn ghost" style="display:none; margin-top:14px;"&gt;Unduh Bukti Mengerjakan (PDF)&lt;/button&gt;
      &lt;p id="pdfHint" style="display:none; font-size:0.8rem; color:var(--ink-soft); margin-top:8px;"&gt;Setelah diunduh, cetak dokumen ini (ukuran F4) dan serahkan ke guru mata pelajaran sebagai bukti pengerjaan.&lt;/p&gt;
    &lt;/div&gt;
  &lt;/section&gt;

  &lt;!-- ===================== PENUTUP: BUKU CATATAN ===================== --&gt;
  &lt;section class="section" id="penutup"&gt;
    &lt;div class="section-tag"&gt;&lt;span class="num"&gt;10&lt;/span&gt; Penutup Pembelajaran&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Tugas Individu di Buku Catatan&lt;/h2&gt;
    &lt;div class="closing-task"&gt;
      &lt;div class="lbl"&gt;1. Catat Nilai Evaluasi&lt;/div&gt;
      &lt;p style="margin:0;"&gt;Salin &lt;strong&gt;Nilai Akhir Tugas Praktik&lt;/strong&gt; yang muncul di layar ke buku catatan kalian, pada kolom &lt;strong&gt;"Nilai Evaluasi"&lt;/strong&gt; (buat tabel kecil: Tanggal | Materi | Nilai Evaluasi), sebagai bukti dan rekam jejak pencapaian belajar kalian.&lt;/p&gt;
    &lt;/div&gt;
    &lt;div class="closing-task" style="margin-top:14px;"&gt;
      &lt;div class="lbl"&gt;2. Tulis Resume Materi&lt;/div&gt;
      &lt;p style="margin:0;"&gt;Buatlah &lt;strong&gt;resume (rangkuman) materi "Fitur Lanjut Pengolah Kata untuk Dokumen Profesional"&lt;/strong&gt; di buku catatan, mencakup: style &amp;amp; heading, daftar isi otomatis, tabel &amp;amp; gambar, mail merge, referensi/sitasi, serta fitur otomatis lainnya. Tulis dengan bahasa dan pemahaman kalian sendiri.&lt;/p&gt;
    &lt;/div&gt;
  &lt;/section&gt;

&lt;/main&gt;

&lt;footer&gt;
  INFORMATIKA - FITUR LANJUT PENGOLAH KATA UNTUK DOKUMEN PROFESIONAL - FASE E KELAS X SMK
&lt;/footer&gt;
&lt;/div&gt;

&lt;script&gt;
  const GAS_ENDPOINT = "https://script.google.com/macros/s/AKfycbwKp7DrBTALJMlw8crjK7RgXIO8LVcU4yVEd9WJNs_vgSXkVxfw7fwkGbOT2IBNOjg3uQ/exec";
  const JUDUL_MATERI = "Fitur Lanjut Pengolah Kata untuk Dokumen Profesional";

  // type: "match" = dinilai berdasarkan kemiripan dengan reference; "open" = dinilai berdasarkan panjang minimal (tugas kreatif tanpa naskah acuan tetap)
  const LATIHAN = [
    { title: "Latihan Mengetik dengan Keyboard", type:"match",
      instruksi: "Ketik ulang alfabet besar-kecil, angka, contoh operasi hitung, dan paragraf berikut PERSIS seperti aslinya (perhatikan huruf besar/kecil dan tanda baca).",
      reference: "ABCDEFGHIJKLMNOPQRSTUVWXYZ\nabcdefghijklmnopqrstuvwxyz\n1234567890\n2 + 2 = 4\nDi dalam sebuah hadits qudsy dijelaskan bahwa Allah SWT sangat menyukai dan mencintai hamba-hamba-Nya, yang banyak mengingat-Nya dan datang kepada-Nya dengan ibadah, membawa kebaikan dan amal-amal saleh serta memohon ampun dan bertobat atas dosa dan kesalahan yang dilakukannya." },
    { title: "Latihan Mengetik Teks/Paragraf", type:"match",
      instruksi: "Ketik ulang paragraf berikut dengan memperhatikan penggunaan tombol Shift untuk simbol di atas angka.",
      reference: "Ingatlah selalu bahwa untuk mengetik tanda yang berada di atas angka, harus menekan shift bersamaan dengan tanda tersebut. Seperti tanda % yang berada di atas angka 5, jika ingin mengetik angka lima saja, kita tidak perlu menekan shift. Contohnya $500 yang digunakan di luar negeri, contoh kedua yaitu seperti judul Tom &amp; Jerry." },
    { title: "Latihan Jenis, Ukuran, dan Gaya Huruf", type:"match",
      instruksi: "Ketik keempat baris berikut, lalu format sesuai keterangannya menggunakan tombol Bold, Italic, dan Underline pada toolbar di atas.",
      reference: "Times New Roman 12 Bold\nTimes New Roman 12 Italic\nTimes New Roman 12 Underline\nTimes New Roman 12 Bold Italic Underline" },
    { title: "Latihan Warna Huruf dan Perataan Paragraf", type:"match",
      instruksi: "Ketik ketiga baris berikut lalu beri warna huruf sesuai keterangan menggunakan tombol warna pada toolbar, kemudian ketik paragraf di bawahnya dan ratakan kiri-kanan (justify).",
      reference: "Times New Roman 12 Font Color: Red\nTimes New Roman 14 Font Color: Blue\nTimes New Roman 16 Font Color: Green\nPerkembangan ilmu pengetahuan dan teknologi semakin lama menjadi semakin penting artinya, baik untuk kepentingan sipil maupun militer, kepentingan damai maupun perang." },
    { title: "Latihan Penomoran dan Pembutiran", type:"match",
      instruksi: "Ketik daftar alat menggunakan Bullet List, lalu ketik daftar bahan menggunakan Numbered List (gunakan tombol list pada toolbar).",
      reference: "Alat-alat yang dibutuhkan: Nampan, Ompreng, Ember, Gayung, Kompor.\nBahan yang diperlukan: Air bersih satu ember, Minyak goreng satu liter, Telur ayam 5 butir, Cabe bawang dan garam secukupnya." },
    { title: "Latihan Tabulasi", type:"match",
      instruksi: "Ketik ulang tiga baris tanggal berikut menggunakan tombol Tab agar sejajar rapi.",
      reference: "Jakarta, 27 Maret 1987\nBandung, 28 Agustus 1945\nSurabaya, 2 Januari 2009" },
    { title: "Latihan Membuat Daftar Isi (Manual)", type:"match",
      instruksi: "Ketik ulang daftar isi berikut lengkap dengan titik-titik penghubung (dot leader) sebelum nomor halaman.",
      reference: "Daftar Isi\nKata Pengantar ..... i\nDaftar Isi ..... ii\nBAB I ..... 1\nBAB II ..... 4\nBAB III ..... 7\nDaftar Pustaka ..... 10" },
    { title: "Latihan Word Art (Simulasi)", type:"open", minChars: 10,
      instruksi: "Karena WordArt tidak tersedia di kotak ini, ketik sebuah judul singkat (nama sekolah/kelas kalian), lalu format dengan ukuran Sangat Besar dan warna mencolok pada toolbar untuk mensimulasikan efek WordArt." },
    { title: "Latihan Shapes dan Teks dalam Shapes (Simulasi)", type:"open", minChars: 10,
      instruksi: "Ketik sebuah kalimat singkat yang biasanya diletakkan di dalam sebuah shape (kotak/oval), lalu format rata tengah (Center) menggunakan toolbar." },
    { title: "Latihan Clip Art &amp; AutoShapes (Deskripsi)", type:"open", minChars: 20,
      instruksi: "Karena bagian ini aslinya berupa gambar clip art, tuliskan deskripsi singkat (2-3 kalimat) tentang ilustrasi yang akan kalian sisipkan di dokumen asli kalian di MS Word." },
    { title: "Latihan Membuat Tabel Data Diri", type:"match",
      instruksi: "Karena kotak jawaban belum berupa tabel sungguhan, ketik data berikut per baris dengan format: Nama | Kelas | Hobi | Cita-cita | Musik.",
      reference: "Nama | Kelas | Hobi | Cita-cita | Musik\nEntong | 2 SD | Baca | Presiden | Pop\nSiti | 3 SD | Ngerumpi | Sekretaris | Rock\nUcup | 4 SD | Menulis | Direktur | Dangdut" },
    { title: "Latihan Membuat Tabel Jadwal Pelajaran", type:"match",
      instruksi: "Ketik jadwal pelajaran berikut per baris dengan format: Hari | Pelajaran 1 | Pelajaran 2 | Pelajaran 3.",
      reference: "Senin | Upacara | Matematika | Bahasa\nSelasa | Bahasa Inggris | IPS | Matematika\nRabu | Agama | Penjas | Matematika" },
    { title: "Latihan Tabel &amp; Menghitung Jumlah Uang", type:"match",
      instruksi: "Ketik data berikut, lalu hitung sendiri jumlahnya (latihan menggabungkan tabel dengan operasi hitung sederhana).",
      reference: "Di Rumah | Di Kantong | Jumlahnya\n5000 | 3000 | 8000\n2000 | 5000 | 7000\n10000 | 500 | 10500" },
    { title: "Latihan Membuat Surat Resmi", type:"match",
      instruksi: "Ketik ulang bagian inti surat resmi berikut, lengkap dengan nomor surat, hal, dan salam pembuka/penutup.",
      reference: "No : 076/FQ/III/2009  Jakarta, 22 Maret 2009\nHal : Pemberitahuan dan Undangan\n\nKepada Yth,\nBapak/Ibu Orang tua murid\nDi tempat\n\nAssalamu'alaikum Wr.Wb.\nSehubungan dengan datangnya hari besar, kami akan mengadakan acara yang Insya Allah akan dilaksanakan pada Hari Minggu, Pukul 07.00 WIB.\n\nWassalamu'alaikum Wr.Wb." },
    { title: "Latihan Membuat Cover Makalah", type:"match",
      instruksi: "Ketik ulang susunan cover makalah berikut, gunakan perataan tengah (Center) dan Bold untuk judul.",
      reference: "MAKALAH\nHUKUM NUN MATI DAN TANWIN\nDisusun sebagai tugas mata pelajaran Agama Islam\n\nDisusun Oleh\nRAHMAT FAUZI\nKelas 8 A\n\nSEKOLAH MENENGAH PERTAMA NEGERI 176\nJAKARTA BARAT\nTAHUN 2010" },
    { title: "Latihan Membuat Pengumuman", type:"match",
      instruksi: "Ketik ulang teks pengumuman berikut sesuai aslinya.",
      reference: "Telah hilang dompet tanpa isinya dengan ciri-ciri warna coklat, berbahan kulit, robek dikit di bagian tengahnya, yang hilang pada Hari Senin, 12 Maret 2010 sekitar pukul 09.00 WIB di sekitar Monas. Bagi yang menemukan, diharapkan menghubungi nomor di bawah ini, terima kasih." },
    { title: "Latihan Membuat Bagan/Struktur Organisasi (Teks Bertingkat)", type:"open", minChars: 30,
      instruksi: "Karena bagan berupa kotak-kotak yang dihubungkan garis, tuliskan struktur organisasi dalam bentuk daftar bertingkat (indentasi) sebagai gambaran teksnya. Contoh: Ketua, lalu di bawahnya Wakil Ketua, lalu Sekretaris &amp; Bendahara, lalu Anggota." },
    { title: "Latihan Drop Cap dan Kolom Koran", type:"match",
      instruksi: "Ketik ulang paragraf berikut, lalu perbesar ukuran huruf pertama saja (blok satu huruf pertama, pilih ukuran Sangat Besar) untuk mensimulasikan efek Drop Cap.",
      reference: "GEGER Jakarta! Selama dua hari diguyur hujan kawasan Jakarta langsung berubah menjadi kota air kotor dengan sampah yang begitu melimpah dan komunitas warga yang terserang berbagai penyakit." },
    { title: "Latihan Simbol dan Karakter Khusus", type:"match",
      instruksi: "Ketik ulang simbol-simbol khusus berikut menggunakan keyboard atau fitur Insert Symbol yang tersedia di perangkat kalian.",
      reference: "± Rp 10.000.000,- untuk satu unit motor\nΠ = 3,14\nx ≥ 7\nSonic®\nSony Entertainment™" }
  ];

  const container = document.getElementById('latihanContainer');
  const pasteFlags = new Array(LATIHAN.length).fill(false);
  let currentEditor = null;

  LATIHAN.forEach((item, idx) =&gt; {
    const card = document.createElement('div');
    card.className = 'latihan-card';

    const head = document.createElement('div');
    head.className = 'latihan-head';
    head.innerHTML = '&lt;div class="lnum"&gt;LATIHAN ' + (idx+1) + ' / ' + LATIHAN.length + '&lt;/div&gt;&lt;h4&gt;' + item.title + '&lt;/h4&gt;';
    card.appendChild(head);

    const body = document.createElement('div');
    body.className = 'latihan-body';

    const instr = document.createElement('div');
    instr.className = 'latihan-instruksi';
    instr.textContent = item.instruksi;
    body.appendChild(instr);

    if (item.reference) {
      const refBox = document.createElement('div');
      refBox.className = 'reference-box';
      const rlbl = document.createElement('span');
      rlbl.className = 'rlbl';
      rlbl.textContent = 'Naskah Acuan (ketik ulang, jangan disalin)';
      refBox.appendChild(rlbl);
      const refText = document.createElement('div');
      refText.textContent = item.reference;
      refBox.appendChild(refText);
      body.appendChild(refBox);
    }

    const editor = document.createElement('div');
    editor.className = 'editor-box';
    editor.contentEditable = 'true';
    editor.setAttribute('data-placeholder', 'Ketik jawaban latihan di sini...');
    editor.dataset.idx = idx;

    editor.addEventListener('focus', () =&gt; { currentEditor = editor; });
    editor.addEventListener('paste', (e) =&gt; {
      e.preventDefault();
      pasteFlags[idx] = true;
      const flagEl = card.querySelector('.flag');
      flagEl.classList.add('show');
      flagEl.textContent = '[PERINGATAN] Percobaan tempel terdeteksi  -  latihan ini akan bernilai 0';
    });
    editor.addEventListener('drop', (e) =&gt; e.preventDefault());

    body.appendChild(editor);

    const meta = document.createElement('div');
    meta.className = 'editor-meta';
    meta.innerHTML = '&lt;span class="charcount"&gt;0 karakter&lt;/span&gt;&lt;span class="flag"&gt;&lt;/span&gt;';
    body.appendChild(meta);

    editor.addEventListener('input', () =&gt; {
      const len = editor.innerText.trim().length;
      meta.querySelector('.charcount').textContent = len + ' karakter';
    });

    card.appendChild(body);
    container.appendChild(card);
  });

  // Toolbar
  document.getElementById('toolbar').addEventListener('mousedown', (e) =&gt; {
    if (e.target.tagName === 'BUTTON') e.preventDefault(); // keep selection in editor
  });
  document.querySelectorAll('#toolbar button[data-cmd]').forEach(btn =&gt; {
    btn.addEventListener('click', () =&gt; {
      if (!currentEditor) { alert('Klik di dalam kotak jawaban terlebih dahulu.'); return; }
      currentEditor.focus();
      const cmd = btn.dataset.cmd;
      const val = btn.dataset.val || null;
      document.execCommand(cmd, false, val);
    });
  });
  document.getElementById('fontSizeSelect').addEventListener('change', (e) =&gt; {
    if (!currentEditor) return;
    currentEditor.focus();
    document.execCommand('fontSize', false, e.target.value);
  });
  document.getElementById('fontFamilySelect').addEventListener('change', (e) =&gt; {
    if (!currentEditor) return;
    currentEditor.focus();
    document.execCommand('fontName', false, e.target.value);
  });

  function normWords(text){
    return Array.from(new Set(
      text.toLowerCase().replace(/[^a-z0-9\s]/gi, ' ').split(/\s+/).filter(w =&gt; w.length &gt;= 3)
    ));
  }

  function scoreLatihan(idx){
    const item = LATIHAN[idx];
    const editor = document.querySelectorAll('.editor-box')[idx];
    const typed = editor.innerText.trim();

    if (pasteFlags[idx]) return 0;
    if (typed.length === 0) return 0;

    if (item.type === 'open') {
      const min = item.minChars || 15;
      return Math.round(Math.min(100, (typed.length / min) * 100));
    }

    const ref = item.reference;
    const lengthRatio = Math.min(1, typed.length / (0.5 * ref.length));
    const refWords = normWords(ref);
    const typedLower = typed.toLowerCase();
    let matched = 0;
    refWords.forEach(w =&gt; { if (typedLower.indexOf(w) !== -1) matched++; });
    const overlapRatio = refWords.length ? (matched / refWords.length) : 1;
    return Math.round(100 * (0.4 * lengthRatio + 0.6 * overlapRatio));
  }

  // ============================================================
  // BAGIAN 1: HITUNG SKOR LATIHAN MENGETIK (1-19)
  // ============================================================
  let latihanScore = null;

  document.getElementById('btnHitungLatihan').addEventListener('click', () =&gt; {
    const noAbsen = document.getElementById('noAbsen').value.trim();
    const nama = document.getElementById('nama').value.trim();
    const kelas = document.getElementById('kelas').value.trim();
    const msg = document.getElementById('latihanMsg');

    if (!noAbsen || !nama || !kelas) {
      msg.textContent = 'Lengkapi No. Absen, Nama, dan Kelas terlebih dahulu.';
      return;
    }

    let total = 0;
    let pasteCount = 0;
    for (let i = 0; i &lt; LATIHAN.length; i++) {
      total += scoreLatihan(i);
      if (pasteFlags[i]) pasteCount++;
    }
    latihanScore = Math.round(total / LATIHAN.length);

    msg.textContent = '';
    document.getElementById('latihanScoreValue').textContent = latihanScore;
    let detail = 'Skor dihitung dari kemiripan &amp; kelengkapan jawaban pada ' + LATIHAN.length + ' latihan (kontribusi 50% dari nilai akhir).';
    if (pasteCount &gt; 0) {
      detail = '[PERINGATAN] Terdeteksi ' + pasteCount + ' latihan dengan percobaan tempel (dinilai 0). ' + detail;
    }
    document.getElementById('latihanResultDetail').textContent = detail;
    document.getElementById('latihanResultPanel').style.display = 'block';

    // Buka bagian evaluasi setelah skor latihan dihitung
    const evalSection = document.getElementById('evaluasi');
    evalSection.style.display = 'block';
    evalSection.scrollIntoView({ behavior: 'smooth', block: 'start' });
  });

  // ============================================================
  // BAGIAN 2: EVALUASI DOKUMEN MASTER (drag&amp;drop + ketik cepat)
  // ============================================================
  const GAS_ENDPOINT2 = GAS_ENDPOINT; // reuse
  const KKM = 75;
  const MAX_ATTEMPTS = 3;
  const EVAL_DRAG_COUNT = 6;
  const EVAL_TYPE_COUNT = 6;

  const dragDropQuestions = [
    { id: "dd1", func: "Fitur untuk membuat daftar pustaka otomatis berdasarkan kutipan.", ans: "References / Bibliography" },
    { id: "dd2", func: "Gaya teks bawaan untuk menentukan judul utama bab dokumen.", ans: "Heading 1" },
    { id: "dd3", func: "Mengirim satu format surat/sertifikat ke banyak penerima otomatis.", ans: "Mail Merge" },
    { id: "dd4", func: "Membuat struktur urutan bab beserta nomor halamannya secara otomatis.", ans: "Table of Contents" },
    { id: "dd5", func: "Memaksa teks berpindah ke halaman baru tanpa menekan enter berkali-kali.", ans: "Page Break" },
    { id: "dd6", func: "Menambahkan keterangan teks kecil tepat di bawah gambar atau tabel.", ans: "Caption" },
    { id: "dd7", func: "Memberikan penjelasan rujukan yang diletakkan di bagian paling bawah halaman.", ans: "Footnote" },
    { id: "dd8", func: "Area berulang di bagian atas setiap lembar halaman dokumen.", ans: "Header" },
    { id: "dd9", func: "Teks atau gambar samar (transparan) di latar belakang halaman.", ans: "Watermark" },
    { id: "dd10", func: "Mengatur orientasi kertas agar melebar (mendatar).", ans: "Landscape" },
    { id: "dd11", func: "Mengatur batas jarak kosong di tepi halaman untuk dicetak.", ans: "Margins" },
    { id: "dd12", func: "Membagi paragraf menjadi beberapa lajur seperti koran.", ans: "Columns" },
    { id: "dd13", func: "Menggabungkan dua sel atau lebih di dalam tabel menjadi satu sel utuh.", ans: "Merge Cells" },
    { id: "dd14", func: "Fitur melacak setiap perubahan, penambahan, penghapusan teks oleh editor.", ans: "Track Changes" },
    { id: "dd15", func: "Menyalin format gaya huruf dari satu teks dan menerapkannya ke teks lain.", ans: "Format Painter" }
  ];

  const typingQuestions = [
    { q: "Ketik nama tab menu untuk mengatur 'Margins' dan ukuran kertas.", a: ["Page Layout", "Layout"] },
    { q: "Fitur 'Heading' biasanya berada di tab menu utama, ketik nama tab-nya.", a: ["Home"] },
    { q: "Ketik nama fitur untuk menyisipkan penomoran halaman otomatis.", a: ["Page Number", "Page Numbers"] },
    { q: "Tombol pintas keyboard (Shortcut) untuk menebalkan teks.", a: ["Ctrl+B", "Ctrl + B", "Control+B"] },
    { q: "Tombol pintas keyboard (Shortcut) untuk memiringkan teks.", a: ["Ctrl+I", "Ctrl + I", "Control+I"] },
    { q: "Tombol pintas keyboard (Shortcut) untuk memberi garis bawah teks.", a: ["Ctrl+U", "Ctrl + U", "Control+U"] },
    { q: "Tombol shortcut untuk membuat paragraf menjadi rata tengah.", a: ["Ctrl+E", "Ctrl + E", "Control+E"] },
    { q: "Tombol shortcut untuk membuat paragraf menjadi rata kiri dan kanan (justify).", a: ["Ctrl+J", "Ctrl + J", "Control+J"] },
    { q: "Ketik nama fitur untuk membatalkan perintah terakhir yang kamu lakukan.", a: ["Undo"] },
    { q: "Ketik nama menu untuk mengubah warna latar belakang keseluruhan halaman.", a: ["Page Color"] },
    { q: "Tombol pintas keyboard (Shortcut) untuk menyimpan dokumen secara cepat.", a: ["Ctrl+S", "Ctrl + S", "Control+S"] },
    { q: "Tombol pintas keyboard (Shortcut) untuk mencetak (print) dokumen.", a: ["Ctrl+P", "Ctrl + P", "Control+P"] },
    { q: "Tombol pintas keyboard (Shortcut) untuk menyalin (copy) teks.", a: ["Ctrl+C", "Ctrl + C", "Control+C"] },
    { q: "Tombol pintas keyboard (Shortcut) untuk menempelkan (paste) teks.", a: ["Ctrl+V", "Ctrl + V", "Control+V"] },
    { q: "Format file ekstensi standar penyimpanan Microsoft Word versi modern (setelah 2007).", a: [".docx", "docx"] },
    { q: "Format dokumen populer yang bentuknya tidak mudah berubah saat dibuka di beda perangkat.", a: [".pdf", "pdf"] },
    { q: "Ketik nama fitur untuk membuat tulisan/teks berukuran besar dan artistik.", a: ["WordArt", "Word Art"] },
    { q: "Fitur pembuat surat massal bernama...", a: ["Mail Merge"] },
    { q: "Membuat huruf pertama paragraf menjadi besar dan memakan beberapa baris disebut...", a: ["Drop Cap"] },
    { q: "Fitur yang mengoreksi ejaan/tata bahasa yang salah dengan garis bawah merah/biru.", a: ["Spelling &amp; Grammar", "Spelling", "Grammar"] }
  ];

  function shuffleArray(array){
    const a = array.slice();
    for (let i = a.length - 1; i &gt; 0; i--) {
      const j = Math.floor(Math.random() * (i + 1));
      [a[i], a[j]] = [a[j], a[i]];
    }
    return a;
  }

  let evalAttemptScores = [];
  let evalAttemptDetails = [];
  let evalAttemptQuestionLogs = [];
  let currentAttemptDragLog = [];
  let currentAttemptTypeLog = [];
  let evalFinalAttemptIndex = null;
  let evalFinalScore = null;
  let combinedFinalScore = null;
  let selectedChip = null;
  let dragCorrect = 0, dragAnswered = 0;
  let typeCorrect = 0, typeAnswered = 0, typeIndex = 0, currentTypeSet = [];

  function renderAttemptStrip(){
    const strip = document.getElementById('attemptStrip');
    strip.innerHTML = '';
    for (let i = 0; i &lt; MAX_ATTEMPTS; i++) {
      const pill = document.createElement('div');
      pill.className = 'attempt-pill';
      if (i &lt; evalAttemptScores.length) {
        const s = evalAttemptScores[i];
        pill.classList.add('done', s &gt;= KKM ? 'pass' : 'fail');
        pill.textContent = 'Percobaan ' + (i+1) + ': ' + s;
      } else if (i === evalAttemptScores.length) {
        pill.classList.add('current');
        pill.textContent = 'Percobaan ' + (i+1) + ': belum dimulai';
      } else {
        pill.textContent = 'Percobaan ' + (i+1) + ': -';
      }
      strip.appendChild(pill);
    }
  }
  renderAttemptStrip();

  document.getElementById('btnMulaiEvaluasi').addEventListener('click', startEvalAttempt);
  document.getElementById('btnCobaLagi').addEventListener('click', () =&gt; {
    document.getElementById('finalResultPanel').style.display = 'none';
    startEvalAttempt();
  });

  function startEvalAttempt(){
    dragCorrect = 0; dragAnswered = 0;
    typeCorrect = 0; typeAnswered = 0; typeIndex = 0;
    currentAttemptDragLog = [];
    currentAttemptTypeLog = [];
    document.getElementById('finalResultPanel').style.display = 'none';
    renderDragBatch();
  }

  function renderDragBatch(){
    const panel = document.getElementById('gamePanel');
    const pool = shuffleArray(dragDropQuestions).slice(0, EVAL_DRAG_COUNT);
    selectedChip = null;
    panel.innerHTML =
      '&lt;div class="game-subtitle"&gt;Bagian A - Cocokkan Fitur&lt;/div&gt;' +
      '&lt;div class="game-instruction"&gt;Cara main: &lt;strong&gt;1)&lt;/strong&gt; Ketuk salah satu jawaban di kotak biru di bawah untuk memilihnya, &lt;strong&gt;2)&lt;/strong&gt; lalu ketuk kotak soal yang sesuai untuk menempatkannya. Bisa dikerjakan dengan mouse maupun layar sentuh (HP/tablet).&lt;/div&gt;' +
      '&lt;div class="game-progress" id="dragProgress"&gt;0 / ' + EVAL_DRAG_COUNT + ' soal dijawab&lt;/div&gt;' +
      '&lt;div class="drop-grid" id="dropGrid"&gt;&lt;/div&gt;' +
      '&lt;div class="drag-pool" id="dragPool"&gt;&lt;/div&gt;';

    const dropGrid = document.getElementById('dropGrid');
    const dragPool = document.getElementById('dragPool');

    pool.forEach(q =&gt; {
      const zone = document.createElement('div');
      zone.className = 'droppable';
      zone.dataset.expected = q.id;
      zone.innerHTML =
        '&lt;div class="func-text"&gt;' + q.func + '&lt;/div&gt;' +
        '&lt;div class="drop-target"&gt;&lt;span class="placeholder-text"&gt;Ketuk di sini setelah memilih jawaban&lt;/span&gt;&lt;/div&gt;';
      dropGrid.appendChild(zone);

      zone.addEventListener('click', () =&gt; {
        if (zone.classList.contains('filled') || zone.classList.contains('wrong')) return; // sudah dikunci
        if (!selectedChip) return; // belum pilih jawaban
        handleDragDrop(zone, selectedChip, q);
      });
    });

    const shuffledAnswers = shuffleArray(pool);
    shuffledAnswers.forEach(q =&gt; {
      const chip = document.createElement('div');
      chip.className = 'draggable-chip';
      chip.dataset.id = q.id;
      chip.textContent = q.ans;
      chip.addEventListener('click', () =&gt; {
        if (chip.classList.contains('used')) return;
        document.querySelectorAll('.draggable-chip').forEach(c =&gt; c.classList.remove('selected'));
        if (selectedChip === chip) { selectedChip = null; return; } // ketuk lagi = batal pilih
        selectedChip = chip;
        chip.classList.add('selected');
      });
      dragPool.appendChild(chip);
    });
  }

  function handleDragDrop(zone, chip, question){
    const target = zone.querySelector('.drop-target');
    const isCorrect = chip.dataset.id === question.id;
    dragAnswered++;

    currentAttemptDragLog.push({ func: question.func, correctAns: question.ans, userAns: chip.textContent.trim(), isCorrect: isCorrect });

    if (isCorrect) {
      dragCorrect++;
      zone.classList.add('filled');
      target.innerHTML = '&lt;span style="font-family:\'IBM Plex Mono\',monospace; font-size:0.8rem; color:#177A46; font-weight:700;"&gt;[BENAR] ' + question.ans + '&lt;/span&gt;';
      chip.classList.add('used');
    } else {
      // Salah: kunci soal ini (tidak dapat nilai), tetap lanjut - tidak ada pengulangan pada soal yang sama.
      // Chip yang salah TIDAK dihapus dari pool karena mungkin cocok untuk zona lain yang masih terbuka.
      zone.classList.add('wrong');
      target.innerHTML = '&lt;span class="correct-reveal"&gt;[SALAH] Jawaban benar: ' + question.ans + '&lt;/span&gt;';
    }

    chip.classList.remove('selected');
    selectedChip = null;

    document.getElementById('dragProgress').textContent = dragAnswered + ' / ' + EVAL_DRAG_COUNT + ' soal dijawab';

    if (dragAnswered &gt;= EVAL_DRAG_COUNT) {
      setTimeout(renderTypeBatch, 500);
    }
  }

  function renderTypeBatch(){
    currentTypeSet = shuffleArray(typingQuestions).slice(0, EVAL_TYPE_COUNT);
    typeIndex = 0;
    renderTypeQuestion();
  }

  function renderTypeQuestion(){
    const panel = document.getElementById('gamePanel');
    if (typeIndex &gt;= currentTypeSet.length) {
      finishEvalAttempt();
      return;
    }
    const q = currentTypeSet[typeIndex];
    panel.innerHTML =
      '&lt;div class="game-subtitle"&gt;Bagian B - Ketik Cepat&lt;/div&gt;' +
      '&lt;div class="game-progress"&gt;Soal ' + (typeIndex+1) + ' / ' + EVAL_TYPE_COUNT + '&lt;/div&gt;' +
      '&lt;div class="type-box"&gt;' +
        '&lt;div class="type-question-text"&gt;' + q.q + '&lt;/div&gt;' +
        '&lt;form id="typeForm"&gt;&lt;input type="text" id="typeInput" class="type-input" autocomplete="off" placeholder="Ketik jawabanmu..." required&gt;' +
        '&lt;div class="type-feedback" id="typeFeedback"&gt;&lt;/div&gt;&lt;/form&gt;' +
      '&lt;/div&gt;';

    const input = document.getElementById('typeInput');
    setTimeout(() =&gt; input.focus(), 50);

    document.getElementById('typeForm').addEventListener('submit', (e) =&gt; {
      e.preventDefault();
      const userAns = input.value.trim().toLowerCase().replace(/\s+/g, ' ');
      const isCorrect = q.a.some(ans =&gt; ans.toLowerCase().replace(/\s+/g, ' ') === userAns);
      typeAnswered++;
      const feedback = document.getElementById('typeFeedback');

      currentAttemptTypeLog.push({ q: q.q, correctAns: q.a[0], userAns: input.value.trim(), isCorrect: isCorrect });

      if (isCorrect) {
        typeCorrect++;
        input.classList.add('correct');
        feedback.className = 'type-feedback ok';
        feedback.textContent = 'Benar! [BENAR]';
      } else {
        input.classList.add('wrong');
        feedback.className = 'type-feedback no';
        feedback.textContent = 'Kurang tepat. Jawaban: ' + q.a[0];
      }
      input.disabled = true;

      // Salah atau benar, tetap lanjut ke soal berikutnya  -  tidak ada pengulangan.
      setTimeout(() =&gt; { typeIndex++; renderTypeQuestion(); }, 1100);
    });
  }

  function finishEvalAttempt(){
    const attemptScore = Math.round(((dragCorrect + typeCorrect) / (EVAL_DRAG_COUNT + EVAL_TYPE_COUNT)) * 100);
    evalAttemptScores.push(attemptScore);
    evalAttemptDetails.push({ drag: dragCorrect, type: typeCorrect });
    evalAttemptQuestionLogs.push({ drag: currentAttemptDragLog.slice(), type: currentAttemptTypeLog.slice() });
    renderAttemptStrip();

    document.getElementById('gamePanel').innerHTML =
      '&lt;p style="text-align:center; color:#33414F; font-size:0.95rem;"&gt;Percobaan ke-' + evalAttemptScores.length + ' selesai. Skor: &lt;strong&gt;' + attemptScore + '&lt;/strong&gt; (KKM = ' + KKM + ')&lt;/p&gt;';

    const finalPanel = document.getElementById('finalResultPanel');
    const label = document.getElementById('finalResultLabel');
    const scoreEl = document.getElementById('finalScoreValue');
    const detailEl = document.getElementById('finalResultDetail');
    const btnCoba = document.getElementById('btnCobaLagi');

    if (attemptScore &gt;= KKM) {
      evalFinalScore = attemptScore;
      evalFinalAttemptIndex = evalAttemptScores.length - 1;
      label.textContent = 'Nilai Evaluasi (Tercapai KKM)';
      scoreEl.textContent = evalFinalScore;
      detailEl.textContent = 'Selamat, kamu mencapai KKM pada percobaan ke-' + evalAttemptScores.length + '. Nilai evaluasi ini digabung 50:50 dengan skor Latihan Mengetik.';
      btnCoba.style.display = 'none';
      finalPanel.style.display = 'block';
      finalizeAndSubmit();
    } else if (evalAttemptScores.length &lt; MAX_ATTEMPTS) {
      label.textContent = 'Belum Mencapai KKM';
      scoreEl.textContent = attemptScore;
      detailEl.textContent = 'Skor percobaan ke-' + evalAttemptScores.length + ' adalah ' + attemptScore + ', belum mencapai KKM (' + KKM + '). Sisa kesempatan: ' + (MAX_ATTEMPTS - evalAttemptScores.length) + ' kali.';
      btnCoba.style.display = 'inline-block';
      finalPanel.style.display = 'block';
    } else {
      evalFinalScore = Math.max(...evalAttemptScores);
      evalFinalAttemptIndex = evalAttemptScores.indexOf(evalFinalScore);
      label.textContent = 'Nilai Evaluasi (Nilai Tertinggi dari 3 Percobaan)';
      scoreEl.textContent = evalFinalScore;
      detailEl.textContent = 'Percobaan sudah 3 kali dan belum mencapai KKM. Nilai tertinggi (' + evalFinalScore + ') dari 3 percobaan akan digunakan dan digabung 50:50 dengan skor Latihan Mengetik.';
      btnCoba.style.display = 'none';
      finalPanel.style.display = 'block';
      finalizeAndSubmit();
    }
  }

  function finalizeAndSubmit(){
    if (latihanScore === null) {
      document.getElementById('finalResultDetail').textContent += ' (Hitung dulu Skor Latihan Mengetik di Bagian 1 sebelum nilai akhir bisa dikirim.)';
      return;
    }
    combinedFinalScore = Math.round((latihanScore * 0.5) + (evalFinalScore * 0.5));
    document.getElementById('finalResultLabel').textContent = 'Nilai Akhir Tugas Praktik (Terkirim ke Guru)';
    document.getElementById('finalScoreValue').textContent = combinedFinalScore;
    document.getElementById('finalResultDetail').textContent =
      'Nilai akhir = 50% Skor Latihan Mengetik (' + latihanScore + ') + 50% Nilai Evaluasi (' + evalFinalScore + ') = ' + combinedFinalScore + '. Salin nilai ini ke buku catatan kalian pada kolom "Nilai Evaluasi". Mengirim ke guru...';

    const noAbsen = document.getElementById('noAbsen').value.trim();
    const nama = document.getElementById('nama').value.trim();
    const kelas = document.getElementById('kelas').value.trim();

    document.getElementById('btnUnduhPDF').style.display = 'inline-block';
    document.getElementById('pdfHint').style.display = 'block';

    fetch(GAS_ENDPOINT2, {
      method: 'POST',
      mode: 'no-cors',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ noAbsen: noAbsen, nama: nama, kelas: kelas, skor: combinedFinalScore, judulMateri: JUDUL_MATERI })
    }).then(() =&gt; {
      document.getElementById('finalResultDetail').textContent =
        'Nilai akhir = 50% Skor Latihan Mengetik (' + latihanScore + ') + 50% Nilai Evaluasi (' + evalFinalScore + ') = ' + combinedFinalScore + '. Nilai sudah terkirim ke guru. Unduh &amp; cetak bukti mengerjakan di bawah ini, lalu jangan lupa salin ke buku catatan kalian.';
    }).catch(() =&gt; {
      document.getElementById('finalResultDetail').textContent =
        'Nilai akhir = ' + combinedFinalScore + ', tetapi gagal terkirim otomatis. Unduh &amp; cetak bukti mengerjakan di bawah ini sebagai bukti fisik, tunjukkan ke guru, dan tetap catat di buku catatan kalian.';
    });
  }

  // ============================================================
  // BUKTI MENGERJAKAN (PDF, ukuran F4) - dibuat LANGSUNG dengan jsPDF
  // (teks asli/vektor, bukan screenshot atau dialog print browser,
  // sehingga hasilnya konsisten di HP maupun laptop dan tidak kosong)
  // ============================================================
  function downloadBuktiPDF(){
    if (combinedFinalScore === null) {
      alert('Selesaikan dulu Bagian 1 (Latihan Mengetik) dan Bagian 2 (Evaluasi Dokumen Master) sampai Nilai Akhir Tugas Praktik muncul, baru bukti PDF bisa diunduh.');
      return;
    }
    if (!window.jspdf) {
      alert('Pustaka pembuat PDF gagal dimuat (kemungkinan koneksi internet bermasalah). Coba muat ulang halaman lalu unduh lagi.');
      return;
    }

    const noAbsen = document.getElementById('noAbsen').value.trim();
    const nama = document.getElementById('nama').value.trim();
    const kelas = document.getElementById('kelas').value.trim();
    const now = new Date();
    const tanggalCetak = now.toLocaleDateString('id-ID', { day:'numeric', month:'long', year:'numeric' }) +
      ', ' + now.toLocaleTimeString('id-ID', { hour:'2-digit', minute:'2-digit' });

    const { jsPDF } = window.jspdf;
    const doc = new jsPDF({ unit: 'mm', format: [215, 330] }); // ukuran kertas F4
    const pageW = 215, pageH = 330;
    const marginX = 16, marginTop = 16, marginBottom = 16;
    const contentW = pageW - marginX * 2;
    let y = marginTop;

    function ensureSpace(h){
      if (y + h &gt; pageH - marginBottom) { doc.addPage([pageW, pageH]); y = marginTop; }
    }
    function text(str, opts){
      opts = opts || {};
      const size = opts.size || 10;
      const style = opts.style || 'normal';
      const align = opts.align || 'left';
      const gapAfter = opts.gap !== undefined ? opts.gap : 2;
      doc.setFont('helvetica', style);
      doc.setFontSize(size);
      const x = align === 'center' ? pageW / 2 : marginX;
      const lines = doc.splitTextToSize(String(str), contentW);
      lines.forEach(ln =&gt; {
        ensureSpace(size * 0.5);
        doc.text(ln, x, y, { align: align });
        y += size * 0.45;
      });
      y += gapAfter;
    }
    function divider(){
      ensureSpace(5);
      doc.setDrawColor(60);
      doc.setLineWidth(0.3);
      doc.line(marginX, y, pageW - marginX, y);
      y += 5;
    }

    // ---- KOP ----
    text('BUKTI MENGERJAKAN TUGAS PRAKTIK', { size:16, style:'bold', align:'center', gap:2 });
    text(JUDUL_MATERI, { size:11, align:'center', gap:1 });
    text('Informatika - Fase E - Kelas X SMK', { size:9, align:'center', gap:4 });
    divider();

    // ---- IDENTITAS ----
    text('No. Absen : ' + (noAbsen || '-'), { size:10, gap:1 });
    text('Nama      : ' + (nama || '-'), { size:10, gap:1 });
    text('Kelas     : ' + (kelas || '-'), { size:10, gap:1 });
    text('Dicetak   : ' + tanggalCetak, { size:10, gap:4 });
    divider();

    // ---- RINGKASAN NILAI ----
    text('RINGKASAN NILAI', { size:12, style:'bold', gap:3 });
    text('1. Latihan Mengetik (1-' + LATIHAN.length + ')  -  Bobot 50%  -  Skor: ' + (latihanScore !== null ? latihanScore : '-'), { size:10, gap:1 });
    text('2. Evaluasi Dokumen Master (percobaan ke-' + (evalFinalAttemptIndex !== null ? (evalFinalAttemptIndex + 1) : '-') + ' dari ' + evalAttemptScores.length + ', KKM=' + KKM + ')  -  Bobot 50%  -  Skor: ' + (evalFinalScore !== null ? evalFinalScore : '-'), { size:10, gap:1 });
    if (evalAttemptScores.length) {
      text('   Rincian tiap percobaan: ' + evalAttemptScores.map((s,i) =&gt; 'Percobaan ' + (i+1) + ' = ' + s).join('   |   '), { size:9, gap:2 });
    }
    text('NILAI AKHIR TUGAS PRAKTIK : ' + combinedFinalScore, { size:14, style:'bold', gap:4 });
    divider();

    // ---- RINCIAN JAWABAN EVALUASI (BENAR &amp; SALAH) ----
    if (evalFinalAttemptIndex !== null &amp;&amp; evalAttemptQuestionLogs[evalFinalAttemptIndex]) {
      const logDetail = evalAttemptQuestionLogs[evalFinalAttemptIndex];
      text('RINCIAN JAWABAN EVALUASI (Percobaan ke-' + (evalFinalAttemptIndex + 1) + ')', { size:12, style:'bold', gap:3 });

      text('Bagian A - Cocokkan Fitur', { size:10, style:'bold', gap:1 });
      logDetail.drag.forEach((r, i) =&gt; {
        ensureSpace(10);
        text((i+1) + '. ' + r.func, { size:9, gap:0.5 });
        text('    Jawaban kamu: ' + r.userAns + '   |   Jawaban benar: ' + r.correctAns + '   |   ' + (r.isCorrect ? 'BENAR' : 'SALAH'), { size:9, style: r.isCorrect ? 'normal' : 'bold', gap:2 });
      });

      text('Bagian B - Ketik Cepat', { size:10, style:'bold', gap:1 });
      logDetail.type.forEach((r, i) =&gt; {
        ensureSpace(10);
        text((i+1) + '. ' + r.q, { size:9, gap:0.5 });
        text('    Jawaban kamu: ' + (r.userAns || '(kosong)') + '   |   Jawaban benar: ' + r.correctAns + '   |   ' + (r.isCorrect ? 'BENAR' : 'SALAH'), { size:9, style: r.isCorrect ? 'normal' : 'bold', gap:2 });
      });
      divider();
    }

    // ---- JAWABAN LATIHAN MENGETIK 1-19 ----
    text('JAWABAN LATIHAN MENGETIK (1-' + LATIHAN.length + ')', { size:12, style:'bold', gap:3 });
    LATIHAN.forEach((item, idx) =&gt; {
      const editor = document.querySelectorAll('.editor-box')[idx];
      const typed = editor ? editor.innerText.trim() : '';
      const s = scoreLatihan(idx);
      ensureSpace(12);
      text('Latihan ' + (idx+1) + ' - ' + item.title + '  (skor: ' + s + ')', { size:10, style:'bold', gap:1 });
      text(typed ? typed : '(belum diisi)', { size:9, gap:3 });
    });

    divider();
    ensureSpace(22);
    text('Tanda tangan siswa,', { size:10, gap:16 });
    text(nama || '(.....................................)', { size:10, gap:6 });
    ensureSpace(22);
    text('Tanda tangan guru mata pelajaran,', { size:10, gap:16 });
    text('(.....................................)', { size:10, gap:2 });

    const namaFile = 'Bukti-Tugas-Praktik-' + (nama ? nama.replace(/[^a-zA-Z0-9]+/g,'_') : 'siswa') + '.pdf';
    doc.save(namaFile);
  }

  document.getElementById('btnUnduhPDF').addEventListener('click', downloadBuktiPDF);
&lt;/script&gt;

&lt;/body&gt;
&lt;/html&gt;

&lt;/body&gt;
&lt;/html&gt;</description><link>http://kitab-investasi.blogspot.com/2026/09/fitur-lanjut-pengolah-kata-untuk.html</link><thr:total>0</thr:total><author>nof_rizal07@yahoo.co.id (abang_cool)</author></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-9000860041661554971.post-5689077165551123896</guid><pubDate>Mon, 07 Sep 2026 05:59:32 +0000</pubDate><atom:updated>2026-09-14T08:22:47.401+07:00</atom:updated><title>Pengenalan Aplikasi Pengolah Kata untuk Administrasi Perkantoran</title><description>&lt;!DOCTYPE html&gt;
&lt;html lang="id"&gt;
&lt;head&gt;
&lt;meta charset="UTF-8"&gt;
&lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&gt;
&lt;title&gt;Informatika X - Pengenalan Aplikasi Pengolah Kata untuk Administrasi Perkantoran&lt;/title&gt;
&lt;link rel="preconnect" href="https://fonts.googleapis.com"&gt;
&lt;link href="https://fonts.googleapis.com/css2?family=Source+Serif+4:opsz,wght@8..60,400;8..60,600;8..60,700&amp;family=Inter:wght@400;500;600;700&amp;display=swap" rel="stylesheet"&gt;
&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"&gt;&lt;/script&gt;
&lt;style&gt;
  :root{
    --ink:#182634; --paper:#f6f3ea; --card:#ffffff; --line:#dcd3bd;
    --teal:#0e6f63; --teal-dark:#0a5249;
    --gold:#b9791d; --gold-dark:#8f5c12;
    --danger:#c1392b; --ok:#1f7a5c;
    --tint:#e2f2ee;
  }
  *{box-sizing:border-box;}
  body{margin:0; background:var(--paper); color:var(--ink); font-family:'Inter', sans-serif; line-height:1.55; padding-bottom:64px;}
  .letterhead{background:linear-gradient(135deg, var(--teal-dark), var(--teal)); padding:30px 24px 22px; text-align:center; color:#fff;}
  .letterhead .eyebrow{font-size:12.5px; letter-spacing:.06em; color:#cdeee7; margin-bottom:8px; font-weight:600;}
  .letterhead h1{font-family:'Source Serif 4', serif; font-weight:700; font-size:clamp(23px,4vw,31px); margin:0 0 8px; max-width:800px; margin-left:auto; margin-right:auto;}
  .letterhead p.sub{margin:0; font-size:14.5px; color:#e2f3ef; max-width:700px; margin-left:auto; margin-right:auto;}
  main{max-width:820px; margin:0 auto; padding:0 24px;}
  section{margin-top:38px;}
  h2.section-title{
    font-family:'Source Serif 4', serif; font-size:21px; font-weight:700; color:var(--ink);
    background:var(--tint); border-left:6px solid var(--gold); padding:10px 14px; border-radius:3px; margin:0 0 16px;
  }
  h3.step-title{font-family:'Source Serif 4', serif; font-size:17px; font-weight:700; color:var(--teal-dark); margin:0 0 10px; display:flex; align-items:center; gap:8px;}
  h3.step-title .num{background:var(--gold); color:#fff; width:25px; height:25px; border-radius:50%; display:inline-flex; align-items:center; justify-content:center; font-size:13px; font-family:'Inter',sans-serif; flex:none;}
  .card{background:var(--card); border:1px solid var(--line); border-radius:6px; padding:22px 24px; margin-bottom:16px; box-shadow:0 1px 2px rgba(24,38,52,.04);}
  .card h3{font-family:'Source Serif 4', serif; font-size:17.5px; margin:0 0 8px; color:var(--teal-dark);}
  .card p, .card li{font-size:15px; color:#2b3746;}
  .card ul, .card ol{padding-left:20px; margin:8px 0;}
  table.std{width:100%; border-collapse:collapse; margin-top:8px; font-size:14.5px;}
  table.std th, table.std td{border:1px solid var(--line); padding:8px 10px; text-align:left;}
  table.std th{background:var(--tint); font-family:'Source Serif 4', serif; color:var(--teal-dark);}
  code.kbd{background:#eef3f1; border:1px solid var(--line); border-radius:3px; padding:1px 6px; font-family:monospace; font-size:13px; color:var(--teal-dark);}
  details{margin-bottom:10px;}
  details summary{cursor:pointer; font-weight:600; padding:6px 0; list-style:none; color:var(--ink);}
  details summary::-webkit-details-marker{display:none;}
  details summary::before{content:"+ "; color:var(--gold); font-weight:700;}
  details[open] summary::before{content:"- ";}

  .resume-card{background:#fbf4e6; border:1px solid #e6d3a0; border-left:6px solid var(--gold); border-radius:6px; padding:20px 24px;}
  .resume-card ul{margin:0; padding-left:20px;}
  .resume-card li{font-size:14.5px; margin-bottom:7px; color:#2b3746;}
  .resume-card b{color:var(--gold-dark);}

  fieldset{border:1px solid var(--line); border-radius:8px; padding:20px 22px; background:var(--card); margin-bottom:18px;}
  legend{font-family:'Source Serif 4', serif; font-weight:700; padding:0 8px; color:var(--teal-dark); font-size:16px;}
  label.field-label{display:block; font-size:13.5px; font-weight:600; margin:12px 0 5px;}
  input[type=text], input[type=number], select, textarea{
    width:100%; padding:9px 10px; font-size:15px; border:1px solid #b7ad93; border-radius:4px;
    font-family:inherit; background:#fdfcf9;
  }
  textarea{min-height:110px; resize:vertical; line-height:1.6;}
  input:focus, select:focus, textarea:focus{outline:2px solid var(--gold); outline-offset:1px;}

  .quiz-item{border-top:1px dashed var(--line); padding-top:16px; margin-top:16px;}
  .quiz-item:first-child{border-top:none; padding-top:0; margin-top:0;}
  .quiz-item p.q{font-weight:600; margin:0 0 10px;}
  .quiz-item .opt{display:flex; align-items:flex-start; gap:9px; padding:7px 9px; border-radius:4px; margin-bottom:5px; cursor:pointer; font-size:14.5px;}
  .quiz-item .opt:hover{background:var(--tint);}
  .quiz-item input[type=radio]{margin-top:3px;}

  .essay-item{border-top:1px dashed var(--line); padding-top:16px; margin-top:16px;}
  .essay-item:first-child{border-top:none; padding-top:0; margin-top:0;}
  .essay-item p.q{font-weight:600; margin:0 0 10px;}
  .essay-note{font-size:12.5px; color:var(--danger); margin-top:6px; font-weight:600;}
  .essay-count{font-size:12.5px; color:#7a8390; margin-top:4px;}

  .game-toolbar{display:flex; justify-content:space-between; align-items:center; margin-bottom:8px; flex-wrap:wrap; gap:8px;}
  .game-toolbar a{font-size:13px; color:var(--gold-dark); text-decoration:none; font-weight:700;}
  .game-toolbar a:hover{text-decoration:underline;}
  .game-wrap{border:2px solid var(--teal); border-radius:8px; overflow:hidden; background:#f0fdf4;}
  .game-wrap iframe{display:block; width:100%; height:720px; border:0;}

  .status-chip{display:inline-flex; align-items:center; gap:6px; font-size:13.5px; font-weight:700; padding:7px 14px; border-radius:20px; background:#f5e8d2; color:var(--gold-dark); margin-top:12px;}
  .status-chip.ok-chip{background:#d9f0e5; color:var(--ok);}
  .status-chip .dot{width:8px; height:8px; border-radius:50%; background:currentColor;}

  button.submit-btn{background:linear-gradient(135deg, var(--teal-dark), var(--teal)); color:#fff; border:none; border-radius:6px; padding:14px 22px; font-size:15.5px; font-weight:700; cursor:pointer; font-family:'Inter', sans-serif; width:100%; margin-top:6px;}
  button.submit-btn:hover{filter:brightness(1.08);}
  button.submit-btn:disabled{background:#b9c0bd; cursor:not-allowed;}

  button.pdf-btn{background:linear-gradient(135deg, var(--gold-dark), var(--gold)); color:#fff; border:none; border-radius:6px; padding:14px 22px; font-size:15.5px; font-weight:700; cursor:pointer; font-family:'Inter', sans-serif; width:100%; margin-top:10px;}
  button.pdf-btn:hover{filter:brightness(1.08);}
  button.pdf-btn:disabled{background:#d8cbb0; cursor:not-allowed;}

  .msg{padding:12px 14px; border-radius:6px; font-size:14.5px; margin-top:14px; display:none;}
  .msg.show{display:block;}
  .msg.ok{background:#d9f0e5; color:var(--ok); border:1px solid #a9dcc3;}
  .msg.err{background:#fbe2db; color:var(--danger); border:1px solid #eeb7a7;}
  .msg.wait{background:#eef0eb; color:#555; border:1px solid var(--line);}

  .stamp{display:inline-block; border:2px solid var(--gold); color:var(--gold-dark); border-radius:6px; padding:6px 12px; font-family:'Source Serif 4', serif; font-weight:700; font-size:13px; transform:rotate(-3deg);}
  .checklist{font-size:13.5px; color:#3d4a58; margin-top:14px; padding:14px 16px; background:var(--tint); border-radius:6px;}
  .checklist div{display:flex; align-items:center; gap:8px; margin-bottom:6px;}
  .checklist .mark{width:16px; height:16px; border-radius:50%; border:2px solid #9aa5a1; display:inline-block; flex:none; position:relative;}
  .checklist .mark.done{background:var(--ok); border-color:var(--ok);}
  .checklist .mark.done::after{content:"v"; color:#fff; font-size:10px; font-weight:700; position:absolute; inset:0; display:flex; align-items:center; justify-content:center;}

  footer{max-width:820px; margin:48px auto 0; padding:0 24px; font-size:12.5px; color:#7a8390; text-align:center;}
&lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;

&lt;div class="letterhead"&gt;
  &lt;div class="eyebrow"&gt;MATA PELAJARAN INFORMATIKA - KELAS X SMK&lt;/div&gt;
  &lt;h1&gt;Pengenalan Aplikasi Pengolah Kata untuk Administrasi Perkantoran&lt;/h1&gt;
  &lt;p class="sub"&gt;Membuat, mengedit, memformat, dan menyimpan dokumen administrasi sesuai standar perkantoran&lt;/p&gt;
&lt;/div&gt;

&lt;main&gt;

  &lt;!-- ================= MATERI ================= --&gt;
  &lt;section id="materi"&gt;
    &lt;h2 class="section-title"&gt;A. Materi Pembelajaran&lt;/h2&gt;

    &lt;div class="card"&gt;
      &lt;h3&gt;1. Apa itu Aplikasi Pengolah Kata?&lt;/h3&gt;
      &lt;p&gt;&lt;b&gt;Aplikasi pengolah kata (word processor)&lt;/b&gt; adalah perangkat lunak yang digunakan untuk membuat, menyunting (mengedit), memformat, menyimpan, dan mencetak dokumen berbasis teks. Dalam dunia administrasi perkantoran, aplikasi ini menjadi alat utama untuk menghasilkan surat, memo, nota dinas, laporan, proposal, undangan, hingga dokumen kontrak.&lt;/p&gt;
      &lt;p&gt;Berbeda dengan mesin tik manual, aplikasi pengolah kata modern memungkinkan pengguna mengedit teks berulang kali tanpa merusak dokumen, menyisipkan gambar dan tabel, memeriksa ejaan otomatis, serta menyimpan dokumen dalam berbagai format digital yang mudah dibagikan.&lt;/p&gt;
      &lt;table class="std"&gt;
        &lt;tr&gt;&lt;th&gt;Aplikasi&lt;/th&gt;&lt;th&gt;Sifat&lt;/th&gt;&lt;th&gt;Karakteristik&lt;/th&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td&gt;Microsoft Word&lt;/td&gt;&lt;td&gt;Berbayar (desktop)&lt;/td&gt;&lt;td&gt;Standar industri, fitur paling lengkap, format asli .docx&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td&gt;Google Docs&lt;/td&gt;&lt;td&gt;Gratis (berbasis web/cloud)&lt;/td&gt;&lt;td&gt;Kolaborasi real-time, otomatis tersimpan di Google Drive&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td&gt;LibreOffice Writer&lt;/td&gt;&lt;td&gt;Gratis &amp; open source&lt;/td&gt;&lt;td&gt;Alternatif Word untuk desktop, kompatibel dengan .docx&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td&gt;WPS Writer&lt;/td&gt;&lt;td&gt;Gratis (versi dasar)&lt;/td&gt;&lt;td&gt;Ringan, tampilan mirip Microsoft Word&lt;/td&gt;&lt;/tr&gt;
      &lt;/table&gt;
    &lt;/div&gt;

    &lt;div class="card"&gt;
      &lt;h3&gt;2. Mengenal Antarmuka (Ribbon/Menu)&lt;/h3&gt;
      &lt;p&gt;Sebelum bekerja, kenali dulu letak perintah pada aplikasi pengolah kata. Microsoft Word menggunakan sistem &lt;b&gt;Ribbon&lt;/b&gt; berisi tab menu, sedangkan Google Docs menggunakan &lt;b&gt;menu bar&lt;/b&gt; klasik, namun fungsinya setara:&lt;/p&gt;
      &lt;table class="std"&gt;
        &lt;tr&gt;&lt;th&gt;Microsoft Word (Ribbon)&lt;/th&gt;&lt;th&gt;Google Docs (Menu)&lt;/th&gt;&lt;th&gt;Fungsi utama&lt;/th&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td&gt;Home&lt;/td&gt;&lt;td&gt;Format&lt;/td&gt;&lt;td&gt;Font, ukuran huruf, warna, perataan teks, bullet/numbering&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td&gt;Insert&lt;/td&gt;&lt;td&gt;Insert&lt;/td&gt;&lt;td&gt;Menyisipkan gambar, tabel, header/footer, nomor halaman, shape&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td&gt;Layout&lt;/td&gt;&lt;td&gt;File &amp;gt; Page setup&lt;/td&gt;&lt;td&gt;Ukuran kertas, orientasi, margin, kolom&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td&gt;References&lt;/td&gt;&lt;td&gt;Insert &amp;gt; Table of contents&lt;/td&gt;&lt;td&gt;Daftar isi, catatan kaki, kutipan&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td&gt;Review&lt;/td&gt;&lt;td&gt;Tools&lt;/td&gt;&lt;td&gt;Spell check, komentar, lacak perubahan (track changes)&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td&gt;View&lt;/td&gt;&lt;td&gt;View&lt;/td&gt;&lt;td&gt;Mode tampilan, zoom, tampilkan penggaris&lt;/td&gt;&lt;/tr&gt;
      &lt;/table&gt;
    &lt;/div&gt;

    &lt;div class="card"&gt;
      &lt;h3&gt;3. Membuat Dokumen Baru&lt;/h3&gt;
      &lt;ol&gt;
        &lt;li&gt;Buka aplikasi pengolah kata, lalu pilih &lt;b&gt;Blank document / Dokumen kosong&lt;/b&gt; atau gunakan template yang tersedia (misalnya template surat resmi).&lt;/li&gt;
        &lt;li&gt;Atur terlebih dahulu ukuran kertas (umumnya &lt;b&gt;A4&lt;/b&gt; untuk dokumen perkantoran di Indonesia) melalui menu &lt;i&gt;Layout &amp;gt; Size&lt;/i&gt;.&lt;/li&gt;
        &lt;li&gt;Atur margin halaman sebelum mulai mengetik agar tata letak dokumen konsisten.&lt;/li&gt;
        &lt;li&gt;Mulai mengetik isi dokumen sesuai kebutuhan (surat, laporan, memo, dsb).&lt;/li&gt;
      &lt;/ol&gt;
    &lt;/div&gt;

    &lt;div class="card"&gt;
      &lt;h3&gt;4. Mengedit Dokumen&lt;/h3&gt;
      &lt;p&gt;Mengedit adalah proses menyunting teks yang sudah ditulis. Beberapa teknik dasar mengedit dokumen:&lt;/p&gt;
      &lt;ul&gt;
        &lt;li&gt;&lt;b&gt;Menyisipkan (Insert)&lt;/b&gt; - menambahkan kata, kalimat, gambar, atau tabel di posisi kursor.&lt;/li&gt;
        &lt;li&gt;&lt;b&gt;Menghapus (Delete/Backspace)&lt;/b&gt; - membuang karakter, kata, atau paragraf yang tidak diperlukan.&lt;/li&gt;
        &lt;li&gt;&lt;b&gt;Menyalin &amp; menempel (Copy-Paste)&lt;/b&gt; - menggandakan teks/objek ke bagian lain dokumen.&lt;/li&gt;
        &lt;li&gt;&lt;b&gt;Memindahkan (Cut-Paste)&lt;/b&gt; - memindahkan teks/objek dari satu tempat ke tempat lain.&lt;/li&gt;
        &lt;li&gt;&lt;b&gt;Mencari &amp; mengganti (Find &amp; Replace)&lt;/b&gt; - menemukan kata tertentu dan menggantinya secara otomatis di seluruh dokumen, sangat berguna saat merevisi nomor surat atau nama instansi yang berulang.&lt;/li&gt;
        &lt;li&gt;&lt;b&gt;Undo &amp; Redo&lt;/b&gt; - membatalkan atau mengulang perubahan terakhir.&lt;/li&gt;
      &lt;/ul&gt;
      &lt;p&gt;Shortcut keyboard yang wajib dikuasai staf administrasi:&lt;/p&gt;
      &lt;p&gt;
        &lt;code class="kbd"&gt;Ctrl+C&lt;/code&gt; salin ,
        &lt;code class="kbd"&gt;Ctrl+X&lt;/code&gt; potong ,
        &lt;code class="kbd"&gt;Ctrl+V&lt;/code&gt; tempel ,
        &lt;code class="kbd"&gt;Ctrl+Z&lt;/code&gt; batalkan ,
        &lt;code class="kbd"&gt;Ctrl+Y&lt;/code&gt; ulangi ,
        &lt;code class="kbd"&gt;Ctrl+S&lt;/code&gt; simpan ,
        &lt;code class="kbd"&gt;Ctrl+P&lt;/code&gt; cetak ,
        &lt;code class="kbd"&gt;Ctrl+F&lt;/code&gt; cari
      &lt;/p&gt;
    &lt;/div&gt;

    &lt;div class="card"&gt;
      &lt;h3&gt;5. Memformat Dokumen&lt;/h3&gt;
      &lt;p&gt;Format dokumen menentukan tampilan visual sekaligus keterbacaan dan profesionalitas dokumen resmi.&lt;/p&gt;
      &lt;details&gt;
        &lt;summary&gt;Jenis dan ukuran huruf (font)&lt;/summary&gt;
        &lt;p&gt;Dokumen resmi perkantoran di Indonesia umumnya menggunakan huruf &lt;b&gt;Times New Roman ukuran 12pt&lt;/b&gt; atau &lt;b&gt;Arial ukuran 11pt&lt;/b&gt;, karena mudah dibaca dan bersifat formal. Hindari font dekoratif (misalnya Comic Sans) untuk dokumen resmi.&lt;/p&gt;
      &lt;/details&gt;
      &lt;details&gt;
        &lt;summary&gt;Perataan teks (alignment)&lt;/summary&gt;
        &lt;ul&gt;
          &lt;li&gt;&lt;b&gt;Rata kiri (Align Left)&lt;/b&gt; - umum untuk draf/kerja.&lt;/li&gt;
          &lt;li&gt;&lt;b&gt;Rata tengah (Center)&lt;/b&gt; - untuk judul dokumen.&lt;/li&gt;
          &lt;li&gt;&lt;b&gt;Rata kanan (Align Right)&lt;/b&gt; - untuk tempat &amp; tanggal surat.&lt;/li&gt;
          &lt;li&gt;&lt;b&gt;Rata kiri-kanan (Justify)&lt;/b&gt; - standar untuk isi/paragraf surat resmi agar tepi kiri dan kanan sama rata.&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/details&gt;
      &lt;details&gt;
        &lt;summary&gt;Spasi baris &amp; margin&lt;/summary&gt;
        &lt;p&gt;Spasi baris dokumen resmi umumnya &lt;b&gt;1,15 sampai 1,5&lt;/b&gt;. Margin standar (Normal) yang lazim digunakan adalah &lt;b&gt;2,54 cm&lt;/b&gt; di seluruh sisi, meskipun instansi tertentu memakai margin khusus (misal 4 cm kiri &amp; atas, 3 cm kanan &amp; bawah) sesuai pedoman tata naskah dinas.&lt;/p&gt;
      &lt;/details&gt;
      &lt;details&gt;
        &lt;summary&gt;Elemen pendukung lain&lt;/summary&gt;
        &lt;ul&gt;
          &lt;li&gt;&lt;b&gt;Bullet &amp; Numbering&lt;/b&gt; - merapikan daftar poin atau langkah bernomor.&lt;/li&gt;
          &lt;li&gt;&lt;b&gt;Tabel&lt;/b&gt; - menyajikan data terstruktur (misalnya daftar hadir, rincian anggaran).&lt;/li&gt;
          &lt;li&gt;&lt;b&gt;Header/Footer &amp; Page Number&lt;/b&gt; - nomor halaman dan identitas dokumen berulang di tiap halaman.&lt;/li&gt;
          &lt;li&gt;&lt;b&gt;Watermark, Page Break, Columns&lt;/b&gt; - pengaturan tata letak lanjutan untuk dokumen kompleks (kontrak, buletin, laporan panjang).&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/details&gt;
    &lt;/div&gt;

    &lt;div class="card"&gt;
      &lt;h3&gt;6. Standar Dokumen Administrasi Perkantoran&lt;/h3&gt;
      &lt;p&gt;Dokumen resmi (misalnya surat dinas) memiliki struktur baku yang harus dikenali sebelum diketik:&lt;/p&gt;
      &lt;table class="std"&gt;
        &lt;tr&gt;&lt;th&gt;Bagian&lt;/th&gt;&lt;th&gt;Keterangan&lt;/th&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td&gt;Kop surat (letterhead)&lt;/td&gt;&lt;td&gt;Logo, nama instansi, dan alamat di bagian atas dokumen&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td&gt;Nomor, Hal, Lampiran&lt;/td&gt;&lt;td&gt;Kode administrasi dan ringkasan isi surat&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td&gt;Tanggal surat&lt;/td&gt;&lt;td&gt;Ditulis rata kanan, mengikuti tempat penerbitan&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td&gt;Alamat tujuan&lt;/td&gt;&lt;td&gt;Nama dan alamat penerima surat&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td&gt;Salam pembuka &amp; isi&lt;/td&gt;&lt;td&gt;Paragraf pembuka, isi pokok, dan penutup&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td&gt;Tanda tangan &amp; nama jelas&lt;/td&gt;&lt;td&gt;Pengesahan dokumen oleh pejabat berwenang&lt;/td&gt;&lt;/tr&gt;
      &lt;/table&gt;
    &lt;/div&gt;

    &lt;div class="card"&gt;
      &lt;h3&gt;7. Menyimpan Dokumen&lt;/h3&gt;
      &lt;ul&gt;
        &lt;li&gt;&lt;b&gt;.docx&lt;/b&gt; - format standar Microsoft Word, mudah diedit kembali.&lt;/li&gt;
        &lt;li&gt;&lt;b&gt;.pdf&lt;/b&gt; - untuk dokumen final yang tidak boleh diubah, tampilan konsisten di semua perangkat.&lt;/li&gt;
        &lt;li&gt;&lt;b&gt;.odt&lt;/b&gt; - format terbuka (open document), digunakan LibreOffice.&lt;/li&gt;
        &lt;li&gt;&lt;b&gt;.rtf&lt;/b&gt; - format teks kaya yang kompatibel lintas aplikasi lama.&lt;/li&gt;
      &lt;/ul&gt;
      &lt;p&gt;Gunakan shortcut &lt;code class="kbd"&gt;Ctrl+S&lt;/code&gt; secara berkala saat mengetik agar dokumen tidak hilang. Beri &lt;b&gt;nama file yang jelas&lt;/b&gt;, memuat jenis dokumen, nomor/nama, dan tanggal, misalnya &lt;code class="kbd"&gt;Surat_Undangan_Rapat_04Sep2026.docx&lt;/code&gt;, bukan nama acak seperti &lt;code class="kbd"&gt;dokumen1.docx&lt;/code&gt;. Untuk dokumen berbasis Google Docs, penyimpanan berjalan otomatis ke Google Drive setiap ada perubahan.&lt;/p&gt;
    &lt;/div&gt;

    &lt;div class="card"&gt;
      &lt;h3&gt;8. Kolaborasi &amp; Berbagi Dokumen&lt;/h3&gt;
      &lt;p&gt;Aplikasi berbasis cloud seperti Google Docs memungkinkan beberapa staf mengerjakan satu dokumen secara bersamaan (real-time). Pengaturan akses berbagi umumnya terdiri dari:&lt;/p&gt;
      &lt;ul&gt;
        &lt;li&gt;&lt;b&gt;Viewer (Pelihat)&lt;/b&gt; - hanya bisa membaca dokumen.&lt;/li&gt;
        &lt;li&gt;&lt;b&gt;Commenter (Pemberi komentar)&lt;/b&gt; - bisa menambahkan catatan tanpa mengubah isi.&lt;/li&gt;
        &lt;li&gt;&lt;b&gt;Editor&lt;/b&gt; - bisa mengubah langsung isi dokumen.&lt;/li&gt;
      &lt;/ul&gt;
      &lt;p&gt;Fitur &lt;b&gt;Version History / Riwayat Versi&lt;/b&gt; mencatat setiap perubahan sehingga dokumen bisa dikembalikan ke versi sebelumnya jika terjadi kesalahan, sangat penting untuk dokumen administrasi yang dikerjakan bersama tim.&lt;/p&gt;
    &lt;/div&gt;

    &lt;div class="card"&gt;
      &lt;h3&gt;9. Etika dan Keamanan Dokumen Digital&lt;/h3&gt;
      &lt;ul&gt;
        &lt;li&gt;Jangan mengubah atau menghapus dokumen milik orang lain tanpa izin, terutama pada dokumen bersama (shared document).&lt;/li&gt;
        &lt;li&gt;Lindungi dokumen penting/rahasia dengan kata sandi (password protect) sebelum dibagikan.&lt;/li&gt;
        &lt;li&gt;Cantumkan sumber jika mengutip isi dari dokumen atau publikasi lain (hindari plagiarisme).&lt;/li&gt;
        &lt;li&gt;Selalu buat cadangan (backup) dokumen penting di lebih dari satu tempat penyimpanan.&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/div&gt;
  &lt;/section&gt;

  &lt;!-- ================= RESUME ================= --&gt;
  &lt;section id="resume"&gt;
    &lt;h2 class="section-title"&gt;B. Resume Materi&lt;/h2&gt;
    &lt;div class="resume-card"&gt;
      &lt;ul&gt;
        &lt;li&gt;&lt;b&gt;Definisi:&lt;/b&gt; aplikasi pengolah kata (word processor) untuk membuat, mengedit, memformat, menyimpan, dan mencetak dokumen teks. Contoh: Microsoft Word, Google Docs, LibreOffice Writer, WPS Writer.&lt;/li&gt;
        &lt;li&gt;&lt;b&gt;Antarmuka:&lt;/b&gt; perintah terkumpul dalam Ribbon (Word: Home, Insert, Layout, References, Review, View) atau menu bar (Google Docs: Format, Insert, File, Tools, View).&lt;/li&gt;
        &lt;li&gt;&lt;b&gt;Membuat dokumen:&lt;/b&gt; mulai dari Blank document, atur ukuran kertas A4, lalu atur margin sebelum mengetik.&lt;/li&gt;
        &lt;li&gt;&lt;b&gt;Mengedit:&lt;/b&gt; insert, delete, copy-paste, cut-paste, find &amp; replace, undo-redo, dipercepat dengan shortcut &lt;code class="kbd"&gt;Ctrl+C/X/V/Z/Y/S/P/F&lt;/code&gt;.&lt;/li&gt;
        &lt;li&gt;&lt;b&gt;Memformat:&lt;/b&gt; font resmi Times New Roman 12pt / Arial 11pt; perataan left/center/right/justify; spasi baris 1,15 sampai 1,5; margin standar 2,54 cm; dilengkapi bullet, numbering, tabel, header/footer.&lt;/li&gt;
        &lt;li&gt;&lt;b&gt;Struktur surat resmi:&lt;/b&gt; kop surat, nomor/hal/lampiran, tanggal, alamat tujuan, salam &amp; isi, tanda tangan.&lt;/li&gt;
        &lt;li&gt;&lt;b&gt;Menyimpan:&lt;/b&gt; .docx (bisa diedit), .pdf (final, tidak diedit), .odt, .rtf, dengan nama file jelas (jenis dokumen + nama/nomor + tanggal).&lt;/li&gt;
        &lt;li&gt;&lt;b&gt;Kolaborasi:&lt;/b&gt; hak akses viewer/commenter/editor, dan version history untuk melacak &amp; mengembalikan perubahan.&lt;/li&gt;
        &lt;li&gt;&lt;b&gt;Etika &amp; keamanan:&lt;/b&gt; hormati dokumen bersama, lindungi dokumen rahasia dengan password, hindari plagiarisme, selalu backup.&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/div&gt;
  &lt;/section&gt;

  &lt;!-- ================= TUGAS PRIBADI (GABUNGAN) ================= --&gt;
  &lt;section id="tugas"&gt;
    &lt;h2 class="section-title"&gt;C. Tugas Pribadi (Dikerjakan Langsung di Web Ini)&lt;/h2&gt;
    &lt;div class="card"&gt;
      &lt;p&gt;Tugas ini terdiri atas empat langkah: identitas, uji keterampilan (game), soal pilihan ganda, dan soal esai. &lt;b&gt;Nilai Evaluasi Akhir bersumber dari 15 soal (10 PG + 5 esai) dengan skor total 100&lt;/b&gt;, sedangkan skor game ditampilkan terpisah sebagai informasi keterampilan. Setelah berhasil dikirim, unduh bukti pengerjaan dalam format PDF ukuran F4, cetak, lalu serahkan ke guru. &lt;span class="stamp"&gt;1x kirim per siswa&lt;/span&gt;&lt;/p&gt;
    &lt;/div&gt;

    &lt;form id="taskForm" novalidate&gt;

      &lt;fieldset&gt;
        &lt;legend&gt;Identitas Siswa&lt;/legend&gt;
        &lt;label class="field-label" for="noAbsen"&gt;No. Absen&lt;/label&gt;
        &lt;input type="number" id="noAbsen" min="1" max="60" placeholder="Contoh: 12" required&gt;
        &lt;label class="field-label" for="nama"&gt;Nama Lengkap&lt;/label&gt;
        &lt;input type="text" id="nama" placeholder="Tulis nama lengkap" required&gt;
        &lt;label class="field-label" for="kelas"&gt;Kelas&lt;/label&gt;
        &lt;select id="kelas" required&gt;
          &lt;option value="" disabled selected&gt;- Pilih kelas -&lt;/option&gt;
          &lt;option value="X TB1"&gt;X TB1&lt;/option&gt;
          &lt;option value="X TB2"&gt;X TB2&lt;/option&gt;
          &lt;option value="X TO1"&gt;X TO1&lt;/option&gt;
          &lt;option value="X TO2"&gt;X TO2&lt;/option&gt;
          &lt;option value="X TJKT1"&gt;X TJKT1&lt;/option&gt;
          &lt;option value="X TJKT2"&gt;X TJKT2&lt;/option&gt;
        &lt;/select&gt;
      &lt;/fieldset&gt;

      &lt;fieldset&gt;
        &lt;h3 class="step-title"&gt;&lt;span class="num"&gt;1&lt;/span&gt; Uji Keterampilan - Game Master Pengolah Kata&lt;/h3&gt;
        &lt;p style="font-size:14.5px; color:#4a5568; margin-top:0;"&gt;Seret (drag) kartu tugas ke ikon fitur pengolah kata yang tepat. Mainkan sampai selesai (50 tantangan). Skor ini bersifat informasi keterampilan dan tidak dihitung ke Nilai Evaluasi Akhir.&lt;/p&gt;
        &lt;div class="game-toolbar"&gt;
          &lt;span&gt;&lt;/span&gt;
          &lt;a href="data:text/html;base64,PCFET0NUWVBFIGh0bWw+CjxodG1sIGxhbmc9ImlkIj4KPGhlYWQ+CiAgICA8bWV0YSBjaGFyc2V0PSJVVEYtOCI+CiAgICA8bWV0YSBuYW1lPSJ2aWV3cG9ydCIgY29udGVudD0id2lkdGg9ZGV2aWNlLXdpZHRoLCBpbml0aWFsLXNjYWxlPTEuMCwgbWF4aW11bS1zY2FsZT0xLjAsIHVzZXItc2NhbGFibGU9bm8iPgogICAgPHRpdGxlPkdhbWUgQWRtaW5pc3RyYXNpOiBNYXN0ZXIgUGVuZ29sYWggS2F0YTwvdGl0bGU+CiAgICA8IS0tIFRhaWx3aW5kIENTUyB1bnR1ayBTdHlsaW5nIENlcGF0IGRhbiBSZXNwb25zaWYgLS0+CiAgICA8c2NyaXB0IHNyYz0iaHR0cHM6Ly9jZG4udGFpbHdpbmRjc3MuY29tIj48L3NjcmlwdD4KICAgIDwhLS0gRm9udEF3ZXNvbWUgdW50dWsgSWtvbiBNZW51IFBlbmdvbGFoIEthdGEgLS0+CiAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Imh0dHBzOi8vY2RuanMuY2xvdWRmbGFyZS5jb20vYWpheC9saWJzL2ZvbnQtYXdlc29tZS82LjQuMC9jc3MvYWxsLm1pbi5jc3MiPgogICAgPCEtLSBHb29nbGUgRm9udHMgKFBvcHBpbnMpIC0tPgogICAgPGxpbmsgaHJlZj0iaHR0cHM6Ly9mb250cy5nb29nbGVhcGlzLmNvbS9jc3MyP2ZhbWlseT1Qb3BwaW5zOndnaHRANDAwOzYwMDs3MDAmZGlzcGxheT1zd2FwIiByZWw9InN0eWxlc2hlZXQiPgogICAgCiAgICA8c3R5bGU+CiAgICAgICAgYm9keSB7CiAgICAgICAgICAgIGZvbnQtZmFtaWx5OiAnUG9wcGlucycsIHNhbnMtc2VyaWY7CiAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6ICNmMGZkZjQ7IC8qIEhpamF1IHNhbmdhdCBtdWRhL3NlZ2FyICovCiAgICAgICAgICAgIHRvdWNoLWFjdGlvbjogcGFuLXk7IC8qIE1lbmNlZ2FoIHB1bGwtdG8tcmVmcmVzaCBkaSBtb2JpbGUgKi8KICAgICAgICAgICAgb3ZlcmZsb3cteDogaGlkZGVuOwogICAgICAgIH0KCiAgICAgICAgLyogQW5pbWFzaSAqLwogICAgICAgIC5ib3VuY2UtaW4gewogICAgICAgICAgICBhbmltYXRpb246IGJvdW5jZUluIDAuNXMgY3ViaWMtYmV6aWVyKDAuMTc1LCAwLjg4NSwgMC4zMiwgMS4yNzUpOwogICAgICAgIH0KICAgICAgICBAa2V5ZnJhbWVzIGJvdW5jZUluIHsKICAgICAgICAgICAgMCUgeyB0cmFuc2Zvcm06IHNjYWxlKDAuNSk7IG9wYWNpdHk6IDA7IH0KICAgICAgICAgICAgMTAwJSB7IHRyYW5zZm9ybTogc2NhbGUoMSk7IG9wYWNpdHk6IDE7IH0KICAgICAgICB9CgogICAgICAgIC5zaGFrZSB7CiAgICAgICAgICAgIGFuaW1hdGlvbjogc2hha2UgMC40czsKICAgICAgICB9CiAgICAgICAgQGtleWZyYW1lcyBzaGFrZSB7CiAgICAgICAgICAgIDAlLCAxMDAlIHsgdHJhbnNmb3JtOiB0cmFuc2xhdGVYKDApOyB9CiAgICAgICAgICAgIDI1JSB7IHRyYW5zZm9ybTogdHJhbnNsYXRlWCgtMTBweCk7IH0KICAgICAgICAgICAgNTAlIHsgdHJhbnNmb3JtOiB0cmFuc2xhdGVYKDEwcHgpOyB9CiAgICAgICAgICAgIDc1JSB7IHRyYW5zZm9ybTogdHJhbnNsYXRlWCgtMTBweCk7IH0KICAgICAgICB9CgogICAgICAgIC8qIFN0eWxpbmcgS2FydHUgRHJhZ2dhYmxlICovCiAgICAgICAgLmRyYWdnYWJsZS1jYXJkIHsKICAgICAgICAgICAgY3Vyc29yOiBncmFiOwogICAgICAgICAgICB0b3VjaC1hY3Rpb246IG5vbmU7IC8qIFBlbnRpbmcgdW50dWsgY3VzdG9tIHRvdWNoIGRyYWcgKi8KICAgICAgICAgICAgdXNlci1zZWxlY3Q6IG5vbmU7CiAgICAgICAgICAgIHRyYW5zaXRpb246IHRyYW5zZm9ybSAwLjFzOwogICAgICAgIH0KICAgICAgICAuZHJhZ2dhYmxlLWNhcmQ6YWN0aXZlIHsKICAgICAgICAgICAgY3Vyc29yOiBncmFiYmluZzsKICAgICAgICB9CiAgICAgICAgLmRyYWdnaW5nIHsKICAgICAgICAgICAgb3BhY2l0eTogMC44OwogICAgICAgICAgICB0cmFuc2Zvcm06IHNjYWxlKDEuMDUpOwogICAgICAgICAgICB6LWluZGV4OiA1MDsKICAgICAgICB9CgogICAgICAgIC8qIFN0eWxpbmcgRHJvcCBab25lICovCiAgICAgICAgLmRyb3Atem9uZSB7CiAgICAgICAgICAgIHRyYW5zaXRpb246IGFsbCAwLjNzIGVhc2U7CiAgICAgICAgfQogICAgICAgIC5kcm9wLXpvbmUuZHJhZy1vdmVyIHsKICAgICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogI2RiZWFmZTsgLyogQmlydSBtdWRhIHNhYXQgZGktaG92ZXIgKi8KICAgICAgICAgICAgYm9yZGVyLWNvbG9yOiAjM2I4MmY2OwogICAgICAgICAgICB0cmFuc2Zvcm06IHNjYWxlKDEuMDUpOwogICAgICAgIH0KICAgICAgICAuZHJvcC16b25lLmNvcnJlY3QgewogICAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjZGNmY2U3OwogICAgICAgICAgICBib3JkZXItY29sb3I6ICMyMmM1NWU7CiAgICAgICAgICAgIGNvbG9yOiAjMTY2NTM0OwogICAgICAgIH0KICAgICAgICAuZHJvcC16b25lLndyb25nIHsKICAgICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogI2ZlZTJlMjsKICAgICAgICAgICAgYm9yZGVyLWNvbG9yOiAjZWY0NDQ0OwogICAgICAgICAgICBjb2xvcjogIzk5MWIxYjsKICAgICAgICB9CgogICAgICAgIC8qIFV0aWxpdHkgdW50dWsgY3VzdG9tIGRyYWcgbW9iaWxlICovCiAgICAgICAgLmFic29sdXRlLWRyYWcgewogICAgICAgICAgICBwb3NpdGlvbjogYWJzb2x1dGUgIWltcG9ydGFudDsKICAgICAgICAgICAgcG9pbnRlci1ldmVudHM6IG5vbmU7IC8qIFN1cGF5YSBlbGVtZW4gZGkgYmF3YWhueWEgKGRyb3Agem9uZSkgYmlzYSB0ZXJkZXRla3NpICovCiAgICAgICAgfQogICAgPC9zdHlsZT4KPC9oZWFkPgo8Ym9keSBjbGFzcz0ibWluLWgtc2NyZWVuIGZsZXggZmxleC1jb2wgaXRlbXMtY2VudGVyIGp1c3RpZnktY2VudGVyIHAtNCI+CgogICAgPCEtLSBMQVlBUiBNVUxBSSAtLT4KICAgIDxkaXYgaWQ9InN0YXJ0LXNjcmVlbiIgY2xhc3M9ImJnLXdoaXRlIHJvdW5kZWQtM3hsIHNoYWRvdy0yeGwgcC04IG1heC13LW1kIHctZnVsbCB0ZXh0LWNlbnRlciBib3VuY2UtaW4gYm9yZGVyLXQtOCBib3JkZXItYmx1ZS01MDAiPgogICAgICAgIDxpIGNsYXNzPSJmYS1zb2xpZCBmYS1sYXB0b3AtZmlsZSB0ZXh0LTZ4bCB0ZXh0LWJsdWUtNTAwIG1iLTQiPjwvaT4KICAgICAgICA8aDEgY2xhc3M9InRleHQtM3hsIGZvbnQtYm9sZCB0ZXh0LWdyYXktODAwIG1iLTIiPk1hc3RlciBQZW5nb2xhaCBLYXRhPC9oMT4KICAgICAgICA8cCBjbGFzcz0idGV4dC1ncmF5LTYwMCBtYi02IHRleHQtc20iPlVqaSBrZWFobGlhbiBhZG1pbmlzdHJhc2kgcGVya2FudG9yYW5tdSEgQmFjYSB0dWdhcyBkYXJpIGF0YXNhbiBkYW4gdGFyaWsgKGRyYWcpIGthcnR1IHR1Z2FzIGtlIGFsYXQvZml0dXIgeWFuZyB0ZXBhdC48L3A+CiAgICAgICAgPGJ1dHRvbiBvbmNsaWNrPSJzdGFydEdhbWUoKSIgY2xhc3M9InctZnVsbCBiZy1ibHVlLTYwMCBob3ZlcjpiZy1ibHVlLTcwMCB0ZXh0LXdoaXRlIGZvbnQtYm9sZCBweS0zIHB4LTYgcm91bmRlZC14bCB0cmFuc2l0aW9uIGR1cmF0aW9uLTIwMCB0cmFuc2Zvcm0gaG92ZXI6c2NhbGUtMTA1IHNoYWRvdy1sZyI+CiAgICAgICAgICAgIE11bGFpIEJla2VyamEgPGkgY2xhc3M9ImZhLXNvbGlkIGZhLXBsYXkgbWwtMiI+PC9pPgogICAgICAgIDwvYnV0dG9uPgogICAgPC9kaXY+CgogICAgPCEtLSBBUkVBIFBFUk1BSU5BTiAtLT4KICAgIDxkaXYgaWQ9ImdhbWUtc2NyZWVuIiBjbGFzcz0iaGlkZGVuIHctZnVsbCBtYXgtdy0zeGwgZmxleCBmbGV4LWNvbCBoLVs5MHZoXSBqdXN0aWZ5LWJldHdlZW4iPgogICAgICAgIDwhLS0gSGVhZGVyOiBTa29yICYgUHJvZ3JlcyAtLT4KICAgICAgICA8ZGl2IGNsYXNzPSJiZy13aGl0ZSByb3VuZGVkLTJ4bCBzaGFkb3ctbWQgcC00IGZsZXgganVzdGlmeS1iZXR3ZWVuIGl0ZW1zLWNlbnRlciBtYi00Ij4KICAgICAgICAgICAgPGRpdiBjbGFzcz0idGV4dC1ibHVlLTYwMCBmb250LWJvbGQiPgogICAgICAgICAgICAgICAgPGkgY2xhc3M9ImZhLXNvbGlkIGZhLWxpc3QtY2hlY2siPjwvaT4gVHVnYXM6IDxzcGFuIGlkPSJwcm9ncmVzcy10ZXh0Ij4xLzEwPC9zcGFuPgogICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgPGRpdiBjbGFzcz0idGV4dC1ncmVlbi02MDAgZm9udC1ib2xkIHRleHQteGwiPgogICAgICAgICAgICAgICAgPGkgY2xhc3M9ImZhLXNvbGlkIGZhLXN0YXIgdGV4dC15ZWxsb3ctNDAwIj48L2k+IFNrb3I6IDxzcGFuIGlkPSJzY29yZS10ZXh0Ij4wPC9zcGFuPgogICAgICAgICAgICA8L2Rpdj4KICAgICAgICA8L2Rpdj4KCiAgICAgICAgPCEtLSBBcmVhIFBlcnRhbnlhYW4gKEthcnR1IERyYWdnYWJsZSkgLS0+CiAgICAgICAgPGRpdiBjbGFzcz0iZmxleC1ncm93IGZsZXggZmxleC1jb2wgaXRlbXMtY2VudGVyIGp1c3RpZnktY2VudGVyIG1iLTYgcmVsYXRpdmUiIGlkPSJkcmFnLWNvbnRhaW5lciI+CiAgICAgICAgICAgIDxoMiBjbGFzcz0idGV4dC1ncmF5LTYwMCB0ZXh0LWNlbnRlciB0ZXh0LXNtIGZvbnQtc2VtaWJvbGQgbWItMyB1cHBlcmNhc2UgdHJhY2tpbmctd2lkZSI+VHVnYXMgQW5kYTo8L2gyPgogICAgICAgICAgICA8ZGl2IGlkPSJ0YXNrLWNhcmQiIGNsYXNzPSJkcmFnZ2FibGUtY2FyZCBiZy1ibHVlLTUwMCB0ZXh0LXdoaXRlIHJvdW5kZWQtMnhsIHNoYWRvdy14bCBwLTYgdy1mdWxsIG1heC13LXNtIHRleHQtY2VudGVyIGJvcmRlci1iLTQgYm9yZGVyLWJsdWUtNzAwIG14LWF1dG8iIGRyYWdnYWJsZT0idHJ1ZSI+CiAgICAgICAgICAgICAgICA8aSBjbGFzcz0iZmEtc29saWQgZmEtZW52ZWxvcGUtb3Blbi10ZXh0IHRleHQtM3hsIG1iLTMgdGV4dC1ibHVlLTIwMCI+PC9pPgogICAgICAgICAgICAgICAgPHAgaWQ9InRhc2stZGVzYyIgY2xhc3M9InRleHQtbGcgZm9udC1zZW1pYm9sZCBsZWFkaW5nLXNudWciPgogICAgICAgICAgICAgICAgICAgIDwhLS0gRGVza3JpcHNpIGFrYW4gZGktbG9hZCBkaSBzaW5pIC0tPgogICAgICAgICAgICAgICAgPC9wPgogICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0ibXQtNCB0ZXh0LWJsdWUtMjAwIHRleHQteHMgZmxleCBpdGVtcy1jZW50ZXIganVzdGlmeS1jZW50ZXIgZ2FwLTIiPgogICAgICAgICAgICAgICAgICAgIDxpIGNsYXNzPSJmYS1zb2xpZCBmYS1oYW5kLXBvaW50ZXIiPjwvaT4gVGFyaWsga2FydHUgaW5pIGtlIGFsYXQgZGkgYmF3YWgKICAgICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICA8L2Rpdj4KICAgICAgICA8L2Rpdj4KCiAgICAgICAgPCEtLSBBcmVhIERyb3AgWm9uZSAoUGlsaWhhbiBBbGF0KSAtLT4KICAgICAgICA8ZGl2IGNsYXNzPSJncmlkIGdyaWQtY29scy0yIG1kOmdyaWQtY29scy0zIGdhcC0zIG1kOmdhcC00IHBiLTQiIGlkPSJkcm9wLXpvbmVzLWNvbnRhaW5lciI+CiAgICAgICAgICAgIDwhLS0gS290YWsgcGlsaWhhbiBha2FuIGRpLWdlbmVyYXRlIG9sZWggSmF2YVNjcmlwdCAtLT4KICAgICAgICA8L2Rpdj4KICAgIDwvZGl2PgoKICAgIDwhLS0gTEFZQVIgQUtISVIgLS0+CiAgICA8ZGl2IGlkPSJlbmQtc2NyZWVuIiBjbGFzcz0iaGlkZGVuIGJnLXdoaXRlIHJvdW5kZWQtM3hsIHNoYWRvdy0yeGwgcC04IG1heC13LW1kIHctZnVsbCB0ZXh0LWNlbnRlciBib3VuY2UtaW4gYm9yZGVyLXQtOCBib3JkZXItZ3JlZW4tNTAwIj4KICAgICAgICA8aSBjbGFzcz0iZmEtc29saWQgZmEtYXdhcmQgdGV4dC03eGwgdGV4dC15ZWxsb3ctNDAwIG1iLTQiPjwvaT4KICAgICAgICA8aDEgY2xhc3M9InRleHQtM3hsIGZvbnQtYm9sZCB0ZXh0LWdyYXktODAwIG1iLTIiPktlcmphIEJhZ3VzITwvaDE+CiAgICAgICAgPHAgY2xhc3M9InRleHQtZ3JheS02MDAgbWItMiI+QW5kYSB0ZWxhaCBtZW55ZWxlc2Fpa2FuIGphbSBrZXJqYSBkZW5nYW4gYmFpay48L3A+CiAgICAgICAgPGRpdiBjbGFzcz0idGV4dC01eGwgZm9udC1ib2xkIHRleHQtYmx1ZS02MDAgbXktNiIgaWQ9ImZpbmFsLXNjb3JlIj4xMDA8L2Rpdj4KICAgICAgICA8cCBpZD0iZmVlZGJhY2stbXNnIiBjbGFzcz0idGV4dC1ncmF5LTYwMCBmb250LXNlbWlib2xkIG1iLTYiPjwvcD4KICAgICAgICA8YnV0dG9uIG9uY2xpY2s9InJlc2V0R2FtZSgpIiBjbGFzcz0idy1mdWxsIGJnLWdyZWVuLTUwMCBob3ZlcjpiZy1ncmVlbi02MDAgdGV4dC13aGl0ZSBmb250LWJvbGQgcHktMyBweC02IHJvdW5kZWQteGwgdHJhbnNpdGlvbiBkdXJhdGlvbi0yMDAgc2hhZG93LWxnIj4KICAgICAgICAgICAgTWFpbiBMYWdpIDxpIGNsYXNzPSJmYS1zb2xpZCBmYS1yb3RhdGUtcmlnaHQgbWwtMiI+PC9pPgogICAgICAgIDwvYnV0dG9uPgogICAgPC9kaXY+CgogICAgPHNjcmlwdD4KICAgICAgICAvLyAtLS0gREFUQSBNQVNURVIgLS0tCiAgICAgICAgLy8gS3VtcHVsYW4gc2VtdWEgYWxhdC9maXR1ciB1bnR1ayBtZW1idWF0IHBlbmdlY29oIChkaXN0cmFjdG9ycykKICAgICAgICBjb25zdCBhbGxUb29scyA9IFsKICAgICAgICAgICAgeyBpZDogJ25ldycsIG5hbWU6ICdOZXcgRG9jdW1lbnQnLCBpY29uOiAnZmEtZmlsZS1jaXJjbGUtcGx1cycgfSwKICAgICAgICAgICAgeyBpZDogJ3NhdmUnLCBuYW1lOiAnU2F2ZSAvIFNhdmUgQXMnLCBpY29uOiAnZmEtZmxvcHB5LWRpc2snIH0sCiAgICAgICAgICAgIHsgaWQ6ICdib2xkJywgbmFtZTogJ0JvbGQnLCBpY29uOiAnZmEtYm9sZCcgfSwKICAgICAgICAgICAgeyBpZDogJ2p1c3RpZnknLCBuYW1lOiAnSnVzdGlmeScsIGljb246ICdmYS1hbGlnbi1qdXN0aWZ5JyB9LAogICAgICAgICAgICB7IGlkOiAnY29weScsIG5hbWU6ICdDb3B5JywgaWNvbjogJ2ZhLWNvcHknIH0sCiAgICAgICAgICAgIHsgaWQ6ICdwYWdlc2l6ZScsIG5hbWU6ICdQYWdlIFNpemUnLCBpY29uOiAnZmEtZmlsZS1saW5lcycgfSwKICAgICAgICAgICAgeyBpZDogJ3VuZG8nLCBuYW1lOiAnVW5kbycsIGljb246ICdmYS1yb3RhdGUtbGVmdCcgfSwKICAgICAgICAgICAgeyBpZDogJ251bWJlcmluZycsIG5hbWU6ICdOdW1iZXJpbmcnLCBpY29uOiAnZmEtbGlzdC1vbCcgfSwKICAgICAgICAgICAgeyBpZDogJ2ZpbmQnLCBuYW1lOiAnRmluZCAmIFJlcGxhY2UnLCBpY29uOiAnZmEtbWFnbmlmeWluZy1nbGFzcy1hcnJvdy1yaWdodCcgfSwKICAgICAgICAgICAgeyBpZDogJ3BkZicsIG5hbWU6ICdFeHBvcnQgUERGJywgaWNvbjogJ2ZhLWZpbGUtcGRmJyB9LAogICAgICAgICAgICB7IGlkOiAnaXRhbGljJywgbmFtZTogJ0l0YWxpYycsIGljb246ICdmYS1pdGFsaWMnIH0sCiAgICAgICAgICAgIHsgaWQ6ICdwcmludCcsIG5hbWU6ICdQcmludCcsIGljb246ICdmYS1wcmludCcgfSwKICAgICAgICAgICAgeyBpZDogJ2NlbnRlcicsIG5hbWU6ICdDZW50ZXIgQWxpZ24nLCBpY29uOiAnZmEtYWxpZ24tY2VudGVyJyB9LAogICAgICAgICAgICB7IGlkOiAnZm9udGNvbG9yJywgbmFtZTogJ0ZvbnQgQ29sb3InLCBpY29uOiAnZmEtcGFsZXR0ZScgfSwKICAgICAgICAgICAgeyBpZDogJ3VuZGVybGluZScsIG5hbWU6ICdVbmRlcmxpbmUnLCBpY29uOiAnZmEtdW5kZXJsaW5lJyB9LAogICAgICAgICAgICB7IGlkOiAnYWxpZ25sZWZ0JywgbmFtZTogJ0FsaWduIExlZnQnLCBpY29uOiAnZmEtYWxpZ24tbGVmdCcgfSwKICAgICAgICAgICAgeyBpZDogJ2FsaWducmlnaHQnLCBuYW1lOiAnQWxpZ24gUmlnaHQnLCBpY29uOiAnZmEtYWxpZ24tcmlnaHQnIH0sCiAgICAgICAgICAgIHsgaWQ6ICdjdXQnLCBuYW1lOiAnQ3V0JywgaWNvbjogJ2ZhLXNjaXNzb3JzJyB9LAogICAgICAgICAgICB7IGlkOiAncGFzdGUnLCBuYW1lOiAnUGFzdGUnLCBpY29uOiAnZmEtcGFzdGUnIH0sCiAgICAgICAgICAgIHsgaWQ6ICdyZWRvJywgbmFtZTogJ1JlZG8nLCBpY29uOiAnZmEtcm90YXRlLXJpZ2h0JyB9LAogICAgICAgICAgICB7IGlkOiAnYnVsbGV0cycsIG5hbWU6ICdCdWxsZXRzJywgaWNvbjogJ2ZhLWxpc3QtdWwnIH0sCiAgICAgICAgICAgIHsgaWQ6ICdsaW5lc3BhY2luZycsIG5hbWU6ICdMaW5lIFNwYWNpbmcnLCBpY29uOiAnZmEtYXJyb3dzLXVwLWRvd24nIH0sCiAgICAgICAgICAgIHsgaWQ6ICdtYXJnaW5zJywgbmFtZTogJ01hcmdpbnMnLCBpY29uOiAnZmEtbWF4aW1pemUnIH0sCiAgICAgICAgICAgIHsgaWQ6ICd0YWJsZScsIG5hbWU6ICdJbnNlcnQgVGFibGUnLCBpY29uOiAnZmEtdGFibGUnIH0sCiAgICAgICAgICAgIHsgaWQ6ICdwaWN0dXJlJywgbmFtZTogJ0luc2VydCBQaWN0dXJlJywgaWNvbjogJ2ZhLWltYWdlJyB9LAogICAgICAgICAgICB7IGlkOiAnaGVhZGVyJywgbmFtZTogJ0hlYWRlcicsIGljb246ICdmYS1oZWFkaW5nJyB9LAogICAgICAgICAgICB7IGlkOiAnZm9vdGVyJywgbmFtZTogJ0Zvb3RlcicsIGljb246ICdmYS1zaG9lLXByaW50cycgfSwKICAgICAgICAgICAgeyBpZDogJ3BhZ2VudW1iZXInLCBuYW1lOiAnUGFnZSBOdW1iZXInLCBpY29uOiAnZmEtYXJyb3ctZG93bi0xLTknIH0sCiAgICAgICAgICAgIHsgaWQ6ICdwYWdlYnJlYWsnLCBuYW1lOiAnUGFnZSBCcmVhaycsIGljb246ICdmYS1maWxlLWRhc2hlZC1saW5lJyB9LAogICAgICAgICAgICB7IGlkOiAnY29sdW1ucycsIG5hbWU6ICdDb2x1bW5zJywgaWNvbjogJ2ZhLXRhYmxlLWNvbHVtbnMnIH0sCiAgICAgICAgICAgIHsgaWQ6ICdvcmllbnRhdGlvbicsIG5hbWU6ICdPcmllbnRhdGlvbicsIGljb246ICdmYS1tb2JpbGUtc2NyZWVuJyB9LAogICAgICAgICAgICB7IGlkOiAnd2F0ZXJtYXJrJywgbmFtZTogJ1dhdGVybWFyaycsIGljb246ICdmYS1zdGFtcCcgfSwKICAgICAgICAgICAgeyBpZDogJ3NwZWxsY2hlY2snLCBuYW1lOiAnU3BlbGwgQ2hlY2snLCBpY29uOiAnZmEtc3BlbGwtY2hlY2snIH0sCiAgICAgICAgICAgIHsgaWQ6ICdtYWlsbWVyZ2UnLCBuYW1lOiAnTWFpbCBNZXJnZScsIGljb246ICdmYS1lbnZlbG9wZXMtYnVsaycgfSwKICAgICAgICAgICAgeyBpZDogJ3N1cGVyc2NyaXB0JywgbmFtZTogJ1N1cGVyc2NyaXB0JywgaWNvbjogJ2ZhLXN1cGVyc2NyaXB0JyB9LAogICAgICAgICAgICB7IGlkOiAnc3Vic2NyaXB0JywgbmFtZTogJ1N1YnNjcmlwdCcsIGljb246ICdmYS1zdWJzY3JpcHQnIH0sCiAgICAgICAgICAgIHsgaWQ6ICdoaWdobGlnaHQnLCBuYW1lOiAnSGlnaGxpZ2h0JywgaWNvbjogJ2ZhLWhpZ2hsaWdodGVyJyB9LAogICAgICAgICAgICB7IGlkOiAnaHlwZXJsaW5rJywgbmFtZTogJ0h5cGVybGluaycsIGljb246ICdmYS1saW5rJyB9LAogICAgICAgICAgICB7IGlkOiAnZm9ybWF0cGFpbnRlcicsIG5hbWU6ICdGb3JtYXQgUGFpbnRlcicsIGljb246ICdmYS1wYWludC1yb2xsZXInIH0sCiAgICAgICAgICAgIHsgaWQ6ICd0ZXh0Ym94JywgbmFtZTogJ1RleHQgQm94JywgaWNvbjogJ2ZhLXNxdWFyZS1wZW4nIH0sCiAgICAgICAgICAgIHsgaWQ6ICd3b3JkY291bnQnLCBuYW1lOiAnV29yZCBDb3VudCcsIGljb246ICdmYS1jYWxjdWxhdG9yJyB9LAogICAgICAgICAgICB7IGlkOiAnem9vbScsIG5hbWU6ICdab29tJywgaWNvbjogJ2ZhLW1hZ25pZnlpbmctZ2xhc3MtcGx1cycgfSwKICAgICAgICAgICAgeyBpZDogJ3N0cmlrZXRocm91Z2gnLCBuYW1lOiAnU3RyaWtldGhyb3VnaCcsIGljb246ICdmYS1zdHJpa2V0aHJvdWdoJyB9LAogICAgICAgICAgICB7IGlkOiAnaW5kZW50aW5jcmVhc2UnLCBuYW1lOiAnSW5jcmVhc2UgSW5kZW50JywgaWNvbjogJ2ZhLWluZGVudCcgfSwKICAgICAgICAgICAgeyBpZDogJ2luZGVudGRlY3JlYXNlJywgbmFtZTogJ0RlY3JlYXNlIEluZGVudCcsIGljb246ICdmYS1vdXRkZW50JyB9LAogICAgICAgICAgICB7IGlkOiAnY2hhcnQnLCBuYW1lOiAnSW5zZXJ0IENoYXJ0JywgaWNvbjogJ2ZhLWNoYXJ0LXBpZScgfSwKICAgICAgICAgICAgeyBpZDogJ3NoYXBlcycsIG5hbWU6ICdJbnNlcnQgU2hhcGVzJywgaWNvbjogJ2ZhLXNoYXBlcycgfSwKICAgICAgICAgICAgeyBpZDogJ3N5bWJvbCcsIG5hbWU6ICdJbnNlcnQgU3ltYm9sJywgaWNvbjogJ2ZhLW9tZWdhJyB9LAogICAgICAgICAgICB7IGlkOiAnZm9udGZhbWlseScsIG5hbWU6ICdGb250IFN0eWxlJywgaWNvbjogJ2ZhLWZvbnQnIH0KICAgICAgICBdOwoKICAgICAgICAvLyBEYWZ0YXIgNTAgUGVydGFueWFhbgogICAgICAgIGNvbnN0IHF1ZXN0aW9ucyA9IFsKICAgICAgICAgICAgLy8gU2VzaSAxOiBEYXNhciAmIFBlbnlpbXBhbmFuCiAgICAgICAgICAgIHsgdGFzazogIkJvcyBtZW1pbnRhIEFuZGEgbWVtYnVhdCBzdXJhdCBwZW5hd2FyYW4gYmFydSBkYXJpIGtlcnRhcyBrb3NvbmcuIiwgY29ycmVjdElkOiAibmV3IiB9LAogICAgICAgICAgICB7IHRhc2s6ICJBbmRhIHN1ZGFoIG1lbmdldGlrIGxhcG9yYW4uIFNla2FyYW5nIEFuZGEgaGFydXMgbWVueWltcGFubnlhIGRlbmdhbiBuYW1hIGZpbGUgYmFydSAnTGFwb3Jhbl9CdWxhbl9JbmknLiIsIGNvcnJlY3RJZDogInNhdmUiIH0sCiAgICAgICAgICAgIHsgdGFzazogIkRva3VtZW4ga29udHJhayBzdWRhaCBmaW5hbC4gQW5kYSBoYXJ1cyBtZW55aW1wYW5ueWEga2UgZm9ybWF0IHlhbmcgdGlkYWsgYmlzYSBkaWVkaXQgc2VtYmFyYW5nYW4uIiwgY29ycmVjdElkOiAicGRmIiB9LAogICAgICAgICAgICB7IHRhc2s6ICJTaW1wYW4gcGVtYmFydWFuIHBla2VyamFhbiB5YW5nIGJhcnUgc2FqYSBBbmRhIGtldGlrIGFnYXIgdGlkYWsgaGlsYW5nIGppa2EgdGliYS10aWJhIG1hdGkgbGFtcHUuIiwgY29ycmVjdElkOiAic2F2ZSIgfSwKICAgICAgICAgICAgeyB0YXNrOiAiQ2V0YWsgMyByYW5na2FwIGRva3VtZW4gcGVyamFuamlhbiBrZXJqYXNhbWEgaW5pIG1lbmdndW5ha2FuIHByaW50ZXIgZGkgcnVhbmcgbWVldGluZy4iLCBjb3JyZWN0SWQ6ICJwcmludCIgfSwKICAgICAgICAgICAgCiAgICAgICAgICAgIC8vIFNlc2kgMjogRm9ybWF0IEZvbnQgJiBUZWtzCiAgICAgICAgICAgIHsgdGFzazogIkp1ZHVsIGtvcCBzdXJhdCBoYXJ1cyB0ZXJsaWhhdCBsZWJpaCB0ZWJhbCBkYW4gbWVuY29sb2sgZGFyaSB0ZWtzIGxhaW5ueWEuIiwgY29ycmVjdElkOiAiYm9sZCIgfSwKICAgICAgICAgICAgeyB0YXNrOiAiQmVyaSBnYXJpcyBiYXdhaCBwYWRhIGthdGEgJ1BFTlRJTkcnIGRpIHBlbmd1bXVtYW4gaW50ZXJuYWwga2FudG9yLiIsIGNvcnJlY3RJZDogInVuZGVybGluZSIgfSwKICAgICAgICAgICAgeyB0YXNrOiAiSmFkaWthbiB0ZWtzIGt1dGlwYW4gcGVudGluZyBpbmkgbWVuamFkaSBtaXJpbmcgYWdhciBiZXJiZWRhIGRhcmkgdGVrcyBwYXJhZ3JhZiBsYWlubnlhLiIsIGNvcnJlY3RJZDogIml0YWxpYyIgfSwKICAgICAgICAgICAgeyB0YXNrOiAiVWJhaCBqZW5pcyBnYXlhIHR1bGlzYW4gZG9rdW1lbiBzdXJhdCByZXNtaSBpbmkgZGFyaSBmb250IGRlZmF1bHQgbWVuamFkaSBBcmlhbCBhdGF1IFRpbWVzIE5ldyBSb21hbi4iLCBjb3JyZWN0SWQ6ICJmb250ZmFtaWx5IiB9LAogICAgICAgICAgICB7IHRhc2s6ICJVYmFoIHdhcm5hIHRla3MgcGVyaW5nYXRhbiBkaSBwZW5ndW11bWFuIGluaSBkYXJpIGhpdGFtIG1lbmphZGkgbWVyYWggdGVyYW5nLiIsIGNvcnJlY3RJZDogImZvbnRjb2xvciIgfSwKICAgICAgICAgICAgeyB0YXNrOiAiQmVyaSB3YXJuYSBsYXRhciBrdW5pbmcgKHNlcGVydGkgc3RhYmlsbykgcGFkYSBrYWxpbWF0IHlhbmcgaGFydXMgc2VnZXJhIGRpcmV2aXNpIG9sZWggdGltLiIsIGNvcnJlY3RJZDogImhpZ2hsaWdodCIgfSwKICAgICAgICAgICAgeyB0YXNrOiAiQmVyaSBnYXJpcyBjb3JldGFuIGRpIHRlbmdhaCB0ZWtzIHVudHVrIG1lbmFuZGFpIGhhcmdhIGxhbWEgcHJvZHVrIHlhbmcgc3VkYWggZGlza29uLiIsIGNvcnJlY3RJZDogInN0cmlrZXRocm91Z2giIH0sCiAgICAgICAgICAgIHsgdGFzazogIlNhbGluIGdheWEgaHVydWYgZGFuIHdhcm5hIGRhcmkgSnVkdWwgMSwgbGFsdSB0ZXJhcGthbiBzZWNhcmEgaW5zdGFuIGtlIEp1ZHVsIDIgdGFucGEgbWVuZ2F0dXIgdWxhbmcuIiwgY29ycmVjdElkOiAiZm9ybWF0cGFpbnRlciIgfSwKICAgICAgICAgICAgCiAgICAgICAgICAgIC8vIFNlc2kgMzogUGVyYXRhYW4gJiBQYXJhZ3JhZgogICAgICAgICAgICB7IHRhc2s6ICJBZ2FyIHN1cmF0IHJlc21pIHRlcmxpaGF0IHJhcGksIHNpc2kga2FuYW4gZGFuIGtpcmkgcGFyYWdyYWYgaGFydXMgc2VqYWphciByYXRhLiIsIGNvcnJlY3RJZDogImp1c3RpZnkiIH0sCiAgICAgICAgICAgIHsgdGFzazogIkZvcm1hdCB0YW5nZ2FsIHN1cmF0IGRpIGJhZ2lhbiBhdGFzIGhhcnVzIGRpcmF0YWthbiBraHVzdXMga2Ugc2lzaSBraXJpIGRva3VtZW4uIiwgY29ycmVjdElkOiAiYWxpZ25sZWZ0IiB9LAogICAgICAgICAgICB7IHRhc2s6ICJQb3Npc2lrYW4gYmxvayB0YW5kYSB0YW5nYW4gZGlyZWt0dXIgYWdhciBiZXJhZGEgc2VqYWphciBkaSBtYXJnaW4ga2FuYW4gYmF3YWguIiwgY29ycmVjdElkOiAiYWxpZ25yaWdodCIgfSwKICAgICAgICAgICAgeyB0YXNrOiAiUHVzYXRrYW4ganVkdWwgbGFwb3JhbiBhZ2FyIGJlcmFkYSB0ZXBhdCBkaSB0ZW5nYWgtdGVuZ2FoIGhhbGFtYW4gc2VjYXJhIGhvcml6b250YWwuIiwgY29ycmVjdElkOiAiY2VudGVyIiB9LAogICAgICAgICAgICB7IHRhc2s6ICJUZWtzIGxhcG9yYW4gdGVybGFsdSBwYWRhdCBkaWJhY2EuIFViYWggamFyYWsgYW50YXIgYmFyaXMgdGVrcyAoc3Bhc2kgYmFyaXMpIG1lbmphZGkgMSw1LiIsIGNvcnJlY3RJZDogImxpbmVzcGFjaW5nIiB9LAogICAgICAgICAgICB7IHRhc2s6ICJEb3JvbmcgcGFyYWdyYWYgaW5pIGxlYmloIG1lbmpvcm9rIGtlIGRhbGFtIChrZSBrYW5hbikgYWdhciBtYXN1ayBzZWJhZ2FpIGJhZ2lhbiBkYXJpIHN1Yi1iYWIuIiwgY29ycmVjdElkOiAiaW5kZW50aW5jcmVhc2UiIH0sCiAgICAgICAgICAgIHsgdGFzazogIlRhcmlrIGtlbWJhbGkgdGVrcyB5YW5nIHBvc2lzaW55YSB0ZXJsYWx1IG1lbmpvcm9rIGtlIGRhbGFtIGFnYXIgc2VqYWphciBsYWdpIGRlbmdhbiBiYXRhcyBraXJpIG5vcm1hbC4iLCBjb3JyZWN0SWQ6ICJpbmRlbnRkZWNyZWFzZSIgfSwKICAgICAgICAgICAgCiAgICAgICAgICAgIC8vIFNlc2kgNDogTmF2aWdhc2ksIENvcHksIFBhc3RlICYgVW5kbwogICAgICAgICAgICB7IHRhc2s6ICJBbmRhIG1lbWJhdGFsa2FuIHNlYnVhaCBrZXRpa2FuIChVbmRvKSwgdGFwaSBiZXJ1YmFoIHBpa2lyYW4gZGFuIGluZ2luIG1lbmdlbWJhbGlrYW4ga2V0aWthbiB0ZXJzZWJ1dC4iLCBjb3JyZWN0SWQ6ICJyZWRvIiB9LAogICAgICAgICAgICB7IHRhc2s6ICJBbmRhIGluZ2luIG1lbWluZGFoa2FuIHRla3MgYWxhbWF0IGRhcmkgZG9rdW1lbiBsYW1hIHRhbnBhIG1lbmdldGlrIHVsYW5nIChMYW5na2FoIHBlcnRhbWE6IFNhbGluKS4iLCBjb3JyZWN0SWQ6ICJjb3B5IiB9LAogICAgICAgICAgICB7IHRhc2s6ICJTZXRlbGFoIG1lbnlhbGluIChDb3B5KSB0ZWtzIGRhcmkgZW1haWwsIHRlbXBlbGthbiB0ZWtzIHRlcnNlYnV0IGtlIGRhbGFtIGRva3VtZW4gV29yZCBBbmRhLiIsIGNvcnJlY3RJZDogInBhc3RlIiB9LAogICAgICAgICAgICB7IHRhc2s6ICJQaW5kYWhrYW4gcGFyYWdyYWYgaW5pIGtlIGJhYiBsYWluLiAoTGFuZ2thaCBwZXJ0YW1hOiBQb3RvbmcvaGlsYW5na2FuIGRhcmkgdGVtcGF0IGFzbGlueWEpLiIsIGNvcnJlY3RJZDogImN1dCIgfSwKICAgICAgICAgICAgeyB0YXNrOiAiVXBzISBBbmRhIHRpZGFrIHNlbmdhamEgbWVuZ2hhcHVzIHBhcmFncmFmIHBlbnRpbmcuIEJhdGFsa2FuIGtlc2FsYWhhbiB0ZXJzZWJ1dCBhZ2FyIGtlbWJhbGkgc2VwZXJ0aSBzZW11bGEuIiwgY29ycmVjdElkOiAidW5kbyIgfSwKICAgICAgICAgICAgeyB0YXNrOiAiQWRhIGtlc2FsYWhhbiBrZXRpayBuYW1hIHBlcnVzYWhhYW4gZGkgNTAgaGFsYW1hbi4gVGVtdWthbiBrYXRhIHRlcnNlYnV0IGRhbiBnYW50aSBzZW11YW55YSBzZWthbGlndXMuIiwgY29ycmVjdElkOiAiZmluZCIgfSwKICAgICAgICAgICAgCiAgICAgICAgICAgIC8vIFNlc2kgNTogVGF0YSBMZXRhayBIYWxhbWFuIChQYWdlIExheW91dCkKICAgICAgICAgICAgeyB0YXNrOiAiU3RhbmRhciBwZXJ1c2FoYWFuIG1lbmdoYXJ1c2thbiBkb2t1bWVuIHJlc21pIGRpY2V0YWsga2h1c3VzIGRpIGtlcnRhcyB1a3VyYW4gQTQuIiwgY29ycmVjdElkOiAicGFnZXNpemUiIH0sCiAgICAgICAgICAgIHsgdGFzazogIkF0dXIgYmF0YXMga29zb25nIGRpIHBpbmdnaXIga2VydGFzIChtYXJnaW4gYXRhcywgYmF3YWgsIGtpcmksIGthbmFuKSBtZW5qYWRpIHRlcGF0IDIgY20uIiwgY29ycmVjdElkOiAibWFyZ2lucyIgfSwKICAgICAgICAgICAgeyB0YXNrOiAiVWJhaCBwb3Npc2kga2VydGFzIHVudHVrIG1lbmNldGFrIHRhYmVsIHBhbmphbmcgZGFyaSBiZXJkaXJpIChQb3J0cmFpdCkgbWVuamFkaSBtZW5kYXRhciAoTGFuZHNjYXBlKS4iLCBjb3JyZWN0SWQ6ICJvcmllbnRhdGlvbiIgfSwKICAgICAgICAgICAgeyB0YXNrOiAiVWJhaCBmb3JtYXQgYXJ0aWtlbCBidWxldGluIHBlcnVzYWhhYW4gaW5pIG1lbmphZGkgZHVhIGJhZ2lhbiB0ZWtzIHlhbmcgYmVyZGFtcGluZ2FuIChzZXBlcnRpIGtvcmFuKS4iLCBjb3JyZWN0SWQ6ICJjb2x1bW5zIiB9LAogICAgICAgICAgICB7IHRhc2s6ICJQYWtzYSBqdWR1bCBCYWIgMiBhZ2FyIGxhbmdzdW5nIGRpbXVsYWkgZGkgaGFsYW1hbiBiYXJ1LCB0ZXJwaXNhaCBkYXJpIGhhbGFtYW4gQmFiIDEuIiwgY29ycmVjdElkOiAicGFnZWJyZWFrIiB9LAogICAgICAgICAgICB7IHRhc2s6ICJUYW1iYWhrYW4gdHVsaXNhbiB0cmFuc3BhcmFuIGJlcnR1bGlza2FuICdSQUhBU0lBJyBkaSBsYXRhciBiZWxha2FuZyBoYWxhbWFuIGtvbnRyYWsga2VyamEuIiwgY29ycmVjdElkOiAid2F0ZXJtYXJrIiB9LAogICAgICAgICAgICAKICAgICAgICAgICAgLy8gU2VzaSA2OiBFbGVtZW4gU2lzaXBhbiAoSW5zZXJ0IEVsZW1lbnRzKQogICAgICAgICAgICB7IHRhc2s6ICJTaXNpcGthbiBnYW1iYXIgbG9nbyBwZXJ1c2FoYWFuIEFuZGEgZGkgYmFnaWFuIHN1ZHV0IGF0YXMgZG9rdW1lbiBwcm9wb3NhbC4iLCBjb3JyZWN0SWQ6ICJwaWN0dXJlIiB9LAogICAgICAgICAgICB7IHRhc2s6ICJNYXN1a2thbiBkYWZ0YXIgbmFtYSBkYW4gbm9tb3IgdGVsZXBvbiBrbGllbiBkYWxhbSBmb3JtYXQgYmFyaXMgZGFuIGtvbG9tIGtvdGFrLWtvdGFrIHlhbmcgcmFwaS4iLCBjb3JyZWN0SWQ6ICJ0YWJsZSIgfSwKICAgICAgICAgICAgeyB0YXNrOiAiVGFtYmFoa2FuIG5hbWEgaW5zdGFuc2kgYWdhciBzZWxhbHUgbXVuY3VsIGJlcnVsYW5nIGRpIG1hcmdpbiBhdGFzIHNldGlhcCBoYWxhbWFuIGRva3VtZW4uIiwgY29ycmVjdElkOiAiaGVhZGVyIiB9LAogICAgICAgICAgICB7IHRhc2s6ICJUYW1iYWhrYW4gYWxhbWF0IGRhbiBrb250YWsga2FudG9yIGFnYXIgb3RvbWF0aXMgdGVyY2V0YWsgZGkgbWFyZ2luIGJhd2FoIHNldGlhcCBoYWxhbWFuLiIsIGNvcnJlY3RJZDogImZvb3RlciIgfSwKICAgICAgICAgICAgeyB0YXNrOiAiQmVyaSBub21vciB1cnV0IGhhbGFtYW4gZGkgcG9qb2sgYWdhciBkb2t1bWVuIDEwMCBsZW1iYXIgaW5pIHRpZGFrIHRlcnN1c3VuIGFjYWsgamlrYSB0ZXJjZWNlci4iLCBjb3JyZWN0SWQ6ICJwYWdlbnVtYmVyIiB9LAogICAgICAgICAgICB7IHRhc2s6ICJCdWF0IHNlYnVhaCBrb3RhayB0ZWtzIG1lbGF5YW5nIHlhbmcgYmlzYSBkaWdlc2VyIGJlYmFzIHVudHVrIG1lbWJlcmkgY2F0YXRhbiB0YW1iYWhhbiBkaSBwaW5nZ2lyIHN1cmF0LiIsIGNvcnJlY3RJZDogInRleHRib3giIH0sCiAgICAgICAgICAgIHsgdGFzazogIlNpc2lwa2FuIGJlbnR1ayBiYW5ndW4gZGF0YXIgKHBhbmFoL2tvdGFrKSB1bnR1ayBtZW5nZ2FtYmFyIGRpYWdyYW0gYWx1ciBvcGVyYXNpb25hbCAoU09QKS4iLCBjb3JyZWN0SWQ6ICJzaGFwZXMiIH0sCiAgICAgICAgICAgIHsgdGFzazogIlNpc2lwa2FuIGdyYWZpayBkaWFncmFtIGJhdGFuZyB1bnR1ayBtZW12aXN1YWxpc2FzaWthbiBwZXJzZW50YXNlIGRhdGEgcGVuanVhbGFuIGJ1bGFuIGluaS4iLCBjb3JyZWN0SWQ6ICJjaGFydCIgfSwKICAgICAgICAgICAgeyB0YXNrOiAiU2lzaXBrYW4gdGF1dGFuIGludGVybmV0IChsaW5rKSBhZ2FyIHRla3MgJ0tsaWsgZGkgc2luaScgYmlzYSBkaWtsaWsgZGFuIG1lbWJ1a2Egd2Vic2l0ZSBwcm9maWwgcGVydXNhaGFhbi4iLCBjb3JyZWN0SWQ6ICJoeXBlcmxpbmsiIH0sCiAgICAgICAgICAgIHsgdGFzazogIk1hc3Vra2FuIGthcmFrdGVyIGtodXN1cyBzZXBlcnRpIGxhbWJhbmcgSGFrIENpcHRhICjCqSkgYXRhdSBUcmFkZW1hcmsgKOKEoikgeWFuZyB0aWRhayBhZGEgZGkga2V5Ym9hcmQuIiwgY29ycmVjdElkOiAic3ltYm9sIiB9LAogICAgICAgICAgICAKICAgICAgICAgICAgLy8gU2VzaSA3OiBGaXR1ciBMYW5qdXRhbiAmIFBlbm9tb3JhbgogICAgICAgICAgICB7IHRhc2s6ICJBbmRhIHBlcmx1IG1lbWJ1YXQgZGFmdGFyIGxhbmdrYWgtbGFuZ2thaCBrZXJqYSB5YW5nIGJlcnVydXRhbiBzZWNhcmEgb3RvbWF0aXMgKDEsIDIsIDMsIGRzdCkuIiwgY29ycmVjdElkOiAibnVtYmVyaW5nIiB9LAogICAgICAgICAgICB7IHRhc2s6ICJCdWF0IGRhZnRhciBwZXJhbGF0YW4gQVRLIGthbnRvciBtZW5nZ3VuYWthbiBzaW1ib2wgdGl0aWstdGl0aWsgYnVsYXQgZGkgZGVwYW5ueWEgKGJ1a2FuIGFuZ2thKS4iLCBjb3JyZWN0SWQ6ICJidWxsZXRzIiB9LAogICAgICAgICAgICB7IHRhc2s6ICJLZXRpa2thbiBhbmdrYSAyIGtlY2lsIG1lbGF5YW5nIGRpIGF0YXMgcGFkYSB0ZWtzIG1ldGVyIHBlcnNlZ2kgKG3CsikgdW50dWsgbGFwb3JhbiBzZXJ0aWZpa2F0IHRhbmFoLiIsIGNvcnJlY3RJZDogInN1cGVyc2NyaXB0IiB9LAogICAgICAgICAgICB7IHRhc2s6ICJUdWxpc2thbiBhbmdrYSAyIGtlY2lsIGRpIGJhd2FoIHBhZGEgcnVtdXMga2ltaWEgYWlyIChI4oKCTykgZGkganVybmFsIHBlbmVsaXRpYW4gbGluZ2t1bmdhbi4iLCBjb3JyZWN0SWQ6ICJzdWJzY3JpcHQiIH0sCiAgICAgICAgICAgIHsgdGFzazogIkJ1YXQgMTAwIHN1cmF0IHVuZGFuZ2FuIHJhcGF0IGRhcmkgc2F0dSBmb3JtYXQsIGRpIG1hbmEgbmFtYSBwZW5lcmltYW55YSBkaXRhcmlrIG90b21hdGlzIGRhcmkgZGF0YWJhc2UgRXhjZWwuIiwgY29ycmVjdElkOiAibWFpbG1lcmdlIiB9LAogICAgICAgICAgICAKICAgICAgICAgICAgLy8gU2VzaSA4OiBSZXZpZXcgJiBUYW1waWxhbgogICAgICAgICAgICB7IHRhc2s6ICJKYWxhbmthbiBwZW5nZWNla2FuIG90b21hdGlzIHVudHVrIG1lbGloYXQgYXBha2FoIGFkYSBrYXRhLWthdGEgYmFoYXNhIEluZ2dyaXMgeWFuZyBzYWxhaCBrZXRpayAodHlwbykuIiwgY29ycmVjdElkOiAic3BlbGxjaGVjayIgfSwKICAgICAgICAgICAgeyB0YXNrOiAiQXRhc2FuIEFuZGEgYmVydGFueWEgdW50dWsgYmFoYW4gcHJlc2VudGFzaSwgc3VkYWggYmVyYXBhIGJhbnlhayBqdW1sYWgga2F0YSB5YW5nIEFuZGEga2V0aWsgZGFsYW0gYXJ0aWtlbCBpbmk/IiwgY29ycmVjdElkOiAid29yZGNvdW50IiB9LAogICAgICAgICAgICB7IHRhc2s6ICJQZXJiZXNhciAoWm9vbSkgdGFtcGlsYW4gbGVtYmFyIGtlcmphIEFuZGEgZGkgbGF5YXIga29tcHV0ZXIgbWVuamFkaSAxNTAlIGFnYXIgaHVydWZueWEgdGVybGloYXQgbGViaWggamVsYXMuIiwgY29ycmVjdElkOiAiem9vbSIgfQogICAgICAgIF07CgogICAgICAgIC8vIC0tLSBWQVJJQUJFTCBTVEFURSAtLS0KICAgICAgICBsZXQgY3VycmVudFF1ZXN0aW9uSW5kZXggPSAwOwogICAgICAgIGxldCBzY29yZSA9IDA7CiAgICAgICAgbGV0IGN1cnJlbnRPcHRpb25zID0gW107CiAgICAgICAgCiAgICAgICAgLy8gLS0tIEVMRU1FTiBET00gLS0tCiAgICAgICAgY29uc3Qgc3RhcnRTY3JlZW4gPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnc3RhcnQtc2NyZWVuJyk7CiAgICAgICAgY29uc3QgZ2FtZVNjcmVlbiA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdnYW1lLXNjcmVlbicpOwogICAgICAgIGNvbnN0IGVuZFNjcmVlbiA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdlbmQtc2NyZWVuJyk7CiAgICAgICAgY29uc3QgdGFza0NhcmQgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgndGFzay1jYXJkJyk7CiAgICAgICAgY29uc3QgdGFza0Rlc2MgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgndGFzay1kZXNjJyk7CiAgICAgICAgY29uc3QgZHJvcFpvbmVzQ29udGFpbmVyID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2Ryb3Atem9uZXMtY29udGFpbmVyJyk7CiAgICAgICAgY29uc3QgcHJvZ3Jlc3NUZXh0ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3Byb2dyZXNzLXRleHQnKTsKICAgICAgICBjb25zdCBzY29yZVRleHQgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnc2NvcmUtdGV4dCcpOwoKICAgICAgICAvLyBWYXJpYWJlbCB1bnR1ayBEcmFnIFRvdWNoIE1vYmlsZQogICAgICAgIGxldCBzdGFydFggPSAwLCBzdGFydFkgPSAwOwogICAgICAgIGxldCBpbml0aWFsWCA9IDAsIGluaXRpYWxZID0gMDsKICAgICAgICBsZXQgY2xvbmVDYXJkID0gbnVsbDsKCiAgICAgICAgLy8gLS0tIEZVTkdTSSBMT0dJS0EgR0FNRSAtLS0KCiAgICAgICAgZnVuY3Rpb24gc3RhcnRHYW1lKCkgewogICAgICAgICAgICBzdGFydFNjcmVlbi5jbGFzc0xpc3QuYWRkKCdoaWRkZW4nKTsKICAgICAgICAgICAgZ2FtZVNjcmVlbi5jbGFzc0xpc3QucmVtb3ZlKCdoaWRkZW4nKTsKICAgICAgICAgICAgZ2FtZVNjcmVlbi5jbGFzc0xpc3QuYWRkKCdib3VuY2UtaW4nKTsKICAgICAgICAgICAgY3VycmVudFF1ZXN0aW9uSW5kZXggPSAwOwogICAgICAgICAgICBzY29yZSA9IDA7CiAgICAgICAgICAgIHVwZGF0ZVNjb3JlKCk7CiAgICAgICAgICAgIGxvYWRRdWVzdGlvbigpOwogICAgICAgIH0KCiAgICAgICAgZnVuY3Rpb24gbG9hZFF1ZXN0aW9uKCkgewogICAgICAgICAgICAvLyBDZWsgamlrYSBnYW1lIHNlbGVzYWkKICAgICAgICAgICAgaWYgKGN1cnJlbnRRdWVzdGlvbkluZGV4ID49IHF1ZXN0aW9ucy5sZW5ndGgpIHsKICAgICAgICAgICAgICAgIGVuZEdhbWUoKTsKICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgY29uc3QgcSA9IHF1ZXN0aW9uc1tjdXJyZW50UXVlc3Rpb25JbmRleF07CiAgICAgICAgICAgIHRhc2tEZXNjLnRleHRDb250ZW50ID0gcS50YXNrOwogICAgICAgICAgICBwcm9ncmVzc1RleHQudGV4dENvbnRlbnQgPSBgJHtjdXJyZW50UXVlc3Rpb25JbmRleCArIDF9LyR7cXVlc3Rpb25zLmxlbmd0aH1gOwogICAgICAgICAgICAKICAgICAgICAgICAgLy8gUmVzZXQga2FydHUgdHVnYXMKICAgICAgICAgICAgdGFza0NhcmQuc3R5bGUudmlzaWJpbGl0eSA9ICd2aXNpYmxlJzsKICAgICAgICAgICAgdGFza0NhcmQuc3R5bGUub3BhY2l0eSA9ICcxJzsKICAgICAgICAgICAgdGFza0NhcmQuY2xhc3NMaXN0LnJlbW92ZSgnc2hha2UnKTsKICAgICAgICAgICAgdGFza0NhcmQuY2xhc3NMaXN0LmFkZCgnYm91bmNlLWluJyk7CiAgICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4gdGFza0NhcmQuY2xhc3NMaXN0LnJlbW92ZSgnYm91bmNlLWluJyksIDUwMCk7CgogICAgICAgICAgICBnZW5lcmF0ZURyb3Bab25lcyhxLmNvcnJlY3RJZCk7CiAgICAgICAgfQoKICAgICAgICBmdW5jdGlvbiBnZW5lcmF0ZURyb3Bab25lcyhjb3JyZWN0SWQpIHsKICAgICAgICAgICAgZHJvcFpvbmVzQ29udGFpbmVyLmlubmVySFRNTCA9ICcnOwogICAgICAgICAgICBjdXJyZW50T3B0aW9ucyA9IFtdOwoKICAgICAgICAgICAgLy8gQ2FyaSBvYmplayBhbGF0IHlhbmcgYmVuYXIKICAgICAgICAgICAgY29uc3QgY29ycmVjdFRvb2wgPSBhbGxUb29scy5maW5kKHQgPT4gdC5pZCA9PT0gY29ycmVjdElkKTsKICAgICAgICAgICAgY3VycmVudE9wdGlvbnMucHVzaChjb3JyZWN0VG9vbCk7CgogICAgICAgICAgICAvLyBQaWxpaCA0IHBlbmdlY29oIChkaXN0cmFjdG9ycykgc2VjYXJhIGFjYWsKICAgICAgICAgICAgLy8gVG90YWwgNSBwaWxpaGFuICgxIGJlbmFyLCA0IHNhbGFoKSBkaSBzZXRpYXAgc29hbAogICAgICAgICAgICBsZXQgZGlzdHJhY3RvcnMgPSBhbGxUb29scy5maWx0ZXIodCA9PiB0LmlkICE9PSBjb3JyZWN0SWQpOwogICAgICAgICAgICBkaXN0cmFjdG9ycyA9IGRpc3RyYWN0b3JzLnNvcnQoKCkgPT4gMC41IC0gTWF0aC5yYW5kb20oKSkuc2xpY2UoMCwgNCk7CiAgICAgICAgICAgIGN1cnJlbnRPcHRpb25zID0gY3VycmVudE9wdGlvbnMuY29uY2F0KGRpc3RyYWN0b3JzKTsKCiAgICAgICAgICAgIC8vIEFjYWsgdXJ1dGFuIHRhbXBpbAogICAgICAgICAgICBjdXJyZW50T3B0aW9ucy5zb3J0KCgpID0+IDAuNSAtIE1hdGgucmFuZG9tKCkpOwoKICAgICAgICAgICAgLy8gUmVuZGVyIGtvdGFrIGFsYXQKICAgICAgICAgICAgY3VycmVudE9wdGlvbnMuZm9yRWFjaCh0b29sID0+IHsKICAgICAgICAgICAgICAgIGNvbnN0IHpvbmUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTsKICAgICAgICAgICAgICAgIHpvbmUuY2xhc3NOYW1lID0gJ2Ryb3Atem9uZSBiZy13aGl0ZSBib3JkZXItNCBib3JkZXItZGFzaGVkIGJvcmRlci1ncmF5LTMwMCByb3VuZGVkLTJ4bCBwLTQgZmxleCBmbGV4LWNvbCBpdGVtcy1jZW50ZXIganVzdGlmeS1jZW50ZXIgdGV4dC1jZW50ZXIgY3Vyc29yLXBvaW50ZXIgbWluLWgtWzEwMHB4XSBzaGFkb3ctc20nOwogICAgICAgICAgICAgICAgem9uZS5kYXRhc2V0LmlkID0gdG9vbC5pZDsKICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgem9uZS5pbm5lckhUTUwgPSBgCiAgICAgICAgICAgICAgICAgICAgPGkgY2xhc3M9ImZhLXNvbGlkICR7dG9vbC5pY29ufSB0ZXh0LTN4bCB0ZXh0LWdyYXktNTAwIG1iLTIgem9uZS1pY29uIHRyYW5zaXRpb24tY29sb3JzIj48L2k+CiAgICAgICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9ImZvbnQtc2VtaWJvbGQgdGV4dC1ncmF5LTcwMCB0ZXh0LXNtIHpvbmUtdGV4dCB0cmFuc2l0aW9uLWNvbG9ycyI+JHt0b29sLm5hbWV9PC9zcGFuPgogICAgICAgICAgICAgICAgYDsKCiAgICAgICAgICAgICAgICAvLyBFdmVudCBMaXN0ZW5lcnMgdW50dWsgTW91c2UgKERlc2t0b3ApCiAgICAgICAgICAgICAgICB6b25lLmFkZEV2ZW50TGlzdGVuZXIoJ2RyYWdvdmVyJywgaGFuZGxlRHJhZ092ZXIpOwogICAgICAgICAgICAgICAgem9uZS5hZGRFdmVudExpc3RlbmVyKCdkcmFnZW50ZXInLCBoYW5kbGVEcmFnRW50ZXIpOwogICAgICAgICAgICAgICAgem9uZS5hZGRFdmVudExpc3RlbmVyKCdkcmFnbGVhdmUnLCBoYW5kbGVEcmFnTGVhdmUpOwogICAgICAgICAgICAgICAgem9uZS5hZGRFdmVudExpc3RlbmVyKCdkcm9wJywgaGFuZGxlRHJvcCk7CgogICAgICAgICAgICAgICAgZHJvcFpvbmVzQ29udGFpbmVyLmFwcGVuZENoaWxkKHpvbmUpOwogICAgICAgICAgICB9KTsKICAgICAgICB9CgogICAgICAgIGZ1bmN0aW9uIHVwZGF0ZVNjb3JlKCkgewogICAgICAgICAgICBzY29yZVRleHQudGV4dENvbnRlbnQgPSBzY29yZTsKICAgICAgICB9CgogICAgICAgIGZ1bmN0aW9uIGNoZWNrQW5zd2VyKHNlbGVjdGVkSWQsIGRyb3Bab25lRWxlbWVudCkgewogICAgICAgICAgICBjb25zdCBjb3JyZWN0SWQgPSBxdWVzdGlvbnNbY3VycmVudFF1ZXN0aW9uSW5kZXhdLmNvcnJlY3RJZDsKICAgICAgICAgICAgY29uc3QgaWNvbkVsID0gZHJvcFpvbmVFbGVtZW50LnF1ZXJ5U2VsZWN0b3IoJy56b25lLWljb24nKTsKICAgICAgICAgICAgY29uc3QgdGV4dEVsID0gZHJvcFpvbmVFbGVtZW50LnF1ZXJ5U2VsZWN0b3IoJy56b25lLXRleHQnKTsKCiAgICAgICAgICAgIGlmIChzZWxlY3RlZElkID09PSBjb3JyZWN0SWQpIHsKICAgICAgICAgICAgICAgIC8vIEJlbmFyCiAgICAgICAgICAgICAgICBzY29yZSArPSAxMDsKICAgICAgICAgICAgICAgIHVwZGF0ZVNjb3JlKCk7CiAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgIGRyb3Bab25lRWxlbWVudC5jbGFzc0xpc3QuYWRkKCdjb3JyZWN0Jyk7CiAgICAgICAgICAgICAgICBpY29uRWwuY2xhc3NMaXN0LnJlbW92ZSgndGV4dC1ncmF5LTUwMCcpOwogICAgICAgICAgICAgICAgaWNvbkVsLmNsYXNzTGlzdC5hZGQoJ3RleHQtZ3JlZW4tNjAwJyk7CiAgICAgICAgICAgICAgICB0ZXh0RWwuY2xhc3NMaXN0LmFkZCgndGV4dC1ncmVlbi04MDAnKTsKICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgLy8gU2VtYnVueWlrYW4ga2FydHUgdHVnYXMgZGVuZ2FuIGVmZWsKICAgICAgICAgICAgICAgIHRhc2tDYXJkLnN0eWxlLm9wYWNpdHkgPSAnMCc7CiAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgIC8vIExhbmp1dCBwZXJ0YW55YWFuIGJlcmlrdXRueWEKICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4gewogICAgICAgICAgICAgICAgICAgIGN1cnJlbnRRdWVzdGlvbkluZGV4Kys7CiAgICAgICAgICAgICAgICAgICAgbG9hZFF1ZXN0aW9uKCk7CiAgICAgICAgICAgICAgICB9LCAxMDAwKTsKCiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAvLyBTYWxhaCDigJQgdGlkYWsgZGFwYXQgbmlsYWksIGxhbmdzdW5nIGxhbmp1dCBrZSBzb2FsIGJlcmlrdXRueWEKICAgICAgICAgICAgICAgIGRyb3Bab25lRWxlbWVudC5jbGFzc0xpc3QuYWRkKCd3cm9uZycpOwogICAgICAgICAgICAgICAgaWNvbkVsLmNsYXNzTGlzdC5yZW1vdmUoJ3RleHQtZ3JheS01MDAnKTsKICAgICAgICAgICAgICAgIGljb25FbC5jbGFzc0xpc3QuYWRkKCd0ZXh0LXJlZC02MDAnKTsKICAgICAgICAgICAgICAgIHRleHRFbC5jbGFzc0xpc3QuYWRkKCd0ZXh0LXJlZC04MDAnKTsKCiAgICAgICAgICAgICAgICB0YXNrQ2FyZC5jbGFzc0xpc3QuYWRkKCdzaGFrZScpOwogICAgICAgICAgICAgICAgdGFza0NhcmQuc3R5bGUudmlzaWJpbGl0eSA9ICd2aXNpYmxlJzsgLy8gUGFzdGlrYW4gdGVybGloYXQgbGFnaQoKICAgICAgICAgICAgICAgIC8vIEt1bmNpIHNlbXVhIGtvdGFrIGphd2FiYW4gYWdhciB0aWRhayBiaXNhIGRpY29iYSB1bGFuZyBwYWRhIHNvYWwgaW5pCiAgICAgICAgICAgICAgICBkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKCcuZHJvcC16b25lJykuZm9yRWFjaCh6ID0+IHsKICAgICAgICAgICAgICAgICAgICB6LnN0eWxlLnBvaW50ZXJFdmVudHMgPSAnbm9uZSc7CiAgICAgICAgICAgICAgICB9KTsKCiAgICAgICAgICAgICAgICAvLyBTZW1idW55aWthbiBrYXJ0dSB0dWdhcyBsYWx1IGxhbmp1dCBrZSBwZXJ0YW55YWFuIGJlcmlrdXRueWEKICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4gewogICAgICAgICAgICAgICAgICAgIHRhc2tDYXJkLnN0eWxlLm9wYWNpdHkgPSAnMCc7CiAgICAgICAgICAgICAgICB9LCA1MDApOwoKICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4gewogICAgICAgICAgICAgICAgICAgIGN1cnJlbnRRdWVzdGlvbkluZGV4Kys7CiAgICAgICAgICAgICAgICAgICAgbG9hZFF1ZXN0aW9uKCk7CiAgICAgICAgICAgICAgICB9LCAxMTAwKTsKICAgICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgZnVuY3Rpb24gZW5kR2FtZSgpIHsKICAgICAgICAgICAgZ2FtZVNjcmVlbi5jbGFzc0xpc3QuYWRkKCdoaWRkZW4nKTsKICAgICAgICAgICAgZW5kU2NyZWVuLmNsYXNzTGlzdC5yZW1vdmUoJ2hpZGRlbicpOwogICAgICAgICAgICBlbmRTY3JlZW4uY2xhc3NMaXN0LmFkZCgnYm91bmNlLWluJyk7CiAgICAgICAgICAgIAogICAgICAgICAgICBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnZmluYWwtc2NvcmUnKS50ZXh0Q29udGVudCA9IHNjb3JlOwoKICAgICAgICAgICAgLy8gS2lyaW0gc2tvciBha2hpciBrZSBoYWxhbWFuIGluZHVrIChkaXBha2FpIHVudHVrIG1lbnlhdHVrYW4KICAgICAgICAgICAgLy8gaGFzaWwgZ2FtZSBkZW5nYW4gVHVnYXMgUHJpYmFkaSBkaSBoYWxhbWFuIG1hdGVyaSkKICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICAgIHdpbmRvdy5wYXJlbnQucG9zdE1lc3NhZ2UoewogICAgICAgICAgICAgICAgICAgIHNvdXJjZTogJ21hc3Rlci1wZW5nb2xhaC1rYXRhJywKICAgICAgICAgICAgICAgICAgICBzY29yZTogc2NvcmUsCiAgICAgICAgICAgICAgICAgICAgbWF4U2NvcmU6IHF1ZXN0aW9ucy5sZW5ndGggKiAxMAogICAgICAgICAgICAgICAgfSwgJyonKTsKICAgICAgICAgICAgfSBjYXRjaCAoZXJyKSB7IC8qIGFiYWlrYW4gamlrYSB0aWRhayBiZXJqYWxhbiBkaSBkYWxhbSBpZnJhbWUgKi8gfQogICAgICAgICAgICAKICAgICAgICAgICAgbGV0IGZlZWRiYWNrID0gIiI7CiAgICAgICAgICAgIC8vIE1lbnllc3VhaWthbiBsb2dpa2EgcG9pbiB1bnR1ayBtYWtzaW1hbCBza29yIDUwMCAoNTAgc29hbCkKICAgICAgICAgICAgaWYgKHNjb3JlID09PSA1MDApIGZlZWRiYWNrID0gIkx1YXIgQmlhc2EgU2VtcHVybmEhIEFuZGEgYWRhbGFoIFNhbmcgTWFzdGVyIFBlbmdvbGFoIEthdGEuIPCfjJ8iOwogICAgICAgICAgICBlbHNlIGlmIChzY29yZSA+PSA0MDApIGZlZWRiYWNrID0gIkhlYmF0IHNla2FsaSEgS2V0ZXJhbXBpbGFuIGFwbGlrYXNpIHBlcmthbnRvcmFuIEFuZGEgc2V0YXJhIHNla3JldGFyaXMgaGFuZGFsLiDwn5GNIjsKICAgICAgICAgICAgZWxzZSBpZiAoc2NvcmUgPj0gMjUwKSBmZWVkYmFjayA9ICJDdWt1cCBiYWlrLCB0YXBpIG1hc2loIGJhbnlhayBmaXR1ciBsYW5qdXRhbiB5YW5nIHBlcmx1IEFuZGEgcGVsYWphcmkuIFRldGFwIHNlbWFuZ2F0ISDwn5OaIjsKICAgICAgICAgICAgZWxzZSBmZWVkYmFjayA9ICJKYW5nYW4gbWVueWVyYWghIFRlcnVzIGJlcmxhdGloIGFnYXIgQW5kYSBsZWJpaCB0ZXJiaWFzYSBkZW5nYW4gZml0dXItZml0dXIgYWRtaW5pc3RyYXNpLiDwn5KqIjsKICAgICAgICAgICAgCiAgICAgICAgICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdmZWVkYmFjay1tc2cnKS50ZXh0Q29udGVudCA9IGZlZWRiYWNrOwogICAgICAgIH0KCiAgICAgICAgZnVuY3Rpb24gcmVzZXRHYW1lKCkgewogICAgICAgICAgICBlbmRTY3JlZW4uY2xhc3NMaXN0LmFkZCgnaGlkZGVuJyk7CiAgICAgICAgICAgIHN0YXJ0R2FtZSgpOwogICAgICAgIH0KCiAgICAgICAgLy8gLS0tIEVWRU5UIEhBTkRMRVJTIERSQUcgJiBEUk9QIChERVNLVE9QIC8gTU9VU0UpIC0tLQogICAgICAgIAogICAgICAgIHRhc2tDYXJkLmFkZEV2ZW50TGlzdGVuZXIoJ2RyYWdzdGFydCcsIChlKSA9PiB7CiAgICAgICAgICAgIGUuZGF0YVRyYW5zZmVyLnNldERhdGEoJ3RleHQvcGxhaW4nLCAndGFzaycpOwogICAgICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHRhc2tDYXJkLmNsYXNzTGlzdC5hZGQoJ29wYWNpdHktNTAnKSwgMCk7CiAgICAgICAgfSk7CgogICAgICAgIHRhc2tDYXJkLmFkZEV2ZW50TGlzdGVuZXIoJ2RyYWdlbmQnLCAoKSA9PiB7CiAgICAgICAgICAgIHRhc2tDYXJkLmNsYXNzTGlzdC5yZW1vdmUoJ29wYWNpdHktNTAnKTsKICAgICAgICB9KTsKCiAgICAgICAgZnVuY3Rpb24gaGFuZGxlRHJhZ092ZXIoZSkgewogICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7IC8vIFdhamliIGFnYXIgYmlzYSBkaS1kcm9wCiAgICAgICAgfQoKICAgICAgICBmdW5jdGlvbiBoYW5kbGVEcmFnRW50ZXIoZSkgewogICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7CiAgICAgICAgICAgIGNvbnN0IHpvbmUgPSBlLnRhcmdldC5jbG9zZXN0KCcuZHJvcC16b25lJyk7CiAgICAgICAgICAgIGlmICh6b25lKSB6b25lLmNsYXNzTGlzdC5hZGQoJ2RyYWctb3ZlcicpOwogICAgICAgIH0KCiAgICAgICAgZnVuY3Rpb24gaGFuZGxlRHJhZ0xlYXZlKGUpIHsKICAgICAgICAgICAgY29uc3Qgem9uZSA9IGUudGFyZ2V0LmNsb3Nlc3QoJy5kcm9wLXpvbmUnKTsKICAgICAgICAgICAgaWYgKHpvbmUpIHpvbmUuY2xhc3NMaXN0LnJlbW92ZSgnZHJhZy1vdmVyJyk7CiAgICAgICAgfQoKICAgICAgICBmdW5jdGlvbiBoYW5kbGVEcm9wKGUpIHsKICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpOwogICAgICAgICAgICBjb25zdCB6b25lID0gZS50YXJnZXQuY2xvc2VzdCgnLmRyb3Atem9uZScpOwogICAgICAgICAgICBpZiAoem9uZSkgewogICAgICAgICAgICAgICAgem9uZS5jbGFzc0xpc3QucmVtb3ZlKCdkcmFnLW92ZXInKTsKICAgICAgICAgICAgICAgIGNvbnN0IHNlbGVjdGVkSWQgPSB6b25lLmRhdGFzZXQuaWQ7CiAgICAgICAgICAgICAgICBjaGVja0Fuc3dlcihzZWxlY3RlZElkLCB6b25lKTsKICAgICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgLy8gLS0tIEVWRU5UIEhBTkRMRVJTIERSQUcgJiBEUk9QIChNT0JJTEUgLyBUT1VDSCBTQ1JFRU4pIC0tLQogICAgICAgIC8vIEthcmVuYSBIVE1MNSBEcmFnICYgRHJvcCBrdXJhbmcgcmVzcG9uc2lmIGRpIGxheWFyIHNlbnR1aCwga2l0YSBidWF0IGt1c3RvbQogICAgICAgIAogICAgICAgIHRhc2tDYXJkLmFkZEV2ZW50TGlzdGVuZXIoJ3RvdWNoc3RhcnQnLCBoYW5kbGVUb3VjaFN0YXJ0LCB7cGFzc2l2ZTogZmFsc2V9KTsKICAgICAgICB0YXNrQ2FyZC5hZGRFdmVudExpc3RlbmVyKCd0b3VjaG1vdmUnLCBoYW5kbGVUb3VjaE1vdmUsIHtwYXNzaXZlOiBmYWxzZX0pOwogICAgICAgIHRhc2tDYXJkLmFkZEV2ZW50TGlzdGVuZXIoJ3RvdWNoZW5kJywgaGFuZGxlVG91Y2hFbmQpOwoKICAgICAgICBmdW5jdGlvbiBoYW5kbGVUb3VjaFN0YXJ0KGUpIHsKICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpOyAvLyBNZW5jZWdhaCBzY3JvbGxpbmcgc2FhdCBtZW55ZW50dWgga2FydHUKICAgICAgICAgICAgY29uc3QgdG91Y2ggPSBlLnRvdWNoZXNbMF07CiAgICAgICAgICAgIAogICAgICAgICAgICAvLyBCdWF0IGtsb25pbmdhbiBrYXJ0dSB1bnR1ayB2aXN1YWwgZHJhZwogICAgICAgICAgICBjb25zdCByZWN0ID0gdGFza0NhcmQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7CiAgICAgICAgICAgIGNsb25lQ2FyZCA9IHRhc2tDYXJkLmNsb25lTm9kZSh0cnVlKTsKICAgICAgICAgICAgY2xvbmVDYXJkLmNsYXNzTGlzdC5hZGQoJ2Fic29sdXRlLWRyYWcnLCAnc2hhZG93LTJ4bCcsICdvcGFjaXR5LTkwJywgJ3NjYWxlLTEwNScpOwogICAgICAgICAgICAKICAgICAgICAgICAgLy8gU2V0IHBvc2lzaSBhd2FsCiAgICAgICAgICAgIGNsb25lQ2FyZC5zdHlsZS53aWR0aCA9IGAke3JlY3Qud2lkdGh9cHhgOwogICAgICAgICAgICBjbG9uZUNhcmQuc3R5bGUuaGVpZ2h0ID0gYCR7cmVjdC5oZWlnaHR9cHhgOwogICAgICAgICAgICBjbG9uZUNhcmQuc3R5bGUubGVmdCA9IGAke3JlY3QubGVmdH1weGA7CiAgICAgICAgICAgIGNsb25lQ2FyZC5zdHlsZS50b3AgPSBgJHtyZWN0LnRvcH1weGA7CiAgICAgICAgICAgIAogICAgICAgICAgICBkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKGNsb25lQ2FyZCk7CiAgICAgICAgICAgIHRhc2tDYXJkLnN0eWxlLnZpc2liaWxpdHkgPSAnaGlkZGVuJzsgLy8gU2VtYnVueWlrYW4gYXNsaW55YQoKICAgICAgICAgICAgLy8gSGl0dW5nIG9mZnNldCBzZW50dWhhbgogICAgICAgICAgICBzdGFydFggPSB0b3VjaC5jbGllbnRYOwogICAgICAgICAgICBzdGFydFkgPSB0b3VjaC5jbGllbnRZOwogICAgICAgICAgICBpbml0aWFsWCA9IHJlY3QubGVmdDsKICAgICAgICAgICAgaW5pdGlhbFkgPSByZWN0LnRvcDsKICAgICAgICB9CgogICAgICAgIGZ1bmN0aW9uIGhhbmRsZVRvdWNoTW92ZShlKSB7CiAgICAgICAgICAgIGlmICghY2xvbmVDYXJkKSByZXR1cm47CiAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTsKICAgICAgICAgICAgY29uc3QgdG91Y2ggPSBlLnRvdWNoZXNbMF07CiAgICAgICAgICAgIAogICAgICAgICAgICBjb25zdCBkeCA9IHRvdWNoLmNsaWVudFggLSBzdGFydFg7CiAgICAgICAgICAgIGNvbnN0IGR5ID0gdG91Y2guY2xpZW50WSAtIHN0YXJ0WTsKICAgICAgICAgICAgCiAgICAgICAgICAgIGNsb25lQ2FyZC5zdHlsZS5sZWZ0ID0gYCR7aW5pdGlhbFggKyBkeH1weGA7CiAgICAgICAgICAgIGNsb25lQ2FyZC5zdHlsZS50b3AgPSBgJHtpbml0aWFsWSArIGR5fXB4YDsKCiAgICAgICAgICAgIC8vIEVmZWsgaG92ZXIgcGFkYSBkcm9wem9uZSBzYWF0IHRvdWNoIG1vdmUKICAgICAgICAgICAgZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbCgnLmRyb3Atem9uZScpLmZvckVhY2goeiA9PiB6LmNsYXNzTGlzdC5yZW1vdmUoJ2RyYWctb3ZlcicpKTsKICAgICAgICAgICAgCiAgICAgICAgICAgIC8vIFNlbWJ1bnlpa2FuIGtsb25pbmdhbiBzZW1lbnRhcmEgdW50dWsgbWVuZGV0ZWtzaSBlbGVtZW4gZGkgYmF3YWhueWEKICAgICAgICAgICAgY2xvbmVDYXJkLnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7CiAgICAgICAgICAgIGNvbnN0IGVsZW1CZWxvdyA9IGRvY3VtZW50LmVsZW1lbnRGcm9tUG9pbnQodG91Y2guY2xpZW50WCwgdG91Y2guY2xpZW50WSk7CiAgICAgICAgICAgIGNsb25lQ2FyZC5zdHlsZS5kaXNwbGF5ID0gJ2Jsb2NrJzsKCiAgICAgICAgICAgIGlmIChlbGVtQmVsb3cpIHsKICAgICAgICAgICAgICAgIGNvbnN0IHpvbmUgPSBlbGVtQmVsb3cuY2xvc2VzdCgnLmRyb3Atem9uZScpOwogICAgICAgICAgICAgICAgaWYgKHpvbmUpIHpvbmUuY2xhc3NMaXN0LmFkZCgnZHJhZy1vdmVyJyk7CiAgICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIGZ1bmN0aW9uIGhhbmRsZVRvdWNoRW5kKGUpIHsKICAgICAgICAgICAgaWYgKCFjbG9uZUNhcmQpIHJldHVybjsKICAgICAgICAgICAgCiAgICAgICAgICAgIGNvbnN0IHRvdWNoID0gZS5jaGFuZ2VkVG91Y2hlc1swXTsKICAgICAgICAgICAgCiAgICAgICAgICAgIC8vIERldGVrc2kgem9uYSBkcm9wCiAgICAgICAgICAgIGNsb25lQ2FyZC5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnOwogICAgICAgICAgICBjb25zdCBlbGVtQmVsb3cgPSBkb2N1bWVudC5lbGVtZW50RnJvbVBvaW50KHRvdWNoLmNsaWVudFgsIHRvdWNoLmNsaWVudFkpOwogICAgICAgICAgICAKICAgICAgICAgICAgLy8gSGFwdXMga2xvbmluZ2FuIHZpc3VhbAogICAgICAgICAgICBkb2N1bWVudC5ib2R5LnJlbW92ZUNoaWxkKGNsb25lQ2FyZCk7CiAgICAgICAgICAgIGNsb25lQ2FyZCA9IG51bGw7CiAgICAgICAgICAgIAogICAgICAgICAgICBsZXQgZHJvcHBlZE9uWm9uZSA9IGZhbHNlOwoKICAgICAgICAgICAgaWYgKGVsZW1CZWxvdykgewogICAgICAgICAgICAgICAgY29uc3Qgem9uZSA9IGVsZW1CZWxvdy5jbG9zZXN0KCcuZHJvcC16b25lJyk7CiAgICAgICAgICAgICAgICBpZiAoem9uZSkgewogICAgICAgICAgICAgICAgICAgIGRyb3BwZWRPblpvbmUgPSB0cnVlOwogICAgICAgICAgICAgICAgICAgIHpvbmUuY2xhc3NMaXN0LnJlbW92ZSgnZHJhZy1vdmVyJyk7CiAgICAgICAgICAgICAgICAgICAgY29uc3Qgc2VsZWN0ZWRJZCA9IHpvbmUuZGF0YXNldC5pZDsKICAgICAgICAgICAgICAgICAgICBjaGVja0Fuc3dlcihzZWxlY3RlZElkLCB6b25lKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQoKICAgICAgICAgICAgLy8gSmlrYSB0aWRhayBkaWxlcGFzIGRpIGRyb3Agem9uZSwga2VtYmFsaWthbiBrYXJ0dSBrZSBwb3Npc2kgYXdhbAogICAgICAgICAgICBpZiAoIWRyb3BwZWRPblpvbmUpIHsKICAgICAgICAgICAgICAgIHRhc2tDYXJkLnN0eWxlLnZpc2liaWxpdHkgPSAndmlzaWJsZSc7CiAgICAgICAgICAgICAgICB0YXNrQ2FyZC5jbGFzc0xpc3QuYWRkKCdzaGFrZScpOwogICAgICAgICAgICAgICAgc2V0VGltZW91dCgoKSA9PiB0YXNrQ2FyZC5jbGFzc0xpc3QucmVtb3ZlKCdzaGFrZScpLCA0MDApOwogICAgICAgICAgICB9CiAgICAgICAgfQoKICAgIDwvc2NyaXB0Pgo8L2JvZHk+CjwvaHRtbD4=" target="_blank" rel="noopener"&gt;Buka game di layar penuh (tab baru)&lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="game-wrap"&gt;
          &lt;iframe id="gameFrame" src="data:text/html;base64,PCFET0NUWVBFIGh0bWw+CjxodG1sIGxhbmc9ImlkIj4KPGhlYWQ+CiAgICA8bWV0YSBjaGFyc2V0PSJVVEYtOCI+CiAgICA8bWV0YSBuYW1lPSJ2aWV3cG9ydCIgY29udGVudD0id2lkdGg9ZGV2aWNlLXdpZHRoLCBpbml0aWFsLXNjYWxlPTEuMCwgbWF4aW11bS1zY2FsZT0xLjAsIHVzZXItc2NhbGFibGU9bm8iPgogICAgPHRpdGxlPkdhbWUgQWRtaW5pc3RyYXNpOiBNYXN0ZXIgUGVuZ29sYWggS2F0YTwvdGl0bGU+CiAgICA8IS0tIFRhaWx3aW5kIENTUyB1bnR1ayBTdHlsaW5nIENlcGF0IGRhbiBSZXNwb25zaWYgLS0+CiAgICA8c2NyaXB0IHNyYz0iaHR0cHM6Ly9jZG4udGFpbHdpbmRjc3MuY29tIj48L3NjcmlwdD4KICAgIDwhLS0gRm9udEF3ZXNvbWUgdW50dWsgSWtvbiBNZW51IFBlbmdvbGFoIEthdGEgLS0+CiAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9Imh0dHBzOi8vY2RuanMuY2xvdWRmbGFyZS5jb20vYWpheC9saWJzL2ZvbnQtYXdlc29tZS82LjQuMC9jc3MvYWxsLm1pbi5jc3MiPgogICAgPCEtLSBHb29nbGUgRm9udHMgKFBvcHBpbnMpIC0tPgogICAgPGxpbmsgaHJlZj0iaHR0cHM6Ly9mb250cy5nb29nbGVhcGlzLmNvbS9jc3MyP2ZhbWlseT1Qb3BwaW5zOndnaHRANDAwOzYwMDs3MDAmZGlzcGxheT1zd2FwIiByZWw9InN0eWxlc2hlZXQiPgogICAgCiAgICA8c3R5bGU+CiAgICAgICAgYm9keSB7CiAgICAgICAgICAgIGZvbnQtZmFtaWx5OiAnUG9wcGlucycsIHNhbnMtc2VyaWY7CiAgICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6ICNmMGZkZjQ7IC8qIEhpamF1IHNhbmdhdCBtdWRhL3NlZ2FyICovCiAgICAgICAgICAgIHRvdWNoLWFjdGlvbjogcGFuLXk7IC8qIE1lbmNlZ2FoIHB1bGwtdG8tcmVmcmVzaCBkaSBtb2JpbGUgKi8KICAgICAgICAgICAgb3ZlcmZsb3cteDogaGlkZGVuOwogICAgICAgIH0KCiAgICAgICAgLyogQW5pbWFzaSAqLwogICAgICAgIC5ib3VuY2UtaW4gewogICAgICAgICAgICBhbmltYXRpb246IGJvdW5jZUluIDAuNXMgY3ViaWMtYmV6aWVyKDAuMTc1LCAwLjg4NSwgMC4zMiwgMS4yNzUpOwogICAgICAgIH0KICAgICAgICBAa2V5ZnJhbWVzIGJvdW5jZUluIHsKICAgICAgICAgICAgMCUgeyB0cmFuc2Zvcm06IHNjYWxlKDAuNSk7IG9wYWNpdHk6IDA7IH0KICAgICAgICAgICAgMTAwJSB7IHRyYW5zZm9ybTogc2NhbGUoMSk7IG9wYWNpdHk6IDE7IH0KICAgICAgICB9CgogICAgICAgIC5zaGFrZSB7CiAgICAgICAgICAgIGFuaW1hdGlvbjogc2hha2UgMC40czsKICAgICAgICB9CiAgICAgICAgQGtleWZyYW1lcyBzaGFrZSB7CiAgICAgICAgICAgIDAlLCAxMDAlIHsgdHJhbnNmb3JtOiB0cmFuc2xhdGVYKDApOyB9CiAgICAgICAgICAgIDI1JSB7IHRyYW5zZm9ybTogdHJhbnNsYXRlWCgtMTBweCk7IH0KICAgICAgICAgICAgNTAlIHsgdHJhbnNmb3JtOiB0cmFuc2xhdGVYKDEwcHgpOyB9CiAgICAgICAgICAgIDc1JSB7IHRyYW5zZm9ybTogdHJhbnNsYXRlWCgtMTBweCk7IH0KICAgICAgICB9CgogICAgICAgIC8qIFN0eWxpbmcgS2FydHUgRHJhZ2dhYmxlICovCiAgICAgICAgLmRyYWdnYWJsZS1jYXJkIHsKICAgICAgICAgICAgY3Vyc29yOiBncmFiOwogICAgICAgICAgICB0b3VjaC1hY3Rpb246IG5vbmU7IC8qIFBlbnRpbmcgdW50dWsgY3VzdG9tIHRvdWNoIGRyYWcgKi8KICAgICAgICAgICAgdXNlci1zZWxlY3Q6IG5vbmU7CiAgICAgICAgICAgIHRyYW5zaXRpb246IHRyYW5zZm9ybSAwLjFzOwogICAgICAgIH0KICAgICAgICAuZHJhZ2dhYmxlLWNhcmQ6YWN0aXZlIHsKICAgICAgICAgICAgY3Vyc29yOiBncmFiYmluZzsKICAgICAgICB9CiAgICAgICAgLmRyYWdnaW5nIHsKICAgICAgICAgICAgb3BhY2l0eTogMC44OwogICAgICAgICAgICB0cmFuc2Zvcm06IHNjYWxlKDEuMDUpOwogICAgICAgICAgICB6LWluZGV4OiA1MDsKICAgICAgICB9CgogICAgICAgIC8qIFN0eWxpbmcgRHJvcCBab25lICovCiAgICAgICAgLmRyb3Atem9uZSB7CiAgICAgICAgICAgIHRyYW5zaXRpb246IGFsbCAwLjNzIGVhc2U7CiAgICAgICAgfQogICAgICAgIC5kcm9wLXpvbmUuZHJhZy1vdmVyIHsKICAgICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogI2RiZWFmZTsgLyogQmlydSBtdWRhIHNhYXQgZGktaG92ZXIgKi8KICAgICAgICAgICAgYm9yZGVyLWNvbG9yOiAjM2I4MmY2OwogICAgICAgICAgICB0cmFuc2Zvcm06IHNjYWxlKDEuMDUpOwogICAgICAgIH0KICAgICAgICAuZHJvcC16b25lLmNvcnJlY3QgewogICAgICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjZGNmY2U3OwogICAgICAgICAgICBib3JkZXItY29sb3I6ICMyMmM1NWU7CiAgICAgICAgICAgIGNvbG9yOiAjMTY2NTM0OwogICAgICAgIH0KICAgICAgICAuZHJvcC16b25lLndyb25nIHsKICAgICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogI2ZlZTJlMjsKICAgICAgICAgICAgYm9yZGVyLWNvbG9yOiAjZWY0NDQ0OwogICAgICAgICAgICBjb2xvcjogIzk5MWIxYjsKICAgICAgICB9CgogICAgICAgIC8qIFV0aWxpdHkgdW50dWsgY3VzdG9tIGRyYWcgbW9iaWxlICovCiAgICAgICAgLmFic29sdXRlLWRyYWcgewogICAgICAgICAgICBwb3NpdGlvbjogYWJzb2x1dGUgIWltcG9ydGFudDsKICAgICAgICAgICAgcG9pbnRlci1ldmVudHM6IG5vbmU7IC8qIFN1cGF5YSBlbGVtZW4gZGkgYmF3YWhueWEgKGRyb3Agem9uZSkgYmlzYSB0ZXJkZXRla3NpICovCiAgICAgICAgfQogICAgPC9zdHlsZT4KPC9oZWFkPgo8Ym9keSBjbGFzcz0ibWluLWgtc2NyZWVuIGZsZXggZmxleC1jb2wgaXRlbXMtY2VudGVyIGp1c3RpZnktY2VudGVyIHAtNCI+CgogICAgPCEtLSBMQVlBUiBNVUxBSSAtLT4KICAgIDxkaXYgaWQ9InN0YXJ0LXNjcmVlbiIgY2xhc3M9ImJnLXdoaXRlIHJvdW5kZWQtM3hsIHNoYWRvdy0yeGwgcC04IG1heC13LW1kIHctZnVsbCB0ZXh0LWNlbnRlciBib3VuY2UtaW4gYm9yZGVyLXQtOCBib3JkZXItYmx1ZS01MDAiPgogICAgICAgIDxpIGNsYXNzPSJmYS1zb2xpZCBmYS1sYXB0b3AtZmlsZSB0ZXh0LTZ4bCB0ZXh0LWJsdWUtNTAwIG1iLTQiPjwvaT4KICAgICAgICA8aDEgY2xhc3M9InRleHQtM3hsIGZvbnQtYm9sZCB0ZXh0LWdyYXktODAwIG1iLTIiPk1hc3RlciBQZW5nb2xhaCBLYXRhPC9oMT4KICAgICAgICA8cCBjbGFzcz0idGV4dC1ncmF5LTYwMCBtYi02IHRleHQtc20iPlVqaSBrZWFobGlhbiBhZG1pbmlzdHJhc2kgcGVya2FudG9yYW5tdSEgQmFjYSB0dWdhcyBkYXJpIGF0YXNhbiBkYW4gdGFyaWsgKGRyYWcpIGthcnR1IHR1Z2FzIGtlIGFsYXQvZml0dXIgeWFuZyB0ZXBhdC48L3A+CiAgICAgICAgPGJ1dHRvbiBvbmNsaWNrPSJzdGFydEdhbWUoKSIgY2xhc3M9InctZnVsbCBiZy1ibHVlLTYwMCBob3ZlcjpiZy1ibHVlLTcwMCB0ZXh0LXdoaXRlIGZvbnQtYm9sZCBweS0zIHB4LTYgcm91bmRlZC14bCB0cmFuc2l0aW9uIGR1cmF0aW9uLTIwMCB0cmFuc2Zvcm0gaG92ZXI6c2NhbGUtMTA1IHNoYWRvdy1sZyI+CiAgICAgICAgICAgIE11bGFpIEJla2VyamEgPGkgY2xhc3M9ImZhLXNvbGlkIGZhLXBsYXkgbWwtMiI+PC9pPgogICAgICAgIDwvYnV0dG9uPgogICAgPC9kaXY+CgogICAgPCEtLSBBUkVBIFBFUk1BSU5BTiAtLT4KICAgIDxkaXYgaWQ9ImdhbWUtc2NyZWVuIiBjbGFzcz0iaGlkZGVuIHctZnVsbCBtYXgtdy0zeGwgZmxleCBmbGV4LWNvbCBoLVs5MHZoXSBqdXN0aWZ5LWJldHdlZW4iPgogICAgICAgIDwhLS0gSGVhZGVyOiBTa29yICYgUHJvZ3JlcyAtLT4KICAgICAgICA8ZGl2IGNsYXNzPSJiZy13aGl0ZSByb3VuZGVkLTJ4bCBzaGFkb3ctbWQgcC00IGZsZXgganVzdGlmeS1iZXR3ZWVuIGl0ZW1zLWNlbnRlciBtYi00Ij4KICAgICAgICAgICAgPGRpdiBjbGFzcz0idGV4dC1ibHVlLTYwMCBmb250LWJvbGQiPgogICAgICAgICAgICAgICAgPGkgY2xhc3M9ImZhLXNvbGlkIGZhLWxpc3QtY2hlY2siPjwvaT4gVHVnYXM6IDxzcGFuIGlkPSJwcm9ncmVzcy10ZXh0Ij4xLzEwPC9zcGFuPgogICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgPGRpdiBjbGFzcz0idGV4dC1ncmVlbi02MDAgZm9udC1ib2xkIHRleHQteGwiPgogICAgICAgICAgICAgICAgPGkgY2xhc3M9ImZhLXNvbGlkIGZhLXN0YXIgdGV4dC15ZWxsb3ctNDAwIj48L2k+IFNrb3I6IDxzcGFuIGlkPSJzY29yZS10ZXh0Ij4wPC9zcGFuPgogICAgICAgICAgICA8L2Rpdj4KICAgICAgICA8L2Rpdj4KCiAgICAgICAgPCEtLSBBcmVhIFBlcnRhbnlhYW4gKEthcnR1IERyYWdnYWJsZSkgLS0+CiAgICAgICAgPGRpdiBjbGFzcz0iZmxleC1ncm93IGZsZXggZmxleC1jb2wgaXRlbXMtY2VudGVyIGp1c3RpZnktY2VudGVyIG1iLTYgcmVsYXRpdmUiIGlkPSJkcmFnLWNvbnRhaW5lciI+CiAgICAgICAgICAgIDxoMiBjbGFzcz0idGV4dC1ncmF5LTYwMCB0ZXh0LWNlbnRlciB0ZXh0LXNtIGZvbnQtc2VtaWJvbGQgbWItMyB1cHBlcmNhc2UgdHJhY2tpbmctd2lkZSI+VHVnYXMgQW5kYTo8L2gyPgogICAgICAgICAgICA8ZGl2IGlkPSJ0YXNrLWNhcmQiIGNsYXNzPSJkcmFnZ2FibGUtY2FyZCBiZy1ibHVlLTUwMCB0ZXh0LXdoaXRlIHJvdW5kZWQtMnhsIHNoYWRvdy14bCBwLTYgdy1mdWxsIG1heC13LXNtIHRleHQtY2VudGVyIGJvcmRlci1iLTQgYm9yZGVyLWJsdWUtNzAwIG14LWF1dG8iIGRyYWdnYWJsZT0idHJ1ZSI+CiAgICAgICAgICAgICAgICA8aSBjbGFzcz0iZmEtc29saWQgZmEtZW52ZWxvcGUtb3Blbi10ZXh0IHRleHQtM3hsIG1iLTMgdGV4dC1ibHVlLTIwMCI+PC9pPgogICAgICAgICAgICAgICAgPHAgaWQ9InRhc2stZGVzYyIgY2xhc3M9InRleHQtbGcgZm9udC1zZW1pYm9sZCBsZWFkaW5nLXNudWciPgogICAgICAgICAgICAgICAgICAgIDwhLS0gRGVza3JpcHNpIGFrYW4gZGktbG9hZCBkaSBzaW5pIC0tPgogICAgICAgICAgICAgICAgPC9wPgogICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0ibXQtNCB0ZXh0LWJsdWUtMjAwIHRleHQteHMgZmxleCBpdGVtcy1jZW50ZXIganVzdGlmeS1jZW50ZXIgZ2FwLTIiPgogICAgICAgICAgICAgICAgICAgIDxpIGNsYXNzPSJmYS1zb2xpZCBmYS1oYW5kLXBvaW50ZXIiPjwvaT4gVGFyaWsga2FydHUgaW5pIGtlIGFsYXQgZGkgYmF3YWgKICAgICAgICAgICAgICAgIDwvZGl2PgogICAgICAgICAgICA8L2Rpdj4KICAgICAgICA8L2Rpdj4KCiAgICAgICAgPCEtLSBBcmVhIERyb3AgWm9uZSAoUGlsaWhhbiBBbGF0KSAtLT4KICAgICAgICA8ZGl2IGNsYXNzPSJncmlkIGdyaWQtY29scy0yIG1kOmdyaWQtY29scy0zIGdhcC0zIG1kOmdhcC00IHBiLTQiIGlkPSJkcm9wLXpvbmVzLWNvbnRhaW5lciI+CiAgICAgICAgICAgIDwhLS0gS290YWsgcGlsaWhhbiBha2FuIGRpLWdlbmVyYXRlIG9sZWggSmF2YVNjcmlwdCAtLT4KICAgICAgICA8L2Rpdj4KICAgIDwvZGl2PgoKICAgIDwhLS0gTEFZQVIgQUtISVIgLS0+CiAgICA8ZGl2IGlkPSJlbmQtc2NyZWVuIiBjbGFzcz0iaGlkZGVuIGJnLXdoaXRlIHJvdW5kZWQtM3hsIHNoYWRvdy0yeGwgcC04IG1heC13LW1kIHctZnVsbCB0ZXh0LWNlbnRlciBib3VuY2UtaW4gYm9yZGVyLXQtOCBib3JkZXItZ3JlZW4tNTAwIj4KICAgICAgICA8aSBjbGFzcz0iZmEtc29saWQgZmEtYXdhcmQgdGV4dC03eGwgdGV4dC15ZWxsb3ctNDAwIG1iLTQiPjwvaT4KICAgICAgICA8aDEgY2xhc3M9InRleHQtM3hsIGZvbnQtYm9sZCB0ZXh0LWdyYXktODAwIG1iLTIiPktlcmphIEJhZ3VzITwvaDE+CiAgICAgICAgPHAgY2xhc3M9InRleHQtZ3JheS02MDAgbWItMiI+QW5kYSB0ZWxhaCBtZW55ZWxlc2Fpa2FuIGphbSBrZXJqYSBkZW5nYW4gYmFpay48L3A+CiAgICAgICAgPGRpdiBjbGFzcz0idGV4dC01eGwgZm9udC1ib2xkIHRleHQtYmx1ZS02MDAgbXktNiIgaWQ9ImZpbmFsLXNjb3JlIj4xMDA8L2Rpdj4KICAgICAgICA8cCBpZD0iZmVlZGJhY2stbXNnIiBjbGFzcz0idGV4dC1ncmF5LTYwMCBmb250LXNlbWlib2xkIG1iLTYiPjwvcD4KICAgICAgICA8YnV0dG9uIG9uY2xpY2s9InJlc2V0R2FtZSgpIiBjbGFzcz0idy1mdWxsIGJnLWdyZWVuLTUwMCBob3ZlcjpiZy1ncmVlbi02MDAgdGV4dC13aGl0ZSBmb250LWJvbGQgcHktMyBweC02IHJvdW5kZWQteGwgdHJhbnNpdGlvbiBkdXJhdGlvbi0yMDAgc2hhZG93LWxnIj4KICAgICAgICAgICAgTWFpbiBMYWdpIDxpIGNsYXNzPSJmYS1zb2xpZCBmYS1yb3RhdGUtcmlnaHQgbWwtMiI+PC9pPgogICAgICAgIDwvYnV0dG9uPgogICAgPC9kaXY+CgogICAgPHNjcmlwdD4KICAgICAgICAvLyAtLS0gREFUQSBNQVNURVIgLS0tCiAgICAgICAgLy8gS3VtcHVsYW4gc2VtdWEgYWxhdC9maXR1ciB1bnR1ayBtZW1idWF0IHBlbmdlY29oIChkaXN0cmFjdG9ycykKICAgICAgICBjb25zdCBhbGxUb29scyA9IFsKICAgICAgICAgICAgeyBpZDogJ25ldycsIG5hbWU6ICdOZXcgRG9jdW1lbnQnLCBpY29uOiAnZmEtZmlsZS1jaXJjbGUtcGx1cycgfSwKICAgICAgICAgICAgeyBpZDogJ3NhdmUnLCBuYW1lOiAnU2F2ZSAvIFNhdmUgQXMnLCBpY29uOiAnZmEtZmxvcHB5LWRpc2snIH0sCiAgICAgICAgICAgIHsgaWQ6ICdib2xkJywgbmFtZTogJ0JvbGQnLCBpY29uOiAnZmEtYm9sZCcgfSwKICAgICAgICAgICAgeyBpZDogJ2p1c3RpZnknLCBuYW1lOiAnSnVzdGlmeScsIGljb246ICdmYS1hbGlnbi1qdXN0aWZ5JyB9LAogICAgICAgICAgICB7IGlkOiAnY29weScsIG5hbWU6ICdDb3B5JywgaWNvbjogJ2ZhLWNvcHknIH0sCiAgICAgICAgICAgIHsgaWQ6ICdwYWdlc2l6ZScsIG5hbWU6ICdQYWdlIFNpemUnLCBpY29uOiAnZmEtZmlsZS1saW5lcycgfSwKICAgICAgICAgICAgeyBpZDogJ3VuZG8nLCBuYW1lOiAnVW5kbycsIGljb246ICdmYS1yb3RhdGUtbGVmdCcgfSwKICAgICAgICAgICAgeyBpZDogJ251bWJlcmluZycsIG5hbWU6ICdOdW1iZXJpbmcnLCBpY29uOiAnZmEtbGlzdC1vbCcgfSwKICAgICAgICAgICAgeyBpZDogJ2ZpbmQnLCBuYW1lOiAnRmluZCAmIFJlcGxhY2UnLCBpY29uOiAnZmEtbWFnbmlmeWluZy1nbGFzcy1hcnJvdy1yaWdodCcgfSwKICAgICAgICAgICAgeyBpZDogJ3BkZicsIG5hbWU6ICdFeHBvcnQgUERGJywgaWNvbjogJ2ZhLWZpbGUtcGRmJyB9LAogICAgICAgICAgICB7IGlkOiAnaXRhbGljJywgbmFtZTogJ0l0YWxpYycsIGljb246ICdmYS1pdGFsaWMnIH0sCiAgICAgICAgICAgIHsgaWQ6ICdwcmludCcsIG5hbWU6ICdQcmludCcsIGljb246ICdmYS1wcmludCcgfSwKICAgICAgICAgICAgeyBpZDogJ2NlbnRlcicsIG5hbWU6ICdDZW50ZXIgQWxpZ24nLCBpY29uOiAnZmEtYWxpZ24tY2VudGVyJyB9LAogICAgICAgICAgICB7IGlkOiAnZm9udGNvbG9yJywgbmFtZTogJ0ZvbnQgQ29sb3InLCBpY29uOiAnZmEtcGFsZXR0ZScgfSwKICAgICAgICAgICAgeyBpZDogJ3VuZGVybGluZScsIG5hbWU6ICdVbmRlcmxpbmUnLCBpY29uOiAnZmEtdW5kZXJsaW5lJyB9LAogICAgICAgICAgICB7IGlkOiAnYWxpZ25sZWZ0JywgbmFtZTogJ0FsaWduIExlZnQnLCBpY29uOiAnZmEtYWxpZ24tbGVmdCcgfSwKICAgICAgICAgICAgeyBpZDogJ2FsaWducmlnaHQnLCBuYW1lOiAnQWxpZ24gUmlnaHQnLCBpY29uOiAnZmEtYWxpZ24tcmlnaHQnIH0sCiAgICAgICAgICAgIHsgaWQ6ICdjdXQnLCBuYW1lOiAnQ3V0JywgaWNvbjogJ2ZhLXNjaXNzb3JzJyB9LAogICAgICAgICAgICB7IGlkOiAncGFzdGUnLCBuYW1lOiAnUGFzdGUnLCBpY29uOiAnZmEtcGFzdGUnIH0sCiAgICAgICAgICAgIHsgaWQ6ICdyZWRvJywgbmFtZTogJ1JlZG8nLCBpY29uOiAnZmEtcm90YXRlLXJpZ2h0JyB9LAogICAgICAgICAgICB7IGlkOiAnYnVsbGV0cycsIG5hbWU6ICdCdWxsZXRzJywgaWNvbjogJ2ZhLWxpc3QtdWwnIH0sCiAgICAgICAgICAgIHsgaWQ6ICdsaW5lc3BhY2luZycsIG5hbWU6ICdMaW5lIFNwYWNpbmcnLCBpY29uOiAnZmEtYXJyb3dzLXVwLWRvd24nIH0sCiAgICAgICAgICAgIHsgaWQ6ICdtYXJnaW5zJywgbmFtZTogJ01hcmdpbnMnLCBpY29uOiAnZmEtbWF4aW1pemUnIH0sCiAgICAgICAgICAgIHsgaWQ6ICd0YWJsZScsIG5hbWU6ICdJbnNlcnQgVGFibGUnLCBpY29uOiAnZmEtdGFibGUnIH0sCiAgICAgICAgICAgIHsgaWQ6ICdwaWN0dXJlJywgbmFtZTogJ0luc2VydCBQaWN0dXJlJywgaWNvbjogJ2ZhLWltYWdlJyB9LAogICAgICAgICAgICB7IGlkOiAnaGVhZGVyJywgbmFtZTogJ0hlYWRlcicsIGljb246ICdmYS1oZWFkaW5nJyB9LAogICAgICAgICAgICB7IGlkOiAnZm9vdGVyJywgbmFtZTogJ0Zvb3RlcicsIGljb246ICdmYS1zaG9lLXByaW50cycgfSwKICAgICAgICAgICAgeyBpZDogJ3BhZ2VudW1iZXInLCBuYW1lOiAnUGFnZSBOdW1iZXInLCBpY29uOiAnZmEtYXJyb3ctZG93bi0xLTknIH0sCiAgICAgICAgICAgIHsgaWQ6ICdwYWdlYnJlYWsnLCBuYW1lOiAnUGFnZSBCcmVhaycsIGljb246ICdmYS1maWxlLWRhc2hlZC1saW5lJyB9LAogICAgICAgICAgICB7IGlkOiAnY29sdW1ucycsIG5hbWU6ICdDb2x1bW5zJywgaWNvbjogJ2ZhLXRhYmxlLWNvbHVtbnMnIH0sCiAgICAgICAgICAgIHsgaWQ6ICdvcmllbnRhdGlvbicsIG5hbWU6ICdPcmllbnRhdGlvbicsIGljb246ICdmYS1tb2JpbGUtc2NyZWVuJyB9LAogICAgICAgICAgICB7IGlkOiAnd2F0ZXJtYXJrJywgbmFtZTogJ1dhdGVybWFyaycsIGljb246ICdmYS1zdGFtcCcgfSwKICAgICAgICAgICAgeyBpZDogJ3NwZWxsY2hlY2snLCBuYW1lOiAnU3BlbGwgQ2hlY2snLCBpY29uOiAnZmEtc3BlbGwtY2hlY2snIH0sCiAgICAgICAgICAgIHsgaWQ6ICdtYWlsbWVyZ2UnLCBuYW1lOiAnTWFpbCBNZXJnZScsIGljb246ICdmYS1lbnZlbG9wZXMtYnVsaycgfSwKICAgICAgICAgICAgeyBpZDogJ3N1cGVyc2NyaXB0JywgbmFtZTogJ1N1cGVyc2NyaXB0JywgaWNvbjogJ2ZhLXN1cGVyc2NyaXB0JyB9LAogICAgICAgICAgICB7IGlkOiAnc3Vic2NyaXB0JywgbmFtZTogJ1N1YnNjcmlwdCcsIGljb246ICdmYS1zdWJzY3JpcHQnIH0sCiAgICAgICAgICAgIHsgaWQ6ICdoaWdobGlnaHQnLCBuYW1lOiAnSGlnaGxpZ2h0JywgaWNvbjogJ2ZhLWhpZ2hsaWdodGVyJyB9LAogICAgICAgICAgICB7IGlkOiAnaHlwZXJsaW5rJywgbmFtZTogJ0h5cGVybGluaycsIGljb246ICdmYS1saW5rJyB9LAogICAgICAgICAgICB7IGlkOiAnZm9ybWF0cGFpbnRlcicsIG5hbWU6ICdGb3JtYXQgUGFpbnRlcicsIGljb246ICdmYS1wYWludC1yb2xsZXInIH0sCiAgICAgICAgICAgIHsgaWQ6ICd0ZXh0Ym94JywgbmFtZTogJ1RleHQgQm94JywgaWNvbjogJ2ZhLXNxdWFyZS1wZW4nIH0sCiAgICAgICAgICAgIHsgaWQ6ICd3b3JkY291bnQnLCBuYW1lOiAnV29yZCBDb3VudCcsIGljb246ICdmYS1jYWxjdWxhdG9yJyB9LAogICAgICAgICAgICB7IGlkOiAnem9vbScsIG5hbWU6ICdab29tJywgaWNvbjogJ2ZhLW1hZ25pZnlpbmctZ2xhc3MtcGx1cycgfSwKICAgICAgICAgICAgeyBpZDogJ3N0cmlrZXRocm91Z2gnLCBuYW1lOiAnU3RyaWtldGhyb3VnaCcsIGljb246ICdmYS1zdHJpa2V0aHJvdWdoJyB9LAogICAgICAgICAgICB7IGlkOiAnaW5kZW50aW5jcmVhc2UnLCBuYW1lOiAnSW5jcmVhc2UgSW5kZW50JywgaWNvbjogJ2ZhLWluZGVudCcgfSwKICAgICAgICAgICAgeyBpZDogJ2luZGVudGRlY3JlYXNlJywgbmFtZTogJ0RlY3JlYXNlIEluZGVudCcsIGljb246ICdmYS1vdXRkZW50JyB9LAogICAgICAgICAgICB7IGlkOiAnY2hhcnQnLCBuYW1lOiAnSW5zZXJ0IENoYXJ0JywgaWNvbjogJ2ZhLWNoYXJ0LXBpZScgfSwKICAgICAgICAgICAgeyBpZDogJ3NoYXBlcycsIG5hbWU6ICdJbnNlcnQgU2hhcGVzJywgaWNvbjogJ2ZhLXNoYXBlcycgfSwKICAgICAgICAgICAgeyBpZDogJ3N5bWJvbCcsIG5hbWU6ICdJbnNlcnQgU3ltYm9sJywgaWNvbjogJ2ZhLW9tZWdhJyB9LAogICAgICAgICAgICB7IGlkOiAnZm9udGZhbWlseScsIG5hbWU6ICdGb250IFN0eWxlJywgaWNvbjogJ2ZhLWZvbnQnIH0KICAgICAgICBdOwoKICAgICAgICAvLyBEYWZ0YXIgNTAgUGVydGFueWFhbgogICAgICAgIGNvbnN0IHF1ZXN0aW9ucyA9IFsKICAgICAgICAgICAgLy8gU2VzaSAxOiBEYXNhciAmIFBlbnlpbXBhbmFuCiAgICAgICAgICAgIHsgdGFzazogIkJvcyBtZW1pbnRhIEFuZGEgbWVtYnVhdCBzdXJhdCBwZW5hd2FyYW4gYmFydSBkYXJpIGtlcnRhcyBrb3NvbmcuIiwgY29ycmVjdElkOiAibmV3IiB9LAogICAgICAgICAgICB7IHRhc2s6ICJBbmRhIHN1ZGFoIG1lbmdldGlrIGxhcG9yYW4uIFNla2FyYW5nIEFuZGEgaGFydXMgbWVueWltcGFubnlhIGRlbmdhbiBuYW1hIGZpbGUgYmFydSAnTGFwb3Jhbl9CdWxhbl9JbmknLiIsIGNvcnJlY3RJZDogInNhdmUiIH0sCiAgICAgICAgICAgIHsgdGFzazogIkRva3VtZW4ga29udHJhayBzdWRhaCBmaW5hbC4gQW5kYSBoYXJ1cyBtZW55aW1wYW5ueWEga2UgZm9ybWF0IHlhbmcgdGlkYWsgYmlzYSBkaWVkaXQgc2VtYmFyYW5nYW4uIiwgY29ycmVjdElkOiAicGRmIiB9LAogICAgICAgICAgICB7IHRhc2s6ICJTaW1wYW4gcGVtYmFydWFuIHBla2VyamFhbiB5YW5nIGJhcnUgc2FqYSBBbmRhIGtldGlrIGFnYXIgdGlkYWsgaGlsYW5nIGppa2EgdGliYS10aWJhIG1hdGkgbGFtcHUuIiwgY29ycmVjdElkOiAic2F2ZSIgfSwKICAgICAgICAgICAgeyB0YXNrOiAiQ2V0YWsgMyByYW5na2FwIGRva3VtZW4gcGVyamFuamlhbiBrZXJqYXNhbWEgaW5pIG1lbmdndW5ha2FuIHByaW50ZXIgZGkgcnVhbmcgbWVldGluZy4iLCBjb3JyZWN0SWQ6ICJwcmludCIgfSwKICAgICAgICAgICAgCiAgICAgICAgICAgIC8vIFNlc2kgMjogRm9ybWF0IEZvbnQgJiBUZWtzCiAgICAgICAgICAgIHsgdGFzazogIkp1ZHVsIGtvcCBzdXJhdCBoYXJ1cyB0ZXJsaWhhdCBsZWJpaCB0ZWJhbCBkYW4gbWVuY29sb2sgZGFyaSB0ZWtzIGxhaW5ueWEuIiwgY29ycmVjdElkOiAiYm9sZCIgfSwKICAgICAgICAgICAgeyB0YXNrOiAiQmVyaSBnYXJpcyBiYXdhaCBwYWRhIGthdGEgJ1BFTlRJTkcnIGRpIHBlbmd1bXVtYW4gaW50ZXJuYWwga2FudG9yLiIsIGNvcnJlY3RJZDogInVuZGVybGluZSIgfSwKICAgICAgICAgICAgeyB0YXNrOiAiSmFkaWthbiB0ZWtzIGt1dGlwYW4gcGVudGluZyBpbmkgbWVuamFkaSBtaXJpbmcgYWdhciBiZXJiZWRhIGRhcmkgdGVrcyBwYXJhZ3JhZiBsYWlubnlhLiIsIGNvcnJlY3RJZDogIml0YWxpYyIgfSwKICAgICAgICAgICAgeyB0YXNrOiAiVWJhaCBqZW5pcyBnYXlhIHR1bGlzYW4gZG9rdW1lbiBzdXJhdCByZXNtaSBpbmkgZGFyaSBmb250IGRlZmF1bHQgbWVuamFkaSBBcmlhbCBhdGF1IFRpbWVzIE5ldyBSb21hbi4iLCBjb3JyZWN0SWQ6ICJmb250ZmFtaWx5IiB9LAogICAgICAgICAgICB7IHRhc2s6ICJVYmFoIHdhcm5hIHRla3MgcGVyaW5nYXRhbiBkaSBwZW5ndW11bWFuIGluaSBkYXJpIGhpdGFtIG1lbmphZGkgbWVyYWggdGVyYW5nLiIsIGNvcnJlY3RJZDogImZvbnRjb2xvciIgfSwKICAgICAgICAgICAgeyB0YXNrOiAiQmVyaSB3YXJuYSBsYXRhciBrdW5pbmcgKHNlcGVydGkgc3RhYmlsbykgcGFkYSBrYWxpbWF0IHlhbmcgaGFydXMgc2VnZXJhIGRpcmV2aXNpIG9sZWggdGltLiIsIGNvcnJlY3RJZDogImhpZ2hsaWdodCIgfSwKICAgICAgICAgICAgeyB0YXNrOiAiQmVyaSBnYXJpcyBjb3JldGFuIGRpIHRlbmdhaCB0ZWtzIHVudHVrIG1lbmFuZGFpIGhhcmdhIGxhbWEgcHJvZHVrIHlhbmcgc3VkYWggZGlza29uLiIsIGNvcnJlY3RJZDogInN0cmlrZXRocm91Z2giIH0sCiAgICAgICAgICAgIHsgdGFzazogIlNhbGluIGdheWEgaHVydWYgZGFuIHdhcm5hIGRhcmkgSnVkdWwgMSwgbGFsdSB0ZXJhcGthbiBzZWNhcmEgaW5zdGFuIGtlIEp1ZHVsIDIgdGFucGEgbWVuZ2F0dXIgdWxhbmcuIiwgY29ycmVjdElkOiAiZm9ybWF0cGFpbnRlciIgfSwKICAgICAgICAgICAgCiAgICAgICAgICAgIC8vIFNlc2kgMzogUGVyYXRhYW4gJiBQYXJhZ3JhZgogICAgICAgICAgICB7IHRhc2s6ICJBZ2FyIHN1cmF0IHJlc21pIHRlcmxpaGF0IHJhcGksIHNpc2kga2FuYW4gZGFuIGtpcmkgcGFyYWdyYWYgaGFydXMgc2VqYWphciByYXRhLiIsIGNvcnJlY3RJZDogImp1c3RpZnkiIH0sCiAgICAgICAgICAgIHsgdGFzazogIkZvcm1hdCB0YW5nZ2FsIHN1cmF0IGRpIGJhZ2lhbiBhdGFzIGhhcnVzIGRpcmF0YWthbiBraHVzdXMga2Ugc2lzaSBraXJpIGRva3VtZW4uIiwgY29ycmVjdElkOiAiYWxpZ25sZWZ0IiB9LAogICAgICAgICAgICB7IHRhc2s6ICJQb3Npc2lrYW4gYmxvayB0YW5kYSB0YW5nYW4gZGlyZWt0dXIgYWdhciBiZXJhZGEgc2VqYWphciBkaSBtYXJnaW4ga2FuYW4gYmF3YWguIiwgY29ycmVjdElkOiAiYWxpZ25yaWdodCIgfSwKICAgICAgICAgICAgeyB0YXNrOiAiUHVzYXRrYW4ganVkdWwgbGFwb3JhbiBhZ2FyIGJlcmFkYSB0ZXBhdCBkaSB0ZW5nYWgtdGVuZ2FoIGhhbGFtYW4gc2VjYXJhIGhvcml6b250YWwuIiwgY29ycmVjdElkOiAiY2VudGVyIiB9LAogICAgICAgICAgICB7IHRhc2s6ICJUZWtzIGxhcG9yYW4gdGVybGFsdSBwYWRhdCBkaWJhY2EuIFViYWggamFyYWsgYW50YXIgYmFyaXMgdGVrcyAoc3Bhc2kgYmFyaXMpIG1lbmphZGkgMSw1LiIsIGNvcnJlY3RJZDogImxpbmVzcGFjaW5nIiB9LAogICAgICAgICAgICB7IHRhc2s6ICJEb3JvbmcgcGFyYWdyYWYgaW5pIGxlYmloIG1lbmpvcm9rIGtlIGRhbGFtIChrZSBrYW5hbikgYWdhciBtYXN1ayBzZWJhZ2FpIGJhZ2lhbiBkYXJpIHN1Yi1iYWIuIiwgY29ycmVjdElkOiAiaW5kZW50aW5jcmVhc2UiIH0sCiAgICAgICAgICAgIHsgdGFzazogIlRhcmlrIGtlbWJhbGkgdGVrcyB5YW5nIHBvc2lzaW55YSB0ZXJsYWx1IG1lbmpvcm9rIGtlIGRhbGFtIGFnYXIgc2VqYWphciBsYWdpIGRlbmdhbiBiYXRhcyBraXJpIG5vcm1hbC4iLCBjb3JyZWN0SWQ6ICJpbmRlbnRkZWNyZWFzZSIgfSwKICAgICAgICAgICAgCiAgICAgICAgICAgIC8vIFNlc2kgNDogTmF2aWdhc2ksIENvcHksIFBhc3RlICYgVW5kbwogICAgICAgICAgICB7IHRhc2s6ICJBbmRhIG1lbWJhdGFsa2FuIHNlYnVhaCBrZXRpa2FuIChVbmRvKSwgdGFwaSBiZXJ1YmFoIHBpa2lyYW4gZGFuIGluZ2luIG1lbmdlbWJhbGlrYW4ga2V0aWthbiB0ZXJzZWJ1dC4iLCBjb3JyZWN0SWQ6ICJyZWRvIiB9LAogICAgICAgICAgICB7IHRhc2s6ICJBbmRhIGluZ2luIG1lbWluZGFoa2FuIHRla3MgYWxhbWF0IGRhcmkgZG9rdW1lbiBsYW1hIHRhbnBhIG1lbmdldGlrIHVsYW5nIChMYW5na2FoIHBlcnRhbWE6IFNhbGluKS4iLCBjb3JyZWN0SWQ6ICJjb3B5IiB9LAogICAgICAgICAgICB7IHRhc2s6ICJTZXRlbGFoIG1lbnlhbGluIChDb3B5KSB0ZWtzIGRhcmkgZW1haWwsIHRlbXBlbGthbiB0ZWtzIHRlcnNlYnV0IGtlIGRhbGFtIGRva3VtZW4gV29yZCBBbmRhLiIsIGNvcnJlY3RJZDogInBhc3RlIiB9LAogICAgICAgICAgICB7IHRhc2s6ICJQaW5kYWhrYW4gcGFyYWdyYWYgaW5pIGtlIGJhYiBsYWluLiAoTGFuZ2thaCBwZXJ0YW1hOiBQb3RvbmcvaGlsYW5na2FuIGRhcmkgdGVtcGF0IGFzbGlueWEpLiIsIGNvcnJlY3RJZDogImN1dCIgfSwKICAgICAgICAgICAgeyB0YXNrOiAiVXBzISBBbmRhIHRpZGFrIHNlbmdhamEgbWVuZ2hhcHVzIHBhcmFncmFmIHBlbnRpbmcuIEJhdGFsa2FuIGtlc2FsYWhhbiB0ZXJzZWJ1dCBhZ2FyIGtlbWJhbGkgc2VwZXJ0aSBzZW11bGEuIiwgY29ycmVjdElkOiAidW5kbyIgfSwKICAgICAgICAgICAgeyB0YXNrOiAiQWRhIGtlc2FsYWhhbiBrZXRpayBuYW1hIHBlcnVzYWhhYW4gZGkgNTAgaGFsYW1hbi4gVGVtdWthbiBrYXRhIHRlcnNlYnV0IGRhbiBnYW50aSBzZW11YW55YSBzZWthbGlndXMuIiwgY29ycmVjdElkOiAiZmluZCIgfSwKICAgICAgICAgICAgCiAgICAgICAgICAgIC8vIFNlc2kgNTogVGF0YSBMZXRhayBIYWxhbWFuIChQYWdlIExheW91dCkKICAgICAgICAgICAgeyB0YXNrOiAiU3RhbmRhciBwZXJ1c2FoYWFuIG1lbmdoYXJ1c2thbiBkb2t1bWVuIHJlc21pIGRpY2V0YWsga2h1c3VzIGRpIGtlcnRhcyB1a3VyYW4gQTQuIiwgY29ycmVjdElkOiAicGFnZXNpemUiIH0sCiAgICAgICAgICAgIHsgdGFzazogIkF0dXIgYmF0YXMga29zb25nIGRpIHBpbmdnaXIga2VydGFzIChtYXJnaW4gYXRhcywgYmF3YWgsIGtpcmksIGthbmFuKSBtZW5qYWRpIHRlcGF0IDIgY20uIiwgY29ycmVjdElkOiAibWFyZ2lucyIgfSwKICAgICAgICAgICAgeyB0YXNrOiAiVWJhaCBwb3Npc2kga2VydGFzIHVudHVrIG1lbmNldGFrIHRhYmVsIHBhbmphbmcgZGFyaSBiZXJkaXJpIChQb3J0cmFpdCkgbWVuamFkaSBtZW5kYXRhciAoTGFuZHNjYXBlKS4iLCBjb3JyZWN0SWQ6ICJvcmllbnRhdGlvbiIgfSwKICAgICAgICAgICAgeyB0YXNrOiAiVWJhaCBmb3JtYXQgYXJ0aWtlbCBidWxldGluIHBlcnVzYWhhYW4gaW5pIG1lbmphZGkgZHVhIGJhZ2lhbiB0ZWtzIHlhbmcgYmVyZGFtcGluZ2FuIChzZXBlcnRpIGtvcmFuKS4iLCBjb3JyZWN0SWQ6ICJjb2x1bW5zIiB9LAogICAgICAgICAgICB7IHRhc2s6ICJQYWtzYSBqdWR1bCBCYWIgMiBhZ2FyIGxhbmdzdW5nIGRpbXVsYWkgZGkgaGFsYW1hbiBiYXJ1LCB0ZXJwaXNhaCBkYXJpIGhhbGFtYW4gQmFiIDEuIiwgY29ycmVjdElkOiAicGFnZWJyZWFrIiB9LAogICAgICAgICAgICB7IHRhc2s6ICJUYW1iYWhrYW4gdHVsaXNhbiB0cmFuc3BhcmFuIGJlcnR1bGlza2FuICdSQUhBU0lBJyBkaSBsYXRhciBiZWxha2FuZyBoYWxhbWFuIGtvbnRyYWsga2VyamEuIiwgY29ycmVjdElkOiAid2F0ZXJtYXJrIiB9LAogICAgICAgICAgICAKICAgICAgICAgICAgLy8gU2VzaSA2OiBFbGVtZW4gU2lzaXBhbiAoSW5zZXJ0IEVsZW1lbnRzKQogICAgICAgICAgICB7IHRhc2s6ICJTaXNpcGthbiBnYW1iYXIgbG9nbyBwZXJ1c2FoYWFuIEFuZGEgZGkgYmFnaWFuIHN1ZHV0IGF0YXMgZG9rdW1lbiBwcm9wb3NhbC4iLCBjb3JyZWN0SWQ6ICJwaWN0dXJlIiB9LAogICAgICAgICAgICB7IHRhc2s6ICJNYXN1a2thbiBkYWZ0YXIgbmFtYSBkYW4gbm9tb3IgdGVsZXBvbiBrbGllbiBkYWxhbSBmb3JtYXQgYmFyaXMgZGFuIGtvbG9tIGtvdGFrLWtvdGFrIHlhbmcgcmFwaS4iLCBjb3JyZWN0SWQ6ICJ0YWJsZSIgfSwKICAgICAgICAgICAgeyB0YXNrOiAiVGFtYmFoa2FuIG5hbWEgaW5zdGFuc2kgYWdhciBzZWxhbHUgbXVuY3VsIGJlcnVsYW5nIGRpIG1hcmdpbiBhdGFzIHNldGlhcCBoYWxhbWFuIGRva3VtZW4uIiwgY29ycmVjdElkOiAiaGVhZGVyIiB9LAogICAgICAgICAgICB7IHRhc2s6ICJUYW1iYWhrYW4gYWxhbWF0IGRhbiBrb250YWsga2FudG9yIGFnYXIgb3RvbWF0aXMgdGVyY2V0YWsgZGkgbWFyZ2luIGJhd2FoIHNldGlhcCBoYWxhbWFuLiIsIGNvcnJlY3RJZDogImZvb3RlciIgfSwKICAgICAgICAgICAgeyB0YXNrOiAiQmVyaSBub21vciB1cnV0IGhhbGFtYW4gZGkgcG9qb2sgYWdhciBkb2t1bWVuIDEwMCBsZW1iYXIgaW5pIHRpZGFrIHRlcnN1c3VuIGFjYWsgamlrYSB0ZXJjZWNlci4iLCBjb3JyZWN0SWQ6ICJwYWdlbnVtYmVyIiB9LAogICAgICAgICAgICB7IHRhc2s6ICJCdWF0IHNlYnVhaCBrb3RhayB0ZWtzIG1lbGF5YW5nIHlhbmcgYmlzYSBkaWdlc2VyIGJlYmFzIHVudHVrIG1lbWJlcmkgY2F0YXRhbiB0YW1iYWhhbiBkaSBwaW5nZ2lyIHN1cmF0LiIsIGNvcnJlY3RJZDogInRleHRib3giIH0sCiAgICAgICAgICAgIHsgdGFzazogIlNpc2lwa2FuIGJlbnR1ayBiYW5ndW4gZGF0YXIgKHBhbmFoL2tvdGFrKSB1bnR1ayBtZW5nZ2FtYmFyIGRpYWdyYW0gYWx1ciBvcGVyYXNpb25hbCAoU09QKS4iLCBjb3JyZWN0SWQ6ICJzaGFwZXMiIH0sCiAgICAgICAgICAgIHsgdGFzazogIlNpc2lwa2FuIGdyYWZpayBkaWFncmFtIGJhdGFuZyB1bnR1ayBtZW12aXN1YWxpc2FzaWthbiBwZXJzZW50YXNlIGRhdGEgcGVuanVhbGFuIGJ1bGFuIGluaS4iLCBjb3JyZWN0SWQ6ICJjaGFydCIgfSwKICAgICAgICAgICAgeyB0YXNrOiAiU2lzaXBrYW4gdGF1dGFuIGludGVybmV0IChsaW5rKSBhZ2FyIHRla3MgJ0tsaWsgZGkgc2luaScgYmlzYSBkaWtsaWsgZGFuIG1lbWJ1a2Egd2Vic2l0ZSBwcm9maWwgcGVydXNhaGFhbi4iLCBjb3JyZWN0SWQ6ICJoeXBlcmxpbmsiIH0sCiAgICAgICAgICAgIHsgdGFzazogIk1hc3Vra2FuIGthcmFrdGVyIGtodXN1cyBzZXBlcnRpIGxhbWJhbmcgSGFrIENpcHRhICjCqSkgYXRhdSBUcmFkZW1hcmsgKOKEoikgeWFuZyB0aWRhayBhZGEgZGkga2V5Ym9hcmQuIiwgY29ycmVjdElkOiAic3ltYm9sIiB9LAogICAgICAgICAgICAKICAgICAgICAgICAgLy8gU2VzaSA3OiBGaXR1ciBMYW5qdXRhbiAmIFBlbm9tb3JhbgogICAgICAgICAgICB7IHRhc2s6ICJBbmRhIHBlcmx1IG1lbWJ1YXQgZGFmdGFyIGxhbmdrYWgtbGFuZ2thaCBrZXJqYSB5YW5nIGJlcnVydXRhbiBzZWNhcmEgb3RvbWF0aXMgKDEsIDIsIDMsIGRzdCkuIiwgY29ycmVjdElkOiAibnVtYmVyaW5nIiB9LAogICAgICAgICAgICB7IHRhc2s6ICJCdWF0IGRhZnRhciBwZXJhbGF0YW4gQVRLIGthbnRvciBtZW5nZ3VuYWthbiBzaW1ib2wgdGl0aWstdGl0aWsgYnVsYXQgZGkgZGVwYW5ueWEgKGJ1a2FuIGFuZ2thKS4iLCBjb3JyZWN0SWQ6ICJidWxsZXRzIiB9LAogICAgICAgICAgICB7IHRhc2s6ICJLZXRpa2thbiBhbmdrYSAyIGtlY2lsIG1lbGF5YW5nIGRpIGF0YXMgcGFkYSB0ZWtzIG1ldGVyIHBlcnNlZ2kgKG3CsikgdW50dWsgbGFwb3JhbiBzZXJ0aWZpa2F0IHRhbmFoLiIsIGNvcnJlY3RJZDogInN1cGVyc2NyaXB0IiB9LAogICAgICAgICAgICB7IHRhc2s6ICJUdWxpc2thbiBhbmdrYSAyIGtlY2lsIGRpIGJhd2FoIHBhZGEgcnVtdXMga2ltaWEgYWlyIChI4oKCTykgZGkganVybmFsIHBlbmVsaXRpYW4gbGluZ2t1bmdhbi4iLCBjb3JyZWN0SWQ6ICJzdWJzY3JpcHQiIH0sCiAgICAgICAgICAgIHsgdGFzazogIkJ1YXQgMTAwIHN1cmF0IHVuZGFuZ2FuIHJhcGF0IGRhcmkgc2F0dSBmb3JtYXQsIGRpIG1hbmEgbmFtYSBwZW5lcmltYW55YSBkaXRhcmlrIG90b21hdGlzIGRhcmkgZGF0YWJhc2UgRXhjZWwuIiwgY29ycmVjdElkOiAibWFpbG1lcmdlIiB9LAogICAgICAgICAgICAKICAgICAgICAgICAgLy8gU2VzaSA4OiBSZXZpZXcgJiBUYW1waWxhbgogICAgICAgICAgICB7IHRhc2s6ICJKYWxhbmthbiBwZW5nZWNla2FuIG90b21hdGlzIHVudHVrIG1lbGloYXQgYXBha2FoIGFkYSBrYXRhLWthdGEgYmFoYXNhIEluZ2dyaXMgeWFuZyBzYWxhaCBrZXRpayAodHlwbykuIiwgY29ycmVjdElkOiAic3BlbGxjaGVjayIgfSwKICAgICAgICAgICAgeyB0YXNrOiAiQXRhc2FuIEFuZGEgYmVydGFueWEgdW50dWsgYmFoYW4gcHJlc2VudGFzaSwgc3VkYWggYmVyYXBhIGJhbnlhayBqdW1sYWgga2F0YSB5YW5nIEFuZGEga2V0aWsgZGFsYW0gYXJ0aWtlbCBpbmk/IiwgY29ycmVjdElkOiAid29yZGNvdW50IiB9LAogICAgICAgICAgICB7IHRhc2s6ICJQZXJiZXNhciAoWm9vbSkgdGFtcGlsYW4gbGVtYmFyIGtlcmphIEFuZGEgZGkgbGF5YXIga29tcHV0ZXIgbWVuamFkaSAxNTAlIGFnYXIgaHVydWZueWEgdGVybGloYXQgbGViaWggamVsYXMuIiwgY29ycmVjdElkOiAiem9vbSIgfQogICAgICAgIF07CgogICAgICAgIC8vIC0tLSBWQVJJQUJFTCBTVEFURSAtLS0KICAgICAgICBsZXQgY3VycmVudFF1ZXN0aW9uSW5kZXggPSAwOwogICAgICAgIGxldCBzY29yZSA9IDA7CiAgICAgICAgbGV0IGN1cnJlbnRPcHRpb25zID0gW107CiAgICAgICAgCiAgICAgICAgLy8gLS0tIEVMRU1FTiBET00gLS0tCiAgICAgICAgY29uc3Qgc3RhcnRTY3JlZW4gPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnc3RhcnQtc2NyZWVuJyk7CiAgICAgICAgY29uc3QgZ2FtZVNjcmVlbiA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdnYW1lLXNjcmVlbicpOwogICAgICAgIGNvbnN0IGVuZFNjcmVlbiA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdlbmQtc2NyZWVuJyk7CiAgICAgICAgY29uc3QgdGFza0NhcmQgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgndGFzay1jYXJkJyk7CiAgICAgICAgY29uc3QgdGFza0Rlc2MgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgndGFzay1kZXNjJyk7CiAgICAgICAgY29uc3QgZHJvcFpvbmVzQ29udGFpbmVyID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2Ryb3Atem9uZXMtY29udGFpbmVyJyk7CiAgICAgICAgY29uc3QgcHJvZ3Jlc3NUZXh0ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3Byb2dyZXNzLXRleHQnKTsKICAgICAgICBjb25zdCBzY29yZVRleHQgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnc2NvcmUtdGV4dCcpOwoKICAgICAgICAvLyBWYXJpYWJlbCB1bnR1ayBEcmFnIFRvdWNoIE1vYmlsZQogICAgICAgIGxldCBzdGFydFggPSAwLCBzdGFydFkgPSAwOwogICAgICAgIGxldCBpbml0aWFsWCA9IDAsIGluaXRpYWxZID0gMDsKICAgICAgICBsZXQgY2xvbmVDYXJkID0gbnVsbDsKCiAgICAgICAgLy8gLS0tIEZVTkdTSSBMT0dJS0EgR0FNRSAtLS0KCiAgICAgICAgZnVuY3Rpb24gc3RhcnRHYW1lKCkgewogICAgICAgICAgICBzdGFydFNjcmVlbi5jbGFzc0xpc3QuYWRkKCdoaWRkZW4nKTsKICAgICAgICAgICAgZ2FtZVNjcmVlbi5jbGFzc0xpc3QucmVtb3ZlKCdoaWRkZW4nKTsKICAgICAgICAgICAgZ2FtZVNjcmVlbi5jbGFzc0xpc3QuYWRkKCdib3VuY2UtaW4nKTsKICAgICAgICAgICAgY3VycmVudFF1ZXN0aW9uSW5kZXggPSAwOwogICAgICAgICAgICBzY29yZSA9IDA7CiAgICAgICAgICAgIHVwZGF0ZVNjb3JlKCk7CiAgICAgICAgICAgIGxvYWRRdWVzdGlvbigpOwogICAgICAgIH0KCiAgICAgICAgZnVuY3Rpb24gbG9hZFF1ZXN0aW9uKCkgewogICAgICAgICAgICAvLyBDZWsgamlrYSBnYW1lIHNlbGVzYWkKICAgICAgICAgICAgaWYgKGN1cnJlbnRRdWVzdGlvbkluZGV4ID49IHF1ZXN0aW9ucy5sZW5ndGgpIHsKICAgICAgICAgICAgICAgIGVuZEdhbWUoKTsKICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgY29uc3QgcSA9IHF1ZXN0aW9uc1tjdXJyZW50UXVlc3Rpb25JbmRleF07CiAgICAgICAgICAgIHRhc2tEZXNjLnRleHRDb250ZW50ID0gcS50YXNrOwogICAgICAgICAgICBwcm9ncmVzc1RleHQudGV4dENvbnRlbnQgPSBgJHtjdXJyZW50UXVlc3Rpb25JbmRleCArIDF9LyR7cXVlc3Rpb25zLmxlbmd0aH1gOwogICAgICAgICAgICAKICAgICAgICAgICAgLy8gUmVzZXQga2FydHUgdHVnYXMKICAgICAgICAgICAgdGFza0NhcmQuc3R5bGUudmlzaWJpbGl0eSA9ICd2aXNpYmxlJzsKICAgICAgICAgICAgdGFza0NhcmQuc3R5bGUub3BhY2l0eSA9ICcxJzsKICAgICAgICAgICAgdGFza0NhcmQuY2xhc3NMaXN0LnJlbW92ZSgnc2hha2UnKTsKICAgICAgICAgICAgdGFza0NhcmQuY2xhc3NMaXN0LmFkZCgnYm91bmNlLWluJyk7CiAgICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4gdGFza0NhcmQuY2xhc3NMaXN0LnJlbW92ZSgnYm91bmNlLWluJyksIDUwMCk7CgogICAgICAgICAgICBnZW5lcmF0ZURyb3Bab25lcyhxLmNvcnJlY3RJZCk7CiAgICAgICAgfQoKICAgICAgICBmdW5jdGlvbiBnZW5lcmF0ZURyb3Bab25lcyhjb3JyZWN0SWQpIHsKICAgICAgICAgICAgZHJvcFpvbmVzQ29udGFpbmVyLmlubmVySFRNTCA9ICcnOwogICAgICAgICAgICBjdXJyZW50T3B0aW9ucyA9IFtdOwoKICAgICAgICAgICAgLy8gQ2FyaSBvYmplayBhbGF0IHlhbmcgYmVuYXIKICAgICAgICAgICAgY29uc3QgY29ycmVjdFRvb2wgPSBhbGxUb29scy5maW5kKHQgPT4gdC5pZCA9PT0gY29ycmVjdElkKTsKICAgICAgICAgICAgY3VycmVudE9wdGlvbnMucHVzaChjb3JyZWN0VG9vbCk7CgogICAgICAgICAgICAvLyBQaWxpaCA0IHBlbmdlY29oIChkaXN0cmFjdG9ycykgc2VjYXJhIGFjYWsKICAgICAgICAgICAgLy8gVG90YWwgNSBwaWxpaGFuICgxIGJlbmFyLCA0IHNhbGFoKSBkaSBzZXRpYXAgc29hbAogICAgICAgICAgICBsZXQgZGlzdHJhY3RvcnMgPSBhbGxUb29scy5maWx0ZXIodCA9PiB0LmlkICE9PSBjb3JyZWN0SWQpOwogICAgICAgICAgICBkaXN0cmFjdG9ycyA9IGRpc3RyYWN0b3JzLnNvcnQoKCkgPT4gMC41IC0gTWF0aC5yYW5kb20oKSkuc2xpY2UoMCwgNCk7CiAgICAgICAgICAgIGN1cnJlbnRPcHRpb25zID0gY3VycmVudE9wdGlvbnMuY29uY2F0KGRpc3RyYWN0b3JzKTsKCiAgICAgICAgICAgIC8vIEFjYWsgdXJ1dGFuIHRhbXBpbAogICAgICAgICAgICBjdXJyZW50T3B0aW9ucy5zb3J0KCgpID0+IDAuNSAtIE1hdGgucmFuZG9tKCkpOwoKICAgICAgICAgICAgLy8gUmVuZGVyIGtvdGFrIGFsYXQKICAgICAgICAgICAgY3VycmVudE9wdGlvbnMuZm9yRWFjaCh0b29sID0+IHsKICAgICAgICAgICAgICAgIGNvbnN0IHpvbmUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTsKICAgICAgICAgICAgICAgIHpvbmUuY2xhc3NOYW1lID0gJ2Ryb3Atem9uZSBiZy13aGl0ZSBib3JkZXItNCBib3JkZXItZGFzaGVkIGJvcmRlci1ncmF5LTMwMCByb3VuZGVkLTJ4bCBwLTQgZmxleCBmbGV4LWNvbCBpdGVtcy1jZW50ZXIganVzdGlmeS1jZW50ZXIgdGV4dC1jZW50ZXIgY3Vyc29yLXBvaW50ZXIgbWluLWgtWzEwMHB4XSBzaGFkb3ctc20nOwogICAgICAgICAgICAgICAgem9uZS5kYXRhc2V0LmlkID0gdG9vbC5pZDsKICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgem9uZS5pbm5lckhUTUwgPSBgCiAgICAgICAgICAgICAgICAgICAgPGkgY2xhc3M9ImZhLXNvbGlkICR7dG9vbC5pY29ufSB0ZXh0LTN4bCB0ZXh0LWdyYXktNTAwIG1iLTIgem9uZS1pY29uIHRyYW5zaXRpb24tY29sb3JzIj48L2k+CiAgICAgICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9ImZvbnQtc2VtaWJvbGQgdGV4dC1ncmF5LTcwMCB0ZXh0LXNtIHpvbmUtdGV4dCB0cmFuc2l0aW9uLWNvbG9ycyI+JHt0b29sLm5hbWV9PC9zcGFuPgogICAgICAgICAgICAgICAgYDsKCiAgICAgICAgICAgICAgICAvLyBFdmVudCBMaXN0ZW5lcnMgdW50dWsgTW91c2UgKERlc2t0b3ApCiAgICAgICAgICAgICAgICB6b25lLmFkZEV2ZW50TGlzdGVuZXIoJ2RyYWdvdmVyJywgaGFuZGxlRHJhZ092ZXIpOwogICAgICAgICAgICAgICAgem9uZS5hZGRFdmVudExpc3RlbmVyKCdkcmFnZW50ZXInLCBoYW5kbGVEcmFnRW50ZXIpOwogICAgICAgICAgICAgICAgem9uZS5hZGRFdmVudExpc3RlbmVyKCdkcmFnbGVhdmUnLCBoYW5kbGVEcmFnTGVhdmUpOwogICAgICAgICAgICAgICAgem9uZS5hZGRFdmVudExpc3RlbmVyKCdkcm9wJywgaGFuZGxlRHJvcCk7CgogICAgICAgICAgICAgICAgZHJvcFpvbmVzQ29udGFpbmVyLmFwcGVuZENoaWxkKHpvbmUpOwogICAgICAgICAgICB9KTsKICAgICAgICB9CgogICAgICAgIGZ1bmN0aW9uIHVwZGF0ZVNjb3JlKCkgewogICAgICAgICAgICBzY29yZVRleHQudGV4dENvbnRlbnQgPSBzY29yZTsKICAgICAgICB9CgogICAgICAgIGZ1bmN0aW9uIGNoZWNrQW5zd2VyKHNlbGVjdGVkSWQsIGRyb3Bab25lRWxlbWVudCkgewogICAgICAgICAgICBjb25zdCBjb3JyZWN0SWQgPSBxdWVzdGlvbnNbY3VycmVudFF1ZXN0aW9uSW5kZXhdLmNvcnJlY3RJZDsKICAgICAgICAgICAgY29uc3QgaWNvbkVsID0gZHJvcFpvbmVFbGVtZW50LnF1ZXJ5U2VsZWN0b3IoJy56b25lLWljb24nKTsKICAgICAgICAgICAgY29uc3QgdGV4dEVsID0gZHJvcFpvbmVFbGVtZW50LnF1ZXJ5U2VsZWN0b3IoJy56b25lLXRleHQnKTsKCiAgICAgICAgICAgIGlmIChzZWxlY3RlZElkID09PSBjb3JyZWN0SWQpIHsKICAgICAgICAgICAgICAgIC8vIEJlbmFyCiAgICAgICAgICAgICAgICBzY29yZSArPSAxMDsKICAgICAgICAgICAgICAgIHVwZGF0ZVNjb3JlKCk7CiAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgIGRyb3Bab25lRWxlbWVudC5jbGFzc0xpc3QuYWRkKCdjb3JyZWN0Jyk7CiAgICAgICAgICAgICAgICBpY29uRWwuY2xhc3NMaXN0LnJlbW92ZSgndGV4dC1ncmF5LTUwMCcpOwogICAgICAgICAgICAgICAgaWNvbkVsLmNsYXNzTGlzdC5hZGQoJ3RleHQtZ3JlZW4tNjAwJyk7CiAgICAgICAgICAgICAgICB0ZXh0RWwuY2xhc3NMaXN0LmFkZCgndGV4dC1ncmVlbi04MDAnKTsKICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgLy8gU2VtYnVueWlrYW4ga2FydHUgdHVnYXMgZGVuZ2FuIGVmZWsKICAgICAgICAgICAgICAgIHRhc2tDYXJkLnN0eWxlLm9wYWNpdHkgPSAnMCc7CiAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgIC8vIExhbmp1dCBwZXJ0YW55YWFuIGJlcmlrdXRueWEKICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4gewogICAgICAgICAgICAgICAgICAgIGN1cnJlbnRRdWVzdGlvbkluZGV4Kys7CiAgICAgICAgICAgICAgICAgICAgbG9hZFF1ZXN0aW9uKCk7CiAgICAgICAgICAgICAgICB9LCAxMDAwKTsKCiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAvLyBTYWxhaCDigJQgdGlkYWsgZGFwYXQgbmlsYWksIGxhbmdzdW5nIGxhbmp1dCBrZSBzb2FsIGJlcmlrdXRueWEKICAgICAgICAgICAgICAgIGRyb3Bab25lRWxlbWVudC5jbGFzc0xpc3QuYWRkKCd3cm9uZycpOwogICAgICAgICAgICAgICAgaWNvbkVsLmNsYXNzTGlzdC5yZW1vdmUoJ3RleHQtZ3JheS01MDAnKTsKICAgICAgICAgICAgICAgIGljb25FbC5jbGFzc0xpc3QuYWRkKCd0ZXh0LXJlZC02MDAnKTsKICAgICAgICAgICAgICAgIHRleHRFbC5jbGFzc0xpc3QuYWRkKCd0ZXh0LXJlZC04MDAnKTsKCiAgICAgICAgICAgICAgICB0YXNrQ2FyZC5jbGFzc0xpc3QuYWRkKCdzaGFrZScpOwogICAgICAgICAgICAgICAgdGFza0NhcmQuc3R5bGUudmlzaWJpbGl0eSA9ICd2aXNpYmxlJzsgLy8gUGFzdGlrYW4gdGVybGloYXQgbGFnaQoKICAgICAgICAgICAgICAgIC8vIEt1bmNpIHNlbXVhIGtvdGFrIGphd2FiYW4gYWdhciB0aWRhayBiaXNhIGRpY29iYSB1bGFuZyBwYWRhIHNvYWwgaW5pCiAgICAgICAgICAgICAgICBkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKCcuZHJvcC16b25lJykuZm9yRWFjaCh6ID0+IHsKICAgICAgICAgICAgICAgICAgICB6LnN0eWxlLnBvaW50ZXJFdmVudHMgPSAnbm9uZSc7CiAgICAgICAgICAgICAgICB9KTsKCiAgICAgICAgICAgICAgICAvLyBTZW1idW55aWthbiBrYXJ0dSB0dWdhcyBsYWx1IGxhbmp1dCBrZSBwZXJ0YW55YWFuIGJlcmlrdXRueWEKICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4gewogICAgICAgICAgICAgICAgICAgIHRhc2tDYXJkLnN0eWxlLm9wYWNpdHkgPSAnMCc7CiAgICAgICAgICAgICAgICB9LCA1MDApOwoKICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4gewogICAgICAgICAgICAgICAgICAgIGN1cnJlbnRRdWVzdGlvbkluZGV4Kys7CiAgICAgICAgICAgICAgICAgICAgbG9hZFF1ZXN0aW9uKCk7CiAgICAgICAgICAgICAgICB9LCAxMTAwKTsKICAgICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgZnVuY3Rpb24gZW5kR2FtZSgpIHsKICAgICAgICAgICAgZ2FtZVNjcmVlbi5jbGFzc0xpc3QuYWRkKCdoaWRkZW4nKTsKICAgICAgICAgICAgZW5kU2NyZWVuLmNsYXNzTGlzdC5yZW1vdmUoJ2hpZGRlbicpOwogICAgICAgICAgICBlbmRTY3JlZW4uY2xhc3NMaXN0LmFkZCgnYm91bmNlLWluJyk7CiAgICAgICAgICAgIAogICAgICAgICAgICBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnZmluYWwtc2NvcmUnKS50ZXh0Q29udGVudCA9IHNjb3JlOwoKICAgICAgICAgICAgLy8gS2lyaW0gc2tvciBha2hpciBrZSBoYWxhbWFuIGluZHVrIChkaXBha2FpIHVudHVrIG1lbnlhdHVrYW4KICAgICAgICAgICAgLy8gaGFzaWwgZ2FtZSBkZW5nYW4gVHVnYXMgUHJpYmFkaSBkaSBoYWxhbWFuIG1hdGVyaSkKICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICAgIHdpbmRvdy5wYXJlbnQucG9zdE1lc3NhZ2UoewogICAgICAgICAgICAgICAgICAgIHNvdXJjZTogJ21hc3Rlci1wZW5nb2xhaC1rYXRhJywKICAgICAgICAgICAgICAgICAgICBzY29yZTogc2NvcmUsCiAgICAgICAgICAgICAgICAgICAgbWF4U2NvcmU6IHF1ZXN0aW9ucy5sZW5ndGggKiAxMAogICAgICAgICAgICAgICAgfSwgJyonKTsKICAgICAgICAgICAgfSBjYXRjaCAoZXJyKSB7IC8qIGFiYWlrYW4gamlrYSB0aWRhayBiZXJqYWxhbiBkaSBkYWxhbSBpZnJhbWUgKi8gfQogICAgICAgICAgICAKICAgICAgICAgICAgbGV0IGZlZWRiYWNrID0gIiI7CiAgICAgICAgICAgIC8vIE1lbnllc3VhaWthbiBsb2dpa2EgcG9pbiB1bnR1ayBtYWtzaW1hbCBza29yIDUwMCAoNTAgc29hbCkKICAgICAgICAgICAgaWYgKHNjb3JlID09PSA1MDApIGZlZWRiYWNrID0gIkx1YXIgQmlhc2EgU2VtcHVybmEhIEFuZGEgYWRhbGFoIFNhbmcgTWFzdGVyIFBlbmdvbGFoIEthdGEuIPCfjJ8iOwogICAgICAgICAgICBlbHNlIGlmIChzY29yZSA+PSA0MDApIGZlZWRiYWNrID0gIkhlYmF0IHNla2FsaSEgS2V0ZXJhbXBpbGFuIGFwbGlrYXNpIHBlcmthbnRvcmFuIEFuZGEgc2V0YXJhIHNla3JldGFyaXMgaGFuZGFsLiDwn5GNIjsKICAgICAgICAgICAgZWxzZSBpZiAoc2NvcmUgPj0gMjUwKSBmZWVkYmFjayA9ICJDdWt1cCBiYWlrLCB0YXBpIG1hc2loIGJhbnlhayBmaXR1ciBsYW5qdXRhbiB5YW5nIHBlcmx1IEFuZGEgcGVsYWphcmkuIFRldGFwIHNlbWFuZ2F0ISDwn5OaIjsKICAgICAgICAgICAgZWxzZSBmZWVkYmFjayA9ICJKYW5nYW4gbWVueWVyYWghIFRlcnVzIGJlcmxhdGloIGFnYXIgQW5kYSBsZWJpaCB0ZXJiaWFzYSBkZW5nYW4gZml0dXItZml0dXIgYWRtaW5pc3RyYXNpLiDwn5KqIjsKICAgICAgICAgICAgCiAgICAgICAgICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdmZWVkYmFjay1tc2cnKS50ZXh0Q29udGVudCA9IGZlZWRiYWNrOwogICAgICAgIH0KCiAgICAgICAgZnVuY3Rpb24gcmVzZXRHYW1lKCkgewogICAgICAgICAgICBlbmRTY3JlZW4uY2xhc3NMaXN0LmFkZCgnaGlkZGVuJyk7CiAgICAgICAgICAgIHN0YXJ0R2FtZSgpOwogICAgICAgIH0KCiAgICAgICAgLy8gLS0tIEVWRU5UIEhBTkRMRVJTIERSQUcgJiBEUk9QIChERVNLVE9QIC8gTU9VU0UpIC0tLQogICAgICAgIAogICAgICAgIHRhc2tDYXJkLmFkZEV2ZW50TGlzdGVuZXIoJ2RyYWdzdGFydCcsIChlKSA9PiB7CiAgICAgICAgICAgIGUuZGF0YVRyYW5zZmVyLnNldERhdGEoJ3RleHQvcGxhaW4nLCAndGFzaycpOwogICAgICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHRhc2tDYXJkLmNsYXNzTGlzdC5hZGQoJ29wYWNpdHktNTAnKSwgMCk7CiAgICAgICAgfSk7CgogICAgICAgIHRhc2tDYXJkLmFkZEV2ZW50TGlzdGVuZXIoJ2RyYWdlbmQnLCAoKSA9PiB7CiAgICAgICAgICAgIHRhc2tDYXJkLmNsYXNzTGlzdC5yZW1vdmUoJ29wYWNpdHktNTAnKTsKICAgICAgICB9KTsKCiAgICAgICAgZnVuY3Rpb24gaGFuZGxlRHJhZ092ZXIoZSkgewogICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7IC8vIFdhamliIGFnYXIgYmlzYSBkaS1kcm9wCiAgICAgICAgfQoKICAgICAgICBmdW5jdGlvbiBoYW5kbGVEcmFnRW50ZXIoZSkgewogICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7CiAgICAgICAgICAgIGNvbnN0IHpvbmUgPSBlLnRhcmdldC5jbG9zZXN0KCcuZHJvcC16b25lJyk7CiAgICAgICAgICAgIGlmICh6b25lKSB6b25lLmNsYXNzTGlzdC5hZGQoJ2RyYWctb3ZlcicpOwogICAgICAgIH0KCiAgICAgICAgZnVuY3Rpb24gaGFuZGxlRHJhZ0xlYXZlKGUpIHsKICAgICAgICAgICAgY29uc3Qgem9uZSA9IGUudGFyZ2V0LmNsb3Nlc3QoJy5kcm9wLXpvbmUnKTsKICAgICAgICAgICAgaWYgKHpvbmUpIHpvbmUuY2xhc3NMaXN0LnJlbW92ZSgnZHJhZy1vdmVyJyk7CiAgICAgICAgfQoKICAgICAgICBmdW5jdGlvbiBoYW5kbGVEcm9wKGUpIHsKICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpOwogICAgICAgICAgICBjb25zdCB6b25lID0gZS50YXJnZXQuY2xvc2VzdCgnLmRyb3Atem9uZScpOwogICAgICAgICAgICBpZiAoem9uZSkgewogICAgICAgICAgICAgICAgem9uZS5jbGFzc0xpc3QucmVtb3ZlKCdkcmFnLW92ZXInKTsKICAgICAgICAgICAgICAgIGNvbnN0IHNlbGVjdGVkSWQgPSB6b25lLmRhdGFzZXQuaWQ7CiAgICAgICAgICAgICAgICBjaGVja0Fuc3dlcihzZWxlY3RlZElkLCB6b25lKTsKICAgICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgLy8gLS0tIEVWRU5UIEhBTkRMRVJTIERSQUcgJiBEUk9QIChNT0JJTEUgLyBUT1VDSCBTQ1JFRU4pIC0tLQogICAgICAgIC8vIEthcmVuYSBIVE1MNSBEcmFnICYgRHJvcCBrdXJhbmcgcmVzcG9uc2lmIGRpIGxheWFyIHNlbnR1aCwga2l0YSBidWF0IGt1c3RvbQogICAgICAgIAogICAgICAgIHRhc2tDYXJkLmFkZEV2ZW50TGlzdGVuZXIoJ3RvdWNoc3RhcnQnLCBoYW5kbGVUb3VjaFN0YXJ0LCB7cGFzc2l2ZTogZmFsc2V9KTsKICAgICAgICB0YXNrQ2FyZC5hZGRFdmVudExpc3RlbmVyKCd0b3VjaG1vdmUnLCBoYW5kbGVUb3VjaE1vdmUsIHtwYXNzaXZlOiBmYWxzZX0pOwogICAgICAgIHRhc2tDYXJkLmFkZEV2ZW50TGlzdGVuZXIoJ3RvdWNoZW5kJywgaGFuZGxlVG91Y2hFbmQpOwoKICAgICAgICBmdW5jdGlvbiBoYW5kbGVUb3VjaFN0YXJ0KGUpIHsKICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpOyAvLyBNZW5jZWdhaCBzY3JvbGxpbmcgc2FhdCBtZW55ZW50dWgga2FydHUKICAgICAgICAgICAgY29uc3QgdG91Y2ggPSBlLnRvdWNoZXNbMF07CiAgICAgICAgICAgIAogICAgICAgICAgICAvLyBCdWF0IGtsb25pbmdhbiBrYXJ0dSB1bnR1ayB2aXN1YWwgZHJhZwogICAgICAgICAgICBjb25zdCByZWN0ID0gdGFza0NhcmQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7CiAgICAgICAgICAgIGNsb25lQ2FyZCA9IHRhc2tDYXJkLmNsb25lTm9kZSh0cnVlKTsKICAgICAgICAgICAgY2xvbmVDYXJkLmNsYXNzTGlzdC5hZGQoJ2Fic29sdXRlLWRyYWcnLCAnc2hhZG93LTJ4bCcsICdvcGFjaXR5LTkwJywgJ3NjYWxlLTEwNScpOwogICAgICAgICAgICAKICAgICAgICAgICAgLy8gU2V0IHBvc2lzaSBhd2FsCiAgICAgICAgICAgIGNsb25lQ2FyZC5zdHlsZS53aWR0aCA9IGAke3JlY3Qud2lkdGh9cHhgOwogICAgICAgICAgICBjbG9uZUNhcmQuc3R5bGUuaGVpZ2h0ID0gYCR7cmVjdC5oZWlnaHR9cHhgOwogICAgICAgICAgICBjbG9uZUNhcmQuc3R5bGUubGVmdCA9IGAke3JlY3QubGVmdH1weGA7CiAgICAgICAgICAgIGNsb25lQ2FyZC5zdHlsZS50b3AgPSBgJHtyZWN0LnRvcH1weGA7CiAgICAgICAgICAgIAogICAgICAgICAgICBkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKGNsb25lQ2FyZCk7CiAgICAgICAgICAgIHRhc2tDYXJkLnN0eWxlLnZpc2liaWxpdHkgPSAnaGlkZGVuJzsgLy8gU2VtYnVueWlrYW4gYXNsaW55YQoKICAgICAgICAgICAgLy8gSGl0dW5nIG9mZnNldCBzZW50dWhhbgogICAgICAgICAgICBzdGFydFggPSB0b3VjaC5jbGllbnRYOwogICAgICAgICAgICBzdGFydFkgPSB0b3VjaC5jbGllbnRZOwogICAgICAgICAgICBpbml0aWFsWCA9IHJlY3QubGVmdDsKICAgICAgICAgICAgaW5pdGlhbFkgPSByZWN0LnRvcDsKICAgICAgICB9CgogICAgICAgIGZ1bmN0aW9uIGhhbmRsZVRvdWNoTW92ZShlKSB7CiAgICAgICAgICAgIGlmICghY2xvbmVDYXJkKSByZXR1cm47CiAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTsKICAgICAgICAgICAgY29uc3QgdG91Y2ggPSBlLnRvdWNoZXNbMF07CiAgICAgICAgICAgIAogICAgICAgICAgICBjb25zdCBkeCA9IHRvdWNoLmNsaWVudFggLSBzdGFydFg7CiAgICAgICAgICAgIGNvbnN0IGR5ID0gdG91Y2guY2xpZW50WSAtIHN0YXJ0WTsKICAgICAgICAgICAgCiAgICAgICAgICAgIGNsb25lQ2FyZC5zdHlsZS5sZWZ0ID0gYCR7aW5pdGlhbFggKyBkeH1weGA7CiAgICAgICAgICAgIGNsb25lQ2FyZC5zdHlsZS50b3AgPSBgJHtpbml0aWFsWSArIGR5fXB4YDsKCiAgICAgICAgICAgIC8vIEVmZWsgaG92ZXIgcGFkYSBkcm9wem9uZSBzYWF0IHRvdWNoIG1vdmUKICAgICAgICAgICAgZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbCgnLmRyb3Atem9uZScpLmZvckVhY2goeiA9PiB6LmNsYXNzTGlzdC5yZW1vdmUoJ2RyYWctb3ZlcicpKTsKICAgICAgICAgICAgCiAgICAgICAgICAgIC8vIFNlbWJ1bnlpa2FuIGtsb25pbmdhbiBzZW1lbnRhcmEgdW50dWsgbWVuZGV0ZWtzaSBlbGVtZW4gZGkgYmF3YWhueWEKICAgICAgICAgICAgY2xvbmVDYXJkLnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7CiAgICAgICAgICAgIGNvbnN0IGVsZW1CZWxvdyA9IGRvY3VtZW50LmVsZW1lbnRGcm9tUG9pbnQodG91Y2guY2xpZW50WCwgdG91Y2guY2xpZW50WSk7CiAgICAgICAgICAgIGNsb25lQ2FyZC5zdHlsZS5kaXNwbGF5ID0gJ2Jsb2NrJzsKCiAgICAgICAgICAgIGlmIChlbGVtQmVsb3cpIHsKICAgICAgICAgICAgICAgIGNvbnN0IHpvbmUgPSBlbGVtQmVsb3cuY2xvc2VzdCgnLmRyb3Atem9uZScpOwogICAgICAgICAgICAgICAgaWYgKHpvbmUpIHpvbmUuY2xhc3NMaXN0LmFkZCgnZHJhZy1vdmVyJyk7CiAgICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIGZ1bmN0aW9uIGhhbmRsZVRvdWNoRW5kKGUpIHsKICAgICAgICAgICAgaWYgKCFjbG9uZUNhcmQpIHJldHVybjsKICAgICAgICAgICAgCiAgICAgICAgICAgIGNvbnN0IHRvdWNoID0gZS5jaGFuZ2VkVG91Y2hlc1swXTsKICAgICAgICAgICAgCiAgICAgICAgICAgIC8vIERldGVrc2kgem9uYSBkcm9wCiAgICAgICAgICAgIGNsb25lQ2FyZC5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnOwogICAgICAgICAgICBjb25zdCBlbGVtQmVsb3cgPSBkb2N1bWVudC5lbGVtZW50RnJvbVBvaW50KHRvdWNoLmNsaWVudFgsIHRvdWNoLmNsaWVudFkpOwogICAgICAgICAgICAKICAgICAgICAgICAgLy8gSGFwdXMga2xvbmluZ2FuIHZpc3VhbAogICAgICAgICAgICBkb2N1bWVudC5ib2R5LnJlbW92ZUNoaWxkKGNsb25lQ2FyZCk7CiAgICAgICAgICAgIGNsb25lQ2FyZCA9IG51bGw7CiAgICAgICAgICAgIAogICAgICAgICAgICBsZXQgZHJvcHBlZE9uWm9uZSA9IGZhbHNlOwoKICAgICAgICAgICAgaWYgKGVsZW1CZWxvdykgewogICAgICAgICAgICAgICAgY29uc3Qgem9uZSA9IGVsZW1CZWxvdy5jbG9zZXN0KCcuZHJvcC16b25lJyk7CiAgICAgICAgICAgICAgICBpZiAoem9uZSkgewogICAgICAgICAgICAgICAgICAgIGRyb3BwZWRPblpvbmUgPSB0cnVlOwogICAgICAgICAgICAgICAgICAgIHpvbmUuY2xhc3NMaXN0LnJlbW92ZSgnZHJhZy1vdmVyJyk7CiAgICAgICAgICAgICAgICAgICAgY29uc3Qgc2VsZWN0ZWRJZCA9IHpvbmUuZGF0YXNldC5pZDsKICAgICAgICAgICAgICAgICAgICBjaGVja0Fuc3dlcihzZWxlY3RlZElkLCB6b25lKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQoKICAgICAgICAgICAgLy8gSmlrYSB0aWRhayBkaWxlcGFzIGRpIGRyb3Agem9uZSwga2VtYmFsaWthbiBrYXJ0dSBrZSBwb3Npc2kgYXdhbAogICAgICAgICAgICBpZiAoIWRyb3BwZWRPblpvbmUpIHsKICAgICAgICAgICAgICAgIHRhc2tDYXJkLnN0eWxlLnZpc2liaWxpdHkgPSAndmlzaWJsZSc7CiAgICAgICAgICAgICAgICB0YXNrQ2FyZC5jbGFzc0xpc3QuYWRkKCdzaGFrZScpOwogICAgICAgICAgICAgICAgc2V0VGltZW91dCgoKSA9PiB0YXNrQ2FyZC5jbGFzc0xpc3QucmVtb3ZlKCdzaGFrZScpLCA0MDApOwogICAgICAgICAgICB9CiAgICAgICAgfQoKICAgIDwvc2NyaXB0Pgo8L2JvZHk+CjwvaHRtbD4=" title="Game Master Pengolah Kata" loading="lazy"&gt;&lt;/iframe&gt;
        &lt;/div&gt;
        &lt;div class="status-chip" id="gameStatusChip"&gt;&lt;span class="dot"&gt;&lt;/span&gt; Game belum dimainkan/selesai&lt;/div&gt;
      &lt;/fieldset&gt;

      &lt;fieldset&gt;
        &lt;h3 class="step-title"&gt;&lt;span class="num"&gt;2&lt;/span&gt; Soal Pilihan Ganda (60 poin)&lt;/h3&gt;
        &lt;p style="font-size:14.5px; color:#4a5568; margin-top:0;"&gt;Jawab 10 soal pilihan ganda berikut berdasarkan materi di atas. Setiap soal bernilai 6 poin.&lt;/p&gt;
        &lt;div id="quizWrap"&gt;&lt;/div&gt;
      &lt;/fieldset&gt;

      &lt;fieldset&gt;
        &lt;h3 class="step-title"&gt;&lt;span class="num"&gt;3&lt;/span&gt; Soal Esai (40 poin)&lt;/h3&gt;
        &lt;p style="font-size:14.5px; color:#4a5568; margin-top:0;"&gt;Jawab 5 soal esai berikut dengan kalimatmu sendiri berdasarkan materi. Setiap soal bernilai 8 poin.&lt;/p&gt;
        &lt;p class="essay-note"&gt;Jawaban wajib diketik manual. Tempel (paste), seret-lepas teks, dan klik kanan pada kolom jawaban dinonaktifkan.&lt;/p&gt;
        &lt;div id="essayWrap"&gt;&lt;/div&gt;
      &lt;/fieldset&gt;

      &lt;fieldset&gt;
        &lt;h3 class="step-title"&gt;&lt;span class="num"&gt;4&lt;/span&gt; Kirim Hasil &amp; Unduh Bukti&lt;/h3&gt;
        &lt;div class="checklist"&gt;
          &lt;div&gt;&lt;span class="mark" id="chkIdentitas"&gt;&lt;/span&gt; Identitas siswa terisi lengkap&lt;/div&gt;
          &lt;div&gt;&lt;span class="mark" id="chkGame"&gt;&lt;/span&gt; Game uji keterampilan selesai dimainkan&lt;/div&gt;
          &lt;div&gt;&lt;span class="mark" id="chkKuis"&gt;&lt;/span&gt; Semua soal pilihan ganda terjawab&lt;/div&gt;
          &lt;div&gt;&lt;span class="mark" id="chkEsai"&gt;&lt;/span&gt; Semua soal esai terisi (diketik manual)&lt;/div&gt;
        &lt;/div&gt;
        &lt;button type="submit" class="submit-btn" id="submitBtn"&gt;Kirim Hasil Tugas&lt;/button&gt;
        &lt;div class="msg wait" id="msgWait"&gt;Mengirim hasil, mohon tunggu...&lt;/div&gt;
        &lt;div class="msg ok" id="msgOk"&gt;&lt;/div&gt;
        &lt;div class="msg err" id="msgErr"&gt;&lt;/div&gt;
        &lt;button type="button" class="pdf-btn" id="pdfBtn" disabled&gt;Unduh Bukti Mengerjakan (PDF - F4)&lt;/button&gt;
        &lt;p style="font-size:12.5px; color:#7a8390; margin-top:8px; margin-bottom:0;"&gt;Tombol unduh aktif setelah pengiriman berhasil. Cetak dokumen ini (maks. 1 lembar F4) dan serahkan ke guru mata pelajaran sebagai bukti fisik pengerjaan tugas.&lt;/p&gt;
      &lt;/fieldset&gt;

    &lt;/form&gt;
  &lt;/section&gt;

&lt;/main&gt;

&lt;footer&gt;Informatika Kelas X - Pengenalan Aplikasi Pengolah Kata untuk Administrasi Perkantoran - DOK/INFORMATIKA/X/PENGOLAH-KATA&lt;/footer&gt;

&lt;iframe name="hidden_iframe" id="hidden_iframe" style="display:none;"&gt;&lt;/iframe&gt;
&lt;form id="gform" action="https://script.google.com/macros/s/AKfycbwKp7DrBTALJMlw8crjK7RgXIO8LVcU4yVEd9WJNs_vgSXkVxfw7fwkGbOT2IBNOjg3uQ/exec" method="POST" target="hidden_iframe" style="display:none;"&gt;
  &lt;input type="hidden" name="no absen" id="gNoAbsen"&gt;
  &lt;input type="hidden" name="nama" id="gNama"&gt;
  &lt;input type="hidden" name="kelas" id="gKelas"&gt;
  &lt;input type="hidden" name="nilai evaluasi" id="gNilai"&gt;
  &lt;input type="hidden" name="judul materi" id="gJudul"&gt;
&lt;/form&gt;

&lt;script&gt;
const JUDUL_MATERI = "Pengenalan Aplikasi Pengolah Kata untuk Administrasi Perkantoran";
const DOC_CODE = "DOK/INFORMATIKA/X/PENGOLAH-KATA";

/* ---------- Soal Pilihan Ganda (60 poin, 6 poin/soal) ---------- */
const QUESTIONS = [
  { q: "1. Aplikasi pengolah kata digunakan terutama untuk...", opts: ["Mengolah angka dan rumus matematika","Membuat dan mengedit dokumen berbasis teks","Mengedit video","Membuat presentasi slide"], correct: 1 },
  { q: "2. Berikut yang termasuk aplikasi pengolah kata, KECUALI...", opts: ["Microsoft Word","Google Docs","Microsoft Excel","LibreOffice Writer"], correct: 2 },
  { q: "3. Perintah cepat (shortcut) untuk menyimpan dokumen adalah...", opts: ["Ctrl + P","Ctrl + S","Ctrl + C","Ctrl + Z"], correct: 1 },
  { q: "4. Ukuran margin standar (Normal) yang umum digunakan pada dokumen perkantoran adalah...", opts: ["1 cm di semua sisi","2,54 cm di semua sisi","5 cm di semua sisi","0,5 cm di semua sisi"], correct: 1 },
  { q: "5. Jenis huruf (font) yang umum dipakai untuk surat resmi formal adalah...", opts: ["Comic Sans MS","Times New Roman atau Arial","Wingdings","Papyrus"], correct: 1 },
  { q: "6. Bagian dokumen surat resmi yang berisi nama instansi, alamat, dan logo disebut...", opts: ["Kop surat (letterhead)","Lampiran","Perihal","Tembusan"], correct: 0 },
  { q: "7. Fitur Find &amp; Replace digunakan untuk...", opts: ["Mencetak dokumen","Mencari dan mengganti kata secara otomatis","Menyisipkan gambar","Mengatur margin"], correct: 1 },
  { q: "8. Format file yang cocok untuk dokumen final yang tidak ingin diedit ulang oleh penerima adalah...", opts: [".docx",".txt",".pdf",".rtf"], correct: 2 },
  { q: "9. Perataan teks yang membuat teks rata di sisi kiri dan kanan sekaligus disebut...", opts: ["Align Left","Align Right","Center","Justify"], correct: 3 },
  { q: "10. Sebelum menyimpan dokumen administrasi, penamaan file yang baik sebaiknya memuat...", opts: ["Nama acak dan tanggal sembarang","Jenis dokumen, nama/nomor, dan tanggal secara jelas","Hanya angka","Emoji dan simbol"], correct: 1 }
];

const quizWrap = document.getElementById('quizWrap');
QUESTIONS.forEach((item, qi) =&gt; {
  const div = document.createElement('div');
  div.className = 'quiz-item';
  let optsHtml = '';
  item.opts.forEach((opt, oi) =&gt; {
    optsHtml += `&lt;label class="opt"&gt;&lt;input type="radio" name="q${qi}" value="${oi}"&gt;&lt;span&gt;${String.fromCharCode(97+oi)}. ${opt}&lt;/span&gt;&lt;/label&gt;`;
  });
  div.innerHTML = `&lt;p class="q"&gt;${item.q}&lt;/p&gt;${optsHtml}`;
  quizWrap.appendChild(div);
});

/* ---------- Soal Esai (40 poin, 8 poin/soal, dinilai dari kata kunci materi) ---------- */
const ESSAY = [
  {
    q: "1. Jelaskan perbedaan aplikasi pengolah kata berbasis desktop dan berbasis cloud (online), lengkap dengan satu contoh aplikasi untuk masing-masing jenis.",
    groups: [["desktop"], ["cloud","online","internet"], ["microsoft word"], ["google docs"], ["offline"], ["kolaborasi","real-time","realtime","bersama-sama"]]
  },
  {
    q: "2. Sebutkan minimal tiga teknik dasar mengedit dokumen beserta shortcut keyboard yang digunakan untuk masing-masing teknik tersebut.",
    groups: [["copy","salin"], ["paste","tempel"], ["cut","potong"], ["undo","batalkan"], ["redo","ulangi"], ["find","replace","cari","ganti"], ["ctrl"]]
  },
  {
    q: "3. Jelaskan standar format penulisan dokumen resmi perkantoran meliputi jenis huruf, ukuran huruf, margin, dan spasi baris yang tepat.",
    groups: [["times new roman"], ["arial"], ["12"], ["margin"], ["2,54","2.54"], ["spasi"], ["1,15","1.15","1,5","1.5"], ["justify","rata kiri kanan"]]
  },
  {
    q: "4. Sebutkan bagian-bagian struktur surat resmi secara berurutan, mulai dari kop surat hingga tanda tangan.",
    groups: [["kop surat"], ["nomor"], ["hal","lampiran"], ["tanggal"], ["alamat tujuan","alamat"], ["salam","isi"], ["tanda tangan"]]
  },
  {
    q: "5. Jelaskan mengapa etika dan keamanan dokumen digital penting diterapkan di lingkungan administrasi perkantoran.",
    groups: [["password","kata sandi"], ["backup","cadangan"], ["izin"], ["plagiarisme"], ["rahasia","kerahasiaan"], ["hak akses","akses"]]
  }
];
const POIN_PER_ESAI = 40 / ESSAY.length;

const essayWrap = document.getElementById('essayWrap');
ESSAY.forEach((item, ei) =&gt; {
  const div = document.createElement('div');
  div.className = 'essay-item';
  div.innerHTML = `&lt;p class="q"&gt;${item.q}&lt;/p&gt;
    &lt;textarea id="essay${ei}" data-idx="${ei}" placeholder="Ketik jawabanmu di sini (minimal beberapa kalimat)..."&gt;&lt;/textarea&gt;
    &lt;p class="essay-count" id="essayCount${ei}"&gt;0 karakter&lt;/p&gt;`;
  essayWrap.appendChild(div);
});

// Nonaktifkan paste, drag-drop teks, dan klik kanan pada semua kolom esai
document.querySelectorAll('#essayWrap textarea').forEach((ta, idx) =&gt; {
  ta.addEventListener('paste', e =&gt; {
    e.preventDefault();
    showEssayBlockedNotice(idx);
  });
  ta.addEventListener('drop', e =&gt; e.preventDefault());
  ta.addEventListener('contextmenu', e =&gt; e.preventDefault());
  ta.addEventListener('input', () =&gt; {
    document.getElementById('essayCount' + idx).textContent = ta.value.length + ' karakter';
    updateChecklist();
  });
});
function showEssayBlockedNotice(idx){
  const el = document.getElementById('essayCount' + idx);
  const old = el.textContent;
  el.textContent = 'Tempel (paste) dinonaktifkan - ketik manual jawabanmu.';
  el.style.color = 'var(--danger)';
  setTimeout(() =&gt; { el.textContent = old; el.style.color = ''; }, 2200);
}

function scoreEssay(idx){
  const text = document.getElementById('essay' + idx).value.toLowerCase().trim();
  if(text.length &lt; 15) return 0;
  const groups = ESSAY[idx].groups;
  let matched = 0;
  groups.forEach(g =&gt; { if(g.some(k =&gt; text.includes(k))) matched++; });
  return Math.round((matched / groups.length) * POIN_PER_ESAI);
}

/* ---------- Skor game via postMessage dari iframe (informasi, tidak masuk nilai evaluasi) ---------- */
let gameFinished = false;
let gameScoreRaw = null;
const GAME_MAX = 500;
const gameStatusChip = document.getElementById('gameStatusChip');

window.addEventListener('message', function(e){
  if(e.data &amp;&amp; e.data.source === 'master-pengolah-kata'){
    gameScoreRaw = e.data.score;
    gameFinished = true;
    const pct = Math.round((gameScoreRaw / GAME_MAX) * 100);
    gameStatusChip.classList.add('ok-chip');
    gameStatusChip.innerHTML = `&lt;span class="dot"&gt;&lt;/span&gt; Game selesai - Skor: ${gameScoreRaw}/${GAME_MAX} (${pct}%)`;
    updateChecklist();
  }
});

/* ---------- Validasi &amp; checklist real-time ---------- */
const form = document.getElementById('taskForm');
const chkIdentitas = document.getElementById('chkIdentitas');
const chkGame = document.getElementById('chkGame');
const chkKuis = document.getElementById('chkKuis');
const chkEsai = document.getElementById('chkEsai');

function isIdentitasLengkap(){
  return document.getElementById('noAbsen').value.trim() &amp;&amp;
         document.getElementById('nama').value.trim() &amp;&amp;
         document.getElementById('kelas').value;
}
function isKuisLengkap(){
  return QUESTIONS.every((_, qi) =&gt; form.querySelector(`input[name="q${qi}"]:checked`));
}
function isEsaiLengkap(){
  return ESSAY.every((_, ei) =&gt; document.getElementById('essay' + ei).value.trim().length &gt;= 15);
}
function updateChecklist(){
  chkIdentitas.classList.toggle('done', !!isIdentitasLengkap());
  chkGame.classList.toggle('done', gameFinished);
  chkKuis.classList.toggle('done', isKuisLengkap());
  chkEsai.classList.toggle('done', isEsaiLengkap());
}
form.addEventListener('input', updateChecklist);
form.addEventListener('change', updateChecklist);
updateChecklist();

/* ---------- Submit ---------- */
const submitBtn = document.getElementById('submitBtn');
const pdfBtn = document.getElementById('pdfBtn');
const msgWait = document.getElementById('msgWait');
const msgOk = document.getElementById('msgOk');
const msgErr = document.getElementById('msgErr');

let hasilAkhir = null; // menyimpan rincian nilai untuk PDF

form.addEventListener('submit', function(e){
  e.preventDefault();
  msgOk.classList.remove('show');
  msgErr.classList.remove('show');

  const noAbsen = document.getElementById('noAbsen').value.trim();
  const nama = document.getElementById('nama').value.trim();
  const kelas = document.getElementById('kelas').value;

  if(!isIdentitasLengkap()){
    msgErr.textContent = "Lengkapi dahulu No. Absen, Nama, dan Kelas.";
    msgErr.classList.add('show');
    return;
  }
  if(!gameFinished){
    msgErr.textContent = "Selesaikan dahulu game uji keterampilan sampai layar akhir muncul.";
    msgErr.classList.add('show');
    return;
  }
  let unanswered = [];
  QUESTIONS.forEach((_, qi) =&gt; { if(!form.querySelector(`input[name="q${qi}"]:checked`)) unanswered.push(qi+1); });
  if(unanswered.length){
    msgErr.textContent = "Soal pilihan ganda nomor " + unanswered.join(', ') + " belum dijawab.";
    msgErr.classList.add('show');
    return;
  }
  if(!isEsaiLengkap()){
    msgErr.textContent = "Lengkapi semua jawaban esai (ketik manual, minimal beberapa kalimat).";
    msgErr.classList.add('show');
    return;
  }

  let correctCount = 0;
  QUESTIONS.forEach((item, qi) =&gt; {
    const checked = form.querySelector(`input[name="q${qi}"]:checked`);
    if(parseInt(checked.value, 10) === item.correct) correctCount++;
  });
  const skorPG = Math.round((correctCount / QUESTIONS.length) * 60);

  let skorEsai = 0;
  ESSAY.forEach((_, ei) =&gt; { skorEsai += scoreEssay(ei); });
  skorEsai = Math.min(40, skorEsai);

  const nilaiEvaluasi = Math.min(100, skorPG + skorEsai);
  const skorGamePersen = Math.round((gameScoreRaw / GAME_MAX) * 100);

  hasilAkhir = {
    noAbsen, nama, kelas,
    skorPG, skorEsai, nilaiEvaluasi,
    skorGameRaw: gameScoreRaw, skorGamePersen,
    waktu: new Date()
  };

  document.getElementById('gNoAbsen').value = noAbsen;
  document.getElementById('gNama').value = nama;
  document.getElementById('gKelas').value = kelas;
  document.getElementById('gNilai').value = nilaiEvaluasi;
  document.getElementById('gJudul').value = JUDUL_MATERI;

  submitBtn.disabled = true;
  submitBtn.textContent = "Mengirim...";
  msgWait.classList.add('show');
  document.getElementById('gform').submit();

  setTimeout(() =&gt; {
    msgWait.classList.remove('show');
    msgOk.textContent = `Hasil terkirim. PG: ${skorPG}/60, Esai: ${skorEsai}/40 -&gt; Nilai Evaluasi Akhir: ${nilaiEvaluasi}/100. Skor Uji Keterampilan (informasi): ${skorGamePersen}/100.`;
    msgOk.classList.add('show');
    submitBtn.textContent = "Sudah Terkirim";
    pdfBtn.disabled = false;
  }, 1400);
});

/* ---------- Unduh Bukti Mengerjakan (PDF, ukuran F4 = 215 x 330 mm) ---------- */
pdfBtn.addEventListener('click', function(){
  if(!hasilAkhir) return;
  const { jsPDF } = window.jspdf;
  const doc = new jsPDF({ unit: 'mm', format: [215, 330] });
  const pageW = 215;
  let y = 22;

  doc.setFont('helvetica', 'bold');
  doc.setFontSize(16);
  doc.text('BUKTI MENGERJAKAN TUGAS', pageW/2, y, { align: 'center' }); y += 8;

  doc.setFontSize(12);
  doc.text('Informatika Kelas X SMK', pageW/2, y, { align: 'center' }); y += 6;

  doc.setFont('helvetica', 'normal');
  doc.setFontSize(11);
  doc.text(JUDUL_MATERI, pageW/2, y, { align: 'center', maxWidth: pageW - 40 }); y += 10;

  doc.setFontSize(9);
  doc.text(DOC_CODE, pageW/2, y, { align: 'center' }); y += 6;

  doc.setLineWidth(0.6);
  doc.line(20, y, pageW - 20, y); y += 10;

  doc.setFont('helvetica', 'bold');
  doc.setFontSize(12);
  doc.text('Identitas Siswa', 20, y); y += 8;

  doc.setFont('helvetica', 'normal');
  doc.setFontSize(11);
  const rows1 = [
    ['No. Absen', hasilAkhir.noAbsen],
    ['Nama Lengkap', hasilAkhir.nama],
    ['Kelas', hasilAkhir.kelas],
    ['Tanggal &amp; Waktu', hasilAkhir.waktu.toLocaleString('id-ID')]
  ];
  rows1.forEach(r =&gt; {
    doc.text(r[0], 22, y);
    doc.text(':', 62, y);
    doc.text(String(r[1]), 66, y);
    y += 7;
  });
  y += 6;

  doc.setFont('helvetica', 'bold');
  doc.setFontSize(12);
  doc.text('Rincian Nilai', 20, y); y += 8;

  doc.setFont('helvetica', 'normal');
  doc.setFontSize(11);
  const rows2 = [
    ['Skor Pilihan Ganda (60 poin)', hasilAkhir.skorPG + ' / 60'],
    ['Skor Esai (40 poin)', hasilAkhir.skorEsai + ' / 40'],
    ['Nilai Evaluasi Akhir (100 poin)', hasilAkhir.nilaiEvaluasi + ' / 100'],
  ];
  rows2.forEach(r =&gt; {
    doc.text(r[0], 22, y);
    doc.text(':', 92, y);
    doc.text(String(r[1]), 96, y);
    y += 7;
  });

  doc.setFont('helvetica', 'bold');
  doc.setFontSize(14);
  doc.text('Nilai Evaluasi Akhir: ' + hasilAkhir.nilaiEvaluasi + ' / 100', pageW/2, y + 6, { align: 'center' });
  y += 16;

  doc.setFont('helvetica', 'normal');
  doc.setFontSize(10);
  doc.text('Skor Uji Keterampilan / Game (informasi tambahan, tidak termasuk Nilai Evaluasi):', 22, y); y += 6;
  doc.text(hasilAkhir.skorGameRaw + ' / 500  (' + hasilAkhir.skorGamePersen + ' / 100)', 22, y); y += 12;

  doc.setLineWidth(0.3);
  doc.line(20, y, pageW - 20, y); y += 10;

  doc.setFontSize(10);
  const catatan = 'Dokumen ini adalah bukti otomatis bahwa siswa telah menyelesaikan tugas pada tanggal dan waktu di atas. Cetak dokumen ini (ukuran kertas F4, maksimal 1 lembar) dan serahkan kepada guru mata pelajaran sebagai bukti fisik pengerjaan tugas.';
  const wrapped = doc.splitTextToSize(catatan, pageW - 40);
  doc.text(wrapped, 20, y); y += wrapped.length * 5 + 14;

  doc.text('Tanda tangan Siswa,', 30, y);
  doc.text('Tanda tangan Guru,', pageW - 70, y);
  y += 22;
  doc.text('(' + hasilAkhir.nama + ')', 30, y);
  doc.text('(......................................)', pageW - 70, y);

  const safeName = hasilAkhir.nama.replace(/[^a-zA-Z0-9]+/g, '_');
  doc.save(`Bukti_Tugas_${safeName}_${hasilAkhir.noAbsen}.pdf`);
});
&lt;/script&gt;

&lt;/body&gt;
&lt;/html&gt;</description><link>http://kitab-investasi.blogspot.com/2026/09/pengenalan-aplikasi-pengolah-kata-untuk.html</link><thr:total>0</thr:total><author>nof_rizal07@yahoo.co.id (abang_cool)</author></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-9000860041661554971.post-4680929617969456386</guid><pubDate>Fri, 04 Sep 2026 06:09:31 +0000</pubDate><atom:updated>2026-09-04T13:11:10.859+07:00</atom:updated><title>SERTIFIKAT KOMBEL</title><description>&lt;!DOCTYPE html&gt;
&lt;html lang="id"&gt;
&lt;head&gt;
&lt;meta charset="UTF-8"&gt;
&lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&gt;
&lt;title&gt;Generator Sertifikat&lt;/title&gt;

&lt;link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@700&amp;display=swap" rel="stylesheet"&gt;

&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"&gt;&lt;/script&gt;

&lt;style&gt;

body{
    font-family:Arial,sans-serif;
    background:#eef2f7;
    padding:20px;
    max-width:700px;
    margin:auto;
}

.card{
    background:white;
    padding:24px;
    border-radius:20px;
    box-shadow:0 10px 20px rgba(0,0,0,.1);
}

h2{
    text-align:center;
    color:#1e4668;
}

.confirm-box{
    background:#f0f6ff;
    border-left:5px solid #2c7da0;
    padding:16px;
    border-radius:16px;
    margin-bottom:20px;
    text-align:center;
}

.confirm-box p{
    margin-top:0;
    font-weight:bold;
    color:#1e4668;
}

.confirm-buttons{
    display:flex;
    gap:10px;
    margin-top:10px;
}

.confirm-buttons button{
    flex:1;
}

.yes-btn{
    background:#1f8a4c;
}

.yes-btn:hover{
    background:#166638;
}

.no-btn{
    background:#c0392b;
}

.no-btn:hover{
    background:#962d22;
}

input,select,button{
    width:100%;
    padding:12px;
    margin-top:10px;
    border-radius:12px;
    border:1px solid #ccc;
    font-size:16px;
}

button{
    background:#2c7da0;
    color:white;
    border:none;
    cursor:pointer;
    font-weight:bold;
}

button:hover{
    background:#1f5e7a;
}

button:disabled{
    background:#94a3b8;
    cursor:not-allowed;
}

input:disabled,
select:disabled{
    background:#f1f5f9;
}

#preview{
    width:100%;
    border-radius:12px;
    margin-top:10px;
}

.loading{
    display:none;
    margin-top:15px;
    color:#1e4668;
    font-weight:bold;
    text-align:center;
}

.status{
    margin-top:12px;
    font-weight:bold;
}

.success{
    color:#1f8a4c;
}

.error{
    color:#c0392b;
}

&lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;

&lt;div class="card"&gt;

&lt;h2&gt;&#128220; Generator Sertifikat&lt;/h2&gt;

&lt;!-- ================= KONFIRMASI ================= --&gt;

&lt;div class="confirm-box"&gt;

&lt;p&gt;&#128269; Apakah Anda mengikuti pelatihan?&lt;/p&gt;

&lt;div class="confirm-buttons"&gt;

&lt;button class="yes-btn" onclick="confirmIkut()"&gt;
✅ YA, IKUT
&lt;/button&gt;

&lt;button class="no-btn" onclick="confirmTidakIkut()"&gt;
❌ TIDAK
&lt;/button&gt;

&lt;/div&gt;

&lt;div id="statusKonfirmasi" class="status"&gt;&lt;/div&gt;

&lt;/div&gt;

&lt;!-- ================= FORM ================= --&gt;

&lt;label&gt;Nama Lengkap&lt;/label&gt;

&lt;input
type="text"
id="nama"
placeholder="Contoh: Ahmad Fauzi"
disabled&gt;

&lt;label&gt;Peran&lt;/label&gt;

&lt;select id="peran" disabled&gt;
    &lt;option&gt;Peserta&lt;/option&gt;
    &lt;option&gt;Narasumber&lt;/option&gt;
&lt;/select&gt;

&lt;img
id="preview"
src="https://lh3.googleusercontent.com/d/1Hu72T5j34moAaJG9Xnr1rGH3POtJ-Pug"
alt="Template"&gt;

&lt;button
id="downloadBtn"
onclick="generatePDF()"
disabled&gt;

⬇️ UNDUH PDF

&lt;/button&gt;

&lt;div class="loading" id="loading"&gt;
Memproses PDF...
&lt;/div&gt;

&lt;/div&gt;

&lt;script&gt;

// ================= TEMPLATE (DIUBAH) =================

const FILE_ID =
'1Hu72T5j34moAaJG9Xnr1rGH3POtJ-Pug';  // &lt;-- ID baru

const TEMPLATE_URL =
`https://lh3.googleusercontent.com/d/${FILE_ID}`;

// ================= UTIL =================

function showLoading(show){

    document.getElementById('loading').style.display =
        show ? 'block' : 'none';

}

function getRomanMonth(monthIndex){

    const romawi = [
        "I","II","III","IV","V","VI",
        "VII","VIII","IX","X","XI","XII"
    ];

    return romawi[monthIndex];

}

function capitalizeEachWord(text){

    return text
        .toLowerCase()
        .replace(/\b\w/g,c=&gt;c.toUpperCase());

}

// ================= KONFIRMASI =================

function confirmIkut(){

    document.getElementById('nama').disabled = false;

    document.getElementById('peran').disabled = false;

    document.getElementById('downloadBtn').disabled = false;

    document.getElementById('statusKonfirmasi').innerHTML =
        '&lt;span class="success"&gt;✅ Konfirmasi diterima. Anda dapat mengunduh sertifikat.&lt;/span&gt;';

}

function confirmTidakIkut(){

    document.getElementById('nama').disabled = true;

    document.getElementById('peran').disabled = true;

    document.getElementById('downloadBtn').disabled = true;

    document.getElementById('statusKonfirmasi').innerHTML =
        '&lt;span class="error"&gt;❌ Anda tidak dapat mengunduh sertifikat.&lt;/span&gt;';

}

// ================= LOAD IMAGE =================

function loadImage(url){

    return new Promise((resolve,reject)=&gt;{

        const img = new Image();

        img.crossOrigin = "anonymous";

        img.onload = ()=&gt;resolve(img);

        img.onerror = ()=&gt;{

            reject(
                new Error(
                    'Template Google Drive gagal dimuat'
                )
            );

        };

        img.src = url + '?t=' + Date.now();

    });

}

// ================= NOMOR =================

async function generateNomor(){

    const now = new Date();

    const bulan =
        getRomanMonth(now.getMonth());

    const tahun =
        now.getFullYear();

    const nomor =
        Math.floor(Math.random()*900)+100;

    return `${nomor}/K/${bulan}/${tahun}`;

}

// ================= PDF =================

async function generatePDF(){

    const namaInput =
        document.getElementById('nama');

    const peranSelect =
        document.getElementById('peran');

    let nama =
        namaInput.value.trim();

    const peran =
        peranSelect.value;

    if(!nama){

        alert('Nama wajib diisi');

        return;

    }

    nama =
        capitalizeEachWord(nama);

    showLoading(true);

    try{

        await document.fonts.ready;

        const img =
            await loadImage(TEMPLATE_URL);

        const canvas =
            document.createElement('canvas');

        canvas.width = img.width;
        canvas.height = img.height;

        const ctx =
            canvas.getContext('2d');

        ctx.drawImage(
            img,
            0,
            0,
            canvas.width,
            canvas.height
        );

        // ================= POSISI =================

        const nomorY =
            canvas.height * 0.235;

        const namaY =
            canvas.height * 0.3990;

        const peranY =
            canvas.height * 0.5420;

        // ================= STYLE =================

        ctx.textAlign = 'center';

        ctx.textBaseline = 'middle';

        ctx.fillStyle = '#000';

        // nomor
        const nomorSertifikat =
            await generateNomor();

        ctx.font =
            `bold ${canvas.width*0.0125}px Montserrat`;

        ctx.fillText(
            nomorSertifikat,
            canvas.width/2,
            nomorY
        );

        // nama auto shrink
        let fontSize =
            canvas.width * 0.031;

        ctx.font =
            `700 ${fontSize}px Montserrat`;

        let textWidth =
            ctx.measureText(nama).width;

        const maxWidth =
            canvas.width - 180;

        while(
            textWidth &gt; maxWidth &amp;&amp;
            fontSize &gt; 20
        ){

            fontSize -= 2;

            ctx.font =
                `700 ${fontSize}px Montserrat`;

            textWidth =
                ctx.measureText(nama).width;

        }

        ctx.fillText(
            nama,
            canvas.width/2,
            namaY
        );

        // peran
        ctx.font =
            `bold ${canvas.width*0.024}px Montserrat`;

        ctx.fillText(
            peran,
            canvas.width/2,
            peranY
        );

        // ================= PDF =================

        const imageData =
            canvas.toDataURL(
                'image/jpeg',
                1.0
            );

        const { jsPDF } =
            window.jspdf;

        const pdf =
            new jsPDF({

                orientation:
                    canvas.width &gt; canvas.height
                    ? 'landscape'
                    : 'portrait',

                unit:'px',

                format:[
                    canvas.width,
                    canvas.height
                ]

            });

        pdf.addImage(
            imageData,
            'JPEG',
            0,
            0,
            canvas.width,
            canvas.height
        );

        const safeName =
            nama.replace(/[^a-z0-9]/gi,'_');

        pdf.save(
            `Sertifikat_${safeName}.pdf`
        );

    }catch(error){

        console.error(error);

        alert(
            '❌ Gagal membuat PDF\n\n' +
            error.message +
            '\n\nPastikan file Google Drive bersifat PUBLIC.'
        );

    }finally{

        showLoading(false);

    }

}

&lt;/script&gt;

&lt;/body&gt;
&lt;/html&gt;</description><link>http://kitab-investasi.blogspot.com/2026/09/sertifikat-kombel.html</link><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://lh3.googleusercontent.com/d/1Hu72T5j34moAaJG9Xnr1rGH3POtJ-Pug=s72-c" width="72"/><thr:total>0</thr:total><author>nof_rizal07@yahoo.co.id (abang_cool)</author></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-9000860041661554971.post-7228811827870023901</guid><pubDate>Fri, 04 Sep 2026 03:08:01 +0000</pubDate><atom:updated>2026-09-11T07:40:01.163+07:00</atom:updated><title>Ulangan Harian 1 — Petunjuk Kerja BAHASA INDONESIA KELAS XI SMK</title><description>&lt;!DOCTYPE html&gt;
&lt;html lang="id"&gt;
&lt;head&gt;
&lt;meta charset="UTF-8"&gt;
&lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&gt;
&lt;title&gt;Ulangan Harian 1 - Petunjuk Kerja - Kelas XI SMK&lt;/title&gt;
&lt;style&gt;
 :root{
 --ink:#1B2430;
 --ink-soft:#4A5568;
 --paper:#F7F5F0;
 --card:#FFFFFF;
 --line:#D8D2C4;
 --amber:#E8A33D;
 --amber-dark:#8A5A12;
 --green:#3F7D58;
 --green-bg:#E7F2EB;
 --red:#C1443B;
 --red-bg:#FBEAE8;
 }
 *{box-sizing:border-box;}
 body{
 margin:0;
 background:var(--paper);
 color:var(--ink);
 font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
 line-height:1.55;
 }
 .wrap{max-width:760px;margin:0 auto;padding:28px 20px 80px;}
 header.top{border-bottom:3px solid var(--ink);padding-bottom:16px;margin-bottom:22px;}
 .kode{font-size:12px;letter-spacing:.04em;color:var(--ink-soft);}
 h1{font-size:22px;margin:6px 0 4px;font-weight:800;}
 .sub{font-size:14px;color:var(--ink-soft);margin:0;}
 .meta-row{display:flex;flex-wrap:wrap;gap:10px;margin-top:14px;}
 .meta-chip{background:var(--card);border:1px solid var(--line);border-radius:6px;padding:8px 12px;font-size:13px;min-width:130px;}
 .meta-chip b{display:block;font-size:16px;}
 .card{background:var(--card);border:1px solid var(--line);border-radius:8px;padding:20px;margin-bottom:18px;}
 .card h2{font-size:16px;margin:0 0 10px;}
 label{display:block;font-size:13px;color:var(--ink-soft);margin:12px 0 4px;}
 input[type=text],input[type=number]{
 width:100%;padding:10px 12px;border:1px solid var(--line);border-radius:6px;
 font-size:15px;background:#fff;color:var(--ink);
 }
 input:focus{outline:2px solid var(--amber);outline-offset:1px;}
 .btn{
 display:inline-block;border:none;border-radius:6px;padding:12px 20px;
 font-size:15px;font-weight:700;cursor:pointer;margin-top:16px;
 }
 .btn-primary{background:var(--ink);color:#fff;}
 .btn-primary:hover{background:#000;}
 .btn-secondary{background:var(--amber);color:#3A2400;}
 .btn-secondary:hover{background:#d6912e;}
 .btn:disabled{opacity:.5;cursor:not-allowed;}
 .err{color:var(--red);font-size:13px;margin-top:8px;display:none;}
 .stimulus{
 background:#FBF9F2;border:1px solid var(--line);border-left:4px solid var(--amber);
 padding:14px 16px;border-radius:4px;margin-bottom:14px;font-size:14.5px;white-space:pre-line;
 }
 .stimulus .st-title{font-weight:800;font-size:14px;margin-bottom:6px;color:var(--amber-dark);}
 .qgroup{margin-bottom:26px;}
 .q{margin-bottom:20px;padding-bottom:18px;border-bottom:1px solid var(--line);}
 .q:last-child{border-bottom:none;}
 .q-num{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px;color:var(--ink-soft);}
 .q-text{font-size:15px;font-weight:600;margin:4px 0 10px;}
 .opt{
 display:flex;gap:10px;align-items:flex-start;padding:8px 10px;border-radius:6px;
 cursor:pointer;border:1px solid transparent;font-size:14.5px;
 }
 .opt:hover{background:#F1EFE7;}
 .opt input{margin-top:3px;}
 .opt.selected{background:#FCEFDA;border-color:var(--amber);}
 #progressWrap{position:sticky;top:0;background:var(--paper);padding:10px 0;z-index:5;border-bottom:1px solid var(--line);margin-bottom:16px;}
 #progressBar{height:8px;background:var(--line);border-radius:4px;overflow:hidden;}
 #progressFill{height:100%;background:var(--amber);width:0%;transition:width .2s;}
 #progressText{font-size:12px;color:var(--ink-soft);margin-top:4px;}
 .result-score{font-size:48px;font-weight:800;margin:6px 0;}
 .pass{color:var(--green);}
 .fail{color:var(--red);}
 .result-box{border-radius:8px;padding:20px;text-align:center;}
 .result-box.pass-bg{background:var(--green-bg);border:1px solid var(--green);}
 .result-box.fail-bg{background:var(--red-bg);border:1px solid var(--red);}
 .attempt-log{margin-top:14px;font-size:13px;}
 .attempt-log div{display:flex;justify-content:space-between;padding:6px 0;border-bottom:1px dashed var(--line);}
 .hidden{display:none;}
 footer{margin-top:30px;font-size:12px;color:var(--ink-soft);text-align:center;}

 .essaySection{margin-top:10px;}
 .essayQ{margin-bottom:20px;padding-bottom:16px;border-bottom:1px solid var(--line);}
 .essayQ:last-child{border-bottom:none;}
 .essayQ-num{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px;color:var(--ink-soft);}
 .essayQ-text{font-size:15px;font-weight:600;margin:4px 0 8px;}
 textarea.essayInput{
 width:100%;min-height:80px;padding:10px 12px;border:1px solid var(--line);
 border-radius:6px;font-size:14.5px;font-family:inherit;resize:vertical;background:#fff;color:var(--ink);
 }
 textarea.essayInput:focus{outline:2px solid var(--amber);outline-offset:1px;}
 .charCount{font-size:12px;color:var(--ink-soft);text-align:right;margin-top:3px;}
 .charCount.over{color:var(--red);font-weight:700;}
 .pasteWarn{font-size:12.5px;color:var(--red);font-weight:700;margin-top:4px;display:none;}
 .pasteWarn.show{display:block;}
 .sectionLabel{font-size:13px;font-weight:800;letter-spacing:.02em;color:var(--amber-dark);margin:26px 0 4px;border-top:3px solid var(--ink);padding-top:14px;}

 #printArea{display:none;}
 @media print{
 body *{visibility:hidden;}
 #printArea, #printArea *{visibility:visible;}
 #printArea{display:block;position:absolute;left:0;top:0;width:100%;}
 @page{size:215mm 330mm;margin:14mm;}
 .pbreak{break-before:page;page-break-before:always;}
 .noBreak{break-inside:avoid;page-break-inside:avoid;}
 }
 .pf-kop{text-align:center;border-bottom:3px solid #000;padding-bottom:10px;margin-bottom:14px;}
 .pf-kop h2{margin:0;font-size:16px;}
 .pf-kop p{margin:2px 0 0;font-size:12px;}
 .pf-identitas{width:100%;border-collapse:collapse;font-size:13px;margin-bottom:14px;}
 .pf-identitas td{padding:3px 4px;vertical-align:top;}
 .pf-identitas td.lbl{width:150px;color:#333;}
 .pf-skorbox{border:2px solid #000;border-radius:4px;padding:10px 14px;margin-bottom:16px;display:flex;justify-content:space-between;gap:10px;flex-wrap:wrap;}
 .pf-skoritem{font-size:12px;}
 .pf-skoritem b{display:block;font-size:20px;}
 .pf-essay-q{font-size:13px;font-weight:700;margin-bottom:3px;}
 .pf-essay-a{font-size:12.5px;border:1px solid #999;border-radius:4px;padding:6px 8px;min-height:28px;white-space:pre-wrap;background:#FAFAF7;}
 .pf-ttd{display:flex;justify-content:space-between;margin-top:40px;font-size:12.5px;}
 .pf-ttd div{width:45%;text-align:center;}
 .pf-ttd .garis{margin-top:56px;border-top:1px solid #000;padding-top:4px;}
 .pf-note{font-size:11px;color:#555;margin-top:10px;}
&lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;div class="wrap"&gt;

 &lt;header class="top"&gt;
 &lt;div class="kode"&gt;DOK/B.INDO/XI/PROSEDUR-UH1&lt;/div&gt;
 &lt;h1&gt;Ulangan Harian 1 - Petunjuk Kerja&lt;/h1&gt;
 &lt;p class="sub"&gt;Bahasa Indonesia - Kelas XI SMK - Materi: teks prosedur / petunjuk kerja (evaluasi informasi, perbandingan teks, kaidah kebahasaan, penyusunan &amp;amp; penyajian)&lt;/p&gt;
 &lt;div class="meta-row"&gt;
 &lt;div class="meta-chip"&gt;Pilihan ganda&lt;b&gt;40 butir - bobot 70%&lt;/b&gt;&lt;/div&gt;
 &lt;div class="meta-chip"&gt;Esai&lt;b&gt;10 butir - bobot 30%&lt;/b&gt;&lt;/div&gt;
 &lt;div class="meta-chip"&gt;KKM (nilai akhir)&lt;b&gt;75&lt;/b&gt;&lt;/div&gt;
 &lt;div class="meta-chip"&gt;Kesempatan&lt;b&gt;3 kali&lt;/b&gt;&lt;/div&gt;
 &lt;/div&gt;
 &lt;/header&gt;

 &lt;div id="screen-intro" class="card"&gt;
 &lt;h2&gt;Sebelum mengerjakan&lt;/h2&gt;
 &lt;p style="font-size:14px;"&gt;Setiap peserta mendapat susunan soal dan urutan opsi jawaban yang berbeda-beda, jadi jangan heran jika berbeda dengan teman sebangku. Ulangan terdiri atas &lt;b&gt;40 soal pilihan ganda&lt;/b&gt; dan &lt;b&gt;10 soal esai&lt;/b&gt;. Keduanya dinilai &lt;b&gt;otomatis oleh sistem&lt;/b&gt;: skor esai dihitung dari kesesuaian jawabanmu dengan konsep-konsep kunci pada setiap soal. Nilai akhir = &lt;b&gt;Skor PG x 70% + Skor Esai x 30%&lt;/b&gt;. Kamu punya &lt;b&gt;3 kali kesempatan&lt;/b&gt;. Begitu nilai akhir mencapai atau melebihi KKM (75), nilai itu langsung tersimpan. Jika sampai percobaan ke-3 belum mencapai KKM, sistem otomatis menyimpan &lt;b&gt;nilai tertinggi&lt;/b&gt; beserta rinciannya. &lt;b&gt;Jawaban esai wajib diketik sendiri&lt;/b&gt; - fitur tempel/paste (baik lewat Ctrl+V, klik kanan, maupun tarik-lepas teks) dinonaktifkan pada kolom esai.&lt;/p&gt;
 &lt;p style="font-size:14px;"&gt;Isi No. Absen yang sama setiap kali mencoba, supaya sistem bisa menghitung sisa kesempatanmu dengan benar.&lt;/p&gt;
 &lt;div style="background:#FFF6E6;border:1px solid var(--amber);border-left:4px solid var(--amber-dark);border-radius:6px;padding:12px 14px;margin:10px 0 16px;font-size:13.5px;"&gt;
 &lt;b style="color:var(--amber-dark);"&gt;PENTING - wajib dilakukan setelah nilai akhir tersimpan:&lt;/b&gt;
 &lt;ol style="margin:6px 0 0;padding-left:18px;"&gt;
 &lt;li&gt;&lt;b&gt;Unduh&lt;/b&gt; bukti mengerjakan (PDF, ukuran F4) lewat tombol "Unduh Bukti Mengerjakan (PDF)".&lt;/li&gt;
 &lt;li&gt;&lt;b&gt;Cetak&lt;/b&gt; dokumen tersebut (maksimal 3 lembar).&lt;/li&gt;
 &lt;li&gt;&lt;b&gt;Serahkan hasil cetak ke guru mata pelajaran&lt;/b&gt; sebagai bukti fisik pengerjaan ulangan.&lt;/li&gt;
 &lt;/ol&gt;
 &lt;/div&gt;

 &lt;label for="absen"&gt;No. Absen&lt;/label&gt;
 &lt;input type="number" id="absen" placeholder="Contoh: 14" min="1"&gt;
 &lt;label for="nama"&gt;Nama Lengkap&lt;/label&gt;
 &lt;input type="text" id="nama" placeholder="Tulis nama lengkapmu"&gt;
 &lt;label for="kelas"&gt;Kelas&lt;/label&gt;
 &lt;input type="text" id="kelas" placeholder="Contoh: XI TKR 1"&gt;
 &lt;div class="err" id="introErr"&gt;Isi No. Absen, Nama Lengkap, dan Kelas terlebih dahulu.&lt;/div&gt;
 &lt;button class="btn btn-primary" id="btnCekStatus"&gt;Lanjutkan&lt;/button&gt;
 &lt;/div&gt;

 &lt;div id="screen-status" class="card hidden"&gt;
 &lt;h2 id="statusGreeting"&gt;&lt;/h2&gt;
 &lt;div id="statusBody"&gt;&lt;/div&gt;
 &lt;button class="btn btn-secondary" id="btnMulai"&gt;Mulai Mengerjakan&lt;/button&gt;
 &lt;button class="btn hidden" id="btnUnduhStatus" style="background:var(--green);color:#fff;"&gt;Unduh Bukti Mengerjakan (PDF)&lt;/button&gt;
 &lt;p class="hidden" id="instruksiStatus" style="font-size:12.5px;color:var(--ink-soft);margin-top:6px;"&gt;Setelah diunduh, cetak dokumen ini (maks. 3 lembar F4) dan &lt;b&gt;serahkan ke guru mata pelajaran&lt;/b&gt; sebagai bukti pengerjaan.&lt;/p&gt;
 &lt;button class="btn" id="btnGanti" style="background:transparent;border:1px solid var(--line);"&gt;Ganti No. Absen&lt;/button&gt;
 &lt;/div&gt;

 &lt;div id="screen-quiz" class="hidden"&gt;
 &lt;div id="progressWrap"&gt;
 &lt;div id="progressBar"&gt;&lt;div id="progressFill"&gt;&lt;/div&gt;&lt;/div&gt;
 &lt;div id="progressText"&gt;0 dari 40 soal terjawab&lt;/div&gt;
 &lt;/div&gt;
 &lt;div id="quizBody"&gt;&lt;/div&gt;
 &lt;div class="err" id="quizErr"&gt;Masih ada soal yang belum dijawab. Lengkapi seluruh soal sebelum mengirim.&lt;/div&gt;
 &lt;button class="btn btn-primary" id="btnKirim"&gt;Kirim Jawaban&lt;/button&gt;
 &lt;/div&gt;

 &lt;div id="screen-result" class="card hidden"&gt;
 &lt;div id="resultBoxOuter"&gt;&lt;/div&gt;
 &lt;div class="attempt-log" id="attemptLog"&gt;&lt;/div&gt;
 &lt;button class="btn btn-secondary hidden" id="btnUnduhHasil" style="background:var(--green);color:#fff;"&gt;Unduh Bukti Mengerjakan (PDF)&lt;/button&gt;
 &lt;p class="hidden" id="instruksiHasil" style="font-size:12.5px;color:var(--ink-soft);margin-top:6px;"&gt;Setelah diunduh, cetak dokumen ini (maks. 3 lembar F4) dan &lt;b&gt;serahkan ke guru mata pelajaran&lt;/b&gt; sebagai bukti pengerjaan.&lt;/p&gt;
 &lt;button class="btn btn-secondary hidden" id="btnCobaLagi"&gt;Coba Lagi&lt;/button&gt;
 &lt;button class="btn" id="btnSelesai" style="background:transparent;border:1px solid var(--line);"&gt;Kembali ke Awal&lt;/button&gt;
 &lt;/div&gt;

 &lt;footer&gt;DOK/B.INDO/XI/PROSEDUR-UH1 - Ulangan Harian 1, 40 Butir Pilihan Ganda + 10 Esai, Pokok Bahasan Petunjuk Kerja&lt;/footer&gt;
&lt;/div&gt;

&lt;div id="printArea"&gt;&lt;/div&gt;

&lt;script&gt;
const GROUPS = [
{
 title: "Teks 1 - Cara Mengganti Oli Sepeda Motor",
 stimulus: "Mengganti oli mesin secara berkala menjaga performa sepeda motor tetap optimal. Berikut langkah mengganti oli mesin sepeda motor jenis matic.\n\nAlat dan bahan: kunci pas 17, wadah penampung oli bekas, oli mesin baru sesuai spesifikasi pabrikan, corong, kain lap.\n\nLangkah-langkah:\n1) Panaskan mesin selama tiga menit agar oli lama lebih mudah mengalir, lalu matikan mesin.\n2) Letakkan wadah penampung tepat di bawah baut pembuangan oli.\n3) Buka baut pembuangan oli menggunakan kunci pas 17 secara perlahan agar oli tidak tumpah ke luar wadah.\n4) Biarkan oli lama mengalir habis selama kurang lebih lima menit.\n5) Pasang kembali baut pembuangan oli dan kencangkan hingga rapat, tetapi jangan berlebihan agar ulir baut tidak rusak.\n6) Buka tutup pengisian oli, lalu tuangkan oli baru menggunakan corong sesuai takaran yang tertera pada buku manual.\n7) Pasang kembali tutup pengisian oli, nyalakan mesin, dan periksa ketinggian oli menggunakan dipstick.",
 questions: [
 {q:"Alat yang digunakan untuk membuka baut pembuangan oli adalah...", opts:["Obeng plus","Kunci pas 17","Tang kombinasi","Kunci inggris","Kunci L"], correct:1},
 {q:"Berdasarkan teks, mesin perlu dipanaskan sebelum oli dikuras dengan tujuan...", opts:["Mempercepat proses pemasangan baut","Membuat oli lama lebih mudah mengalir","Mendinginkan komponen mesin","Mengurangi tekanan pada karburator","Menstabilkan putaran mesin"], correct:1},
 {q:"Jika langkah ke-3 dan ke-5 pada teks tersebut ditukar urutannya, akibat yang paling mungkin terjadi adalah...", opts:["Oli baru akan tercampur dengan oli lama","Baut pembuangan tidak dapat dibuka sama sekali","Oli lama tidak dapat dikeluarkan karena baut belum dibuka saat wadah sudah terpasang","Proses penggantian oli menjadi lebih cepat","Tidak ada perbedaan hasil karena urutan bebas"], correct:2},
 {q:"Kalimat \"kencangkan hingga rapat, tetapi jangan berlebihan agar ulir baut tidak rusak\" berfungsi sebagai...", opts:["Latar belakang masalah","Peringatan sekaligus alasan tindakan","Kesimpulan prosedur","Tujuan utama teks","Definisi istilah teknis"], correct:1},
 {q:"Informasi yang TIDAK termuat secara eksplisit dalam teks tersebut adalah...", opts:["Jenis kunci yang digunakan","Lama waktu memanaskan mesin","Interval jarak tempuh ideal untuk mengganti oli","Alat untuk mengecek ketinggian oli","Tujuan memasang wadah penampung"], correct:2}
 ]
},
{
 title: "Teks 2 - Petunjuk Penggunaan Alat Pemadam Api Ringan (APAR)",
 stimulus: "Alat Pemadam Api Ringan (APAR) jenis serbuk kimia kering merupakan alat pertolongan pertama saat terjadi kebakaran skala kecil. Ikuti langkah berikut saat menggunakan APAR, yang dikenal dengan istilah PASS.\n\n1) Pull (tarik): Tarik pin pengaman yang terdapat pada bagian atas tabung.\n2) Aim (arahkan): Arahkan corong atau selang ke titik api, bukan ke kobaran asap.\n3) Squeeze (tekan): Tekan tuas atau pemicu secara mantap agar media pemadam keluar.\n4) Sweep (ayunkan): Ayunkan corong ke kiri dan ke kanan menyapu dasar api hingga api benar-benar padam.\n\nSebelum menggunakan APAR, pastikan posisi tubuh membelakangi arah angin agar asap dan media pemadam tidak mengenai wajah. Setelah kebakaran padam, jangan langsung meninggalkan lokasi; tunggu beberapa saat untuk memastikan tidak ada bara api yang menyala kembali.",
 questions: [
 {q:"Singkatan PASS pada teks tersebut merujuk pada...", opts:["Empat jenis APAR","Empat tahapan menggunakan APAR","Empat bahan pemadam api","Empat lokasi penyimpanan APAR","Empat ukuran tabung"], correct:1},
 {q:"Bagian tabung yang pertama kali harus ditarik adalah...", opts:["Selang","Corong","Pin pengaman","Tuas pemicu","Label tabung"], correct:2},
 {q:"Tujuan mengarahkan corong ke titik api, bukan ke kobaran asap adalah...", opts:["Agar media pemadam lebih hemat","Karena asap tidak mengandung oksigen","Agar sumber api langsung padam, bukan hanya menghilangkan asapnya","Supaya pengguna tidak terlihat panik","Karena asap dapat merusak tabung APAR"], correct:2},
 {q:"Posisi tubuh membelakangi arah angin saat memadamkan api bertujuan untuk...", opts:["Mempercepat proses penyemprotan","Menghindari asap dan media pemadam mengenai wajah pengguna","Membuat api lebih cepat menyebar","Mengurangi tekanan dalam tabung","Memudahkan pengambilan tabung cadangan"], correct:1},
 {q:"Simpulan yang paling tepat berdasarkan seluruh isi teks tersebut adalah...", opts:["APAR hanya dapat digunakan oleh petugas pemadam kebakaran profesional","Penggunaan APAR memerlukan urutan tindakan dan kewaspadaan hingga api benar-benar padam","APAR jenis serbuk kimia kering tidak boleh digunakan untuk kebakaran skala kecil","Kobaran asap lebih berbahaya daripada api itu sendiri","Tuas pemicu hanya berfungsi jika pin belum dilepas"], correct:1}
 ]
},
{
 title: "Teks 3 - Dua Metode Menyeduh Kopi (Perbandingan)",
 stimulus: "Teks A - Menyeduh Kopi Metode V60\nAlat: dripper V60, kertas filter, kopi bubuk giling sedang-halus 15 gram, air panas suhu 92-96 derajat Celsius, timbangan, kettle leher angsa.\nLangkah: 1) Basahi kertas filter dengan air panas untuk menghilangkan aroma kertas. 2) Masukkan kopi bubuk ke dalam filter, ratakan permukaannya. 3) Tuang air panas sedikit demi sedikit membentuk gerakan memutar selama 30 detik untuk proses blooming. 4) Lanjutkan menuang air secara bertahap hingga total air mencapai 250 ml dalam waktu sekitar tiga menit. 5) Biarkan air menetes habis sebelum dripper diangkat.\n\nTeks B - Menyeduh Kopi Metode Tubruk\nAlat: cangkir atau gelas tahan panas, kopi bubuk kasar 10 gram, air panas suhu 90 derajat Celsius, sendok.\nLangkah: 1) Masukkan kopi bubuk langsung ke dalam cangkir. 2) Tuangkan air panas hingga cangkir hampir penuh. 3) Aduk sebentar agar bubuk kopi tercampur rata dengan air. 4) Diamkan selama tiga hingga empat menit hingga ampas kopi mengendap di dasar cangkir. 5) Kopi siap dinikmati tanpa perlu disaring.",
 questions: [
 {q:"Perbedaan utama alat yang digunakan pada kedua metode tersebut adalah...", opts:["Metode V60 tidak memerlukan air panas","Metode V60 menggunakan dripper dan kertas filter, sedangkan metode tubruk tidak","Metode tubruk memerlukan timbangan, metode V60 tidak","Kedua metode sama-sama tidak menggunakan air panas","Metode tubruk memerlukan kettle leher angsa"], correct:1},
 {q:"Persamaan dari kedua prosedur penyeduhan kopi tersebut adalah...", opts:["Keduanya menggunakan kertas filter","Keduanya memerlukan proses penyaringan","Keduanya menggunakan air panas dan kopi bubuk sebagai bahan utama","Keduanya menghasilkan volume kopi yang sama persis","Keduanya membutuhkan waktu penyeduhan yang identik"], correct:2},
 {q:"Ukuran gilingan kopi pada metode V60 lebih halus dibandingkan metode tubruk. Hal ini kemungkinan besar berkaitan dengan...", opts:["Warna kopi yang dihasilkan","Adanya proses penyaringan menggunakan kertas filter pada metode V60","Suhu air yang digunakan","Jenis cangkir yang dipakai","Lama waktu penyimpanan kopi bubuk"], correct:1},
 {q:"Jika seseorang tidak memiliki kertas filter maupun dripper tetapi ingin menikmati kopi dengan cepat tanpa proses penuangan bertahap, metode yang paling sesuai untuk direkomendasikan adalah...", opts:["Metode V60, karena hasilnya lebih jernih","Metode tubruk, karena alat yang dibutuhkan lebih sederhana dan langkahnya lebih singkat","Kedua metode sama-sama tidak dapat dilakukan","Metode V60, karena prosesnya lebih cepat daripada tubruk","Tidak dapat ditentukan karena teks tidak membahas kecepatan penyeduhan"], correct:1},
 {q:"Lama waktu penuangan air pada metode V60 hingga mencapai 250 ml adalah sekitar...", opts:["30 detik","1 menit","3 menit","5 menit","10 menit"], correct:2}
 ]
},
{
 title: "Teks 4 - Langkah Mendaftar Akun SIAKAD Sekolah",
 stimulus: "Berikut langkah pendaftaran akun SIAKAD bagi peserta didik baru.\n1) Buka peramban (browser) lalu ketik alamat siakad.sekolah.sch.id pada bilah alamat.\n2) Klik tombol \"Daftar Akun Baru\" yang terletak di pojok kanan atas laman.\n3) Isi formulir menggunakan Nomor Induk Siswa (NIS) dan tanggal lahir sesuai data yang tercatat di tata usaha.\n4) Buat kata sandi yang terdiri atas kombinasi huruf, angka, dan simbol, minimal delapan karakter.\n5) Klik tombol \"Kirim\", kemudian periksa surel (email) untuk menemukan tautan aktivasi akun.\n6) Klik tautan aktivasi tersebut dalam waktu 24 jam agar akun tidak perlu didaftarkan ulang.\n7) Masuk (login) ke SIAKAD menggunakan NIS dan kata sandi yang telah dibuat.",
 questions: [
 {q:"Data yang digunakan untuk mengisi formulir pendaftaran adalah...", opts:["Nomor telepon dan alamat rumah","NIS dan tanggal lahir","Nama orang tua dan pekerjaan","Alamat surel dan nomor rekening","Nomor induk kependudukan dan agama"], correct:1},
 {q:"Tautan aktivasi akun dikirimkan melalui...", opts:["Pesan singkat (SMS)","Aplikasi SIAKAD langsung","Surel (email)","Media sosial sekolah","Surat resmi dari tata usaha"], correct:2},
 {q:"Batas waktu mengklik tautan aktivasi sebagaimana disebutkan dalam teks adalah...", opts:["1 jam","12 jam","24 jam","48 jam","7 hari"], correct:2},
 {q:"Apabila siswa tidak mengklik tautan aktivasi dalam batas waktu yang ditentukan, konsekuensi yang paling mungkin terjadi berdasarkan teks adalah...", opts:["Akun otomatis aktif dengan sendirinya","Siswa harus mendaftarkan akun dari awal","Kata sandi akan direset otomatis oleh sistem","Data NIS akan terhapus dari sistem sekolah","Tidak ada konsekuensi apa pun"], correct:1},
 {q:"Kalimat \"Buat kata sandi yang terdiri atas kombinasi huruf, angka, dan simbol, minimal delapan karakter\" termasuk ke dalam unsur kebahasaan teks prosedur berupa...", opts:["Kalimat tanya","Kalimat larangan","Kalimat perintah (imperatif) yang memuat syarat/batasan","Kalimat pengandaian","Kalimat pasif"], correct:2}
 ]
},
{
 title: "Teks 5 - Kaidah Kebahasaan Teks Prosedur",
 stimulus: "Teks prosedur memiliki ciri kebahasaan yang khas agar pembaca dapat melaksanakan langkah-langkah dengan tepat. Beberapa ciri tersebut antara lain: penggunaan kalimat imperatif (perintah) seperti \"potong\", \"aduk\", atau \"tekan\"; penggunaan konjungsi temporal seperti \"kemudian\", \"setelah itu\", dan \"selanjutnya\" untuk menunjukkan urutan langkah; penggunaan kata kerja aktif yang menyatakan tindakan konkret; penggunaan kalimat larangan yang biasanya ditandai kata \"jangan\" atau \"hindari\" untuk memberi peringatan; serta penggunaan keterangan alat, bahan, ukuran, atau waktu secara spesifik dan terukur.",
 questions: [
 {q:"Kata yang termasuk konjungsi temporal dalam teks prosedur adalah...", opts:["Karena","Kemudian","Meskipun","Walaupun","Namun"], correct:1},
 {q:"Kalimat \"Jangan menyentuh permukaan wajan yang masih panas\" merupakan contoh kalimat...", opts:["Kalimat tanya","Kalimat larangan","Kalimat berita","Kalimat pengandaian","Kalimat majemuk setara"], correct:1},
 {q:"Fungsi utama konjungsi temporal dalam teks prosedur adalah...", opts:["Menghubungkan dua kalimat yang bertentangan","Menunjukkan urutan atau tahapan pelaksanaan langkah","Menyatakan sebab akibat suatu tindakan","Menyatakan syarat sebuah tindakan","Menyatakan tujuan akhir prosedur"], correct:1},
 {q:"Manakah kalimat berikut yang menggunakan kata kerja imperatif dengan tepat?", opts:["Adonan itu diaduk oleh koki","Adonan akan diaduk hingga rata","Aduklah adonan hingga rata","Adonan telah diaduk hingga rata","Adonan sedang diaduk oleh asisten koki"], correct:2},
 {q:"Perhatikan kalimat berikut: \"Panaskan oven pada suhu 180 derajat Celsius selama sepuluh menit sebelum adonan dimasukkan.\" Unsur kebahasaan yang paling menonjol pada kalimat tersebut, selain kalimat imperatif, adalah...", opts:["Konjungsi pertentangan","Keterangan ukuran/suhu dan waktu yang spesifik dan terukur","Kalimat tanya retoris","Kata kerja pasif","Kalimat majemuk bertingkat sebab-akibat"], correct:1}
 ]
},
{
 title: "Teks 6 - Petunjuk Mengoperasikan Mesin Bubut Sederhana",
 stimulus: "Sebelum mengoperasikan mesin bubut, operator wajib memahami langkah keselamatan dan pengoperasian berikut.\n1) Kenakan alat pelindung diri berupa kacamata safety dan pakaian kerja yang pas di badan, hindari pakaian longgar yang dapat tersangkut komponen berputar.\n2) Periksa benda kerja dan pastikan tercekam kuat pada chuck sebelum mesin dinyalakan.\n3) Atur kecepatan putar (rpm) sesuai jenis material yang akan dibubut; gunakan kecepatan rendah untuk material keras dan kecepatan tinggi untuk material lunak.\n4) Nyalakan mesin dan dekatkan pahat secara perlahan ke benda kerja.\n5) Lakukan pemakanan (feeding) secara bertahap, jangan terlalu dalam agar pahat tidak patah.\n6) Setelah selesai, matikan mesin terlebih dahulu sebelum melepas benda kerja dari chuck.",
 questions: [
 {q:"Alat pelindung diri yang disebutkan dalam teks adalah...", opts:["Helm proyek","Kacamata safety","Sarung tangan karet","Masker respirator","Sepatu boots"], correct:1},
 {q:"Sebelum mesin dinyalakan, hal yang harus dipastikan operator adalah...", opts:["Kecepatan rpm sudah maksimal","Benda kerja tercekam kuat pada chuck","Pahat sudah patah","Mesin dalam keadaan mati total","Ruangan dalam keadaan gelap"], correct:1},
 {q:"Alasan pakaian longgar dilarang dikenakan saat mengoperasikan mesin bubut adalah...", opts:["Membuat operator terlihat kurang rapi","Dapat tersangkut pada komponen mesin yang berputar dan membahayakan keselamatan","Mengurangi kenyamanan gerak operator","Tidak sesuai dengan standar seragam sekolah","Menghambat proses pemakanan benda kerja"], correct:1},
 {q:"Pengaturan kecepatan putar (rpm) pada langkah ketiga bergantung pada...", opts:["Ukuran ruangan bengkel","Jenis material benda kerja","Warna benda kerja","Berat badan operator","Waktu pengerjaan yang tersedia"], correct:1},
 {q:"Mengapa mesin harus dimatikan terlebih dahulu sebelum benda kerja dilepas dari chuck?", opts:["Agar proses pelepasan lebih cepat","Untuk menghindari cedera akibat komponen mesin yang masih berputar","Karena chuck tidak dapat dibuka saat mesin menyala","Agar rpm dapat diatur ulang","Karena benda kerja akan otomatis terlepas saat mesin mati"], correct:1}
 ]
},
{
 title: "Teks 7 - Menyusun Teks Prosedur yang Baik",
 stimulus: "Sebuah teks prosedur yang baik disusun dengan struktur yang jelas, yaitu: (1) judul yang menggambarkan tujuan prosedur secara ringkas, (2) tujuan atau pengantar yang menjelaskan hasil akhir yang ingin dicapai, (3) daftar alat dan bahan (jika diperlukan), dan (4) langkah-langkah yang disusun secara runtut dan bernomor. Setiap langkah sebaiknya ditulis dengan kalimat yang singkat, jelas, dan tidak menimbulkan makna ganda. Penulis juga perlu memastikan bahwa tidak ada langkah penting yang terlewat, karena satu langkah yang hilang dapat menyebabkan pembaca gagal melaksanakan prosedur dengan benar.",
 questions: [
 {q:"Struktur teks prosedur yang disebutkan dalam teks tersebut terdiri atas empat bagian, salah satunya adalah...", opts:["Orientasi","Daftar alat dan bahan","Resolusi","Koda","Abstrak"], correct:1},
 {q:"Alasan setiap langkah dalam teks prosedur harus ditulis dengan kalimat yang tidak menimbulkan makna ganda adalah...", opts:["Agar teks terlihat lebih panjang","Supaya pembaca dapat melaksanakan langkah dengan tepat sesuai maksud penulis","Agar teks memenuhi syarat jumlah kata minimal","Supaya pembaca merasa terhibur","Agar teks dapat dikategorikan sebagai karya sastra"], correct:1},
 {q:"Akibat yang paling mungkin terjadi apabila satu langkah penting dalam teks prosedur terlewat adalah...", opts:["Pembaca akan lebih cepat menyelesaikan prosedur","Pembaca berpotensi gagal melaksanakan prosedur dengan benar","Teks menjadi lebih ringkas dan efektif","Tidak berpengaruh apa pun terhadap hasil akhir","Pembaca akan otomatis menambahkan langkah yang hilang"], correct:1},
 {q:"Seorang siswa menulis teks prosedur \"Cara Membuat Nasi Goreng\" namun langsung menuliskan langkah-langkah tanpa mencantumkan bahan yang diperlukan. Berdasarkan teks di atas, kekurangan tulisan siswa tersebut adalah...", opts:["Tidak memiliki judul","Tidak mencantumkan daftar alat dan bahan yang diperlukan sebelum langkah-langkah","Menggunakan kalimat imperatif","Langkah-langkah tidak diberi nomor","Menggunakan konjungsi temporal"], correct:1},
 {q:"Bagian yang menjelaskan hasil akhir yang ingin dicapai dalam teks prosedur disebut...", opts:["Daftar bahan","Tujuan/pengantar","Penutup","Judul","Simpulan"], correct:1}
 ]
},
{
 title: "Teks 8 - Dua Contoh Petunjuk Merakit Rak Buku (Perbandingan)",
 stimulus: "Teks A - Cara Merakit Rak Buku Knock-Down\nAlat dan bahan: obeng plus, papan rak (5 bagian), sekrup (20 buah), dowel kayu (8 buah).\nLangkah:\n1) Susun papan alas dan dua papan samping membentuk huruf U, lalu satukan menggunakan dowel kayu.\n2) Kencangkan sambungan menggunakan sekrup dan obeng plus.\n3) Pasang papan tengah sebagai sekat rak sesuai jarak yang diinginkan.\n4) Pasang papan atas sebagai penutup rak, lalu kencangkan seluruh sekrup hingga rak kokoh berdiri.\n\nTeks B - Cara Merakit Rak Buku\nSiapkan bahan-bahannya. Lalu pasang semua bagian. Kencangkan bagian yang perlu dikencangkan. Setelah itu rak sudah jadi dan siap digunakan.",
 questions: [
 {q:"Perbedaan mencolok antara Teks A dan Teks B adalah...", opts:["Teks A tidak memiliki langkah, Teks B memiliki langkah rinci","Teks A memuat langkah yang rinci dan terukur, sedangkan Teks B ditulis secara umum dan kurang jelas","Teks B mencantumkan alat dan bahan, Teks A tidak","Kedua teks sama-sama rinci dan mudah diikuti","Teks A lebih pendek daripada Teks B"], correct:1},
 {q:"Kalimat \"pasang semua bagian\" pada Teks B dinilai kurang efektif sebagai kalimat prosedur karena...", opts:["Menggunakan kalimat imperatif","Tidak menjelaskan bagian mana yang dipasang dan bagaimana cara memasangnya secara spesifik","Menggunakan konjungsi temporal","Terlalu panjang untuk dipahami","Tidak menggunakan huruf kapital di awal kalimat"], correct:1},
 {q:"Jika seseorang yang belum pernah merakit rak buku hanya diberikan Teks B, kemungkinan besar yang akan terjadi adalah...", opts:["Ia dapat merakit rak dengan sangat mudah karena instruksinya sudah lengkap","Ia akan kesulitan karena teks tidak menjelaskan alat, bahan, dan langkah secara rinci","Ia akan merakit rak lebih cepat dibandingkan menggunakan Teks A","Tidak ada perbedaan hasil rakitan antara menggunakan Teks A atau Teks B","Teks B lebih mudah dipahami karena lebih singkat"], correct:1},
 {q:"Berdasarkan perbandingan kedua teks tersebut, kesimpulan yang paling tepat mengenai kualitas sebuah teks prosedur adalah...", opts:["Semakin singkat sebuah teks prosedur, semakin baik kualitasnya","Kualitas teks prosedur ditentukan oleh kelengkapan alat/bahan serta kejelasan dan keterukuran setiap langkahnya","Teks prosedur tidak memerlukan daftar alat dan bahan","Teks prosedur yang baik tidak perlu menggunakan angka atau ukuran","Panjang pendeknya teks tidak berpengaruh pada pemahaman pembaca"], correct:1},
 {q:"Apabila Teks B ingin diperbaiki agar setara dengan kualitas Teks A, revisi yang paling tepat dilakukan adalah...", opts:["Menghapus seluruh langkah yang ada","Mengganti judul teks menjadi lebih panjang","Menambahkan daftar alat dan bahan serta merincikan setiap langkah secara spesifik dan berurutan","Mengubah seluruh kalimat menjadi kalimat tanya","Menghilangkan tanda baca pada setiap kalimat"], correct:2}
 ]
}
];

// Esai 1-5: materi "Membandingkan Teks Prosedur dengan Teks Lain (Eksplanasi)"
// Esai 6-10: materi "Evaluasi Informasi dalam Teks Prosedur"
// Setiap soal punya beberapa "konsep kunci"; tiap konsep berisi beberapa alternatif kata/frasa (OR).
// Skor esai per soal = (jumlah konsep yang ditemukan / total konsep) x 100, lalu dirata-rata dari 10 soal.
const ESSAYS = [
 { q: "Jelaskan pengertian teks eksplanasi dan bagaimana tujuannya berbeda dengan teks prosedur!",
 concepts: [["fenomena","proses alam","proses sosial","proses ilmiah"], ["sebab-akibat","sebab akibat","kausalitas"], ["memahami","paham"], ["tindakan","melakukan","diikuti"]] },
 { q: "Sebutkan struktur teks eksplanasi (3 bagian) dan jelaskan secara singkat masing-masing bagian tersebut!",
 concepts: [["pernyataan umum"], ["deretan penjelas","deret penjelas","penjelasan sebab akibat","rangkaian penjelas"], ["interpretasi","penutup"]] },
 { q: "Sebutkan minimal 3 persamaan antara teks prosedur dan teks eksplanasi!",
 concepts: [["proses","tahapan"], ["informatif"], ["faktual","fakta"], ["konjungsi"], ["sistematis"]] },
 { q: "Jelaskan perbedaan konjungsi dominan yang digunakan pada teks prosedur dan teks eksplanasi, berikan masing-masing satu contoh katanya!",
 concepts: [["temporal"], ["kausalitas"], ["kemudian","lalu","setelah itu"], ["karena","sebab","akibatnya"]] },
 { q: "Jelaskan langkah-langkah membandingkan teks prosedur dengan teks eksplanasi secara berurutan!",
 concepts: [["membaca"], ["tujuan"], ["struktur"], ["kebahasaan","bahasa"], ["simpulan","kesimpulan"]] },
 { q: "Jelaskan apa yang dimaksud dengan \"mengevaluasi informasi\" dalam teks prosedur, dan bagaimana bedanya dengan sekadar \"memahami\" isi teks!",
 concepts: [["menilai","penilaian"], ["dipercaya","layak"], ["logis","masuk akal"], ["kritis"]] },
 { q: "Sebutkan minimal 4 dari 6 kriteria evaluasi teks prosedur yang telah dipelajari!",
 concepts: [["keakuratan","akurat"], ["kelengkapan","lengkap"], ["kelogisan","logis","urutan"], ["kejelasan","jelas","ambigu"], ["kesesuaian","sesuai tujuan"], ["keselamatan","k3","kelayakan"]] },
 { q: "Jelaskan mengapa kemampuan mengevaluasi teks prosedur penting bagi siswa SMK, kaitkan dengan dunia kerja/kejuruan!",
 concepts: [["kegagalan kerja","gagal kerja"], ["kerusakan alat","rusak"], ["kecelakaan kerja","kecelakaan"], ["kesiapan kerja","job readiness"]] },
 { q: "Sebutkan langkah-langkah mengevaluasi teks prosedur secara berurutan!",
 concepts: [["membaca menyeluruh","membaca"], ["struktur"], ["kriteria"], ["temuan"], ["menyimpulkan","simpulan"], ["rekomendasi","saran perbaikan"]] },
 { q: "Perhatikan temuan berikut: sebuah teks prosedur menuliskan \"Tuang oli mesin baru sebanyak 5 liter\", padahal kapasitas oli mesin sepeda motor umumnya hanya sekitar 0,8-1,2 liter. Kriteria evaluasi apa yang dilanggar pada temuan tersebut, dan jelaskan alasannya!",
 concepts: [["keakuratan","akurat","tidak akurat"], ["spesifikasi","standar"], ["takaran","kapasitas"], ["5 liter","0,8","1,2","tidak sesuai"]] }
];
const ESSAY_MAXLEN = 500;
const PG_WEIGHT = 0.7;
const ESSAY_WEIGHT = 0.3;

function scoreEssayAnswer(answerText, concepts){
 const norm = (answerText || '').toLowerCase();
 let found = 0;
 concepts.forEach(altGroup =&gt; {
 const hit = altGroup.some(alt =&gt; norm.includes(alt.toLowerCase()));
 if(hit) found++;
 });
 return {found: found, total: concepts.length, pct: Math.round((found/concepts.length)*100)};
}

const LETTERS = ["A","B","C","D","E"];
const KKM = 75;
const MAX_ATTEMPT = 3;
let currentAbsen = null, currentNama = null, currentKelas = null, currentRecord = null;
let quizGroups = null;
let answers = {};
let essayAnswers = {};

function shuffle(arr){
 const a = arr.slice();
 for(let i=a.length-1;i&gt;0;i--){
 const j = Math.floor(Math.random()*(i+1));
 [a[i],a[j]] = [a[j],a[i]];
 }
 return a;
}

function buildShuffledQuiz(){
 const groupOrder = shuffle(GROUPS);
 return groupOrder.map(g =&gt; ({
 title: g.title,
 stimulus: g.stimulus,
 questions: shuffle(g.questions).map(q =&gt; {
 const optIdx = shuffle(q.opts.map((_,i)=&gt;i));
 return {
 q: q.q,
 opts: optIdx.map(i =&gt; q.opts[i]),
 correctLetter: LETTERS[optIdx.indexOf(q.correct)]
 };
 })
 }));
}

async function loadRecord(absen){
 try{
 const r = await window.storage.get('siswa:'+absen, true);
 return r ? JSON.parse(r.value) : null;
 }catch(e){
 return null;
 }
}
async function saveRecord(absen, record){
 try{
 await window.storage.set('siswa:'+absen, JSON.stringify(record), true);
 }catch(e){
 console.error('Gagal menyimpan data', e);
 }
}

document.getElementById('btnCekStatus').addEventListener('click', async () =&gt; {
 const absenEl = document.getElementById('absen');
 const namaEl = document.getElementById('nama');
 const kelasEl = document.getElementById('kelas');
 const absen = absenEl.value.trim();
 const nama = namaEl.value.trim();
 const kelas = kelasEl.value.trim();
 const err = document.getElementById('introErr');
 if(!absen || !nama || !kelas){
 err.style.display = 'block';
 return;
 }
 err.style.display = 'none';
 currentAbsen = absen;
 currentNama = nama;
 currentKelas = kelas;
 currentRecord = await loadRecord(absen);
 if(!currentRecord){
 currentRecord = {absen, nama, kelas, attempts: [], final: null};
 } else {
 currentRecord.nama = nama;
 currentRecord.kelas = kelas;
 }
 showStatusScreen();
});

document.getElementById('btnGanti').addEventListener('click', () =&gt; {
 document.getElementById('screen-status').classList.add('hidden');
 document.getElementById('screen-intro').classList.remove('hidden');
});

function showStatusScreen(){
 document.getElementById('screen-intro').classList.add('hidden');
 const statusScreen = document.getElementById('screen-status');
 statusScreen.classList.remove('hidden');
 document.getElementById('statusGreeting').textContent = 'Halo, ' + currentNama + ' (No. Absen ' + currentAbsen + ')';
 const body = document.getElementById('statusBody');
 const btnMulai = document.getElementById('btnMulai');
 const usedAttempts = currentRecord.attempts.length;
 const sisa = MAX_ATTEMPT - usedAttempts;

 const btnUnduhStatus = document.getElementById('btnUnduhStatus');
 if(currentRecord.final){
 const f = currentRecord.final;
 body.innerHTML =
 '&lt;p style="font-size:14px;"&gt;Nilai kamu sudah tersimpan sebagai nilai akhir.&lt;/p&gt;' +
 '&lt;div class="result-box ' + (f.score &gt;= KKM ? 'pass-bg' : 'fail-bg') + '" style="margin-top:10px;"&gt;' +
 '&lt;div style="font-size:13px;color:var(--ink-soft);"&gt;Nilai akhir tersimpan&lt;/div&gt;' +
 '&lt;div class="result-score ' + (f.score &gt;= KKM ? 'pass' : 'fail') + '"&gt;' + f.score + '&lt;/div&gt;' +
 '&lt;div style="font-size:13px;"&gt;' + (f.score &gt;= KKM ? 'Mencapai KKM (75)' : 'Nilai tertinggi dari 3 percobaan (belum mencapai KKM)') + '&lt;/div&gt;' +
 '&lt;div style="font-size:12px;color:var(--ink-soft);margin-top:6px;"&gt;Skor PG ' + f.pgScore + ' (bobot 70%) - Skor Esai ' + f.essayScorePct + ' (bobot 30%)&lt;/div&gt;' +
 '&lt;/div&gt;' +
 renderAttemptListHTML(currentRecord.attempts);
 btnMulai.classList.add('hidden');
 btnUnduhStatus.classList.remove('hidden');
 document.getElementById('instruksiStatus').classList.remove('hidden');
 } else if(sisa &lt;= 0){
 body.innerHTML = '&lt;p style="font-size:14px;"&gt;Kesempatanmu sudah habis. Sistem akan segera mencatat nilai tertinggimu.&lt;/p&gt;';
 btnMulai.classList.add('hidden');
 btnUnduhStatus.classList.add('hidden');
 document.getElementById('instruksiStatus').classList.add('hidden');
 } else {
 btnUnduhStatus.classList.add('hidden');
 document.getElementById('instruksiStatus').classList.add('hidden');
 body.innerHTML =
 '&lt;p style="font-size:14px;"&gt;Sisa kesempatan mengerjakan: &lt;b&gt;' + sisa + ' dari ' + MAX_ATTEMPT + '&lt;/b&gt;.&lt;/p&gt;' +
 (usedAttempts &gt; 0 ? renderAttemptListHTML(currentRecord.attempts) : '');
 btnMulai.classList.remove('hidden');
 btnMulai.textContent = usedAttempts === 0 ? 'Mulai Mengerjakan' : 'Coba Lagi (Percobaan ke-' + (usedAttempts+1) + ')';
 }
}

function renderAttemptListHTML(attempts){
 if(!attempts.length) return '';
 let html = '&lt;div class="attempt-log"&gt;&lt;b style="font-size:13px;"&gt;Riwayat percobaan:&lt;/b&gt;';
 attempts.forEach((a,i) =&gt; {
 html += '&lt;div&gt;&lt;span&gt;Percobaan ' + (i+1) + ' (PG ' + a.pgScore + ' - Esai ' + a.essayScorePct + ')&lt;/span&gt;&lt;span&gt;' + a.score + ' poin&lt;/span&gt;&lt;/div&gt;';
 });
 html += '&lt;/div&gt;';
 return html;
}

document.getElementById('btnMulai').addEventListener('click', startQuiz);

function startQuiz(){
 answers = {};
 essayAnswers = {};
 quizGroups = buildShuffledQuiz();
 document.getElementById('screen-status').classList.add('hidden');
 document.getElementById('screen-result').classList.add('hidden');
 document.getElementById('screen-quiz').classList.remove('hidden');
 renderQuiz();
 window.scrollTo({top:0, behavior:'smooth'});
}

function renderQuiz(){
 const body = document.getElementById('quizBody');
 let html = '';
 let counter = 0;
 quizGroups.forEach((g, gi) =&gt; {
 html += '&lt;div class="qgroup"&gt;&lt;div class="stimulus"&gt;&lt;div class="st-title"&gt;' + esc(g.title) + '&lt;/div&gt;' + esc(g.stimulus) + '&lt;/div&gt;';
 g.questions.forEach((q, qi) =&gt; {
 counter++;
 const qKey = gi + '-' + qi;
 html += '&lt;div class="q" data-qkey="' + qKey + '"&gt;';
 html += '&lt;div class="q-num"&gt;Soal ' + counter + '&lt;/div&gt;';
 html += '&lt;div class="q-text"&gt;' + esc(q.q) + '&lt;/div&gt;';
 q.opts.forEach((opt, oi) =&gt; {
 const letter = LETTERS[oi];
 html += '&lt;label class="opt" data-qkey="' + qKey + '" data-letter="' + letter + '"&gt;' +
 '&lt;input type="radio" name="q-' + qKey + '" value="' + letter + '"&gt;' +
 '&lt;span&gt;&lt;b&gt;' + letter + '.&lt;/b&gt; ' + esc(opt) + '&lt;/span&gt;&lt;/label&gt;';
 });
 html += '&lt;/div&gt;';
 });
 html += '&lt;/div&gt;';
 });

 html += '&lt;div class="sectionLabel"&gt;Bagian II - Esai (10 soal, dinilai otomatis berdasarkan kesesuaian konsep kunci jawabanmu - bobot Esai 30% dari nilai akhir - maksimal ' + ESSAY_MAXLEN + ' karakter per soal - jawaban wajib diketik sendiri, tempel/paste dinonaktifkan)&lt;/div&gt;';
 html += '&lt;div class="essaySection"&gt;';
 ESSAYS.forEach((item, ei) =&gt; {
 html += '&lt;div class="essayQ" data-ekey="' + ei + '"&gt;';
 html += '&lt;div class="essayQ-num"&gt;Esai ' + (ei+1) + '&lt;/div&gt;';
 html += '&lt;div class="essayQ-text"&gt;' + esc(item.q) + '&lt;/div&gt;';
 html += '&lt;textarea class="essayInput" data-ekey="' + ei + '" maxlength="' + ESSAY_MAXLEN + '" placeholder="Ketik jawabanmu di sini (tempel/paste tidak diperbolehkan)..."&gt;&lt;/textarea&gt;';
 html += '&lt;div class="charCount" data-ekey="' + ei + '"&gt;0 / ' + ESSAY_MAXLEN + '&lt;/div&gt;';
 html += '&lt;div class="pasteWarn" data-ekey="' + ei + '"&gt;Menempel (paste) tidak diperbolehkan. Silakan ketik sendiri jawabanmu.&lt;/div&gt;';
 html += '&lt;/div&gt;';
 });
 html += '&lt;/div&gt;';

 body.innerHTML = html;

 body.querySelectorAll('textarea.essayInput').forEach(ta =&gt; {
 ta.addEventListener('input', () =&gt; {
 const ekey = ta.getAttribute('data-ekey');
 essayAnswers[ekey] = ta.value;
 const counterEl = body.querySelector('.charCount[data-ekey="' + ekey + '"]');
 const len = ta.value.length;
 counterEl.textContent = len + ' / ' + ESSAY_MAXLEN;
 counterEl.classList.toggle('over', len &gt;= ESSAY_MAXLEN);
 updateProgress();
 });

 const showPasteWarn = () =&gt; {
 const ekey = ta.getAttribute('data-ekey');
 const warnEl = body.querySelector('.pasteWarn[data-ekey="' + ekey + '"]');
 if(!warnEl) return;
 warnEl.classList.add('show');
 clearTimeout(warnEl._hideTimer);
 warnEl._hideTimer = setTimeout(() =&gt; warnEl.classList.remove('show'), 3500);
 };

 ta.addEventListener('paste', (e) =&gt; { e.preventDefault(); showPasteWarn(); });
 ta.addEventListener('drop', (e) =&gt; { e.preventDefault(); showPasteWarn(); });
 ta.addEventListener('dragover', (e) =&gt; { e.preventDefault(); });
 ta.addEventListener('contextmenu', (e) =&gt; { e.preventDefault(); showPasteWarn(); });
 ta.addEventListener('keydown', (e) =&gt; {
 const key = (e.key || '').toLowerCase();
 const pasteCombo = (e.ctrlKey || e.metaKey) &amp;&amp; key === 'v';
 const shiftInsert = e.shiftKey &amp;&amp; key === 'insert';
 if(pasteCombo || shiftInsert){
 e.preventDefault();
 showPasteWarn();
 }
 });
 });

 body.querySelectorAll('.opt').forEach(optEl =&gt; {
 optEl.addEventListener('click', () =&gt; {
 const qKey = optEl.getAttribute('data-qkey');
 const letter = optEl.getAttribute('data-letter');
 answers[qKey] = letter;
 document.querySelectorAll('.opt[data-qkey="' + qKey + '"]').forEach(o =&gt; o.classList.remove('selected'));
 optEl.classList.add('selected');
 optEl.querySelector('input').checked = true;
 updateProgress();
 });
 });
 updateProgress();
}

function esc(s){
 const d = document.createElement('div');
 d.textContent = s;
 return d.innerHTML;
}

function totalPGQuestions(){
 return quizGroups.reduce((sum,g) =&gt; sum + g.questions.length, 0);
}

function totalQuestions(){
 return totalPGQuestions() + ESSAYS.length;
}

function essayAnsweredCount(){
 return ESSAYS.reduce((n,_,ei) =&gt; n + (essayAnswers[ei] &amp;&amp; essayAnswers[ei].trim() ? 1 : 0), 0);
}

function updateProgress(){
 const total = totalQuestions();
 const answered = Object.keys(answers).length + essayAnsweredCount();
 document.getElementById('progressFill').style.width = (answered/total*100) + '%';
 document.getElementById('progressText').textContent = answered + ' dari ' + total + ' soal terjawab (40 PG + 10 esai)';
}

document.getElementById('btnKirim').addEventListener('click', async () =&gt; {
 const total = totalQuestions();
 const answered = Object.keys(answers).length + essayAnsweredCount();
 const errEl = document.getElementById('quizErr');
 if(answered &lt; total){
 errEl.style.display = 'block';
 let target = null;
 const qEls = document.querySelectorAll('.q');
 for(let i=0;i&lt;qEls.length;i++){
 const qk = qEls[i].getAttribute('data-qkey');
 if(!answers[qk]){ target = qEls[i]; break; }
 }
 if(!target){
 const eEls = document.querySelectorAll('.essayQ');
 for(let i=0;i&lt;eEls.length;i++){
 const ek = eEls[i].getAttribute('data-ekey');
 if(!essayAnswers[ek] || !essayAnswers[ek].trim()){ target = eEls[i]; break; }
 }
 }
 if(target) target.scrollIntoView({behavior:'smooth', block:'center'});
 return;
 }
 errEl.style.display = 'none';

 let correctCount = 0;
 quizGroups.forEach((g, gi) =&gt; {
 g.questions.forEach((q, qi) =&gt; {
 const qKey = gi + '-' + qi;
 if(answers[qKey] === q.correctLetter) correctCount++;
 });
 });
 const pgScore = Math.round(correctCount * (100 / totalPGQuestions()));

 const essaySnapshot = ESSAYS.map((item, ei) =&gt; {
 const ans = (essayAnswers[ei] || '').trim();
 const result = scoreEssayAnswer(ans, item.concepts);
 return {q: item.q, a: ans, found: result.found, total: result.total, pct: result.pct};
 });
 const essayScorePct = Math.round(essaySnapshot.reduce((s,e) =&gt; s + e.pct, 0) / essaySnapshot.length);
 const score = Math.round(pgScore * PG_WEIGHT + essayScorePct * ESSAY_WEIGHT);

 currentRecord.attempts.push({score: score, pgScore: pgScore, essayScorePct: essayScorePct, essay: essaySnapshot, timestamp: new Date().toISOString()});
 const usedAttempts = currentRecord.attempts.length;

 if(score &gt;= KKM){
 currentRecord.final = {score: score, pgScore: pgScore, essayScorePct: essayScorePct, essay: essaySnapshot, source: 'kkm', attemptsUsed: usedAttempts, timestamp: new Date().toISOString()};
 } else if(usedAttempts &gt;= MAX_ATTEMPT){
 let best = currentRecord.attempts[0];
 currentRecord.attempts.forEach(a =&gt; { if(a.score &gt; best.score) best = a; });
 currentRecord.final = {score: best.score, pgScore: best.pgScore, essayScorePct: best.essayScorePct, essay: best.essay, source: 'tertinggi', attemptsUsed: usedAttempts, timestamp: new Date().toISOString()};
 }

 await saveRecord(currentAbsen, currentRecord);
 showResult(score, pgScore, essayScorePct);
});

function showResult(score, pgScore, essayScorePct){
 document.getElementById('screen-quiz').classList.add('hidden');
 const resultScreen = document.getElementById('screen-result');
 resultScreen.classList.remove('hidden');

 const passedNow = score &gt;= KKM;
 const outer = document.getElementById('resultBoxOuter');
 const usedAttempts = currentRecord.attempts.length;
 const sisa = MAX_ATTEMPT - usedAttempts;

 let statusLine;
 if(currentRecord.final &amp;&amp; currentRecord.final.source === 'kkm'){
 statusLine = 'Selamat! Nilai ini sudah mencapai KKM dan tersimpan sebagai nilai akhir.';
 } else if(currentRecord.final &amp;&amp; currentRecord.final.source === 'tertinggi'){
 statusLine = 'Kesempatan sudah habis. Nilai tertinggi dari 3 percobaanmu (' + currentRecord.final.score + ') tersimpan sebagai nilai akhir.';
 } else {
 statusLine = 'Nilai belum mencapai KKM (75). Sisa kesempatan: ' + sisa + '.';
 }

 outer.innerHTML =
 '&lt;div class="result-box ' + (passedNow ? 'pass-bg' : 'fail-bg') + '"&gt;' +
 '&lt;div style="font-size:13px;color:var(--ink-soft);"&gt;Nilai akhir percobaan ini&lt;/div&gt;' +
 '&lt;div class="result-score ' + (passedNow ? 'pass' : 'fail') + '"&gt;' + score + ' / 100&lt;/div&gt;' +
 '&lt;div style="font-size:12px;color:var(--ink-soft);margin-bottom:6px;"&gt;Skor PG ' + pgScore + ' (bobot 70%) + Skor Esai ' + essayScorePct + ' (bobot 30%)&lt;/div&gt;' +
 '&lt;div style="font-size:14px;"&gt;' + statusLine + '&lt;/div&gt;' +
 '&lt;/div&gt;';

 document.getElementById('attemptLog').innerHTML = renderAttemptListHTML(currentRecord.attempts);

 const btnCoba = document.getElementById('btnCobaLagi');
 const btnUnduhHasil = document.getElementById('btnUnduhHasil');
 if(!currentRecord.final &amp;&amp; sisa &gt; 0){
 btnCoba.classList.remove('hidden');
 } else {
 btnCoba.classList.add('hidden');
 }
 if(currentRecord.final){
 btnUnduhHasil.classList.remove('hidden');
 document.getElementById('instruksiHasil').classList.remove('hidden');
 } else {
 btnUnduhHasil.classList.add('hidden');
 document.getElementById('instruksiHasil').classList.add('hidden');
 }
 window.scrollTo({top:0, behavior:'smooth'});
}

document.getElementById('btnCobaLagi').addEventListener('click', startQuiz);

document.getElementById('btnSelesai').addEventListener('click', () =&gt; {
 document.getElementById('screen-result').classList.add('hidden');
 document.getElementById('screen-intro').classList.remove('hidden');
 document.getElementById('absen').value = '';
 document.getElementById('nama').value = '';
 document.getElementById('kelas').value = '';
});

function generatePrintArea(){
 const f = currentRecord.final;
 if(!f) return;
 const tgl = new Date(f.timestamp || Date.now()).toLocaleDateString('id-ID', {day:'numeric', month:'long', year:'numeric'});
 const statusTxt = f.score &gt;= KKM
 ? 'Mencapai KKM (75) pada percobaan ke-' + f.attemptsUsed
 : 'Nilai tertinggi dari 3 kali percobaan (belum mencapai KKM 75)';

 let html = '';
 html += '&lt;div class="pf-kop noBreak"&gt;';
 html += '&lt;h2&gt;Bukti Mengerjakan Ulangan Harian 1 - Petunjuk Kerja&lt;/h2&gt;';
 html += '&lt;p&gt;Mata Pelajaran Bahasa Indonesia - Kelas XI SMK - 40 Soal Pilihan Ganda + 10 Soal Esai - KKM 75&lt;/p&gt;';
 html += '&lt;/div&gt;';

 html += '&lt;table class="pf-identitas noBreak"&gt;';
 html += '&lt;tr&gt;&lt;td class="lbl"&gt;Nama Lengkap&lt;/td&gt;&lt;td&gt;: ' + esc(currentRecord.nama || '') + '&lt;/td&gt;' +
 '&lt;td class="lbl"&gt;No. Absen&lt;/td&gt;&lt;td&gt;: ' + esc(currentRecord.absen || '') + '&lt;/td&gt;&lt;/tr&gt;';
 html += '&lt;tr&gt;&lt;td class="lbl"&gt;Kelas&lt;/td&gt;&lt;td&gt;: ' + esc(currentRecord.kelas || '') + '&lt;/td&gt;' +
 '&lt;td class="lbl"&gt;Tanggal&lt;/td&gt;&lt;td&gt;: ' + tgl + '&lt;/td&gt;&lt;/tr&gt;';
 html += '&lt;/table&gt;';

 html += '&lt;div class="pf-skorbox noBreak"&gt;';
 html += '&lt;div class="pf-skoritem"&gt;Skor Pilihan Ganda (70%)&lt;b&gt;' + f.pgScore + ' / 100&lt;/b&gt;&lt;/div&gt;';
 html += '&lt;div class="pf-skoritem"&gt;Skor Esai Otomatis (30%)&lt;b&gt;' + f.essayScorePct + ' / 100&lt;/b&gt;&lt;/div&gt;';
 html += '&lt;div class="pf-skoritem"&gt;Nilai Akhir&lt;b&gt;' + f.score + ' / 100&lt;/b&gt;&lt;/div&gt;';
 html += '&lt;div class="pf-skoritem"&gt;Status&lt;b style="font-size:13px;"&gt;' + statusTxt + '&lt;/b&gt;&lt;/div&gt;';
 html += '&lt;/div&gt;';

 html += '&lt;div class="pf-kop noBreak" style="border-top:1px solid #000;border-bottom:none;padding-top:8px;margin-top:6px;"&gt;&lt;h2 style="font-size:14px;"&gt;Jawaban Esai (skor otomatis berdasarkan cakupan konsep kunci)&lt;/h2&gt;&lt;/div&gt;';

 f.essay.forEach((item, i) =&gt; {
 const breakClass = (i === 4 || i === 8) ? ' pbreak' : '';
 html += '&lt;div class="noBreak' + breakClass + '" style="margin-bottom:10px;"&gt;';
 html += '&lt;div class="pf-essay-q"&gt;' + (i+1) + '. ' + esc(item.q) + ' &lt;span style="font-weight:400;color:#555;"&gt;(cakupan konsep: ' + item.found + '/' + item.total + ' - skor ' + item.pct + ')&lt;/span&gt;&lt;/div&gt;';
 html += '&lt;div class="pf-essay-a"&gt;' + esc(item.a || '(tidak dijawab)') + '&lt;/div&gt;';
 html += '&lt;/div&gt;';
 });

 html += '&lt;div class="pf-ttd noBreak"&gt;';
 html += '&lt;div&gt;Peserta Didik&lt;div class="garis"&gt;' + esc(currentRecord.nama || '') + '&lt;/div&gt;&lt;/div&gt;';
 html += '&lt;div&gt;Guru Mata Pelajaran&lt;div class="garis"&gt;.............................&lt;/div&gt;&lt;/div&gt;';
 html += '&lt;/div&gt;';
 html += '&lt;p class="pf-note"&gt;&lt;b&gt;Dokumen ini wajib dicetak dan diserahkan kepada guru mata pelajaran Bahasa Indonesia&lt;/b&gt; sebagai bukti fisik pengerjaan ulangan. Nilai akhir = (Skor Pilihan Ganda x 70%) + (Skor Esai Otomatis x 30%). Skor esai dihitung berdasarkan cakupan konsep kunci pada jawaban, sehingga guru tetap disarankan meninjau ulang jawaban esai untuk memastikan kualitas dan kejujuran akademik.&lt;/p&gt;';

 document.getElementById('printArea').innerHTML = html;
}

function downloadProof(){
 if(!currentRecord.final){
 alert('Bukti PDF hanya tersedia setelah nilai akhir tersimpan (mencapai KKM atau kesempatan sudah habis).');
 return;
 }
 generatePrintArea();
 setTimeout(() =&gt; window.print(), 100);
}

document.getElementById('btnUnduhStatus').addEventListener('click', downloadProof);
document.getElementById('btnUnduhHasil').addEventListener('click', downloadProof);
&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;</description><link>http://kitab-investasi.blogspot.com/2026/09/ulangan-harian-1-petunjuk-kerja.html</link><thr:total>0</thr:total><author>nof_rizal07@yahoo.co.id (abang_cool)</author></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-9000860041661554971.post-5290013737713810938</guid><pubDate>Fri, 04 Sep 2026 01:41:45 +0000</pubDate><atom:updated>2026-09-04T08:46:30.437+07:00</atom:updated><title>Latihan Soal Tipe AKM: Pokok Bahasan Petunjuk Kerja</title><description>&lt;style&gt;
@import url('https://fonts.googleapis.com/css2?family=Oswald:wght@400;500;600;700&amp;family=Source+Sans+3:wght@400;500;600;700&amp;family=IBM+Plex+Mono:wght@400;500;600&amp;display=swap');
.epb{
  --blueprint:#0F2A3D;
  --blueprint-deep:#0A1E2C;
  --panel:#4A2E12;
  --paper:#F3F0E6;
  --ink:#132029;
  --amber:#F5A623;
  --amber-deep:#C97F12;
  --mint:#6EC6CA;
  --line:rgba(234,242,245,0.16);
  --off-white:#EAF2F5;
  --muted:#9FB4C2;
}
.epb *{box-sizing:border-box;}
.epb{scroll-behavior:smooth; background:#0A1F2E;}
.epb{
  margin:0;
  position:relative;
  overflow:hidden;
  background:var(--blueprint);
  color:var(--off-white);
  font-family:'Source Sans 3',sans-serif;
  line-height:1.65;
  background-image:
    linear-gradient(var(--line) 1px, transparent 1px),
    linear-gradient(90deg, var(--line) 1px, transparent 1px);
  background-size: 34px 34px;
}
.epb h1, .epb h2, .epb h3, .epb h4{font-family:'Oswald',sans-serif; text-transform:uppercase; letter-spacing:0.02em; margin:0 0 0.5em;}
.epb .mono{font-family:'IBM Plex Mono',monospace;}
.epb a{color:var(--amber);}
.epb .crop{position:absolute; width:22px; height:22px; z-index:5; opacity:.55; pointer-events:none;}
.epb .crop::before, .epb .crop::after{content:"";position:absolute;background:var(--mint);}
.epb .crop::before{width:100%;height:1px;top:50%;left:0;}
.epb .crop::after{width:1px;height:100%;left:50%;top:0;}
.epb .crop.tl{top:14px;left:14px;}
.epb .crop.tr{top:14px;right:14px;}
.epb .crop.bl{bottom:14px;left:14px;}
.epb .crop.br{bottom:14px;right:14px;}
.epb header.cover{
  position:relative;
  padding:40px 24px 36px;
  border-bottom:1px solid var(--line);
  overflow:hidden;
}
.epb .doc-code{font-family:'IBM Plex Mono',monospace; color:var(--amber); letter-spacing:0.15em; font-size:0.78rem; text-transform:uppercase; margin-bottom:18px; display:flex; gap:10px; align-items:center;}
.epb .doc-code::before{content:"◆"; color:var(--amber);}
.epb .cover h1{font-size:clamp(1.6rem,7vw,2.5rem); color:var(--off-white); max-width:16ch; line-height:1.05;}
.epb .cover .subtitle{color:var(--muted); font-size:1.05rem; max-width:60ch; margin-top:14px;}
.epb .meta-strip{
  margin-top:38px; display:grid; grid-template-columns:repeat(auto-fit,minmax(150px,1fr));
  border-top:1px dashed var(--line); border-bottom:1px dashed var(--line);
}
.epb .meta-strip div{padding:14px 16px; border-right:1px dashed var(--line);}
.epb .meta-strip div:last-child{border-right:none;}
.epb .meta-strip .k{font-family:'IBM Plex Mono',monospace; font-size:0.68rem; color:var(--amber); text-transform:uppercase; letter-spacing:0.1em;}
.epb .meta-strip .v{font-size:0.98rem; color:var(--off-white); margin-top:4px; font-weight:600;}
.epb .stamp{
  position:absolute; top:40px; right:20px; width:104px; height:104px;
  border:2.5px solid var(--amber); border-radius:50%;
  display:flex; align-items:center; justify-content:center;
  transform:rotate(-11deg);
  color:var(--amber); font-family:'IBM Plex Mono',monospace;
  text-align:center; font-size:0.62rem; letter-spacing:0.08em; text-transform:uppercase;
  opacity:0.9;
}
.epb .stamp .ring{position:absolute; inset:8px; border:1px dashed var(--amber); border-radius:50%;}
.epb .stamp b{display:block; font-family:'Oswald',sans-serif; font-size:1.05rem; letter-spacing:0.06em; margin-top:4px;}

@media (max-width:760px){.epb .stamp{display:none;}
.epb }


.epb main{max-width:920px; margin:0 auto; padding:0 20px 60px;}
.epb .section{padding-top:64px;}
.epb .eyebrow{font-family:'IBM Plex Mono',monospace; color:var(--amber); font-size:0.78rem; letter-spacing:0.14em; text-transform:uppercase; margin-bottom:10px; display:flex; align-items:center; gap:10px;}
.epb .eyebrow::after{content:""; flex:1; height:1px; background:var(--line);}
.epb h2.section-title{font-size:1.7rem; color:var(--off-white);}
.epb p{color:#DDE7EC;}
.epb .lead{color:var(--muted); font-size:1.02rem; max-width:72ch;}
.epb .panel{
  background:var(--panel); border:1px solid var(--line); border-radius:2px;
  padding:26px 28px; margin:22px 0;
}
.epb .panel.tp{border-left:4px solid var(--mint);}
.epb .panel.warn{border-left:4px solid var(--amber);}
.epb .tp-box{display:grid; gap:14px; margin-top:18px;}
.epb .tp-item{display:flex; gap:14px; align-items:flex-start;}
.epb .tp-item .idx{font-family:'IBM Plex Mono',monospace; color:var(--amber); font-weight:600; min-width:34px;}
.epb .flow{display:grid; grid-template-columns:repeat(auto-fit,minmax(220px,1fr)); gap:14px; margin-top:20px;}
.epb .flow .step{background:var(--blueprint-deep); border:1px solid var(--line); padding:18px; position:relative;}
.epb .flow .step .tag{font-family:'IBM Plex Mono',monospace; color:var(--amber); font-size:0.7rem; letter-spacing:0.1em; text-transform:uppercase;}
.epb .flow .step h4{font-size:1rem; margin-top:8px; color:var(--off-white);}
.epb .flow .step .time{position:absolute; top:16px; right:16px; font-family:'IBM Plex Mono',monospace; font-size:0.7rem; color:var(--amber);}
.epb .grid-3{display:grid; grid-template-columns:repeat(auto-fit,minmax(200px,1fr)); gap:14px; margin-top:16px;}
.epb .card{background:var(--blueprint-deep); border:1px solid var(--line); padding:18px;}
.epb .card h4{color:var(--amber); font-size:0.95rem;}
.epb .criteria{display:grid; gap:16px; margin-top:20px;}
.epb .crit{
  background:var(--blueprint-deep); border:1px solid var(--line);
  display:grid; grid-template-columns:64px 1fr; gap:0;
}
.epb .crit .num{
  background:var(--amber); color:var(--blueprint-deep); font-family:'IBM Plex Mono',monospace;
  font-weight:700; display:flex; align-items:center; justify-content:center; font-size:1.05rem;
}
.epb .crit .body{padding:18px 20px;}
.epb .crit h4{color:var(--off-white); font-size:1.02rem; margin-bottom:6px;}
.epb .crit .q{margin-top:10px; padding-top:10px; border-top:1px dashed var(--line); font-family:'IBM Plex Mono',monospace; font-size:0.86rem; color:var(--amber);}
.epb .timeline{margin-top:24px; position:relative; padding-left:34px;}
.epb .timeline::before{content:""; position:absolute; left:11px; top:6px; bottom:6px; width:2px; background:var(--line);}
.epb .tl-item{position:relative; padding-bottom:26px;}
.epb .tl-item:last-child{padding-bottom:0;}
.epb .tl-item::before{content:""; position:absolute; left:-34px; top:2px; width:22px; height:22px; border-radius:50%; background:var(--blueprint); border:2px solid var(--amber);}
.epb .tl-item h4{color:var(--off-white); font-size:1rem; margin-bottom:4px;}
.epb .doc-sample{
  background:var(--paper); color:var(--ink); border-radius:2px; padding:0; margin-top:22px;
  box-shadow:0 20px 45px rgba(0,0,0,0.35);
}
.epb .doc-sample .doc-head{background:var(--ink); color:var(--paper); padding:12px 22px; font-family:'IBM Plex Mono',monospace; font-size:0.75rem; letter-spacing:0.1em; text-transform:uppercase; display:flex; justify-content:space-between;}
.epb .doc-sample .doc-body{padding:26px 28px 30px;}
.epb .doc-sample h3{font-family:'Oswald',sans-serif; color:var(--ink); font-size:1.25rem; text-transform:none; letter-spacing:0;}
.epb .doc-sample ol{padding-left:22px;}
.epb .doc-sample li{margin-bottom:9px;}
.epb .flag{
  display:inline-block; font-family:'IBM Plex Mono',monospace; font-size:0.7rem; font-weight:600;
  background:#D94E2A; color:#fff; padding:1px 7px; border-radius:2px; margin-left:6px; vertical-align:middle;
}
.epb .doc-sample .note-margin{margin-top:6px; font-family:'IBM Plex Mono',monospace; font-size:0.78rem; color:#8A3A1F; padding-left:8px; border-left:2px solid #D94E2A;}
.epb .legend{display:flex; flex-wrap:wrap; gap:10px 20px; margin-top:16px;}
.epb .legend span{font-family:'IBM Plex Mono',monospace; font-size:0.78rem; color:var(--muted); display:flex; align-items:center; gap:8px;}
.epb .legend .dot{width:10px; height:10px; border-radius:50%; display:inline-block;}
.epb table{width:100%; border-collapse:collapse; margin-top:18px; font-size:0.94rem;}
.epb th, .epb td{border:1px solid var(--line); padding:10px 12px; text-align:left; vertical-align:top;}
.epb th{background:var(--blueprint-deep); font-family:'IBM Plex Mono',monospace; font-size:0.75rem; text-transform:uppercase; letter-spacing:0.06em; color:var(--amber);}
.epb .summary-box{
  border:1px solid var(--amber); background:linear-gradient(180deg, rgba(245,166,35,0.08), transparent);
  padding:24px 26px; margin-top:24px;
}
.epb .summary-box ul{margin:10px 0 0; padding-left:20px;}
.epb .summary-box li{margin-bottom:8px;}
.epb .task-header{
  background:var(--amber); color:var(--blueprint-deep); padding:22px 26px; margin-top:20px;
  display:flex; justify-content:space-between; align-items:center; flex-wrap:wrap; gap:10px;
}
.epb .task-header h2{color:var(--blueprint-deep); font-size:1.4rem; margin:0;}
.epb .task-header .badge{font-family:'IBM Plex Mono',monospace; font-size:0.8rem; background:var(--blueprint-deep); color:var(--amber); padding:6px 12px; border-radius:2px;}
.epb .steps-num{counter-reset:step; margin-top:18px; list-style:none; padding:0;}
.epb .steps-num li{counter-increment:step; position:relative; padding-left:44px; margin-bottom:16px;}
.epb .steps-num li::before{content:counter(step,decimal-leading-zero); position:absolute; left:0; top:0; font-family:'IBM Plex Mono',monospace; color:var(--amber); font-weight:600; font-size:0.95rem; border:1px solid var(--amber); width:30px; height:26px; display:flex; align-items:center; justify-content:center;}
.epb .rubric-scale{display:grid; grid-template-columns:repeat(4,1fr); gap:10px; margin-top:16px;}
.epb .rubric-scale div{background:var(--blueprint-deep); border:1px solid var(--line); padding:12px; text-align:center;}
.epb .rubric-scale .n{font-family:'IBM Plex Mono',monospace; color:var(--amber); font-size:1.3rem; font-weight:700;}
.epb .rubric-scale .l{font-size:0.78rem; color:var(--muted); text-transform:uppercase; letter-spacing:0.05em;}
.epb .notebook{
  background:repeating-linear-gradient(var(--paper), var(--paper) 33px, #D8D3C2 34px);
  color:var(--ink); border-radius:2px; padding:28px 30px; margin-top:20px; position:relative;
  box-shadow:0 20px 45px rgba(0,0,0,0.35);
}
.epb .notebook::before{content:""; position:absolute; left:46px; top:0; bottom:0; width:1.5px; background:#C0453A; opacity:0.5;}
.epb .notebook .content{padding-left:24px;}
.epb .notebook h3{color:var(--ink); font-family:'Oswald',sans-serif; letter-spacing:0.02em; margin-bottom:10px;}
.epb .notebook ul{padding-left:20px;}
.epb footer{border-top:1px solid var(--line); padding:24px 20px 40px; color:var(--muted); font-size:0.86rem;}
.epb footer .doc-code{margin-bottom:10px;}
.epb .divider-dash{border:none; border-top:1px dashed var(--line); margin:44px 0 0;}
.epb::selection{background:var(--amber); color:var(--blueprint-deep);}

&lt;/style&gt;
&lt;div class="epb"&gt;
&lt;div class="crop tl"&gt;&lt;/div&gt;&lt;div class="crop tr"&gt;&lt;/div&gt;&lt;div class="crop bl"&gt;&lt;/div&gt;&lt;div class="crop br"&gt;&lt;/div&gt;

&lt;header class="cover"&gt;
  &lt;div class="stamp"&gt;&lt;div class="ring"&gt;&lt;/div&gt;&lt;span&gt;Latihan Soal&lt;b&gt;Tipe AKM&lt;/b&gt;Fase F&lt;/span&gt;&lt;/div&gt;
  &lt;div class="doc-code"&gt;DOK/B.INDO/XI/PROSEDUR-AKM — Latihan Soal · 50 Butir&lt;/div&gt;
  &lt;h1&gt;Latihan Soal Tipe AKM: Pokok Bahasan Petunjuk Kerja&lt;/h1&gt;
  &lt;p class="subtitle"&gt;Latihan soal literasi membaca bertipe Asesmen Kompetensi Minimum (AKM) untuk Bahasa Indonesia Kelas XI SMK/MAK, mencakup seluruh materi pokok bahasan Petunjuk Kerja: evaluasi informasi, perbandingan teks, kaidah kebahasaan, serta penyusunan dan penyajian teks prosedur.&lt;/p&gt;

  &lt;div class="meta-strip"&gt;
    &lt;div&gt;&lt;div class="k"&gt;Mata Pelajaran&lt;/div&gt;&lt;div class="v"&gt;Bahasa Indonesia&lt;/div&gt;&lt;/div&gt;
    &lt;div&gt;&lt;div class="k"&gt;Jenjang&lt;/div&gt;&lt;div class="v"&gt;SMK/MAK — Kelas XI&lt;/div&gt;&lt;/div&gt;
    &lt;div&gt;&lt;div class="k"&gt;Jumlah Soal&lt;/div&gt;&lt;div class="v"&gt;50 Butir · 5 Opsi&lt;/div&gt;&lt;/div&gt;
    &lt;div&gt;&lt;div class="k"&gt;KKM&lt;/div&gt;&lt;div class="v"&gt;75 · 3 Kali Kesempatan&lt;/div&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/header&gt;

&lt;main&gt;

  &lt;section class="section" id="petunjuk"&gt;
    &lt;div class="eyebrow"&gt;01 — Petunjuk Pengerjaan&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Sebelum Mengerjakan, Baca Dahulu&lt;/h2&gt;

    &lt;div class="panel tp"&gt;
      &lt;p style="margin:0;"&gt;Soal berikut disusun mengikuti pola &lt;b style="color:var(--off-white);"&gt;Asesmen Kompetensi Minimum (AKM)&lt;/b&gt;: setiap kelompok soal diawali sebuah &lt;b style="color:var(--off-white);"&gt;teks stimulus&lt;/b&gt; (teks prosedur atau teks eksplanasi), lalu diikuti beberapa pertanyaan yang menguji kemampuan &lt;b style="color:var(--off-white);"&gt;menemukan informasi, menginterpretasi, membandingkan, dan mengevaluasi&lt;/b&gt; isi teks tersebut — bukan sekadar menghafal definisi.&lt;/p&gt;
    &lt;/div&gt;

    &lt;div class="grid-3"&gt;
      &lt;div class="card"&gt;&lt;h4&gt;50 Soal &amp;amp; 5 Opsi&lt;/h4&gt;&lt;p style="font-size:0.9rem;"&gt;20 soal mudah, 21 soal sedang, 9 soal sulit — pilihan jawaban A sampai E.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;h4&gt;KKM = 75&lt;/h4&gt;&lt;p style="font-size:0.9rem;"&gt;Skor dihitung otomatis dari 50 soal (setiap soal bernilai 2 poin, maksimal 100).&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;h4&gt;3 Kali Kesempatan&lt;/h4&gt;&lt;p style="font-size:0.9rem;"&gt;Jika belum mencapai KKM, kamu dapat mencoba lagi hingga maksimal 3 kali percobaan.&lt;/p&gt;&lt;/div&gt;
    &lt;/div&gt;

    &lt;div class="panel warn" style="margin-top:20px;"&gt;
      &lt;p style="margin:0;"&gt;&lt;b style="color:var(--off-white);"&gt;Aturan pengiriman nilai:&lt;/b&gt; Begitu skor kamu mencapai atau melebihi KKM (75), nilai tersebut langsung dikirim dan tercatat. Jika hingga percobaan ke-3 belum ada yang mencapai KKM, sistem akan otomatis mengirim &lt;b style="color:var(--off-white);"&gt;nilai tertinggi&lt;/b&gt; dari ketiga percobaanmu. Isi No. Absen dengan angka yang sama di setiap percobaan agar sistem dapat menghitung kesempatanmu dengan benar.&lt;/p&gt;
    &lt;/div&gt;
  &lt;/section&gt;

  &lt;hr class="divider-dash"&gt;

  &lt;!-- ============ PETUNJUK MENGERJAKAN ============ --&gt;
  &lt;section class="section" id="cara-mengerjakan"&gt;
    &lt;div class="eyebrow"&gt;02 — Langkah Pengerjaan&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Cara Mengerjakan Latihan Ini&lt;/h2&gt;

    &lt;ol class="steps-num"&gt;
      &lt;li&gt;&lt;b&gt;Isi No. Absen dan Nama Lengkap&lt;/b&gt; pada kolom yang tersedia sebelum mulai menjawab. Gunakan No. Absen yang sama setiap kali mencoba, karena sistem memakainya untuk menghitung sisa kesempatan.&lt;/li&gt;
      &lt;li&gt;&lt;b&gt;Baca teks stimulus&lt;/b&gt; (teks prosedur atau teks eksplanasi) yang muncul sebelum setiap kelompok soal dengan saksama, sebelum menjawab pertanyaan di bawahnya.&lt;/li&gt;
      &lt;li&gt;&lt;b&gt;Jawab seluruh 50 soal&lt;/b&gt; dengan memilih salah satu opsi A–E. Perhatikan label tingkat kesulitan (Mudah/Sedang/Sulit) pada tiap soal sebagai gambaran bobotnya.&lt;/li&gt;
      &lt;li&gt;&lt;b&gt;Tekan tombol "Kirim Jawaban"&lt;/b&gt; setelah semua soal terjawab. Jika masih ada yang kosong, sistem akan menunjukkan nomor yang belum dijawab.&lt;/li&gt;
      &lt;li&gt;&lt;b&gt;Lihat skor yang muncul.&lt;/b&gt; Jika skor sudah mencapai KKM (75), nilai otomatis terkirim dan latihan selesai.&lt;/li&gt;
      &lt;li&gt;&lt;b&gt;Jika skor belum mencapai KKM&lt;/b&gt;, tekan tombol "Coba Lagi" untuk mengulang (maksimal 3 kali percobaan). Jawaban akan direset, tetapi teks stimulus dan soal tetap sama.&lt;/li&gt;
      &lt;li&gt;&lt;b&gt;Setelah selesai&lt;/b&gt; (baik karena sudah mencapai KKM maupun kesempatan sudah habis), tunjukkan skor yang tertera di layar kepada guru sebagai bukti pengerjaan.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/section&gt;

  &lt;hr class="divider-dash"&gt;

  &lt;section class="section" id="kuis"&gt;
    &lt;div class="eyebrow"&gt;03 — Lembar Soal&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Kerjakan 50 Soal Berikut&lt;/h2&gt;

    &lt;div class="panel" id="epbq-form-wrap" style="margin-top:20px;"&gt;
      &lt;div style="display:grid; grid-template-columns:1fr 2fr; gap:14px; margin-bottom:10px;"&gt;
        &lt;div&gt;
          &lt;label class="mono" style="display:block; font-size:0.75rem; color:var(--amber); text-transform:uppercase; letter-spacing:0.08em; margin-bottom:6px;"&gt;No. Absen&lt;/label&gt;
          &lt;input id="epbq-absen" type="text" inputmode="numeric" placeholder="Contoh: 12" style="width:100%; padding:10px 12px; border-radius:2px; border:1px solid var(--line); background:var(--blueprint-deep); color:var(--off-white); font-family:'Source Sans 3',sans-serif; font-size:0.95rem;"&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;label class="mono" style="display:block; font-size:0.75rem; color:var(--amber); text-transform:uppercase; letter-spacing:0.08em; margin-bottom:6px;"&gt;Nama Lengkap&lt;/label&gt;
          &lt;input id="epbq-nama" type="text" placeholder="Tulis nama lengkap" style="width:100%; padding:10px 12px; border-radius:2px; border:1px solid var(--line); background:var(--blueprint-deep); color:var(--off-white); font-family:'Source Sans 3',sans-serif; font-size:0.95rem;"&gt;
        &lt;/div&gt;
      &lt;/div&gt;
      &lt;p id="epbq-attempt-info" class="mono" style="font-size:0.8rem; color:var(--muted); margin:4px 0 18px;"&gt;Masukkan No. Absen untuk melihat sisa kesempatan.&lt;/p&gt;

      &lt;div id="epbq-questions"&gt;&lt;/div&gt;

      &lt;div style="margin-top:24px; display:flex; align-items:center; gap:16px; flex-wrap:wrap;"&gt;
        &lt;button id="epbq-submit" type="button" style="background:var(--amber); color:var(--blueprint-deep); border:none; padding:12px 26px; font-family:'Oswald',sans-serif; text-transform:uppercase; letter-spacing:0.05em; font-weight:600; border-radius:2px; cursor:pointer; font-size:0.95rem;"&gt;Kirim Jawaban&lt;/button&gt;
        &lt;button id="epbq-retry" type="button" style="display:none; background:transparent; color:var(--amber); border:1px solid var(--amber); padding:12px 26px; font-family:'Oswald',sans-serif; text-transform:uppercase; letter-spacing:0.05em; font-weight:600; border-radius:2px; cursor:pointer; font-size:0.95rem;"&gt;Coba Lagi&lt;/button&gt;
        &lt;span id="epbq-status" class="mono" style="font-size:0.85rem; color:var(--muted);"&gt;&lt;/span&gt;
      &lt;/div&gt;

      &lt;div id="epbq-result" style="display:none; margin-top:20px; padding:18px 20px; border:1px solid var(--amber); background:rgba(245,166,35,0.08);"&gt;
        &lt;p style="margin:0; font-size:1.05rem;"&gt;Skor percobaan ini: &lt;b id="epbq-score" style="color:var(--amber); font-size:1.3rem;"&gt;&lt;/b&gt; / 100&lt;/p&gt;
        &lt;p id="epbq-detail" style="margin:8px 0 0; font-size:0.9rem; color:var(--muted);"&gt;&lt;/p&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/section&gt;

&lt;/main&gt;

&lt;footer&gt;
  &lt;div class="doc-code"&gt;DOK/B.INDO/XI/PROSEDUR-AKM — Latihan Soal Tipe AKM, 50 Butir, Pokok Bahasan Petunjuk Kerja&lt;/div&gt;
  &lt;p style="margin:0;"&gt;Referensi: Kurikulum Merdeka — Capaian Pembelajaran Bahasa Indonesia Fase F; Pusat Asesmen dan Pembelajaran Kemendikbudristek — format Asesmen Kompetensi Minimum (AKM) Literasi Membaca.&lt;/p&gt;
&lt;/footer&gt;

&lt;script&gt;
(function(){
  var EPBQ_ENDPOINT = "https://script.google.com/macros/s/AKfycbzM7t2qgAENzxQJXzSYJYL28R6nb3TxJVELLL3CopyEXb51t_gRtrkPOxTpI5mq6VCEKw/exec";
  var EPBQ_MATERI = "Latihan Soal AKM - Pokok Bahasan Petunjuk Kerja (50 Soal)";
  var KKM = 75;
  var MAX_ATTEMPTS = 3;

  var stimuli = [{"id": "A", "judul": "Cara Membuat Teh Hangat", "jenis": "Teks Prosedur", "teks": "Teh hangat adalah minuman yang mudah dibuat dan cocok dinikmati kapan saja. Berikut langkah membuatnya. Pertama, siapkan gelas dan satu kantong teh. Kedua, panaskan air hingga mendidih. Ketiga, masukkan kantong teh ke dalam gelas, lalu tuangkan air panas ke dalamnya. Setelah itu, tambahkan gula sesuai selera. Aduk hingga rata, dan teh hangat siap dinikmati."}, {"id": "B", "judul": "Prosedur Mengganti Baterai Remote TV", "jenis": "Teks Prosedur", "teks": "Remote TV yang tidak merespons biasanya disebabkan baterai yang sudah lemah. Berikut cara menggantinya. Buka penutup baterai di bagian belakang remote dengan menggeser atau menekannya sesuai petunjuk. Keluarkan baterai lama, lalu perhatikan tanda kutub positif (+) dan negatif (–) pada dudukan baterai. Pasang baterai baru sesuai posisi kutub tersebut. Tutup kembali penutup baterai hingga rapat, lalu coba tekan salah satu tombol untuk memastikan remote berfungsi."}, {"id": "C", "judul": "Proses Terjadinya Karat pada Besi", "jenis": "Teks Eksplanasi", "teks": "Karat adalah lapisan berwarna cokelat kemerahan yang muncul pada permukaan besi. Karat terjadi karena besi bereaksi dengan oksigen dan air melalui proses yang disebut oksidasi. Ketika permukaan besi terkena udara lembap dalam waktu lama, oksigen akan berikatan dengan atom besi membentuk senyawa besi oksida. Semakin lama besi terpapar kelembapan, semakin tebal lapisan karat yang terbentuk. Oleh karena itu, besi yang disimpan di tempat lembap akan lebih cepat berkarat dibandingkan besi yang disimpan di tempat kering."}, {"id": "D", "judul": "Prosedur Menyalakan Genset Portabel", "jenis": "Teks Prosedur", "teks": "Genset portabel berguna sebagai sumber listrik cadangan saat listrik padam. Berikut langkah menyalakannya. Pertama, letakkan genset di ruangan tertutup agar terhindar dari hujan. Kedua, periksa jumlah bahan bakar pada tangki genset. Ketiga, tekan tombol starter hingga mesin menyala. Keempat, tunggu beberapa menit sebelum menyambungkan kabel listrik ke genset. Genset kini siap digunakan untuk menyalakan peralatan listrik di rumah."}, {"id": "E", "judul": "Prosedur Membersihkan Filter AC Rumah secara Mandiri", "jenis": "Teks Prosedur", "teks": "Filter AC yang kotor dapat menurunkan kualitas udara dan kinerja pendinginan. Berikut cara membersihkannya. Matikan AC dan cabut sumber listriknya terlebih dahulu. Buka penutup unit indoor AC, lalu lepaskan filter udara secara perlahan. Cuci filter menggunakan air mengalir hingga debu dan kotoran luruh. Keringkan filter di tempat teduh, jangan di bawah sinar matahari langsung agar filter tidak melengkung. Pasang kembali filter setelah benar-benar kering, lalu nyalakan kembali AC seperti biasa."}, {"id": "F", "judul": "Proses Terjadinya Embun di Pagi Hari", "jenis": "Teks Eksplanasi", "teks": "Embun adalah titik-titik air yang muncul pada permukaan benda di pagi hari. Embun terbentuk karena udara di malam hari mengandung uap air yang mendingin seiring turunnya suhu. Ketika suhu udara turun hingga mencapai titik embun, uap air akan mengembun menjadi butiran air kecil pada permukaan benda seperti daun atau rumput. Proses ini biasanya terjadi pada malam hari yang cerah tanpa awan, karena panas bumi lebih cepat terlepas ke atmosfer. Dengan demikian, embun paling sering muncul pada pagi hari yang dingin dan cerah."}, {"id": "G", "judul": "Prosedur Mendaftar Akun Email Baru", "jenis": "Teks Prosedur", "teks": "Memiliki akun email sangat penting untuk berbagai keperluan digital. Berikut langkah mendaftarnya. Buka situs penyedia layanan email, lalu pilih menu 'Buat Akun Baru'. Isi formulir pendaftaran dengan nama lengkap, tanggal lahir, dan nomor telepon aktif. Selanjutnya, buatlah kata sandi yang kuat dengan kombinasi huruf, angka, dan simbol. Perlu diperhatikan, jangan gunakan kata sandi yang sama dengan akun media sosial lain agar lebih aman. Setelah semua data terisi, klik tombol 'Daftar' dan verifikasi akun melalui kode yang dikirim ke nomor telepon."}, {"id": "H", "judul": "Memilah Sampah Rumah Tangga (Sepasang Teks)", "jenis": "Teks Prosedur &amp; Teks Eksplanasi", "teks": "&lt;b&gt;Teks 1 — Prosedur Memilah Sampah Rumah Tangga:&lt;/b&gt; Memilah sampah bertujuan memudahkan proses daur ulang. Sediakan tiga wadah berbeda untuk sampah organik, anorganik, dan B3 (bahan berbahaya beracun). Pisahkan sisa makanan dan daun ke wadah organik. Masukkan plastik, kertas, dan logam ke wadah anorganik. Simpan baterai bekas dan lampu pecah pada wadah B3 secara terpisah. Buang sampah organik setiap hari, sedangkan sampah anorganik dapat dikumpulkan hingga penuh sebelum dibawa ke bank sampah.&lt;br&gt;&lt;br&gt;&lt;b&gt;Teks 2 — Proses Terjadinya Pencemaran akibat Sampah yang Tidak Dipilah:&lt;/b&gt; Sampah yang tidak dipilah akan bercampur antara bahan organik dan anorganik, sehingga proses penguraiannya menjadi lebih lambat. Sampah anorganik seperti plastik membutuhkan waktu ratusan tahun untuk terurai, sehingga menumpuk di tempat pembuangan akhir. Akibatnya, lahan yang tersedia untuk menampung sampah semakin berkurang. Selain itu, zat kimia dari sampah B3 yang tercampur dapat meresap ke dalam tanah dan mencemari sumber air di sekitarnya. Oleh karena itu, pemilahan sampah sejak dari rumah tangga menjadi langkah penting untuk mengurangi dampak pencemaran lingkungan."}];
  var questions = [{"stim": "A", "lvl": "Mudah", "q": "Apa tujuan utama teks prosedur tersebut?", "opts": ["Menjelaskan sejarah teh", "Membuat teh hangat siap diminum", "Membandingkan jenis teh", "Menceritakan pengalaman minum teh", "Menjual produk teh"], "correct": 1}, {"stim": "A", "lvl": "Mudah", "q": "Alat/bahan pertama yang disiapkan dalam teks adalah...", "opts": ["Gula dan sendok", "Air dan panci", "Gelas dan kantong teh", "Termos dan cangkir", "Susu dan kopi"], "correct": 2}, {"stim": "A", "lvl": "Mudah", "q": "Kata “setelah itu” pada teks berfungsi sebagai...", "opts": ["Konjungsi kausalitas", "Konjungsi temporal", "Konjungsi pertentangan", "Konjungsi pilihan", "Konjungsi penjumlahan"], "correct": 1}, {"stim": "A", "lvl": "Mudah", "q": "Kalimat “Aduk hingga rata” termasuk kalimat...", "opts": ["Deklaratif", "Interogatif", "Imperatif", "Persuasif", "Naratif"], "correct": 2}, {"stim": "B", "lvl": "Mudah", "q": "Menurut teks, apa penyebab remote TV tidak merespons?", "opts": ["Remote rusak permanen", "Baterai yang sudah lemah", "TV mati total", "Sinyal remote terganggu", "Remote basah"], "correct": 1}, {"stim": "B", "lvl": "Mudah", "q": "Hal yang harus diperhatikan saat memasang baterai baru adalah...", "opts": ["Warna baterai", "Ukuran remote", "Posisi kutub positif dan negatif", "Merek baterai", "Suhu ruangan"], "correct": 2}, {"stim": "B", "lvl": "Sedang", "q": "Langkah terakhir dalam prosedur tersebut adalah...", "opts": ["Membuka penutup baterai", "Mengeluarkan baterai lama", "Menutup penutup baterai", "Menekan tombol untuk memastikan remote berfungsi", "Membeli baterai baru"], "correct": 3}, {"stim": "B", "lvl": "Sedang", "q": "Mengapa penting memperhatikan tanda kutub baterai saat memasang?", "opts": ["Agar baterai terlihat rapi", "Agar remote berfungsi dengan benar", "Agar baterai lebih awet warnanya", "Karena aturan pabrik semata", "Tidak ada alasan khusus"], "correct": 1}, {"stim": "C", "lvl": "Mudah", "q": "Apa penyebab utama terjadinya karat pada besi menurut teks?", "opts": ["Suhu udara yang panas", "Reaksi besi dengan oksigen dan air", "Sinar matahari langsung", "Getaran mekanis", "Perubahan warna alami"], "correct": 1}, {"stim": "C", "lvl": "Sedang", "q": "Teks tersebut termasuk jenis teks eksplanasi karena...", "opts": ["Berisi langkah-langkah tindakan", "Menjelaskan proses terjadinya suatu fenomena", "Berisi cerita fiksi", "Berisi opini penulis", "Berisi iklan produk"], "correct": 1}, {"stim": "C", "lvl": "Sedang", "q": "Konjungsi “oleh karena itu” pada akhir teks berfungsi sebagai penanda...", "opts": ["Urutan", "Penambahan", "Penekanan", "Simpulan", "Pertentangan"], "correct": 3}, {"stim": "C", "lvl": "Mudah", "q": "Berdasarkan teks, besi akan lebih cepat berkarat jika disimpan di tempat...", "opts": ["Kering", "Lembap", "Dingin", "Bersuhu tinggi", "Tertutup rapat"], "correct": 1}, {"stim": "C", "lvl": "Sedang", "q": "Perbedaan mendasar teks ini dengan teks prosedur adalah...", "opts": ["Teks ini lebih pendek", "Teks ini bertujuan membuat pembaca memahami, bukan melakukan tindakan", "Teks ini tidak memiliki struktur", "Teks ini tidak menggunakan konjungsi", "Teks ini tidak informatif"], "correct": 1}, {"stim": "C", "lvl": "Sedang", "q": "Jika besi disimpan di tempat kering, berdasarkan informasi teks, proses karat akan...", "opts": ["Berlangsung lebih cepat", "Berlangsung lebih lambat", "Tidak berpengaruh sama sekali", "Terjadi secara instan", "Berubah menjadi proses lain"], "correct": 1}, {"stim": "D", "lvl": "Mudah", "q": "Apa tujuan dari prosedur tersebut?", "opts": ["Mematikan genset", "Menyalakan genset sebagai sumber listrik cadangan", "Memperbaiki genset rusak", "Menjual genset", "Menyimpan genset"], "correct": 1}, {"stim": "D", "lvl": "Mudah", "q": "Berapa langkah yang dijelaskan dalam prosedur tersebut?", "opts": ["2 langkah", "3 langkah", "4 langkah", "5 langkah", "6 langkah"], "correct": 2}, {"stim": "D", "lvl": "Sulit", "q": "Instruksi meletakkan genset di ruangan tertutup berpotensi membahayakan karena...", "opts": ["Genset akan cepat rusak", "Risiko keracunan gas karbon monoksida", "Suara genset menjadi lebih keras", "Genset akan kepanasan lebih cepat", "Bahan bakar lebih boros"], "correct": 1}, {"stim": "D", "lvl": "Sulit", "q": "Kekeliruan pada langkah pertama tersebut melanggar kriteria evaluasi teks prosedur, yaitu...", "opts": ["Keakuratan istilah", "Kelengkapan alat", "Keselamatan dan kelayakan praktik", "Kejelasan bahasa", "Kesesuaian judul"], "correct": 2}, {"stim": "D", "lvl": "Sulit", "q": "Rekomendasi perbaikan yang paling tepat untuk langkah pertama adalah...", "opts": ["Genset diletakkan di ruang terbuka atau berventilasi baik", "Genset dinyalakan tanpa bahan bakar", "Genset diletakkan di dalam lemari", "Genset dinyalakan di dalam kamar tidur", "Tidak perlu ada perubahan"], "correct": 0}, {"stim": "D", "lvl": "Mudah", "q": "Kalimat “Periksa jumlah bahan bakar pada tangki genset” termasuk kalimat...", "opts": ["Deklaratif", "Interogatif", "Imperatif", "Persuasif", "Naratif"], "correct": 2}, {"stim": "D", "lvl": "Sedang", "q": "Apakah urutan langkah dalam teks tersebut sudah logis?", "opts": ["Sudah, karena seluruh langkah aman dan berurutan", "Belum, karena langkah pertama membahayakan keselamatan meskipun urutan waktunya runtut", "Sudah, karena tidak ada langkah yang hilang", "Belum, karena tidak menggunakan bahasa baku", "Sudah, karena menggunakan konjungsi temporal"], "correct": 1}, {"stim": "D", "lvl": "Sedang", "q": "Selain keselamatan, aspek apa yang juga perlu diperiksa ulang agar prosedur ini benar-benar aman diikuti pembaca?", "opts": ["Kelengkapan langkah, misalnya instruksi soal ventilasi ruangan", "Jumlah huruf dalam judul", "Warna genset yang digunakan", "Harga bahan bakar", "Merek genset yang disebutkan"], "correct": 0}, {"stim": "E", "lvl": "Mudah", "q": "Apa tujuan prosedur membersihkan filter AC tersebut?", "opts": ["Mengganti unit AC", "Menjaga kualitas udara dan kinerja pendinginan", "Menghemat listrik semata", "Mengecat unit AC", "Memindahkan posisi AC"], "correct": 1}, {"stim": "E", "lvl": "Sedang", "q": "Mengapa filter harus dikeringkan di tempat teduh, bukan di bawah sinar matahari langsung?", "opts": ["Agar warnanya tidak pudar", "Agar filter tidak melengkung atau rusak", "Agar proses lebih cepat", "Karena aturan pabrik tanpa alasan teknis", "Agar debu tidak menempel"], "correct": 1}, {"stim": "E", "lvl": "Mudah", "q": "Kata “unit indoor” dan “filter” pada teks termasuk...", "opts": ["Konjungsi", "Kata teknis", "Kata ganti", "Kata sifat", "Kata seru"], "correct": 1}, {"stim": "E", "lvl": "Sedang", "q": "Kalimat “Matikan AC dan cabut sumber listriknya terlebih dahulu” termasuk kalimat perintah jenis...", "opts": ["Larangan", "Ajakan", "Perintah biasa", "Permintaan", "Persuasif"], "correct": 2}, {"stim": "E", "lvl": "Sedang", "q": "Manakah langkah yang menunjukkan alasan keselamatan sebelum membersihkan filter?", "opts": ["Mencuci filter dengan air mengalir", "Mematikan AC dan mencabut sumber listrik", "Mengeringkan filter di tempat teduh", "Memasang kembali filter", "Menyalakan kembali AC"], "correct": 1}, {"stim": "E", "lvl": "Mudah", "q": "Kalimat “Filter AC yang kotor dapat menurunkan kualitas udara...” termasuk bagian struktur...", "opts": ["Langkah-langkah", "Tujuan", "Alat dan bahan", "Penutup", "Interpretasi"], "correct": 1}, {"stim": "F", "lvl": "Mudah", "q": "Apa yang menyebabkan terbentuknya embun menurut teks?", "opts": ["Hujan yang turun di malam hari", "Penurunan suhu udara hingga titik embun", "Angin kencang di pagi hari", "Sinar matahari pagi", "Kelembapan tanah"], "correct": 1}, {"stim": "F", "lvl": "Sedang", "q": "Penanda wacana “dengan demikian” pada akhir teks berfungsi sebagai penanda...", "opts": ["Urutan", "Penambahan", "Penekanan", "Simpulan", "Pertentangan"], "correct": 3}, {"stim": "F", "lvl": "Mudah", "q": "Berdasarkan teks, embun paling sering muncul pada kondisi cuaca...", "opts": ["Berawan tebal", "Hujan deras", "Cerah tanpa awan", "Berkabut", "Berangin kencang"], "correct": 2}, {"stim": "F", "lvl": "Sedang", "q": "Konjungsi “karena” dalam teks tersebut menunjukkan hubungan...", "opts": ["Pertentangan", "Sebab-akibat", "Pilihan", "Waktu", "Penjumlahan"], "correct": 1}, {"stim": "F", "lvl": "Sedang", "q": "Apa perbedaan fungsi konjungsi kausalitas pada teks ini dengan konjungsi temporal pada teks prosedur?", "opts": ["Keduanya memiliki fungsi yang sama persis", "Kausalitas menjelaskan sebab-akibat proses alami, temporal menandai urutan langkah tindakan", "Kausalitas hanya dipakai dalam teks prosedur", "Temporal hanya dipakai dalam teks eksplanasi", "Keduanya tidak memiliki fungsi apa pun"], "correct": 1}, {"stim": "F", "lvl": "Sulit", "q": "Jika judul teks diubah menjadi “Cara Membuat Embun Buatan”, jenis teks tersebut kemungkinan besar akan berubah menjadi...", "opts": ["Teks deskripsi", "Teks prosedur", "Teks narasi", "Teks anekdot", "Tetap teks eksplanasi"], "correct": 1}, {"stim": "G", "lvl": "Mudah", "q": "Apa tujuan dari prosedur tersebut?", "opts": ["Menghapus akun email", "Mendaftar akun email baru", "Mengganti kata sandi", "Mengirim email", "Menutup akun media sosial"], "correct": 1}, {"stim": "G", "lvl": "Sedang", "q": "Frasa “perlu diperhatikan” pada teks berfungsi sebagai penanda wacana jenis...", "opts": ["Urutan", "Penambahan", "Penekanan", "Simpulan", "Pertentangan"], "correct": 2}, {"stim": "G", "lvl": "Mudah", "q": "Kata “selanjutnya” pada teks menandai...", "opts": ["Sebab-akibat", "Urutan langkah", "Pertentangan", "Pilihan", "Penekanan"], "correct": 1}, {"stim": "G", "lvl": "Sedang", "q": "Mengapa penulis menyarankan agar tidak menggunakan kata sandi yang sama dengan akun lain?", "opts": ["Agar mudah diingat", "Demi keamanan akun", "Agar proses pendaftaran lebih cepat", "Karena aturan pabrik", "Tidak ada alasan khusus"], "correct": 1}, {"stim": "G", "lvl": "Sulit", "q": "Jika seseorang mengikuti prosedur tersebut namun melewatkan langkah verifikasi kode, apa kemungkinan yang terjadi?", "opts": ["Akun langsung terhapus", "Akun belum aktif sepenuhnya", "Tidak terjadi apa-apa", "Kata sandi otomatis berubah", "Proses pendaftaran diulang dari awal secara otomatis"], "correct": 1}, {"stim": "G", "lvl": "Sedang", "q": "Bagian manakah dari teks yang termasuk kalimat persuasif?", "opts": ["“Buka situs penyedia layanan email”", "“Isi formulir pendaftaran dengan nama lengkap”", "“Perlu diperhatikan, jangan gunakan kata sandi yang sama dengan akun media sosial lain agar lebih aman”", "“Klik tombol Daftar”", "“Verifikasi akun melalui kode”"], "correct": 2}, {"stim": "H", "lvl": "Sedang", "q": "Apa persamaan mendasar antara kedua teks tersebut?", "opts": ["Keduanya bersifat fiksi", "Keduanya sama-sama menjelaskan proses/tahapan terkait sampah", "Keduanya tidak memiliki struktur", "Keduanya ditulis dalam bentuk puisi", "Keduanya tidak menggunakan konjungsi"], "correct": 1}, {"stim": "H", "lvl": "Sedang", "q": "Apa perbedaan tujuan utama kedua teks tersebut?", "opts": ["Teks 1 menjelaskan proses, Teks 2 mengarahkan tindakan", "Teks 1 mengarahkan tindakan, Teks 2 menjelaskan proses/dampak", "Keduanya bertujuan menghibur", "Keduanya bertujuan mempromosikan produk", "Keduanya tidak memiliki tujuan jelas"], "correct": 1}, {"stim": "H", "lvl": "Mudah", "q": "Manakah kalimat pada Teks 1 yang merupakan kalimat perintah?", "opts": ["“Memilah sampah bertujuan memudahkan proses daur ulang.”", "“Pisahkan sisa makanan dan daun ke wadah organik.”", "“Sampah yang tidak dipilah akan bercampur.”", "“Plastik membutuhkan waktu ratusan tahun untuk terurai.”", "“Pemilahan sampah menjadi langkah penting.”"], "correct": 1}, {"stim": "H", "lvl": "Sedang", "q": "Konjungsi “sehingga” pada Teks 2 menunjukkan hubungan...", "opts": ["Pertentangan", "Sebab-akibat", "Pilihan", "Waktu", "Penambahan"], "correct": 1}, {"stim": "H", "lvl": "Sedang", "q": "Berdasarkan Teks 2, apa dampak jangka panjang jika sampah tidak dipilah dari rumah tangga?", "opts": ["Sampah otomatis berkurang", "Lahan TPA berkurang dan sumber air tercemar", "Tidak ada dampak apa pun", "Sampah berubah menjadi kompos secara alami", "Proses daur ulang menjadi lebih cepat"], "correct": 1}, {"stim": "H", "lvl": "Sulit", "q": "Jika Teks 1 diikuti dengan benar oleh masyarakat, dampak yang dijelaskan pada Teks 2 kemungkinan akan...", "opts": ["Semakin parah", "Tidak berubah sama sekali", "Berkurang atau dapat dicegah", "Berubah menjadi masalah baru", "Tidak ada hubungannya sama sekali"], "correct": 2}, {"stim": "H", "lvl": "Sulit", "q": "Manakah pernyataan yang paling tepat menggambarkan hubungan antara kedua teks?", "opts": ["Teks 1 adalah solusi/tindakan pencegahan atas masalah yang dijelaskan Teks 2", "Teks 2 adalah solusi atas Teks 1", "Kedua teks membahas topik yang sama sekali berbeda", "Teks 1 dan Teks 2 saling bertentangan", "Teks 1 tidak berkaitan dengan Teks 2"], "correct": 0}, {"stim": "H", "lvl": "Mudah", "q": "Kata “B3” pada Teks 1 merupakan contoh dari...", "opts": ["Konjungsi", "Kata teknis/istilah khusus", "Kata ganti", "Kata sifat", "Kata seru"], "correct": 1}, {"stim": "H", "lvl": "Sulit", "q": "Apabila ingin mengevaluasi kelengkapan Teks 1, aspek apa yang paling perlu diperiksa?", "opts": ["Apakah seluruh jenis sampah rumah tangga sudah tercakup dalam tiga kategori wadah tersebut", "Apakah judul teks menarik", "Apakah teks menggunakan huruf kapital", "Apakah teks memiliki gambar", "Apakah teks ditulis dengan rapi"], "correct": 0}, {"stim": "H", "lvl": "Sulit", "q": "Berdasarkan kedua teks, simpulan yang paling tepat tentang pentingnya teks prosedur dalam menyelesaikan masalah lingkungan adalah...", "opts": ["Teks prosedur tidak ada kaitannya dengan masalah lingkungan", "Teks prosedur berperan sebagai panduan tindakan nyata untuk mencegah dampak negatif yang dijelaskan dalam teks eksplanasi", "Teks eksplanasi lebih penting daripada teks prosedur", "Teks prosedur hanya berguna untuk keperluan akademik", "Kedua jenis teks tidak memiliki hubungan sama sekali"], "correct": 1}];

  var optLabels = ["A","B","C","D","E"];
  var lvlColor = {"Mudah":"#6EC6CA","Sedang":"#F5A623","Sulit":"#D94E2A"};

  var container = document.getElementById("epbq-questions");
  var currentStim = null;
  var qCounter = 0;

  questions.forEach(function(item, idx){
    if(item.stim !== currentStim){
      currentStim = item.stim;
      var stimObj = stimuli.filter(function(s){ return s.id === currentStim; })[0];
      if(stimObj){
        var docSample = document.createElement("div");
        docSample.className = "doc-sample";
        docSample.style.margin = "24px 0 18px";
        docSample.innerHTML =
          '&lt;div class="doc-head"&gt;&lt;span&gt;Teks Stimulus \u00b7 ' + stimObj.jenis + '&lt;/span&gt;&lt;span&gt;Stimulus ' + stimObj.id + '&lt;/span&gt;&lt;/div&gt;' +
          '&lt;div class="doc-body"&gt;&lt;h3 style="color:#132029 !important;"&gt;' + stimObj.judul + '&lt;/h3&gt;' +
          '&lt;p style="color:#132029 !important; margin:8px 0 0;"&gt;' + stimObj.teks + '&lt;/p&gt;&lt;/div&gt;';
        container.appendChild(docSample);
      }
    }

    qCounter++;
    var block = document.createElement("div");
    block.style.marginBottom = "20px";
    block.style.paddingBottom = "16px";
    block.style.borderBottom = "1px dashed rgba(234,242,245,0.16)";

    var tag = document.createElement("span");
    tag.textContent = item.lvl;
    tag.style.display = "inline-block";
    tag.style.fontFamily = "'IBM Plex Mono', monospace";
    tag.style.fontSize = "0.68rem";
    tag.style.letterSpacing = "0.08em";
    tag.style.textTransform = "uppercase";
    tag.style.setProperty("color", lvlColor[item.lvl] || "#9FB4C2", "important");
    tag.style.setProperty("border", "1px solid " + (lvlColor[item.lvl] || "#9FB4C2"), "important");
    tag.style.padding = "2px 8px";
    tag.style.marginBottom = "6px";
    block.appendChild(tag);

    var qEl = document.createElement("p");
    qEl.style.setProperty("color", "#EAF2F5", "important");
    qEl.style.fontWeight = "600";
    qEl.style.margin = "6px 0 8px";
    qEl.textContent = qCounter + ". " + item.q;
    block.appendChild(qEl);

    item.opts.forEach(function(opt, oi){
      var label = document.createElement("label");
      label.style.display = "block";
      label.style.setProperty("color", "#DDE7EC", "important");
      label.style.fontSize = "0.92rem";
      label.style.margin = "4px 0";
      label.style.cursor = "pointer";

      var radio = document.createElement("input");
      radio.type = "radio";
      radio.name = "epbq-q" + idx;
      radio.value = oi;
      radio.style.marginRight = "8px";

      label.appendChild(radio);
      label.appendChild(document.createTextNode(optLabels[oi] + ". " + opt));
      block.appendChild(label);
    });

    container.appendChild(block);
  });

  function stateKey(absen){ return "epbq_akm_" + absen; }
  function loadState(absen){
    try{
      var raw = localStorage.getItem(stateKey(absen));
      if(!raw) return {attempts:0, bestScore:0, sent:false};
      return JSON.parse(raw);
    }catch(e){ return {attempts:0, bestScore:0, sent:false}; }
  }
  function saveState(absen, state){
    try{ localStorage.setItem(stateKey(absen), JSON.stringify(state)); }catch(e){}
  }

  var absenInput = document.getElementById("epbq-absen");
  var attemptInfo = document.getElementById("epbq-attempt-info");
  var submitBtn = document.getElementById("epbq-submit");
  var retryBtn = document.getElementById("epbq-retry");

  function refreshAttemptInfo(){
    var absen = absenInput.value.trim();
    if(!absen){
      attemptInfo.textContent = "Masukkan No. Absen untuk melihat sisa kesempatan.";
      submitBtn.style.display = "inline-block";
      retryBtn.style.display = "none";
      return;
    }
    var st = loadState(absen);
    if(st.sent){
      attemptInfo.textContent = "No. Absen " + absen + " sudah menyelesaikan latihan ini. Nilai tercatat: " + st.bestScore + ".";
      submitBtn.style.display = "none";
      retryBtn.style.display = "none";
    } else {
      attemptInfo.textContent = "No. Absen " + absen + " — kesempatan tersisa: " + (MAX_ATTEMPTS - st.attempts) + " dari " + MAX_ATTEMPTS + ".";
      submitBtn.style.display = "inline-block";
      retryBtn.style.display = "none";
    }
  }
  absenInput.addEventListener("input", refreshAttemptInfo);
  refreshAttemptInfo();

  function resetAnswers(){
    var radios = container.querySelectorAll('input[type="radio"]');
    radios.forEach(function(r){ r.checked = false; });
    window.scrollTo({top: document.getElementById("epbq-questions").offsetTop - 100, behavior:"smooth"});
  }

  retryBtn.addEventListener("click", function(){
    resetAnswers();
    document.getElementById("epbq-result").style.display = "none";
    retryBtn.style.display = "none";
    submitBtn.style.display = "inline-block";
    document.getElementById("epbq-status").textContent = "";
  });

  submitBtn.addEventListener("click", function(){
    var absen = absenInput.value.trim();
    var nama = document.getElementById("epbq-nama").value.trim();
    var statusEl = document.getElementById("epbq-status");

    if(!absen || !nama){
      statusEl.textContent = "Isi No. Absen dan Nama terlebih dahulu.";
      statusEl.style.color = "#F5A623";
      return;
    }

    var st = loadState(absen);
    if(st.sent){
      statusEl.textContent = "No. Absen ini sudah menyelesaikan latihan dan nilainya sudah tercatat.";
      statusEl.style.color = "#F5A623";
      return;
    }
    if(st.attempts &gt;= MAX_ATTEMPTS){
      statusEl.textContent = "Kesempatan sudah habis.";
      statusEl.style.color = "#F5A623";
      return;
    }

    var belumDijawab = [];
    var benar = 0;
    questions.forEach(function(item, idx){
      var checked = document.querySelector('input[name="epbq-q' + idx + '"]:checked');
      if(!checked){
        belumDijawab.push(idx+1);
      } else if(parseInt(checked.value,10) === item.correct){
        benar++;
      }
    });

    if(belumDijawab.length &gt; 0){
      statusEl.textContent = "Masih ada " + belumDijawab.length + " soal yang belum dijawab.";
      statusEl.style.color = "#F5A623";
      return;
    }

    var skor = benar * 2;
    st.attempts += 1;
    st.bestScore = Math.max(st.bestScore, skor);
    saveState(absen, st);

    document.getElementById("epbq-score").textContent = skor;
    document.getElementById("epbq-result").style.display = "block";

    var sisa = MAX_ATTEMPTS - st.attempts;

    if(skor &gt;= KKM){
      document.getElementById("epbq-detail").textContent = "Menjawab benar " + benar + " dari 50 soal. Skor mencapai KKM (75) \u2014 nilai ini akan dikirim ke guru.";
      kirimNilai(absen, nama, skor);
      st.sent = true;
      saveState(absen, st);
      submitBtn.style.display = "none";
      retryBtn.style.display = "none";
    } else if(sisa &gt; 0){
      document.getElementById("epbq-detail").textContent = "Menjawab benar " + benar + " dari 50 soal. Skor belum mencapai KKM (75). Kesempatan tersisa: " + sisa + ".";
      submitBtn.style.display = "none";
      retryBtn.style.display = "inline-block";
      statusEl.textContent = "";
    } else {
      document.getElementById("epbq-detail").textContent = "Menjawab benar " + benar + " dari 50 soal. Kesempatan telah habis. Nilai tertinggi dari 3 percobaan (" + st.bestScore + ") akan dikirim ke guru.";
      kirimNilai(absen, nama, st.bestScore);
      st.sent = true;
      saveState(absen, st);
      submitBtn.style.display = "none";
      retryBtn.style.display = "none";
    }
    refreshAttemptInfo();
  });

  function kirimNilai(absen, nama, skor){
    var statusEl = document.getElementById("epbq-status");
    statusEl.textContent = "Mengirim hasil...";
    statusEl.style.color = "#9FB4C2";

    var payload = new URLSearchParams();
    payload.append("noAbsen", absen);
    payload.append("nama", nama);
    payload.append("skor", skor);
    payload.append("materi", EPBQ_MATERI);
    payload.append("waktu", new Date().toISOString());

    fetch(EPBQ_ENDPOINT, {
      method: "POST",
      mode: "no-cors",
      headers: {"Content-Type":"application/x-www-form-urlencoded"},
      body: payload.toString()
    }).then(function(){
      statusEl.textContent = "Hasil berhasil dikirim ke guru.";
      statusEl.style.color = "#6EC6CA";
    }).catch(function(){
      statusEl.textContent = "Nilai tercatat di perangkat ini, namun pengiriman gagal. Tunjukkan skor ini ke guru.";
      statusEl.style.color = "#F5A623";
    });
  }
})();
&lt;/script&gt;
&lt;/div&gt;</description><link>http://kitab-investasi.blogspot.com/2026/09/latihan-soal-tipe-akm-pokok-bahasan.html</link><thr:total>0</thr:total><author>nof_rizal07@yahoo.co.id (abang_cool)</author></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-9000860041661554971.post-5495090412156498845</guid><pubDate>Tue, 01 Sep 2026 00:34:08 +0000</pubDate><atom:updated>2026-09-01T07:40:10.978+07:00</atom:updated><title>Pencarian Informasi Digital &amp; Kolaborasi Daring</title><description>&lt;!DOCTYPE html&gt;
&lt;html lang="id"&gt;
&lt;head&gt;
&lt;meta charset="UTF-8"&gt;
&lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&gt;
&lt;title&gt;Pencarian Informasi Digital &amp; Kolaborasi Daring — Informatika Kelas X&lt;/title&gt;
&lt;link rel="preconnect" href="https://fonts.googleapis.com"&gt;
&lt;link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500;600;700&amp;family=IBM+Plex+Sans:wght@400;500;600;700&amp;display=swap" rel="stylesheet"&gt;
&lt;style&gt;
  :root{
    --ink: #1F2430;
    --ink-soft: #57606F;
    --paper: #FFFFFF;
    --surface: #F4F6FA;
    --line: #DEE3EA;
    --accent: #2F5DA8;
    --accent-dark: #1E3E75;
    --amber: #E8940C;
    --teal: #0F9D8C;
    --red: #D8503C;
    --radius: 6px;
  }
  *{box-sizing:border-box; margin:0; padding:0;}
  html{scroll-behavior:smooth;}
  body{ font-family:'IBM Plex Sans', sans-serif; background:#FFFFFF; color: var(--ink); line-height:1.6; }
  .mono{font-family:'IBM Plex Mono', monospace;}

  .page-shell{
    max-width: 900px; margin: 16px auto; background:#FFFFFF; border-radius:16px; overflow:hidden;
    box-shadow: 0 8px 32px rgba(20,30,50,0.12), 0 1px 3px rgba(20,30,50,0.08);
    border: 1px solid var(--line);
  }

  /* ===== Browser-chrome hero ===== */
  .browser-hero{ background:#FFFFFF; }
  .tabbar{
    display:flex; align-items:flex-end; gap:4px; padding: 14px 5% 0; background: var(--surface); border-bottom:1px solid var(--line);
  }
  .tabbar .tab{
    background:#FFFFFF; border:1px solid var(--line); border-bottom:none; border-radius:8px 8px 0 0;
    padding:8px 16px; font-family:'IBM Plex Mono', monospace; font-size:0.72rem; color: var(--ink-soft);
  }
  .tabbar .tab.active{ color: var(--accent); font-weight:600; }
  .addressbar{
    margin: 0 5%; margin-top:-1px; background:#FFFFFF; border:1px solid var(--line); border-radius:0 0 8px 8px;
    padding:10px 16px; display:flex; align-items:center; gap:10px; font-family:'IBM Plex Mono', monospace; font-size:0.78rem; color: var(--ink-soft);
  }
  .addressbar .lock{ color: var(--teal); }

  .hero-body{ padding: 32px 5% 44px; }
  .eyebrow{
    font-family:'IBM Plex Mono', monospace; font-size:0.78rem; letter-spacing:0.16em; text-transform:uppercase;
    color: var(--accent); display:flex; align-items:center; gap:10px; margin-bottom:20px;
  }
  .eyebrow::before{ content:""; width:10px; height:10px; border:1.5px solid var(--accent); border-radius:50%; }
  h1.title{
    font-family:'IBM Plex Mono', monospace; font-weight:700;
    font-size: clamp(1.85rem, 4vw, 3.2rem); line-height:1.16; max-width: 21ch; color: var(--ink);
  }
  h1.title span{ color: var(--accent); }
  h1.title mark{ background: linear-gradient(180deg, transparent 62%, #FCE3A8 62%); color:var(--ink); }
  .hero-sub{ margin-top:18px; max-width: 66ch; font-size:1.04rem; color: var(--ink-soft); }
  .meta-strip{
    margin-top:36px; display:grid; grid-template-columns: repeat(auto-fit,minmax(160px,1fr)); gap:1px;
    background: var(--line); border:1px solid var(--line); max-width: 940px;
  }
  .meta-cell{ background: var(--surface); padding:14px 16px; }
  .meta-cell .k{ font-family:'IBM Plex Mono', monospace; font-size:0.66rem; letter-spacing:0.1em; text-transform:uppercase; color: var(--accent); }
  .meta-cell .v{ margin-top:6px; font-size:0.94rem; font-weight:600; color: var(--ink); }

  /* ===== Content ===== */
  main{ background: var(--paper); padding: 8px 0 0; }
  .section{ padding: 40px 5%; max-width: 1180px; margin: 0 auto; border-bottom:1px solid #ECEFF3; }
  .section:last-of-type{border-bottom:none;}
  .section-tag{
    font-family:'IBM Plex Mono', monospace; font-size:0.72rem; letter-spacing:0.14em; text-transform:uppercase;
    color: var(--ink-soft); display:flex; align-items:center; gap:10px; margin-bottom:10px;
  }
  .section-tag .num{ color:#fff; background: var(--accent); padding:3px 8px; border-radius:3px; font-weight:600; }
  h2.section-title{ font-family:'IBM Plex Mono', monospace; font-size: clamp(1.35rem, 2.3vw, 1.9rem); font-weight:700; color: var(--ink); margin-bottom: 22px; max-width: 34ch; }
  h3.sub-title{ font-family:'IBM Plex Mono', monospace; font-size:1.06rem; font-weight:600; color: var(--ink); margin: 26px 0 12px; display:flex; align-items:center; gap:10px; }
  h3.sub-title::before{ content:""; width:8px;height:8px; background: var(--amber); display:inline-block; border-radius:1px; }
  p{ color:#3A4453; max-width: 74ch; margin-bottom: 14px;}
  strong{color:var(--ink);}
  ul, ol{ margin: 8px 0 18px 1.3em; max-width: 74ch;}
  li{margin-bottom:8px; color:#3A4453;}

  .callout{ border-left: 3px solid var(--accent); background:#EDF2FA; padding: 16px 20px; border-radius: 0 6px 6px 0; margin: 18px 0; max-width: 74ch; }
  .callout .lbl{ font-family:'IBM Plex Mono', monospace; font-size:0.7rem; letter-spacing:0.1em; text-transform:uppercase; color: var(--accent-dark); font-weight:700; margin-bottom:6px; }
  .callout.warn{ border-left-color: var(--red); background:#FBEAE6; }
  .callout.warn .lbl{ color:#A5402C; }
  .callout.secure{ border-left-color: var(--teal); background:#E8F6F3; }
  .callout.secure .lbl{ color:#0C7A6C; }

  /* ===== Cards ===== */
  .card-grid{ display:grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: 16px; margin: 20px 0 8px; }
  .card{ background: var(--paper); border: 1.5px solid var(--line); border-radius: var(--radius); padding: 20px; box-shadow: 0 2px 10px rgba(20,30,50,0.05); }
  .card .tag{ font-family:'IBM Plex Mono', monospace; font-size:0.66rem; letter-spacing:0.1em; text-transform:uppercase; color:#fff; background: var(--accent); padding:3px 8px; border-radius:3px; display:inline-block; margin-bottom:12px; }
  .card h4{ font-family:'IBM Plex Mono', monospace; font-size:0.98rem; margin-bottom:8px; color:var(--ink); }
  .card p{font-size:0.89rem; margin-bottom:0;}
  .card code{ font-family:'IBM Plex Mono', monospace; background:var(--surface); padding:1px 6px; border-radius:3px; font-size:0.85em; color: var(--accent-dark); }

  .table-scroll{ overflow-x:auto; margin:18px 0; -webkit-overflow-scrolling:touch; }
  .table-scroll table{ margin:0; }
  table.compare{ width:100%; border-collapse:collapse; font-size:0.9rem; min-width:480px; }
  table.compare th, table.compare td{ border:1px solid var(--line); padding:11px 14px; text-align:left; }
  table.compare th{ background: var(--accent); color:#fff; font-family:'IBM Plex Mono', monospace; font-size:0.74rem; letter-spacing:0.04em; text-transform:uppercase; }
  table.compare tr:nth-child(even) td{ background: var(--surface); }

  /* ===== Diagram ===== */
  .diagram-frame{ margin: 26px 0; background: var(--surface); border-radius: 8px; padding: 18px; border: 1px solid var(--line); }
  .diagram-frame svg{width:100%; height:auto; display:block;}
  .diagram-caption{ font-family:'IBM Plex Mono', monospace; font-size:0.72rem; color: var(--ink-soft); text-align:center; margin-top:10px; letter-spacing:0.03em; }
  .signal{ stroke-dasharray: 6 8; animation: flow 1.6s linear infinite; }
  @keyframes flow{ to{ stroke-dashoffset:-56; } }
  @media (prefers-reduced-motion: reduce){ .signal{animation:none;} }

  /* ===== Summary ===== */
  .summary-box{ background: var(--accent-dark); color: #fff; border-radius: 8px; padding: 26px 28px; margin-top: 10px; }
  .summary-box h4{ font-family:'IBM Plex Mono', monospace; color:#FCD98A; font-size:0.85rem; letter-spacing:0.08em; text-transform:uppercase; margin-bottom:14px; }
  .summary-box ul{ margin:0 0 0 1.1em; max-width:none; }
  .summary-box li{ color:#E6ECF7; margin-bottom:8px; }

  /* ===== Tugas kelompok ===== */
  .task-panel{ border: 1.5px dashed var(--accent); border-radius: 8px; padding: 26px 28px; background: repeating-linear-gradient(135deg, #FFFFFF, #FFFFFF 18px, var(--surface) 18px, var(--surface) 19px); }
  .task-head{ display:flex; align-items:center; gap:12px; flex-wrap:wrap; margin-bottom:12px; }
  .task-head .badge{ font-family:'IBM Plex Mono', monospace; font-size:0.7rem; letter-spacing:0.08em; text-transform:uppercase; background: var(--teal); color:#fff; padding:4px 10px; border-radius:3px; font-weight:700;}
  .task-panel h3{ font-family:'IBM Plex Mono', monospace; font-size:1.22rem; color: var(--ink); }
  .steps-num{ counter-reset: step; margin:16px 0; max-width:78ch; }
  .steps-num li{ counter-increment: step; list-style:none; position:relative; padding-left:34px; margin-bottom:14px; }
  .steps-num li::before{ content: counter(step); position:absolute; left:0; top:0; font-family:'IBM Plex Mono', monospace; font-weight:700; color:#fff; background: var(--accent); width:24px; height:24px; border-radius:50%; display:flex; align-items:center; justify-content:center; font-size:0.8rem; }
  table.rubrik{ width:100%; border-collapse:collapse; margin:18px 0 0; font-size:0.88rem; min-width:520px; }
  table.rubrik th, table.rubrik td{ border:1px solid #C9CFD6; padding:10px 12px; text-align:left; }
  table.rubrik th{ background: var(--accent-dark); color:#fff; font-family:'IBM Plex Mono', monospace; font-size:0.75rem; letter-spacing:0.04em; text-transform:uppercase; }
  table.rubrik tr:nth-child(even) td{ background: var(--surface); }

  .closing-task{ margin-top:22px; background: #FFF6E6; border:1.5px solid var(--amber); border-radius:8px; padding:20px 22px; }
  .closing-task .lbl{ font-family:'IBM Plex Mono', monospace; font-size:0.72rem; letter-spacing:0.1em; text-transform:uppercase; color:#8A5A0A; font-weight:700; margin-bottom:8px; }

  /* ===== Quiz ===== */
  .quiz-panel{ background: var(--surface); border:1px solid var(--line); border-radius: 10px; padding: 30px 28px; color: var(--ink); }
  .quiz-panel h3.sub-title{ color: var(--ink); }
  .quiz-note{ font-size:0.88rem; color: var(--ink-soft); max-width:74ch; margin-bottom:18px;}
  .student-info{ display:grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap:14px; margin: 18px 0 30px; }
  .field label{ display:block; font-family:'IBM Plex Mono', monospace; font-size:0.7rem; letter-spacing:0.06em; text-transform:uppercase; color: var(--accent-dark); margin-bottom:6px; }
  .field input, .field select{
    width:100%; padding:10px 12px; border-radius:5px; border:1px solid var(--line); background:#FFFFFF; color: var(--ink); font-family:'IBM Plex Sans', sans-serif; font-size:0.94rem;
  }
  .field select{ cursor:pointer; }
  .field input:focus, .field select:focus{ outline:2px solid var(--accent); }

  .q-card{ background:#FFFFFF; border:1px solid var(--line); border-radius:8px; padding:18px 20px; margin-bottom:14px; }
  .q-card .q-num{ font-family:'IBM Plex Mono', monospace; font-size:0.72rem; color: var(--accent); letter-spacing:0.08em; margin-bottom:6px; }
  .q-card .q-text{ font-size:0.98rem; color: var(--ink); margin-bottom:12px; font-weight:500; }
  .options{ display:flex; flex-direction:column; gap:8px; }
  .opt{ display:flex; align-items:flex-start; gap:10px; padding:9px 12px; border:1px solid var(--line); border-radius:5px; cursor:pointer; transition: border-color .15s, background .15s; }
  .opt:hover{ border-color: var(--accent); }
  .opt input{ margin-top:3px; accent-color: var(--accent); }
  .opt span{ font-size:0.9rem; color:#33414F; }
  .opt.selected{ border-color: var(--accent); background: rgba(47,93,168,0.07); }

  .quiz-actions{ margin-top:24px; display:flex; align-items:center; gap:16px; flex-wrap:wrap; }
  #btnHitung, #btnKirim{
    font-family:'IBM Plex Mono', monospace; font-weight:600; font-size:0.85rem; letter-spacing:0.04em;
    padding: 12px 22px; border-radius:6px; border:none; cursor:pointer;
  }
  #btnHitung{ background: var(--accent); color:#fff; }
  #btnHitung:hover{ filter:brightness(1.08); }
  #btnKirim{ background: var(--teal); color:#fff; display:none; }
  #btnKirim:hover{ filter:brightness(1.08); }
  #btnKirim:disabled{ opacity:0.6; cursor:not-allowed; }
  #quizMsg{ font-family:'IBM Plex Mono', monospace; font-size:0.85rem; color:#B4791C; }

  .result-panel{ display:none; margin-top:22px; background:#FFFFFF; border:1.5px solid var(--teal); border-radius:8px; padding:22px 24px; }
  .result-panel .score{ font-family:'IBM Plex Mono', monospace; font-size:2.4rem; font-weight:700; color: #0C7A6C; }
  .result-panel .score-lbl{ font-family:'IBM Plex Mono', monospace; font-size:0.72rem; letter-spacing:0.1em; text-transform:uppercase; color: var(--ink-soft); }
  .result-panel p{ color:#33414F; font-size:0.9rem; margin-top:10px; margin-bottom:0; }

  footer{ background: var(--surface); color: var(--ink-soft); text-align:center; padding: 24px 5% 32px; font-family:'IBM Plex Mono', monospace; font-size:0.75rem; letter-spacing:0.04em; border-top:1px solid var(--line); }

  @media (max-width: 700px){
    .card-grid{grid-template-columns:1fr;}
    .hero-body{padding:26px 5% 34px;}
    .section{padding:28px 5%;}
  }
&lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;

&lt;div class="page-shell"&gt;
&lt;div class="browser-hero"&gt;
  &lt;div class="tabbar"&gt;
    &lt;div class="tab active"&gt;&#128269; Pencarian Informasi&lt;/div&gt;
    &lt;div class="tab"&gt;&#129309; Kolaborasi Daring&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="addressbar"&gt;&lt;span class="lock"&gt;&#128274;&lt;/span&gt; https://belajar-informatika.sekolah.id/pencarian-kolaborasi-daring&lt;/div&gt;

  &lt;div class="hero-body"&gt;
    &lt;div class="eyebrow"&gt;Informatika · Fase E · Kelas X SMK&lt;/div&gt;
    &lt;h1 class="title"&gt;Pencarian Informasi Digital &amp; &lt;mark&gt;Kolaborasi&lt;/mark&gt; &lt;span&gt;Daring&lt;/span&gt;&lt;/h1&gt;
    &lt;p class="hero-sub"&gt;Materi ini membahas cara memanfaatkan mesin pencari dan peramban secara efektif, menggunakan layanan komunikasi digital dengan tepat, berkolaborasi lewat media daring, serta menerapkan etika dan keamanan digital yang bertanggung jawab.&lt;/p&gt;

    &lt;div class="meta-strip"&gt;
      &lt;div class="meta-cell"&gt;&lt;div class="k"&gt;Elemen CP&lt;/div&gt;&lt;div class="v"&gt;Pencarian &amp; Kolaborasi Daring&lt;/div&gt;&lt;/div&gt;
      &lt;div class="meta-cell"&gt;&lt;div class="k"&gt;Jenjang&lt;/div&gt;&lt;div class="v"&gt;SMK Kelas X&lt;/div&gt;&lt;/div&gt;
      &lt;div class="meta-cell"&gt;&lt;div class="k"&gt;Alokasi Waktu&lt;/div&gt;&lt;div class="v"&gt;1 Pertemuan · 4 JP (180 menit)&lt;/div&gt;&lt;/div&gt;
      &lt;div class="meta-cell"&gt;&lt;div class="k"&gt;Model&lt;/div&gt;&lt;div class="v"&gt;Praktik, Kerja Kelompok &amp; Kuis&lt;/div&gt;&lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;main&gt;

  &lt;!-- ===================== TUJUAN ===================== --&gt;
  &lt;section class="section" id="tujuan"&gt;
    &lt;div class="section-tag"&gt;&lt;span class="num"&gt;00&lt;/span&gt; Capaian &amp; Tujuan Pembelajaran&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Ke Mana Materi Ini Menuju&lt;/h2&gt;

    &lt;h3 class="sub-title"&gt;Capaian Pembelajaran&lt;/h3&gt;
    &lt;p&gt;Murid mampu memanfaatkan mesin pencari, peramban, layanan komunikasi digital, dan media kolaborasi daring secara efektif, aman, dan bertanggung jawab.&lt;/p&gt;

    &lt;h3 class="sub-title"&gt;Tujuan Pembelajaran&lt;/h3&gt;
    &lt;ol&gt;
      &lt;li&gt;Menjelaskan cara kerja mesin pencari dan menerapkan strategi pencarian informasi yang efektif.&lt;/li&gt;
      &lt;li&gt;Menjelaskan fungsi dan fitur-fitur penting peramban (browser) dalam mengakses informasi digital.&lt;/li&gt;
      &lt;li&gt;Memanfaatkan layanan komunikasi digital (email, pesan instan, video conference) secara tepat dan sopan.&lt;/li&gt;
      &lt;li&gt;Memanfaatkan media kolaborasi daring untuk bekerja sama menyelesaikan tugas kelompok.&lt;/li&gt;
      &lt;li&gt;Menerapkan etika berinternet (netiket), verifikasi informasi, dan keamanan/privasi digital.&lt;/li&gt;
    &lt;/ol&gt;

    &lt;h3 class="sub-title"&gt;Rincian Kegiatan (4 JP × 45 menit)&lt;/h3&gt;
    &lt;div class="table-scroll"&gt;&lt;table class="compare"&gt;
      &lt;tr&gt;&lt;th&gt;Tahap&lt;/th&gt;&lt;th&gt;Kegiatan&lt;/th&gt;&lt;th&gt;Waktu&lt;/th&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Pendahuluan&lt;/td&gt;&lt;td&gt;Apersepsi ("Bagaimana caramu memastikan informasi yang kamu temukan di internet itu benar?"), penyampaian tujuan pembelajaran&lt;/td&gt;&lt;td&gt;15 menit&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Inti — Eksplorasi Konsep&lt;/td&gt;&lt;td&gt;Penjelasan mesin pencari, peramban, komunikasi digital, kolaborasi daring, dan etika/keamanan digital&lt;/td&gt;&lt;td&gt;55 menit&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Inti — Kerja Kelompok&lt;/td&gt;&lt;td&gt;Diskusi dan pengerjaan tugas kelompok riset &amp; kolaborasi dokumen daring&lt;/td&gt;&lt;td&gt;40 menit&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Inti — Presentasi&lt;/td&gt;&lt;td&gt;Presentasi singkat tiap kelompok dan tanggapan guru&lt;/td&gt;&lt;td&gt;20 menit&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Inti — Kuis Individu&lt;/td&gt;&lt;td&gt;Mengerjakan 25 soal pilihan ganda secara mandiri melalui halaman ini&lt;/td&gt;&lt;td&gt;35 menit&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Penutup&lt;/td&gt;&lt;td&gt;Refleksi, penguatan konsep, menulis kesimpulan ringkas di buku catatan&lt;/td&gt;&lt;td&gt;15 menit&lt;/td&gt;&lt;/tr&gt;
    &lt;/table&gt;&lt;/div&gt;
  &lt;/section&gt;

  &lt;!-- ===================== A. MESIN PENCARI ===================== --&gt;
  &lt;section class="section" id="mesin-pencari"&gt;
    &lt;div class="section-tag"&gt;&lt;span class="num"&gt;01&lt;/span&gt; Menemukan Informasi&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Mesin Pencari (Search Engine)&lt;/h2&gt;
    &lt;p&gt;&lt;strong&gt;Mesin pencari&lt;/strong&gt; adalah layanan yang membantu pengguna menemukan informasi di internet berdasarkan kata kunci yang dimasukkan. Contohnya Google, Bing, dan DuckDuckGo. Secara sederhana, mesin pencari bekerja melalui tiga tahap: &lt;strong&gt;crawling&lt;/strong&gt; (menjelajahi halaman-halaman web), &lt;strong&gt;indexing&lt;/strong&gt; (menyimpan dan mengelompokkan informasi halaman tersebut), dan &lt;strong&gt;ranking&lt;/strong&gt; (mengurutkan hasil yang paling relevan dengan kata kunci pencarian).&lt;/p&gt;

    &lt;h3 class="sub-title"&gt;Operator Pencarian agar Hasil Lebih Tepat&lt;/h3&gt;
    &lt;div class="card-grid"&gt;
      &lt;div class="card"&gt;&lt;span class="tag"&gt;Frasa Persis&lt;/span&gt;&lt;h4&gt;Tanda Kutip " "&lt;/h4&gt;&lt;p&gt;Mencari frasa yang harus muncul persis sama. Contoh: &lt;code&gt;"kurikulum merdeka"&lt;/code&gt;&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;span class="tag"&gt;Mengecualikan&lt;/span&gt;&lt;h4&gt;Tanda Minus -&lt;/h4&gt;&lt;p&gt;Mengeluarkan kata tertentu dari hasil pencarian. Contoh: &lt;code&gt;jaguar -mobil&lt;/code&gt;&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;span class="tag"&gt;Batasi Situs&lt;/span&gt;&lt;h4&gt;site:&lt;/h4&gt;&lt;p&gt;Membatasi hasil hanya dari satu situs tertentu. Contoh: &lt;code&gt;site:kemdikbud.go.id&lt;/code&gt;&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;span class="tag"&gt;Format File&lt;/span&gt;&lt;h4&gt;filetype:&lt;/h4&gt;&lt;p&gt;Mencari file dengan format tertentu. Contoh: &lt;code&gt;modul ajar filetype:pdf&lt;/code&gt;&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;span class="tag"&gt;Kata Alternatif&lt;/span&gt;&lt;h4&gt;OR&lt;/h4&gt;&lt;p&gt;Mencari salah satu dari beberapa kata. Contoh: &lt;code&gt;SMK OR SMA jurusan TKJ&lt;/code&gt;&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;span class="tag"&gt;Kata Hilang&lt;/span&gt;&lt;h4&gt;Tanda Bintang *&lt;/h4&gt;&lt;p&gt;Sebagai pengganti kata yang belum diketahui dalam sebuah frasa. Contoh: &lt;code&gt;ibu kota * adalah Jakarta&lt;/code&gt;&lt;/p&gt;&lt;/div&gt;
    &lt;/div&gt;

    &lt;h3 class="sub-title"&gt;Mengevaluasi Kredibilitas Sumber&lt;/h3&gt;
    &lt;p&gt;Tidak semua informasi di internet dapat dipercaya begitu saja. Sebelum menggunakan sebuah sumber, periksa hal-hal berikut:&lt;/p&gt;
    &lt;div class="table-scroll"&gt;&lt;table class="compare"&gt;
      &lt;tr&gt;&lt;th&gt;Aspek&lt;/th&gt;&lt;th&gt;Pertanyaan Kunci&lt;/th&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Penulis/Penerbit&lt;/td&gt;&lt;td&gt;Siapa yang menulis atau menerbitkan informasi ini? Apakah kredibel di bidangnya?&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Waktu Publikasi&lt;/td&gt;&lt;td&gt;Kapan informasi ini dipublikasikan? Apakah masih relevan/terkini?&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Tujuan Konten&lt;/td&gt;&lt;td&gt;Apakah bertujuan memberi informasi, atau justru mempengaruhi opini/menjual sesuatu?&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Bukti Pendukung&lt;/td&gt;&lt;td&gt;Apakah klaim dalam konten didukung data, fakta, atau referensi yang jelas?&lt;/td&gt;&lt;/tr&gt;
    &lt;/table&gt;&lt;/div&gt;
  &lt;/section&gt;

  &lt;!-- ===================== B. PERAMBAN ===================== --&gt;
  &lt;section class="section" id="peramban"&gt;
    &lt;div class="section-tag"&gt;&lt;span class="num"&gt;02&lt;/span&gt; Alat Menjelajah&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Peramban (Browser)&lt;/h2&gt;
    &lt;p&gt;&lt;strong&gt;Peramban (browser)&lt;/strong&gt; adalah perangkat lunak yang digunakan untuk mengakses dan menampilkan halaman web, seperti Google Chrome, Mozilla Firefox, Microsoft Edge, dan Safari.&lt;/p&gt;

    &lt;h3 class="sub-title"&gt;Fitur-Fitur Penting Peramban&lt;/h3&gt;
    &lt;div class="card-grid"&gt;
      &lt;div class="card"&gt;&lt;span class="tag"&gt;Navigasi&lt;/span&gt;&lt;h4&gt;Tab&lt;/h4&gt;&lt;p&gt;Membuka beberapa halaman sekaligus dalam satu jendela peramban.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;span class="tag"&gt;Simpan Cepat&lt;/span&gt;&lt;h4&gt;Bookmark&lt;/h4&gt;&lt;p&gt;Menyimpan alamat situs favorit agar mudah diakses kembali di kemudian hari.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;span class="tag"&gt;Jejak Digital&lt;/span&gt;&lt;h4&gt;Riwayat (History)&lt;/h4&gt;&lt;p&gt;Mencatat daftar situs yang pernah dikunjungi.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;span class="tag"&gt;Privasi&lt;/span&gt;&lt;h4&gt;Mode Incognito/Private&lt;/h4&gt;&lt;p&gt;Menjelajah tanpa menyimpan riwayat, cookie, dan data formulir setelah jendela ditutup.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;span class="tag"&gt;Tambahan Fungsi&lt;/span&gt;&lt;h4&gt;Ekstensi/Add-on&lt;/h4&gt;&lt;p&gt;Program tambahan yang memperluas fungsi peramban, mis. pemblokir iklan atau kamus.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;span class="tag"&gt;Keamanan&lt;/span&gt;&lt;h4&gt;Indikator HTTPS&lt;/h4&gt;&lt;p&gt;Ikon gembok pada address bar menandakan koneksi ke situs sudah terenkripsi dan lebih aman.&lt;/p&gt;&lt;/div&gt;
    &lt;/div&gt;
  &lt;/section&gt;

  &lt;!-- ===================== C. KOMUNIKASI DIGITAL ===================== --&gt;
  &lt;section class="section" id="komunikasi"&gt;
    &lt;div class="section-tag"&gt;&lt;span class="num"&gt;03&lt;/span&gt; Terhubung Secara Digital&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Layanan Komunikasi Digital&lt;/h2&gt;
    &lt;p&gt;Komunikasi digital memungkinkan kita bertukar pesan, ide, dan informasi tanpa harus bertatap muka langsung.&lt;/p&gt;
    &lt;div class="table-scroll"&gt;&lt;table class="compare"&gt;
      &lt;tr&gt;&lt;th&gt;Layanan&lt;/th&gt;&lt;th&gt;Contoh&lt;/th&gt;&lt;th&gt;Etika Penggunaan&lt;/th&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Email&lt;/td&gt;&lt;td&gt;Gmail, Outlook&lt;/td&gt;&lt;td&gt;Gunakan subjek yang jelas, salam pembuka/penutup, bahasa sopan, dan periksa ulang sebelum mengirim.&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Pesan Instan (Chat)&lt;/td&gt;&lt;td&gt;WhatsApp, Telegram&lt;/td&gt;&lt;td&gt;Kirim pesan pada jam wajar, hindari pesan berantai/spam, gunakan bahasa yang jelas dan sopan.&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Video Conference&lt;/td&gt;&lt;td&gt;Google Meet, Zoom&lt;/td&gt;&lt;td&gt;Bergabung tepat waktu, matikan mikrofon saat tidak berbicara, berpakaian dan berlatar belakang pantas.&lt;/td&gt;&lt;/tr&gt;
    &lt;/table&gt;&lt;/div&gt;
  &lt;/section&gt;

  &lt;!-- ===================== D. KOLABORASI DARING ===================== --&gt;
  &lt;section class="section" id="kolaborasi"&gt;
    &lt;div class="section-tag"&gt;&lt;span class="num"&gt;04&lt;/span&gt; Bekerja Bersama&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Media Kolaborasi Daring&lt;/h2&gt;
    &lt;p&gt;&lt;strong&gt;Media kolaborasi daring&lt;/strong&gt; memungkinkan beberapa orang menyunting satu dokumen, spreadsheet, atau presentasi secara bersamaan (real-time) melalui internet — tanpa perlu bertemu di tempat yang sama. Contoh: Google Docs, Google Sheets, Google Slides, dan Google Drive.&lt;/p&gt;

    &lt;div class="diagram-frame"&gt;
      &lt;svg viewBox="0 0 800 260" xmlns="http://www.w3.org/2000/svg"&gt;
        &lt;text x="400" y="26" text-anchor="middle" fill="#1E3E75" font-family="IBM Plex Mono, monospace" font-size="12" letter-spacing="2"&gt;KOLABORASI DOKUMEN REAL-TIME&lt;/text&gt;

        &lt;rect x="330" y="60" width="140" height="110" rx="6" fill="none" stroke="#0F9D8C" stroke-width="2"/&gt;
        &lt;text x="400" y="90" text-anchor="middle" fill="#0F9D8C" font-family="IBM Plex Mono, monospace" font-weight="700" font-size="11"&gt;DOKUMEN&lt;/text&gt;
        &lt;text x="400" y="105" text-anchor="middle" fill="#0F9D8C" font-family="IBM Plex Mono, monospace" font-size="10"&gt;BERSAMA&lt;/text&gt;
        &lt;line x1="345" y1="120" x2="455" y2="120" stroke="#DEE3EA" stroke-width="2"/&gt;
        &lt;line x1="345" y1="135" x2="455" y2="135" stroke="#DEE3EA" stroke-width="2"/&gt;
        &lt;line x1="345" y1="150" x2="425" y2="150" stroke="#DEE3EA" stroke-width="2"/&gt;

        &lt;circle cx="120" cy="60" r="26" fill="none" stroke="#2F5DA8" stroke-width="2"/&gt;
        &lt;text x="120" y="65" text-anchor="middle" fill="#2F5DA8" font-family="IBM Plex Mono, monospace" font-size="10"&gt;Murid A&lt;/text&gt;
        &lt;circle cx="120" cy="200" r="26" fill="none" stroke="#E8940C" stroke-width="2"/&gt;
        &lt;text x="120" y="205" text-anchor="middle" fill="#E8940C" font-family="IBM Plex Mono, monospace" font-size="10"&gt;Murid B&lt;/text&gt;
        &lt;circle cx="680" cy="60" r="26" fill="none" stroke="#D8503C" stroke-width="2"/&gt;
        &lt;text x="680" y="65" text-anchor="middle" fill="#D8503C" font-family="IBM Plex Mono, monospace" font-size="10"&gt;Murid C&lt;/text&gt;
        &lt;circle cx="680" cy="200" r="26" fill="none" stroke="#0F9D8C" stroke-width="2"/&gt;
        &lt;text x="680" y="205" text-anchor="middle" fill="#0F9D8C" font-family="IBM Plex Mono, monospace" font-size="10"&gt;Guru&lt;/text&gt;

        &lt;line class="signal" x1="145" y1="72" x2="330" y2="95" stroke="#2F5DA8" stroke-width="2"/&gt;
        &lt;line class="signal" x1="145" y1="188" x2="330" y2="150" stroke="#E8940C" stroke-width="2"/&gt;
        &lt;line class="signal" x1="655" y1="72" x2="470" y2="95" stroke="#D8503C" stroke-width="2"/&gt;
        &lt;line class="signal" x1="655" y1="188" x2="470" y2="150" stroke="#0F9D8C" stroke-width="2"/&gt;
      &lt;/svg&gt;
      &lt;div class="diagram-caption"&gt;Semua peserta dapat menyunting dokumen yang sama secara bersamaan — perubahan setiap orang langsung terlihat oleh yang lain.&lt;/div&gt;
    &lt;/div&gt;

    &lt;h3 class="sub-title"&gt;Tingkat Akses Berbagi (Sharing Permission)&lt;/h3&gt;
    &lt;div class="table-scroll"&gt;&lt;table class="compare"&gt;
      &lt;tr&gt;&lt;th&gt;Tingkat Akses&lt;/th&gt;&lt;th&gt;Yang Dapat Dilakukan&lt;/th&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Viewer (Melihat)&lt;/td&gt;&lt;td&gt;Hanya dapat membaca/melihat isi dokumen, tidak dapat mengubah apa pun.&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Commenter (Mengomentari)&lt;/td&gt;&lt;td&gt;Dapat melihat dan menambahkan komentar/masukan tanpa mengubah isi asli.&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Editor (Menyunting)&lt;/td&gt;&lt;td&gt;Dapat melihat, mengedit, dan mengubah langsung isi dokumen.&lt;/td&gt;&lt;/tr&gt;
    &lt;/table&gt;&lt;/div&gt;
    &lt;p&gt;Fitur &lt;strong&gt;version history (riwayat versi)&lt;/strong&gt; pada Google Docs memungkinkan kita melihat kembali dan mengembalikan perubahan dokumen dari waktu ke waktu — sangat berguna jika terjadi kesalahan saat berkolaborasi.&lt;/p&gt;
  &lt;/section&gt;

  &lt;!-- ===================== E. ETIKA &amp; KEAMANAN ===================== --&gt;
  &lt;section class="section" id="etika-keamanan"&gt;
    &lt;div class="section-tag"&gt;&lt;span class="num"&gt;05&lt;/span&gt; Bertanggung Jawab&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Etika &amp; Keamanan Digital&lt;/h2&gt;

    &lt;h3 class="sub-title"&gt;Netiket (Etika Berinternet)&lt;/h3&gt;
    &lt;div class="callout"&gt;
      &lt;div class="lbl"&gt;Perilaku yang Dianjurkan&lt;/div&gt;
      &lt;ul style="margin:0 0 0 1.1em;"&gt;
        &lt;li&gt;Berkomunikasi dengan sopan dan menghargai pendapat orang lain, meski berbeda pandangan.&lt;/li&gt;
        &lt;li&gt;Mencantumkan sumber saat mengutip atau menggunakan karya orang lain (menghindari plagiarisme).&lt;/li&gt;
        &lt;li&gt;Tidak menyebarkan konten SARA, ujaran kebencian, atau informasi yang belum diverifikasi.&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/div&gt;

    &lt;h3 class="sub-title"&gt;Verifikasi Informasi &amp; Hoaks&lt;/h3&gt;
    &lt;div class="callout warn"&gt;
      &lt;div class="lbl"&gt;Waspadai Hoaks&lt;/div&gt;
      &lt;p style="margin:0;"&gt;&lt;strong&gt;Hoaks&lt;/strong&gt; adalah informasi yang sengaja dibuat menyesatkan dan tidak berdasarkan fakta. Sebelum membagikan sebuah informasi, bandingkan dengan beberapa sumber terpercaya lain, periksa tanggal publikasi, dan jangan hanya menilai dari judul yang bersifat clickbait.&lt;/p&gt;
    &lt;/div&gt;

    &lt;h3 class="sub-title"&gt;Keamanan &amp; Privasi&lt;/h3&gt;
    &lt;div class="callout secure"&gt;
      &lt;div class="lbl"&gt;Langkah Perlindungan&lt;/div&gt;
      &lt;ul style="margin:0 0 0 1.1em;"&gt;
        &lt;li&gt;Atur pengaturan berbagi (sharing) dokumen daring hanya untuk orang/kelompok yang dituju, sesuai kebutuhan akses.&lt;/li&gt;
        &lt;li&gt;Jangan membagikan data pribadi (kata sandi, nomor identitas) melalui email/chat, apalagi kepada pihak tak dikenal.&lt;/li&gt;
        &lt;li&gt;Waspadai pesan atau email &lt;strong&gt;phishing&lt;/strong&gt; yang meminta data pribadi secara mendesak melalui tautan mencurigakan.&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/div&gt;
  &lt;/section&gt;

  &lt;!-- ===================== F. HUBUNGAN ===================== --&gt;
  &lt;section class="section" id="hubungan"&gt;
    &lt;div class="section-tag"&gt;&lt;span class="num"&gt;06&lt;/span&gt; Keterkaitan&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Hubungan Antar Konsep&lt;/h2&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;strong&gt;Mesin pencari&lt;/strong&gt; membantu menemukan informasi, sedangkan &lt;strong&gt;peramban&lt;/strong&gt; adalah alat yang digunakan untuk mengaksesnya.&lt;/li&gt;
      &lt;li&gt;Informasi yang ditemukan perlu dievaluasi kredibilitasnya sebelum digunakan atau dibagikan lewat &lt;strong&gt;layanan komunikasi digital&lt;/strong&gt;.&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Media kolaborasi daring&lt;/strong&gt; memungkinkan hasil pencarian dan diskusi diolah bersama menjadi karya kelompok.&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Etika dan keamanan digital&lt;/strong&gt; menjadi payung yang melandasi seluruh aktivitas di atas agar dilakukan secara aman dan bertanggung jawab.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/section&gt;

  &lt;!-- ===================== G. RANGKUMAN ===================== --&gt;
  &lt;section class="section" id="rangkuman"&gt;
    &lt;div class="section-tag"&gt;&lt;span class="num"&gt;07&lt;/span&gt; Penguatan Konsep&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Rangkuman Materi&lt;/h2&gt;
    &lt;div class="summary-box"&gt;
      &lt;h4&gt;Poin-Poin Kunci&lt;/h4&gt;
      &lt;ul&gt;
        &lt;li&gt;Mesin pencari bekerja melalui crawling, indexing, dan ranking; gunakan operator pencarian untuk hasil lebih tepat.&lt;/li&gt;
        &lt;li&gt;Evaluasi kredibilitas sumber dengan memeriksa penulis, waktu publikasi, tujuan, dan bukti pendukung.&lt;/li&gt;
        &lt;li&gt;Peramban memiliki fitur tab, bookmark, riwayat, mode incognito, ekstensi, dan indikator keamanan HTTPS.&lt;/li&gt;
        &lt;li&gt;Layanan komunikasi digital (email, chat, video conference) masing-masing punya etika penggunaannya sendiri.&lt;/li&gt;
        &lt;li&gt;Media kolaborasi daring memungkinkan penyuntingan dokumen bersama secara real-time dengan pengaturan akses viewer/commenter/editor.&lt;/li&gt;
        &lt;li&gt;Netiket, verifikasi hoaks, dan keamanan/privasi data adalah dasar berinternet secara bertanggung jawab.&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/div&gt;
  &lt;/section&gt;

  &lt;!-- ===================== TUGAS KELOMPOK ===================== --&gt;
  &lt;section class="section" id="tugas"&gt;
    &lt;div class="section-tag"&gt;&lt;span class="num"&gt;08&lt;/span&gt; Aktivitas Belajar&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Tugas Kelompok&lt;/h2&gt;

    &lt;div class="task-panel"&gt;
      &lt;div class="task-head"&gt;
        &lt;span class="badge"&gt;Kerja Kelompok · 4–5 orang&lt;/span&gt;
        &lt;span class="badge" style="background:var(--accent-dark); color:#fff;"&gt;40 menit diskusi + 20 menit presentasi&lt;/span&gt;
      &lt;/div&gt;
      &lt;h3&gt;Riset &amp; Kolaborasi: Menyusun Artikel Digital Menggunakan Mesin Pencari dan Google Docs&lt;/h3&gt;
      &lt;p&gt;Setiap kelompok melakukan riset singkat tentang sebuah topik teknologi terkini, lalu menyusun hasilnya bersama-sama dalam satu dokumen kolaboratif secara real-time.&lt;/p&gt;

      &lt;ol class="steps-num"&gt;
        &lt;li&gt;&lt;strong&gt;Bentuk kelompok&lt;/strong&gt; beranggotakan 4–5 orang dan tentukan satu topik riset (mis. "Perkembangan Kecerdasan Buatan di Indonesia" atau topik lain yang disetujui guru).&lt;/li&gt;
        &lt;li&gt;&lt;strong&gt;Gunakan mesin pencari&lt;/strong&gt; dengan minimal 2 operator pencarian berbeda (mis. tanda kutip dan site:) untuk menemukan sumber informasi yang relevan.&lt;/li&gt;
        &lt;li&gt;&lt;strong&gt;Evaluasi kredibilitas&lt;/strong&gt; minimal 3 sumber yang ditemukan berdasarkan penulis, waktu publikasi, dan tujuan konten.&lt;/li&gt;
        &lt;li&gt;&lt;strong&gt;Buat satu dokumen Google Docs&lt;/strong&gt; bersama, atur pengaturan berbagi agar seluruh anggota kelompok memiliki akses Editor.&lt;/li&gt;
        &lt;li&gt;&lt;strong&gt;Susun artikel ringkas&lt;/strong&gt; hasil riset secara kolaboratif — seluruh anggota menyunting dokumen yang sama secara bersamaan, lengkap dengan daftar sumber yang digunakan.&lt;/li&gt;
        &lt;li&gt;&lt;strong&gt;Presentasikan&lt;/strong&gt; hasil artikel dan proses kolaborasi kelompok di depan kelas selama maksimal 5 menit per kelompok.&lt;/li&gt;
      &lt;/ol&gt;

      &lt;h3 class="sub-title" style="margin-top:26px;"&gt;Format Laporan&lt;/h3&gt;
      &lt;p&gt;Dokumen memuat: (1) judul &amp; anggota kelompok, (2) daftar kata kunci/operator pencarian yang digunakan, (3) tabel evaluasi kredibilitas 3 sumber, (4) isi artikel ringkas beserta daftar sumber, (5) tautan (link) dokumen Google Docs kelompok.&lt;/p&gt;

      &lt;h3 class="sub-title"&gt;Rubrik Penilaian&lt;/h3&gt;
      &lt;div class="table-scroll"&gt;&lt;table class="rubrik"&gt;
        &lt;tr&gt;&lt;th&gt;Aspek&lt;/th&gt;&lt;th&gt;Indikator&lt;/th&gt;&lt;th&gt;Skor Maks.&lt;/th&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td&gt;Strategi Pencarian&lt;/td&gt;&lt;td&gt;Operator pencarian digunakan dengan tepat dan efektif menemukan sumber relevan&lt;/td&gt;&lt;td&gt;20&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td&gt;Evaluasi Kredibilitas&lt;/td&gt;&lt;td&gt;Evaluasi sumber logis dan sesuai kriteria (penulis, waktu, tujuan, bukti)&lt;/td&gt;&lt;td&gt;20&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td&gt;Kualitas Artikel&lt;/td&gt;&lt;td&gt;Isi artikel jelas, runtut, dan didukung sumber yang valid&lt;/td&gt;&lt;td&gt;25&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td&gt;Bukti Kolaborasi&lt;/td&gt;&lt;td&gt;Dokumen menunjukkan kontribusi nyata seluruh anggota secara real-time&lt;/td&gt;&lt;td&gt;20&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td&gt;Kerja Sama &amp; Presentasi&lt;/td&gt;&lt;td&gt;Seluruh anggota berkontribusi; presentasi jelas dan percaya diri&lt;/td&gt;&lt;td&gt;15&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td colspan="2" style="text-align:right; font-weight:600;"&gt;Total&lt;/td&gt;&lt;td&gt;100&lt;/td&gt;&lt;/tr&gt;
      &lt;/table&gt;&lt;/div&gt;
    &lt;/div&gt;

    &lt;div class="closing-task"&gt;
      &lt;div class="lbl"&gt;Penutup Pembelajaran · Tugas Individu&lt;/div&gt;
      &lt;p style="margin:0;"&gt;&lt;strong&gt;Tulislah satu kesimpulan ringkas (5–7 kalimat) di buku catatan kalian masing-masing&lt;/strong&gt;, yang merangkum keseluruhan materi hari ini: cara kerja mesin pencari dan strategi pencariannya, fitur-fitur peramban, etika layanan komunikasi digital, cara kerja media kolaborasi daring, serta pentingnya netiket dan keamanan digital. Tulis dengan bahasa dan pemahaman kalian sendiri, bukan menyalin ulang materi.&lt;/p&gt;
    &lt;/div&gt;
  &lt;/section&gt;

  &lt;!-- ===================== KUIS INDIVIDU ===================== --&gt;
  &lt;section class="section" id="kuis"&gt;
    &lt;div class="section-tag"&gt;&lt;span class="num"&gt;09&lt;/span&gt; Evaluasi Individu&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Kuis Pilihan Ganda (25 Soal)&lt;/h2&gt;
    &lt;p&gt;Kerjakan seluruh soal berikut secara mandiri. Isi identitas kalian dengan benar — begitu tombol "Hitung &amp; Lihat Skor" ditekan, skor akan otomatis dihitung dan langsung terkirim ke guru.&lt;/p&gt;

    &lt;div class="quiz-panel"&gt;
      &lt;h3 class="sub-title"&gt;Identitas Peserta&lt;/h3&gt;
      &lt;p class="quiz-note"&gt;Pastikan No. Absen, Nama, dan Kelas diisi sesuai data sekolah agar skor tercatat dengan benar.&lt;/p&gt;
      &lt;div class="student-info"&gt;
        &lt;div class="field"&gt;&lt;label for="noAbsen"&gt;No. Absen&lt;/label&gt;&lt;input type="number" id="noAbsen" min="1" placeholder="mis. 12"&gt;&lt;/div&gt;
        &lt;div class="field"&gt;&lt;label for="nama"&gt;Nama Lengkap&lt;/label&gt;&lt;input type="text" id="nama" placeholder="Nama sesuai absensi"&gt;&lt;/div&gt;
        &lt;div class="field"&gt;&lt;label for="kelas"&gt;Kelas&lt;/label&gt;
          &lt;select id="kelas"&gt;
            &lt;option value=""&gt;-- Pilih Kelas --&lt;/option&gt;
            &lt;option value="X TB1"&gt;X TB1&lt;/option&gt;
            &lt;option value="X TB2"&gt;X TB2&lt;/option&gt;
            &lt;option value="X TO1"&gt;X TO1&lt;/option&gt;
            &lt;option value="X TO2"&gt;X TO2&lt;/option&gt;
            &lt;option value="X TJKT1"&gt;X TJKT1&lt;/option&gt;
            &lt;option value="X TJKT2"&gt;X TJKT2&lt;/option&gt;
          &lt;/select&gt;
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;h3 class="sub-title"&gt;Soal&lt;/h3&gt;
      &lt;div id="quizContainer"&gt;&lt;/div&gt;

      &lt;div class="quiz-actions"&gt;
        &lt;button id="btnHitung"&gt;Hitung &amp; Lihat Skor&lt;/button&gt;
        &lt;button id="btnKirim"&gt;Kirim Ulang ke Guru&lt;/button&gt;
        &lt;span id="quizMsg"&gt;&lt;/span&gt;
      &lt;/div&gt;

      &lt;div class="result-panel" id="resultPanel"&gt;
        &lt;div class="score-lbl"&gt;Skor Kamu&lt;/div&gt;
        &lt;div class="score" id="scoreValue"&gt;0&lt;/div&gt;
        &lt;p id="resultDetail"&gt;&lt;/p&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/section&gt;

&lt;/main&gt;

&lt;footer&gt;
  INFORMATIKA · PENCARIAN INFORMASI DIGITAL &amp; KOLABORASI DARING · FASE E KELAS X SMK
&lt;/footer&gt;
&lt;/div&gt;

&lt;script&gt;
  // ============================================================
  // KONFIGURASI PENGIRIMAN SKOR KE GOOGLE SHEETS
  // ------------------------------------------------------------
  // Terhubung ke Google Apps Script Web App yang sudah di-deploy.
  // Kolom yang dikirim: no absen, nama, kelas, skor, judul materi.
  // Pastikan skrip doPost() di Apps Script sudah diperbarui agar
  // menerima 5 kolom tersebut (lihat instruksi terpisah).
  // ============================================================
  const GAS_ENDPOINT = "https://script.google.com/macros/s/AKfycbwKp7DrBTALJMlw8crjK7RgXIO8LVcU4yVEd9WJNs_vgSXkVxfw7fwkGbOT2IBNOjg3uQ/exec";
  const JUDUL_MATERI = "Pencarian Informasi Digital dan Kolaborasi Daring";

  const QUESTIONS = [
    { q: "Program/layanan yang berfungsi mencari informasi di internet berdasarkan kata kunci yang dimasukkan pengguna disebut...",
      opts: ["Peramban", "Mesin pencari", "Server", "Cloud storage", "Protokol"], correct: 1 },
    { q: "Proses mesin pencari menjelajahi dan mengumpulkan halaman-halaman web di internet disebut...",
      opts: ["Indexing", "Ranking", "Crawling", "Caching", "Rendering"], correct: 2 },
    { q: "Untuk mencari frasa yang harus muncul persis sama di hasil pencarian, kita dapat menggunakan operator pencarian berupa...",
      opts: ["Tanda minus (-)", "Tanda kutip (\" \")", "Tanda bintang (*)", "site:", "filetype:"], correct: 1 },
    { q: "Operator pencarian \"site:\" digunakan untuk...",
      opts: ["Mencari file dengan format tertentu", "Mengecualikan kata tertentu dari hasil pencarian", "Membatasi hasil pencarian hanya dari satu situs tertentu", "Mencari sinonim kata", "Menyorot kata kunci"], correct: 2 },
    { q: "Ketika mengevaluasi kredibilitas sebuah sumber informasi di internet, hal yang paling penting diperiksa adalah...",
      opts: ["Warna tampilan situs", "Penulis, sumber, dan waktu publikasi", "Jumlah iklan di halaman", "Panjang artikel", "Jumlah gambar dalam artikel"], correct: 1 },
    { q: "Perangkat lunak yang digunakan untuk mengakses dan menampilkan halaman web disebut...",
      opts: ["Mesin pencari", "Peramban (browser)", "Server", "Router", "Sistem operasi"], correct: 1 },
    { q: "Fitur peramban yang memungkinkan pengguna membuka banyak halaman dalam satu jendela sekaligus disebut...",
      opts: ["Bookmark", "Riwayat (history)", "Tab", "Ekstensi", "Cache"], correct: 2 },
    { q: "Mode penjelajahan pada peramban yang tidak menyimpan riwayat, cookie, dan data formulir setelah jendela ditutup disebut...",
      opts: ["Mode offline", "Mode incognito/private browsing", "Mode hemat data", "Mode pengembang", "Mode baca"], correct: 1 },
    { q: "Fitur peramban yang digunakan untuk menyimpan alamat situs favorit agar mudah diakses kembali disebut...",
      opts: ["Cache", "Bookmark", "Cookie", "Plugin", "Riwayat"], correct: 1 },
    { q: "Layanan komunikasi digital yang paling umum digunakan untuk mengirim surat elektronik formal, misalnya melamar kerja, adalah...",
      opts: ["Instant messaging", "Video conference", "Email", "Forum diskusi", "Media sosial"], correct: 2 },
    { q: "Etika menulis email yang baik antara lain...",
      opts: ["Menggunakan subjek email yang jelas dan relevan", "Menulis tanpa salam pembuka maupun penutup", "Menggunakan huruf kapital semua agar terlihat tegas", "Mengirim email tanpa memeriksa ulang isi pesan", "Menuliskan emoji berlebihan di setiap kalimat"], correct: 0 },
    { q: "Layanan yang memungkinkan pengguna melakukan pertemuan tatap muka secara daring melalui audio dan video disebut...",
      opts: ["Email", "Cloud storage", "Video conference", "Forum online", "Mesin pencari"], correct: 2 },
    { q: "Saat mengikuti video conference untuk keperluan sekolah, sikap yang tepat adalah...",
      opts: ["Mematikan mikrofon saat tidak berbicara agar tidak mengganggu", "Menyalakan mikrofon terus-menerus", "Bergabung tanpa memberi salam", "Mengabaikan instruksi moderator", "Membuka banyak aplikasi lain saat presentasi berlangsung"], correct: 0 },
    { q: "Layanan yang memungkinkan beberapa orang menyunting satu dokumen secara bersamaan dan real-time melalui internet disebut...",
      opts: ["Aplikasi pengolah kata offline", "Media kolaborasi daring, mis. Google Docs", "Peramban", "Mesin pencari", "Antivirus"], correct: 1 },
    { q: "Pada Google Docs, pengaturan akses \"Editor\" berarti pengguna yang diberi akses dapat...",
      opts: ["Hanya melihat dokumen", "Melihat dan memberi komentar saja", "Melihat, mengedit, dan mengubah isi dokumen", "Hanya mengunduh dokumen", "Menghapus akun pemilik dokumen"], correct: 2 },
    { q: "Salah satu manfaat utama media kolaborasi daring dalam kerja kelompok adalah...",
      opts: ["Mengharuskan semua anggota bertemu di tempat yang sama", "Memungkinkan anggota kelompok bekerja bersama tanpa harus bertemu langsung", "Menghilangkan kebutuhan untuk berdiskusi", "Membatasi jumlah anggota yang dapat mengakses dokumen", "Hanya dapat digunakan oleh satu orang dalam satu waktu"], correct: 1 },
    { q: "Fitur pada Google Docs yang memungkinkan pengguna melihat dan mengembalikan perubahan dokumen dari waktu ke waktu disebut...",
      opts: ["Version history/riwayat versi", "Mode incognito", "Bookmark", "Cache", "Filter pencarian"], correct: 0 },
    { q: "Etika berinternet yang baik, atau sering disebut \"netiket\", antara lain...",
      opts: ["Menyebarkan informasi tanpa memeriksa kebenarannya", "Berkomentar dengan sopan dan menghargai pendapat orang lain", "Menyalin karya orang lain tanpa mencantumkan sumber", "Membagikan data pribadi orang lain tanpa izin", "Mengirim pesan berantai tanpa verifikasi"], correct: 1 },
    { q: "Berita atau informasi yang sengaja dibuat menyesatkan dan tidak berdasarkan fakta disebut...",
      opts: ["Opini", "Hoaks", "Editorial", "Testimoni", "Riset ilmiah"], correct: 1 },
    { q: "Langkah paling tepat untuk memverifikasi kebenaran sebuah informasi yang beredar di internet adalah...",
      opts: ["Langsung membagikannya jika judulnya menarik", "Membandingkan dengan beberapa sumber terpercaya lain", "Mempercayainya karena dibagikan banyak orang", "Mengabaikan tanggal publikasinya", "Hanya membaca judul tanpa membaca isi berita"], correct: 1 },
    { q: "Tindakan yang sebaiknya dihindari saat berkolaborasi menggunakan dokumen daring bersama adalah...",
      opts: ["Memberi komentar yang membangun", "Menghapus atau mengubah pekerjaan anggota lain tanpa izin", "Menyimpan dokumen secara berkala", "Membagi tugas dengan jelas", "Berdiskusi melalui kolom komentar"], correct: 1 },
    { q: "Untuk menjaga privasi saat membagikan dokumen daring, sebaiknya pengaturan berbagi (sharing) diatur agar...",
      opts: ["Semua orang di internet dapat mengedit tanpa batasan", "Hanya orang/kelompok yang dituju yang memiliki akses sesuai kebutuhan", "Tidak perlu diatur karena internet selalu aman", "Dibagikan ke sebanyak mungkin orang agar cepat selesai", "Selalu diberi akses sebagai Editor untuk siapa pun"], correct: 1 },
    { q: "Ciri email atau pesan phishing yang patut diwaspadai antara lain...",
      opts: ["Dikirim dari alamat resmi yang dikenal dan terverifikasi", "Meminta data pribadi/kata sandi secara mendesak melalui tautan mencurigakan", "Tidak menyertakan tautan apa pun", "Berisi informasi resmi dari sekolah yang telah diverifikasi", "Menggunakan bahasa formal dan tidak terburu-buru"], correct: 1 },
    { q: "Sikap yang tepat ketika menemukan konten SARA atau ujaran kebencian saat berselancar atau berkolaborasi daring adalah...",
      opts: ["Ikut menyebarkannya agar viral", "Membalasnya dengan komentar yang sama kasarnya", "Tidak menyebarkan, dan melaporkan konten tersebut sesuai mekanisme platform", "Mengabaikannya tanpa melakukan apa pun", "Mengunduh dan menyimpannya untuk koleksi pribadi"], correct: 2 },
    { q: "Manfaat menggunakan operator dan strategi pencarian yang tepat pada mesin pencari adalah...",
      opts: ["Memperlambat proses pencarian", "Menghasilkan informasi yang lebih relevan dan sesuai kebutuhan", "Menyembunyikan seluruh hasil pencarian", "Menghapus riwayat pencarian secara otomatis", "Membuat peramban berhenti berfungsi"], correct: 1 }
  ];

  const LETTERS = ["A","B","C","D","E"];
  const container = document.getElementById('quizContainer');

  QUESTIONS.forEach((item, qi) =&gt; {
    const card = document.createElement('div');
    card.className = 'q-card';
    const num = document.createElement('div');
    num.className = 'q-num';
    num.textContent = 'SOAL ' + (qi+1) + ' / ' + QUESTIONS.length;
    const text = document.createElement('div');
    text.className = 'q-text';
    text.textContent = (qi+1) + '. ' + item.q;
    const opts = document.createElement('div');
    opts.className = 'options';

    item.opts.forEach((optText, oi) =&gt; {
      const label = document.createElement('label');
      label.className = 'opt';
      const input = document.createElement('input');
      input.type = 'radio';
      input.name = 'q' + qi;
      input.value = oi;
      input.addEventListener('change', () =&gt; {
        opts.querySelectorAll('.opt').forEach(o =&gt; o.classList.remove('selected'));
        label.classList.add('selected');
      });
      const span = document.createElement('span');
      span.textContent = LETTERS[oi] + '. ' + optText;
      label.appendChild(input);
      label.appendChild(span);
      opts.appendChild(label);
    });

    card.appendChild(num);
    card.appendChild(text);
    card.appendChild(opts);
    container.appendChild(card);
  });

  let finalScore = null;

  document.getElementById('btnHitung').addEventListener('click', () =&gt; {
    const noAbsen = document.getElementById('noAbsen').value.trim();
    const nama = document.getElementById('nama').value.trim();
    const kelas = document.getElementById('kelas').value.trim();
    const msg = document.getElementById('quizMsg');

    if (!noAbsen || !nama || !kelas) {
      msg.textContent = 'Lengkapi No. Absen, Nama, dan Kelas terlebih dahulu.';
      return;
    }

    let answered = 0, correct = 0;
    QUESTIONS.forEach((item, qi) =&gt; {
      const picked = document.querySelector('input[name="q' + qi + '"]:checked');
      if (picked) {
        answered++;
        if (parseInt(picked.value) === item.correct) correct++;
      }
    });

    if (answered &lt; QUESTIONS.length) {
      msg.textContent = 'Masih ada ' + (QUESTIONS.length - answered) + ' soal yang belum dijawab.';
      return;
    }

    msg.textContent = '';
    finalScore = Math.round((correct / QUESTIONS.length) * 100);

    document.getElementById('scoreValue').textContent = finalScore;
    document.getElementById('resultDetail').textContent =
      'Jawaban benar: ' + correct + ' dari ' + QUESTIONS.length + ' soal. Skor sedang dikirim ke guru...';
    document.getElementById('resultPanel').style.display = 'block';

    kirimSkor(noAbsen, nama, kelas, finalScore);
  });

  function kirimSkor(noAbsen, nama, kelas, skor) {
    const msg = document.getElementById('quizMsg');
    const btnKirim = document.getElementById('btnKirim');
    const resultDetail = document.getElementById('resultDetail');

    if (GAS_ENDPOINT.indexOf('GANTI_DENGAN_URL_WEB_APP_ANDA') !== -1) {
      msg.textContent = 'Pengiriman belum aktif — guru perlu memasang URL Apps Script terlebih dahulu.';
      btnKirim.style.display = 'inline-block';
      return;
    }

    btnKirim.disabled = true;
    msg.textContent = 'Mengirim skor...';

    fetch(GAS_ENDPOINT, {
      method: 'POST',
      mode: 'no-cors',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ noAbsen: noAbsen, nama: nama, kelas: kelas, skor: skor, judulMateri: JUDUL_MATERI })
    }).then(() =&gt; {
      msg.textContent = 'Jawaban terkirim otomatis ke guru.';
      resultDetail.textContent = 'Jawaban benar: ' + Math.round(skor * QUESTIONS.length / 100) + ' dari ' + QUESTIONS.length + ' soal. Skor sudah terkirim ke guru.';
      btnKirim.style.display = 'none';
      btnKirim.disabled = false;
    }).catch(() =&gt; {
      msg.textContent = 'Gagal mengirim otomatis — klik "Kirim Ulang ke Guru", atau foto layar skor ini.';
      btnKirim.style.display = 'inline-block';
      btnKirim.disabled = false;
    });
  }

  document.getElementById('btnKirim').addEventListener('click', () =&gt; {
    const noAbsen = document.getElementById('noAbsen').value.trim();
    const nama = document.getElementById('nama').value.trim();
    const kelas = document.getElementById('kelas').value.trim();
    if (finalScore === null) return;
    kirimSkor(noAbsen, nama, kelas, finalScore);
  });
&lt;/script&gt;

&lt;/body&gt;
&lt;/html&gt;</description><link>http://kitab-investasi.blogspot.com/2026/09/pencarian-informasi-digital-kolaborasi.html</link><thr:total>0</thr:total><author>nof_rizal07@yahoo.co.id (abang_cool)</author></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-9000860041661554971.post-863962356719859888</guid><pubDate>Fri, 21 Aug 2026 02:35:33 +0000</pubDate><atom:updated>2026-08-21T09:35:33.055+07:00</atom:updated><title>Menyajikan Teks Prosedur &amp; Rangkuman Materi Petunjuk Kerja</title><description>&lt;style&gt;
@import url('https://fonts.googleapis.com/css2?family=Oswald:wght@400;500;600;700&amp;family=Source+Sans+3:wght@400;500;600;700&amp;family=IBM+Plex+Mono:wght@400;500;600&amp;display=swap');
.epb{
  --blueprint:#0F2A3D;
  --blueprint-deep:#0A1E2C;
  --panel:#4A2E12;
  --paper:#F3F0E6;
  --ink:#132029;
  --amber:#F5A623;
  --amber-deep:#C97F12;
  --mint:#6EC6CA;
  --line:rgba(234,242,245,0.16);
  --off-white:#EAF2F5;
  --muted:#9FB4C2;
}
.epb *{box-sizing:border-box;}
.epb{scroll-behavior:smooth; background:#0A1F2E;}
.epb{
  margin:0;
  position:relative;
  overflow:hidden;
  background:var(--blueprint);
  color:var(--off-white);
  font-family:'Source Sans 3',sans-serif;
  line-height:1.65;
  background-image:
    linear-gradient(var(--line) 1px, transparent 1px),
    linear-gradient(90deg, var(--line) 1px, transparent 1px);
  background-size: 34px 34px;
}
.epb h1, .epb h2, .epb h3, .epb h4{font-family:'Oswald',sans-serif; text-transform:uppercase; letter-spacing:0.02em; margin:0 0 0.5em;}
.epb .mono{font-family:'IBM Plex Mono',monospace;}
.epb a{color:var(--amber);}
.epb .crop{position:absolute; width:22px; height:22px; z-index:5; opacity:.55; pointer-events:none;}
.epb .crop::before, .epb .crop::after{content:"";position:absolute;background:var(--mint);}
.epb .crop::before{width:100%;height:1px;top:50%;left:0;}
.epb .crop::after{width:1px;height:100%;left:50%;top:0;}
.epb .crop.tl{top:14px;left:14px;}
.epb .crop.tr{top:14px;right:14px;}
.epb .crop.bl{bottom:14px;left:14px;}
.epb .crop.br{bottom:14px;right:14px;}
.epb header.cover{
  position:relative;
  padding:40px 24px 36px;
  border-bottom:1px solid var(--line);
  overflow:hidden;
}
.epb .doc-code{font-family:'IBM Plex Mono',monospace; color:var(--amber); letter-spacing:0.15em; font-size:0.78rem; text-transform:uppercase; margin-bottom:18px; display:flex; gap:10px; align-items:center;}
.epb .doc-code::before{content:"◆"; color:var(--amber);}
.epb .cover h1{font-size:clamp(1.6rem,7vw,2.5rem); color:var(--off-white); max-width:16ch; line-height:1.05;}
.epb .cover .subtitle{color:var(--muted); font-size:1.05rem; max-width:60ch; margin-top:14px;}
.epb .meta-strip{
  margin-top:38px; display:grid; grid-template-columns:repeat(auto-fit,minmax(150px,1fr));
  border-top:1px dashed var(--line); border-bottom:1px dashed var(--line);
}
.epb .meta-strip div{padding:14px 16px; border-right:1px dashed var(--line);}
.epb .meta-strip div:last-child{border-right:none;}
.epb .meta-strip .k{font-family:'IBM Plex Mono',monospace; font-size:0.68rem; color:var(--amber); text-transform:uppercase; letter-spacing:0.1em;}
.epb .meta-strip .v{font-size:0.98rem; color:var(--off-white); margin-top:4px; font-weight:600;}
.epb .stamp{
  position:absolute; top:40px; right:20px; width:104px; height:104px;
  border:2.5px solid var(--amber); border-radius:50%;
  display:flex; align-items:center; justify-content:center;
  transform:rotate(-11deg);
  color:var(--amber); font-family:'IBM Plex Mono',monospace;
  text-align:center; font-size:0.62rem; letter-spacing:0.08em; text-transform:uppercase;
  opacity:0.9;
}
.epb .stamp .ring{position:absolute; inset:8px; border:1px dashed var(--amber); border-radius:50%;}
.epb .stamp b{display:block; font-family:'Oswald',sans-serif; font-size:1.05rem; letter-spacing:0.06em; margin-top:4px;}

@media (max-width:760px){.epb .stamp{display:none;}
.epb }


.epb main{max-width:920px; margin:0 auto; padding:0 20px 60px;}
.epb .section{padding-top:64px;}
.epb .eyebrow{font-family:'IBM Plex Mono',monospace; color:var(--amber); font-size:0.78rem; letter-spacing:0.14em; text-transform:uppercase; margin-bottom:10px; display:flex; align-items:center; gap:10px;}
.epb .eyebrow::after{content:""; flex:1; height:1px; background:var(--line);}
.epb h2.section-title{font-size:1.7rem; color:var(--off-white);}
.epb p{color:#DDE7EC;}
.epb .lead{color:var(--muted); font-size:1.02rem; max-width:72ch;}
.epb .panel{
  background:var(--panel); border:1px solid var(--line); border-radius:2px;
  padding:26px 28px; margin:22px 0;
}
.epb .panel.tp{border-left:4px solid var(--mint);}
.epb .panel.warn{border-left:4px solid var(--amber);}
.epb .tp-box{display:grid; gap:14px; margin-top:18px;}
.epb .tp-item{display:flex; gap:14px; align-items:flex-start;}
.epb .tp-item .idx{font-family:'IBM Plex Mono',monospace; color:var(--amber); font-weight:600; min-width:34px;}
.epb .flow{display:grid; grid-template-columns:repeat(auto-fit,minmax(220px,1fr)); gap:14px; margin-top:20px;}
.epb .flow .step{background:var(--blueprint-deep); border:1px solid var(--line); padding:18px; position:relative;}
.epb .flow .step .tag{font-family:'IBM Plex Mono',monospace; color:var(--amber); font-size:0.7rem; letter-spacing:0.1em; text-transform:uppercase;}
.epb .flow .step h4{font-size:1rem; margin-top:8px; color:var(--off-white);}
.epb .flow .step .time{position:absolute; top:16px; right:16px; font-family:'IBM Plex Mono',monospace; font-size:0.7rem; color:var(--amber);}
.epb .grid-3{display:grid; grid-template-columns:repeat(auto-fit,minmax(200px,1fr)); gap:14px; margin-top:16px;}
.epb .card{background:var(--blueprint-deep); border:1px solid var(--line); padding:18px;}
.epb .card h4{color:var(--amber); font-size:0.95rem;}
.epb .criteria{display:grid; gap:16px; margin-top:20px;}
.epb .crit{
  background:var(--blueprint-deep); border:1px solid var(--line);
  display:grid; grid-template-columns:64px 1fr; gap:0;
}
.epb .crit .num{
  background:var(--amber); color:var(--blueprint-deep); font-family:'IBM Plex Mono',monospace;
  font-weight:700; display:flex; align-items:center; justify-content:center; font-size:1.05rem;
}
.epb .crit .body{padding:18px 20px;}
.epb .crit h4{color:var(--off-white); font-size:1.02rem; margin-bottom:6px;}
.epb .crit .q{margin-top:10px; padding-top:10px; border-top:1px dashed var(--line); font-family:'IBM Plex Mono',monospace; font-size:0.86rem; color:var(--amber);}
.epb .timeline{margin-top:24px; position:relative; padding-left:34px;}
.epb .timeline::before{content:""; position:absolute; left:11px; top:6px; bottom:6px; width:2px; background:var(--line);}
.epb .tl-item{position:relative; padding-bottom:26px;}
.epb .tl-item:last-child{padding-bottom:0;}
.epb .tl-item::before{content:""; position:absolute; left:-34px; top:2px; width:22px; height:22px; border-radius:50%; background:var(--blueprint); border:2px solid var(--amber);}
.epb .tl-item h4{color:var(--off-white); font-size:1rem; margin-bottom:4px;}
.epb .doc-sample{
  background:var(--paper); color:var(--ink); border-radius:2px; padding:0; margin-top:22px;
  box-shadow:0 20px 45px rgba(0,0,0,0.35);
}
.epb .doc-sample .doc-head{background:var(--ink); color:var(--paper); padding:12px 22px; font-family:'IBM Plex Mono',monospace; font-size:0.75rem; letter-spacing:0.1em; text-transform:uppercase; display:flex; justify-content:space-between;}
.epb .doc-sample .doc-body{padding:26px 28px 30px;}
.epb .doc-sample h3{font-family:'Oswald',sans-serif; color:var(--ink); font-size:1.25rem; text-transform:none; letter-spacing:0;}
.epb .doc-sample ol{padding-left:22px;}
.epb .doc-sample li{margin-bottom:9px;}
.epb .flag{
  display:inline-block; font-family:'IBM Plex Mono',monospace; font-size:0.7rem; font-weight:600;
  background:#D94E2A; color:#fff; padding:1px 7px; border-radius:2px; margin-left:6px; vertical-align:middle;
}
.epb .doc-sample .note-margin{margin-top:6px; font-family:'IBM Plex Mono',monospace; font-size:0.78rem; color:#8A3A1F; padding-left:8px; border-left:2px solid #D94E2A;}
.epb .legend{display:flex; flex-wrap:wrap; gap:10px 20px; margin-top:16px;}
.epb .legend span{font-family:'IBM Plex Mono',monospace; font-size:0.78rem; color:var(--muted); display:flex; align-items:center; gap:8px;}
.epb .legend .dot{width:10px; height:10px; border-radius:50%; display:inline-block;}
.epb table{width:100%; border-collapse:collapse; margin-top:18px; font-size:0.94rem;}
.epb th, .epb td{border:1px solid var(--line); padding:10px 12px; text-align:left; vertical-align:top;}
.epb th{background:var(--blueprint-deep); font-family:'IBM Plex Mono',monospace; font-size:0.75rem; text-transform:uppercase; letter-spacing:0.06em; color:var(--amber);}
.epb .summary-box{
  border:1px solid var(--amber); background:linear-gradient(180deg, rgba(245,166,35,0.08), transparent);
  padding:24px 26px; margin-top:24px;
}
.epb .summary-box ul{margin:10px 0 0; padding-left:20px;}
.epb .summary-box li{margin-bottom:8px;}
.epb .task-header{
  background:var(--amber); color:var(--blueprint-deep); padding:22px 26px; margin-top:20px;
  display:flex; justify-content:space-between; align-items:center; flex-wrap:wrap; gap:10px;
}
.epb .task-header h2{color:var(--blueprint-deep); font-size:1.4rem; margin:0;}
.epb .task-header .badge{font-family:'IBM Plex Mono',monospace; font-size:0.8rem; background:var(--blueprint-deep); color:var(--amber); padding:6px 12px; border-radius:2px;}
.epb .steps-num{counter-reset:step; margin-top:18px; list-style:none; padding:0;}
.epb .steps-num li{counter-increment:step; position:relative; padding-left:44px; margin-bottom:16px;}
.epb .steps-num li::before{content:counter(step,decimal-leading-zero); position:absolute; left:0; top:0; font-family:'IBM Plex Mono',monospace; color:var(--amber); font-weight:600; font-size:0.95rem; border:1px solid var(--amber); width:30px; height:26px; display:flex; align-items:center; justify-content:center;}
.epb .rubric-scale{display:grid; grid-template-columns:repeat(4,1fr); gap:10px; margin-top:16px;}
.epb .rubric-scale div{background:var(--blueprint-deep); border:1px solid var(--line); padding:12px; text-align:center;}
.epb .rubric-scale .n{font-family:'IBM Plex Mono',monospace; color:var(--amber); font-size:1.3rem; font-weight:700;}
.epb .rubric-scale .l{font-size:0.78rem; color:var(--muted); text-transform:uppercase; letter-spacing:0.05em;}
.epb .notebook{
  background:repeating-linear-gradient(var(--paper), var(--paper) 33px, #D8D3C2 34px);
  color:var(--ink); border-radius:2px; padding:28px 30px; margin-top:20px; position:relative;
  box-shadow:0 20px 45px rgba(0,0,0,0.35);
}
.epb .notebook::before{content:""; position:absolute; left:46px; top:0; bottom:0; width:1.5px; background:#C0453A; opacity:0.5;}
.epb .notebook .content{padding-left:24px;}
.epb .notebook h3{color:var(--ink); font-family:'Oswald',sans-serif; letter-spacing:0.02em; margin-bottom:10px;}
.epb .notebook ul{padding-left:20px;}
.epb footer{border-top:1px solid var(--line); padding:24px 20px 40px; color:var(--muted); font-size:0.86rem;}
.epb footer .doc-code{margin-bottom:10px;}
.epb .divider-dash{border:none; border-top:1px dashed var(--line); margin:44px 0 0;}
.epb::selection{background:var(--amber); color:var(--blueprint-deep);}

&lt;/style&gt;
&lt;div class="epb"&gt;
&lt;div class="crop tl"&gt;&lt;/div&gt;&lt;div class="crop tr"&gt;&lt;/div&gt;&lt;div class="crop bl"&gt;&lt;/div&gt;&lt;div class="crop br"&gt;&lt;/div&gt;

&lt;header class="cover"&gt;
  &lt;div class="stamp"&gt;&lt;div class="ring"&gt;&lt;/div&gt;&lt;span&gt;Modul Ajar&lt;b&gt;Terverifikasi&lt;/b&gt;Fase F&lt;/span&gt;&lt;/div&gt;
  &lt;div class="doc-code"&gt;DOK/B.INDO/XI/PROSEDUR-SAJIKAN — 3 JP · 1 Pertemuan&lt;/div&gt;
  &lt;h1&gt;Menyajikan Teks Prosedur &amp;amp; Rangkuman Materi Petunjuk Kerja&lt;/h1&gt;
  &lt;p class="subtitle"&gt;Materi Bahasa Indonesia Kelas XI SMK/MAK — melatih murid menyajikan teks prosedur secara lisan/tulisan sekaligus mereview seluruh materi pokok bahasan Petunjuk Kerja.&lt;/p&gt;

  &lt;div class="meta-strip"&gt;
    &lt;div&gt;&lt;div class="k"&gt;Mata Pelajaran&lt;/div&gt;&lt;div class="v"&gt;Bahasa Indonesia&lt;/div&gt;&lt;/div&gt;
    &lt;div&gt;&lt;div class="k"&gt;Jenjang&lt;/div&gt;&lt;div class="v"&gt;SMK/MAK — Kelas XI&lt;/div&gt;&lt;/div&gt;
    &lt;div&gt;&lt;div class="k"&gt;Elemen&lt;/div&gt;&lt;div class="v"&gt;Berbicara, Menulis &amp;amp; Memirsa&lt;/div&gt;&lt;/div&gt;
    &lt;div&gt;&lt;div class="k"&gt;Alokasi Waktu&lt;/div&gt;&lt;div class="v"&gt;3 JP (3 × 45 menit)&lt;/div&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/header&gt;

&lt;main&gt;

  &lt;!-- ============ TUJUAN PEMBELAJARAN ============ --&gt;
  &lt;section class="section" id="tujuan"&gt;
    &lt;div class="eyebrow"&gt;01 — Identitas Pembelajaran&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Capaian &amp;amp; Tujuan Pembelajaran&lt;/h2&gt;

    &lt;div class="panel tp"&gt;
      &lt;div class="eyebrow" style="margin-bottom:6px;"&gt;Capaian Pembelajaran (Elemen Berbicara, Menulis &amp;amp; Memirsa)&lt;/div&gt;
      &lt;p&gt;Murid mampu menyajikan gagasan dan hasil karya berupa teks prosedur secara lisan maupun tulisan dengan struktur dan kaidah kebahasaan yang tepat, serta mampu mereview pemahamannya terhadap materi yang telah dipelajari.&lt;/p&gt;
    &lt;/div&gt;

    &lt;div class="panel"&gt;
      &lt;div class="eyebrow" style="margin-bottom:6px;"&gt;Tujuan Pembelajaran&lt;/div&gt;
      &lt;p style="font-size:1.05rem; color:var(--off-white); font-weight:600;"&gt;Murid mampu menyajikan teks prosedur yang telah dibuat secara lisan/tulisan dan mereview seluruh materi pokok bahasan petunjuk kerja.&lt;/p&gt;

      &lt;div class="tp-box"&gt;
        &lt;div class="tp-item"&gt;&lt;span class="idx mono"&gt;TP.1&lt;/span&gt;&lt;p&gt;Murid dapat menyajikan teks prosedur secara lisan dengan intonasi, artikulasi, dan sikap yang tepat.&lt;/p&gt;&lt;/div&gt;
        &lt;div class="tp-item"&gt;&lt;span class="idx mono"&gt;TP.2&lt;/span&gt;&lt;p&gt;Murid dapat menyajikan teks prosedur secara tulisan dengan struktur dan kaidah kebahasaan yang benar.&lt;/p&gt;&lt;/div&gt;
        &lt;div class="tp-item"&gt;&lt;span class="idx mono"&gt;TP.3&lt;/span&gt;&lt;p&gt;Murid dapat mereview kembali materi evaluasi informasi, perbandingan teks, dan kaidah kebahasaan teks prosedur.&lt;/p&gt;&lt;/div&gt;
        &lt;div class="tp-item"&gt;&lt;span class="idx mono"&gt;TP.4&lt;/span&gt;&lt;p&gt;Murid dapat menjawab pertanyaan reviu materi pokok bahasan petunjuk kerja secara mandiri.&lt;/p&gt;&lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;

    &lt;div class="eyebrow" style="margin-top:26px; margin-bottom:6px;"&gt;8 Profil Lulusan yang Dikembangkan&lt;/div&gt;
    &lt;div class="grid-3"&gt;
      &lt;div class="card"&gt;&lt;h4&gt;Komunikasi&lt;/h4&gt;&lt;p style="font-size:0.9rem;"&gt;Menyajikan teks prosedur secara lisan dan tulisan dengan jelas.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;h4&gt;Kemandirian&lt;/h4&gt;&lt;p style="font-size:0.9rem;"&gt;Mengerjakan reviu materi secara mandiri.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;h4&gt;Kolaborasi&lt;/h4&gt;&lt;p style="font-size:0.9rem;"&gt;Bekerja sama menyiapkan dan menyajikan teks prosedur kelompok.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;h4&gt;Penalaran Kritis&lt;/h4&gt;&lt;p style="font-size:0.9rem;"&gt;Mereview dan menghubungkan seluruh materi yang telah dipelajari.&lt;/p&gt;&lt;/div&gt;
    &lt;/div&gt;
  &lt;/section&gt;

  &lt;hr class="divider-dash"&gt;

  &lt;!-- ============ MATERI A: RECAP SELURUH UNIT ============ --&gt;
  &lt;section class="section" id="materi-a"&gt;
    &lt;div class="eyebrow"&gt;02 — Materi Inti A&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Mengingat Kembali Materi Pokok Bahasan "Petunjuk Kerja"&lt;/h2&gt;
    &lt;p class="lead"&gt;Sebelum menyajikan teks prosedur, mari mengingat kembali seluruh materi yang telah dipelajari pada pokok bahasan Petunjuk Kerja.&lt;/p&gt;

    &lt;div class="timeline"&gt;
      &lt;div class="tl-item"&gt;&lt;h4 class="mono"&gt;01 · Evaluasi Informasi dalam Teks Prosedur&lt;/h4&gt;&lt;p&gt;Menilai keakuratan, kelengkapan, kelogisan urutan, kejelasan bahasa, kesesuaian tujuan, dan keselamatan sebuah teks prosedur.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="tl-item"&gt;&lt;h4 class="mono"&gt;02 · Membandingkan Teks Prosedur dengan Teks Lain&lt;/h4&gt;&lt;p&gt;Menemukan persamaan dan perbedaan teks prosedur dengan teks eksplanasi berdasarkan tujuan, struktur, dan kebahasaan.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="tl-item"&gt;&lt;h4 class="mono"&gt;03 · Kaidah Kebahasaan Teks Prosedur (Bagian 1)&lt;/h4&gt;&lt;p&gt;Mengidentifikasi kalimat imperatif, deklaratif, persuasif, dan konjungsi temporal.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="tl-item"&gt;&lt;h4 class="mono"&gt;04 · Kaidah Kebahasaan (Bagian 2) &amp;amp; Menyusun Teks Prosedur&lt;/h4&gt;&lt;p&gt;Menganalisis kalimat perintah, kata teknis, penanda wacana, serta menyusun teks prosedur baru.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="tl-item"&gt;&lt;h4 class="mono"&gt;05 · Menyajikan Teks Prosedur (Materi Hari Ini)&lt;/h4&gt;&lt;p&gt;Menyajikan teks prosedur yang telah disusun secara lisan maupun tulisan kepada audiens.&lt;/p&gt;&lt;/div&gt;
    &lt;/div&gt;
  &lt;/section&gt;

  &lt;hr class="divider-dash"&gt;

  &lt;!-- ============ MATERI B: MENYAJIKAN LISAN ============ --&gt;
  &lt;section class="section" id="materi-b"&gt;
    &lt;div class="eyebrow"&gt;03 — Materi Inti B&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Menyajikan Teks Prosedur secara Lisan&lt;/h2&gt;
    &lt;p class="lead"&gt;Menyajikan teks prosedur secara lisan berarti menyampaikan langkah-langkah tersebut secara langsung di hadapan pendengar.&lt;/p&gt;

    &lt;div class="grid-3"&gt;
      &lt;div class="card"&gt;&lt;h4&gt;Intonasi&lt;/h4&gt;&lt;p style="font-size:0.9rem;"&gt;Naik-turunnya nada suara untuk menekankan bagian penting.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;h4&gt;Artikulasi&lt;/h4&gt;&lt;p style="font-size:0.9rem;"&gt;Kejelasan pelafalan setiap kata agar mudah dipahami pendengar.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;h4&gt;Sikap &amp;amp; Kepercayaan Diri&lt;/h4&gt;&lt;p style="font-size:0.9rem;"&gt;Berdiri tegak, tenang, dan yakin saat menyajikan.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;h4&gt;Kontak Mata&lt;/h4&gt;&lt;p style="font-size:0.9rem;"&gt;Memandang audiens secara merata, tidak hanya membaca naskah.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;h4&gt;Kecepatan Bicara&lt;/h4&gt;&lt;p style="font-size:0.9rem;"&gt;Tidak terlalu cepat maupun terlalu lambat.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;h4&gt;Bahasa Tubuh&lt;/h4&gt;&lt;p style="font-size:0.9rem;"&gt;Gestur yang mendukung penjelasan, bukan mengganggu.&lt;/p&gt;&lt;/div&gt;
    &lt;/div&gt;
  &lt;/section&gt;

  &lt;hr class="divider-dash"&gt;

  &lt;!-- ============ MATERI C: MENYAJIKAN TULISAN ============ --&gt;
  &lt;section class="section" id="materi-c"&gt;
    &lt;div class="eyebrow"&gt;04 — Materi Inti C&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Menyajikan Teks Prosedur secara Tulisan&lt;/h2&gt;
    &lt;p class="lead"&gt;Menyajikan teks prosedur secara tulisan berarti menuangkan langkah-langkah dalam bentuk teks yang dapat dibaca, seperti artikel, poster, atau infografis.&lt;/p&gt;

    &lt;div class="grid-3"&gt;
      &lt;div class="card"&gt;&lt;h4&gt;Kerapian Struktur&lt;/h4&gt;&lt;p style="font-size:0.9rem;"&gt;Tujuan, alat/bahan, dan langkah tersusun jelas dan berurutan.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;h4&gt;Ejaan &amp;amp; Tanda Baca&lt;/h4&gt;&lt;p style="font-size:0.9rem;"&gt;Penulisan sesuai kaidah bahasa Indonesia yang baku.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;h4&gt;Kejelasan Langkah&lt;/h4&gt;&lt;p style="font-size:0.9rem;"&gt;Setiap langkah ditulis ringkas namun tidak ambigu.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;h4&gt;Media Visual Pendukung&lt;/h4&gt;&lt;p style="font-size:0.9rem;"&gt;Dapat disertai gambar, diagram, atau foto agar lebih mudah dipahami.&lt;/p&gt;&lt;/div&gt;
    &lt;/div&gt;
  &lt;/section&gt;

  &lt;hr class="divider-dash"&gt;

  &lt;!-- ============ MATERI D: PERBEDAAN LISAN &amp; TULISAN ============ --&gt;
  &lt;section class="section" id="materi-d"&gt;
    &lt;div class="eyebrow"&gt;05 — Materi Inti D&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Perbedaan Menyajikan secara Lisan dan Tulisan&lt;/h2&gt;

    &lt;table&gt;
      &lt;tr&gt;&lt;th style="width:22%;"&gt;Aspek&lt;/th&gt;&lt;th&gt;Penyajian Lisan&lt;/th&gt;&lt;th&gt;Penyajian Tulisan&lt;/th&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Media&lt;/td&gt;&lt;td&gt;Suara dan bahasa tubuh&lt;/td&gt;&lt;td&gt;Teks dan visual pendukung&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Kelebihan&lt;/td&gt;&lt;td&gt;Interaktif, bisa tanya jawab langsung&lt;/td&gt;&lt;td&gt;Dapat dibaca ulang dan disimpan lama&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Kekurangan&lt;/td&gt;&lt;td&gt;Sulit diulang, bergantung pada memori pembicara&lt;/td&gt;&lt;td&gt;Tidak ada interaksi langsung dengan audiens&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Penilaian Utama&lt;/td&gt;&lt;td&gt;Intonasi, artikulasi, sikap, kontak mata&lt;/td&gt;&lt;td&gt;Struktur, ejaan, kejelasan langkah&lt;/td&gt;&lt;/tr&gt;
    &lt;/table&gt;
  &lt;/section&gt;

  &lt;hr class="divider-dash"&gt;

  &lt;!-- ============ MATERI E: LANGKAH MENYAJIKAN ============ --&gt;
  &lt;section class="section" id="materi-e"&gt;
    &lt;div class="eyebrow"&gt;06 — Materi Inti E&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Langkah-Langkah Menyajikan Teks Prosedur&lt;/h2&gt;

    &lt;div class="timeline"&gt;
      &lt;div class="tl-item"&gt;&lt;h4 class="mono"&gt;01 · Memahami Isi Teks&lt;/h4&gt;&lt;p&gt;Membaca ulang teks prosedur yang akan disajikan agar benar-benar dipahami.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="tl-item"&gt;&lt;h4 class="mono"&gt;02 · Menyiapkan Media Bantu&lt;/h4&gt;&lt;p&gt;Menyiapkan alat peraga, gambar, atau catatan poin penting bila diperlukan.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="tl-item"&gt;&lt;h4 class="mono"&gt;03 · Berlatih Menyajikan&lt;/h4&gt;&lt;p&gt;Berlatih menyampaikan secara lisan dengan intonasi dan kecepatan yang tepat.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="tl-item"&gt;&lt;h4 class="mono"&gt;04 · Menyajikan di Depan Audiens&lt;/h4&gt;&lt;p&gt;Menyampaikan teks prosedur dengan percaya diri, jelas, dan runtut.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="tl-item"&gt;&lt;h4 class="mono"&gt;05 · Menerima Umpan Balik&lt;/h4&gt;&lt;p&gt;Menerima masukan dari pendengar untuk perbaikan penyajian berikutnya.&lt;/p&gt;&lt;/div&gt;
    &lt;/div&gt;
  &lt;/section&gt;

  &lt;hr class="divider-dash"&gt;

  &lt;!-- ============ MATERI F: TABEL RANGKUMAN SELURUH UNIT ============ --&gt;
  &lt;section class="section" id="materi-f"&gt;
    &lt;div class="eyebrow"&gt;07 — Materi Inti F&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Rangkuman Seluruh Materi Pokok Bahasan "Petunjuk Kerja"&lt;/h2&gt;

    &lt;table&gt;
      &lt;tr&gt;&lt;th style="width:26%;"&gt;Sub-Materi&lt;/th&gt;&lt;th&gt;Poin Kunci&lt;/th&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Evaluasi Informasi&lt;/td&gt;&lt;td&gt;6 kriteria: keakuratan, kelengkapan, kelogisan urutan, kejelasan bahasa, kesesuaian tujuan, keselamatan/kelayakan&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Membandingkan Teks&lt;/td&gt;&lt;td&gt;Teks prosedur mengarahkan tindakan; teks eksplanasi menjelaskan proses agar dipahami&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Kaidah Kebahasaan (1)&lt;/td&gt;&lt;td&gt;Kalimat imperatif, deklaratif, persuasif, dan konjungsi temporal&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Kaidah Kebahasaan (2) &amp;amp; Menyusun&lt;/td&gt;&lt;td&gt;Kalimat perintah, kata teknis, penanda wacana, dan 5 langkah menyusun teks prosedur&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Menyajikan Teks Prosedur&lt;/td&gt;&lt;td&gt;Penyajian lisan (intonasi, artikulasi, sikap) dan tulisan (struktur, ejaan, kejelasan)&lt;/td&gt;&lt;/tr&gt;
    &lt;/table&gt;
  &lt;/section&gt;

  &lt;hr class="divider-dash"&gt;

  &lt;!-- ============ PEMODELAN ============ --&gt;
  &lt;section class="section" id="contoh"&gt;
    &lt;div class="eyebrow"&gt;08 — Pemodelan&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Contoh Penerapan: Cuplikan Naskah Penyajian Lisan&lt;/h2&gt;
    &lt;p class="lead"&gt;Guru membacakan dan membahas bersama cuplikan berikut sebagai model penyajian sebelum murid berlatih dalam kelompok.&lt;/p&gt;

    &lt;div class="doc-sample"&gt;
      &lt;div class="doc-head"&gt;&lt;span&gt;Lampiran · Cuplikan Naskah Presentasi&lt;/span&gt;&lt;span&gt;Dokumen-01&lt;/span&gt;&lt;/div&gt;
      &lt;div class="doc-body"&gt;
        &lt;h3 style="color:#132029 !important;"&gt;Menyajikan Prosedur "Mengisi Daya Ponsel dengan Aman"&lt;/h3&gt;
        &lt;p style="margin:10px 0; color:#132029 !important;"&gt;&lt;i&gt;"Selamat pagi, teman-teman. Pada kesempatan ini, kelompok kami akan menyajikan teks prosedur berjudul 'Mengisi Daya Ponsel dengan Aman'."&lt;/i&gt; &lt;b&gt;(pembukaan — kontak mata ke seluruh audiens)&lt;/b&gt;&lt;/p&gt;
        &lt;p style="margin:10px 0; color:#132029 !important;"&gt;&lt;i&gt;"Tujuan dari prosedur ini adalah agar pengisian daya ponsel dilakukan dengan aman dan tidak merusak baterai."&lt;/i&gt; &lt;b&gt;(kalimat deklaratif — disampaikan dengan intonasi datar dan jelas)&lt;/b&gt;&lt;/p&gt;
        &lt;p style="margin:10px 0; color:#132029 !important;"&gt;&lt;i&gt;"Pertama, pastikan menggunakan kabel dan adaptor asli sesuai spesifikasi ponsel."&lt;/i&gt; &lt;b&gt;(kalimat perintah dengan konjungsi temporal — intonasi naik pada kata "pertama")&lt;/b&gt;&lt;/p&gt;
        &lt;p style="margin:10px 0 0; color:#132029 !important;"&gt;&lt;i&gt;"Dengan demikian, ponsel akan lebih awet dan aman digunakan dalam jangka panjang. Terima kasih atas perhatiannya."&lt;/i&gt; &lt;b&gt;(penutup — kecepatan bicara diperlambat, sikap tenang)&lt;/b&gt;&lt;/p&gt;
      &lt;/div&gt;
    &lt;/div&gt;

    &lt;div class="panel" style="margin-top:22px;"&gt;
      &lt;p style="margin:0;"&gt;&lt;b style="color:var(--off-white);"&gt;Simpulan model penyajian:&lt;/b&gt; Naskah di atas menunjukkan pembukaan yang jelas, penekanan intonasi pada kata kunci ("pertama", "dengan demikian"), serta penutup yang tenang dan sopan — semua ini mendukung penyampaian yang mudah dipahami audiens.&lt;/p&gt;
    &lt;/div&gt;
  &lt;/section&gt;

  &lt;hr class="divider-dash"&gt;

  &lt;!-- ============ RANGKUMAN ============ --&gt;
  &lt;section class="section" id="rangkuman"&gt;
    &lt;div class="eyebrow"&gt;09 — Ringkasan Materi&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Poin-Poin Penting&lt;/h2&gt;
    &lt;div class="summary-box"&gt;
      &lt;ul&gt;
        &lt;li&gt;Menyajikan teks prosedur secara lisan menekankan intonasi, artikulasi, sikap, kontak mata, kecepatan bicara, dan bahasa tubuh.&lt;/li&gt;
        &lt;li&gt;Menyajikan teks prosedur secara tulisan menekankan kerapian struktur, ejaan, kejelasan langkah, dan media visual pendukung.&lt;/li&gt;
        &lt;li&gt;Penyajian lisan bersifat interaktif namun sulit diulang, sedangkan penyajian tulisan dapat dibaca ulang namun tidak interaktif.&lt;/li&gt;
        &lt;li&gt;Seluruh materi pokok bahasan Petunjuk Kerja mencakup evaluasi informasi, perbandingan teks, kaidah kebahasaan, penyusunan, dan penyajian teks prosedur.&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/div&gt;
  &lt;/section&gt;

  &lt;hr class="divider-dash"&gt;

  &lt;!-- ============ TUGAS KELOMPOK ============ --&gt;
  &lt;section class="section" id="tugas-kelompok"&gt;
    &lt;div class="eyebrow"&gt;10 — Lembar Kerja&lt;/div&gt;
    &lt;div class="task-header"&gt;
      &lt;h2&gt;Tugas Kelompok: Menyajikan Teks Prosedur Hasil Karya Kelompok&lt;/h2&gt;
      &lt;span class="badge"&gt;Durasi ± 60 menit&lt;/span&gt;
    &lt;/div&gt;

    &lt;p style="margin-top:18px;"&gt;&lt;b style="color:var(--off-white);"&gt;Tujuan tugas:&lt;/b&gt; Murid secara berkelompok menyajikan teks prosedur yang telah disusun pada pertemuan sebelumnya secara lisan di depan kelas, dengan memperhatikan intonasi, artikulasi, dan sikap penyajian yang tepat.&lt;/p&gt;

    &lt;h4 style="color:var(--off-white); margin-top:24px;"&gt;Petunjuk Pengerjaan&lt;/h4&gt;
    &lt;ol class="steps-num"&gt;
      &lt;li&gt;&lt;b&gt;Berkumpul dalam kelompok&lt;/b&gt; yang sama seperti saat menyusun teks prosedur pada pertemuan sebelumnya.&lt;/li&gt;
      &lt;li&gt;&lt;b&gt;Baca ulang teks prosedur&lt;/b&gt; yang telah disusun kelompok, lalu tentukan pembagian bagian yang akan disampaikan tiap anggota.&lt;/li&gt;
      &lt;li&gt;&lt;b&gt;Siapkan media bantu&lt;/b&gt; sederhana jika diperlukan (poin penting, gambar, atau alat peraga).&lt;/li&gt;
      &lt;li&gt;&lt;b&gt;Berlatih menyajikan&lt;/b&gt; secara lisan dalam kelompok sebelum tampil di depan kelas.&lt;/li&gt;
      &lt;li&gt;&lt;b&gt;Sajikan teks prosedur&lt;/b&gt; di depan kelas selama maksimal 5 menit per kelompok, dilanjutkan umpan balik singkat dari guru dan kelompok lain.&lt;/li&gt;
    &lt;/ol&gt;

    &lt;h4 style="color:var(--off-white); margin-top:26px;"&gt;Lembar Persiapan Penyajian&lt;/h4&gt;
    &lt;table&gt;
      &lt;tr&gt;&lt;th style="width:26%;"&gt;Bagian&lt;/th&gt;&lt;th&gt;Catatan Persiapan Kelompok&lt;/th&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Judul Teks Prosedur&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Pembagian Penyaji&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Media Bantu yang Digunakan&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Bagian yang Perlu Ditekankan&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;/table&gt;

    &lt;h4 style="color:var(--off-white); margin-top:26px;"&gt;Rubrik Penilaian Presentasi Kelompok&lt;/h4&gt;
    &lt;table&gt;
      &lt;tr&gt;&lt;th style="width:22%;"&gt;Aspek Penilaian&lt;/th&gt;&lt;th&gt;Skor 4 (Sangat Baik)&lt;/th&gt;&lt;th&gt;Skor 3 (Baik)&lt;/th&gt;&lt;th&gt;Skor 2 (Cukup)&lt;/th&gt;&lt;th&gt;Skor 1 (Kurang)&lt;/th&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Intonasi &amp;amp; Artikulasi&lt;/td&gt;&lt;td&gt;Jelas, tepat, mudah dipahami&lt;/td&gt;&lt;td&gt;Jelas namun kurang bervariasi&lt;/td&gt;&lt;td&gt;Kurang jelas di beberapa bagian&lt;/td&gt;&lt;td&gt;Sulit dipahami&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Sikap &amp;amp; Kontak Mata&lt;/td&gt;&lt;td&gt;Percaya diri, kontak mata merata&lt;/td&gt;&lt;td&gt;Cukup percaya diri&lt;/td&gt;&lt;td&gt;Kurang percaya diri, jarang kontak mata&lt;/td&gt;&lt;td&gt;Gugup, tidak ada kontak mata&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Kejelasan Isi&lt;/td&gt;&lt;td&gt;Isi runtut dan mudah diikuti&lt;/td&gt;&lt;td&gt;Isi cukup runtut&lt;/td&gt;&lt;td&gt;Ada bagian yang membingungkan&lt;/td&gt;&lt;td&gt;Isi tidak runtut&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Kekompakan Kelompok&lt;/td&gt;&lt;td&gt;Seluruh anggota berperan aktif&lt;/td&gt;&lt;td&gt;Sebagian besar anggota aktif&lt;/td&gt;&lt;td&gt;Hanya sebagian kecil anggota aktif&lt;/td&gt;&lt;td&gt;Didominasi satu orang&lt;/td&gt;&lt;/tr&gt;
    &lt;/table&gt;
  &lt;/section&gt;

  &lt;hr class="divider-dash"&gt;

  &lt;!-- ============ TUGAS INDIVIDU: KUIS 25 PERTANYAAN ============ --&gt;
  &lt;section class="section" id="tugas-individu"&gt;
    &lt;div class="eyebrow"&gt;11 — Penutup Pembelajaran&lt;/div&gt;
    &lt;div class="task-header"&gt;
      &lt;h2&gt;Tugas Individu: Reviu 25 Pertanyaan Materi Petunjuk Kerja&lt;/h2&gt;
      &lt;span class="badge"&gt;Dikerjakan Mandiri · Otomatis Bernilai&lt;/span&gt;
    &lt;/div&gt;

    &lt;p style="margin-top:18px;"&gt;&lt;b style="color:var(--off-white);"&gt;Petunjuk:&lt;/b&gt; Isi No. Absen dan Nama, lalu jawab 25 pertanyaan pilihan ganda (5 opsi) berikut yang mereviu seluruh materi pokok bahasan Petunjuk Kerja — terdiri atas 10 soal tingkat mudah, 10 soal tingkat sedang, dan 5 soal tingkat sulit. Skor akan muncul otomatis dan hasilnya tercatat otomatis.&lt;/p&gt;

    &lt;div class="panel" id="epbq-form-wrap" style="margin-top:20px;"&gt;
      &lt;div style="display:grid; grid-template-columns:1fr 2fr; gap:14px; margin-bottom:22px;"&gt;
        &lt;div&gt;
          &lt;label class="mono" style="display:block; font-size:0.75rem; color:var(--amber); text-transform:uppercase; letter-spacing:0.08em; margin-bottom:6px;"&gt;No. Absen&lt;/label&gt;
          &lt;input id="epbq-absen" type="text" inputmode="numeric" placeholder="Contoh: 12" style="width:100%; padding:10px 12px; border-radius:2px; border:1px solid var(--line); background:var(--blueprint-deep); color:var(--off-white); font-family:'Source Sans 3',sans-serif; font-size:0.95rem;"&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;label class="mono" style="display:block; font-size:0.75rem; color:var(--amber); text-transform:uppercase; letter-spacing:0.08em; margin-bottom:6px;"&gt;Nama Lengkap&lt;/label&gt;
          &lt;input id="epbq-nama" type="text" placeholder="Tulis nama lengkap" style="width:100%; padding:10px 12px; border-radius:2px; border:1px solid var(--line); background:var(--blueprint-deep); color:var(--off-white); font-family:'Source Sans 3',sans-serif; font-size:0.95rem;"&gt;
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;div id="epbq-questions"&gt;&lt;/div&gt;

      &lt;div style="margin-top:24px; display:flex; align-items:center; gap:16px; flex-wrap:wrap;"&gt;
        &lt;button id="epbq-submit" type="button" style="background:var(--amber); color:var(--blueprint-deep); border:none; padding:12px 26px; font-family:'Oswald',sans-serif; text-transform:uppercase; letter-spacing:0.05em; font-weight:600; border-radius:2px; cursor:pointer; font-size:0.95rem;"&gt;Kirim Jawaban&lt;/button&gt;
        &lt;span id="epbq-status" class="mono" style="font-size:0.85rem; color:var(--muted);"&gt;&lt;/span&gt;
      &lt;/div&gt;

      &lt;div id="epbq-result" style="display:none; margin-top:20px; padding:18px 20px; border:1px solid var(--amber); background:rgba(245,166,35,0.08);"&gt;
        &lt;p style="margin:0; font-size:1.05rem;"&gt;Skor kamu: &lt;b id="epbq-score" style="color:var(--amber); font-size:1.3rem;"&gt;&lt;/b&gt; / 100&lt;/p&gt;
        &lt;p id="epbq-detail" style="margin:8px 0 0; font-size:0.9rem; color:var(--muted);"&gt;&lt;/p&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/section&gt;

&lt;script&gt;
(function(){
  var EPBQ_ENDPOINT = "https://script.google.com/macros/s/AKfycbzM7t2qgAENzxQJXzSYJYL28R6nb3TxJVELLL3CopyEXb51t_gRtrkPOxTpI5mq6VCEKw/exec";
  var EPBQ_MATERI = "Menyajikan Teks Prosedur &amp; Rangkuman Materi Petunjuk Kerja";

  var questions = [
    {lvl:"Mudah", q:"1. Apa tujuan utama teks prosedur?", opts:["Menghibur pembaca","Mengarahkan pembaca melakukan tindakan","Menceritakan pengalaman pribadi","Membujuk pembaca membeli barang","Menjelaskan pendapat penulis"], correct:1},
    {lvl:"Mudah", q:"2. Bagian struktur teks prosedur yang berisi hasil akhir/catatan tambahan disebut...", opts:["Tujuan","Alat dan bahan","Langkah-langkah","Penutup/hasil","Interpretasi"], correct:3},
    {lvl:"Mudah", q:"3. Kalimat yang berisi perintah kepada pembaca disebut kalimat...", opts:["Deklaratif","Interogatif","Imperatif","Persuasif","Naratif"], correct:2},
    {lvl:"Mudah", q:"4. Kata penghubung yang menandai urutan waktu disebut konjungsi...", opts:["Kausalitas","Temporal","Pertentangan","Pilihan","Penjumlahan"], correct:1},
    {lvl:"Mudah", q:"5. Teks yang menjelaskan proses terjadinya suatu fenomena berdasarkan sebab-akibat disebut teks...", opts:["Prosedur","Eksplanasi","Deskripsi","Narasi","Anekdot"], correct:1},
    {lvl:"Mudah", q:"6. Istilah khusus dalam bidang keahlian tertentu disebut...", opts:["Konjungsi","Kata teknis","Kata baku","Kata ganti","Kata sifat"], correct:1},
    {lvl:"Mudah", q:"7. Kalimat yang membujuk pembaca agar mengikuti langkah dengan sungguh-sungguh disebut kalimat...", opts:["Imperatif","Deklaratif","Persuasif","Interogatif","Naratif"], correct:2},
    {lvl:"Mudah", q:"8. Manakah contoh konjungsi temporal?", opts:["Karena","Kemudian","Meskipun","Atau","Tetapi"], correct:1},
    {lvl:"Mudah", q:"9. Langkah pertama dalam menyusun teks prosedur adalah...", opts:["Merevisi teks","Menentukan tujuan","Menyajikan secara lisan","Mencari kata teknis","Menilai teks orang lain"], correct:1},
    {lvl:"Mudah", q:"10. Menyajikan teks prosedur secara lisan berarti menyampaikannya melalui...", opts:["Tulisan di buku","Berbicara di depan orang lain","Gambar diam","Video tanpa suara","Simbol"], correct:1},

    {lvl:"Sedang", q:"11. Berikut ini yang termasuk kriteria evaluasi teks prosedur, KECUALI...", opts:["Keakuratan","Kelengkapan","Kelogisan urutan","Kepopuleran penulis","Kesesuaian tujuan"], correct:3},
    {lvl:"Sedang", q:"12. Manakah pasangan yang tepat untuk membedakan teks prosedur dan teks eksplanasi?", opts:["Prosedur=memahami, Eksplanasi=melakukan","Prosedur=melakukan tindakan, Eksplanasi=memahami proses","Keduanya sama-sama persuasif","Keduanya tidak berstruktur","Keduanya tidak memakai konjungsi"], correct:1},
    {lvl:"Sedang", q:"13. \"Selain itu, pastikan area kerja dalam keadaan bersih.\" Kalimat tersebut mengandung penanda wacana jenis...", opts:["Urutan","Penambahan","Penekanan","Simpulan","Pertentangan"], correct:1},
    {lvl:"Sedang", q:"14. Kalimat \"Jangan sentuh permukaan yang masih panas\" termasuk kalimat perintah jenis...", opts:["Ajakan","Permintaan","Larangan","Deklaratif","Persuasif"], correct:2},
    {lvl:"Sedang", q:"15. Ciri kalimat deklaratif dalam teks prosedur adalah...", opts:["Selalu diakhiri tanda seru","Berupa kalimat berita tanpa perintah","Selalu menggunakan kata \"jangan\"","Selalu berupa pertanyaan","Menggunakan konjungsi temporal"], correct:1},
    {lvl:"Sedang", q:"16. Manakah contoh kata teknis bidang tata boga?", opts:["Karburator","Partisi","Marinasi","Ejector pin","Velg"], correct:2},
    {lvl:"Sedang", q:"17. Fungsi utama menyajikan teks prosedur secara tulisan dibanding lisan adalah...", opts:["Lebih cepat dipahami tanpa membaca","Dapat dibaca ulang dan disimpan","Tidak memerlukan struktur","Tidak perlu memperhatikan kaidah kebahasaan","Hanya bisa disampaikan satu arah"], correct:1},
    {lvl:"Sedang", q:"18. Ketika membandingkan dua teks, langkah setelah membaca kedua teks adalah...", opts:["Menyimpulkan langsung","Mengidentifikasi tujuan masing-masing teks","Menyajikan secara lisan","Menerbitkan teks","Menghapus salah satu teks"], correct:1},
    {lvl:"Sedang", q:"19. Aspek yang TIDAK termasuk penilaian presentasi lisan adalah...", opts:["Intonasi","Artikulasi","Sikap","Jumlah halaman naskah","Kontak mata"], correct:3},
    {lvl:"Sedang", q:"20. \"Dengan demikian, kompos siap digunakan sebagai pupuk.\" Kalimat ini menunjukkan penanda wacana jenis...", opts:["Penambahan","Penekanan","Simpulan","Urutan","Pertentangan"], correct:2},

    {lvl:"Sulit", q:"21. Sebuah teks prosedur menyebutkan takaran bahan yang tidak sesuai standar umum. Kekeliruan ini melanggar kriteria evaluasi...", opts:["Kelogisan urutan","Keakuratan","Kesesuaian tujuan","Kelengkapan","Keselamatan"], correct:1},
    {lvl:"Sulit", q:"22. Sebuah teks prosedur tidak mencantumkan langkah verifikasi hasil akhir, padahal langkah tersebut penting untuk memastikan keberhasilan. Kekurangan ini termasuk pelanggaran kriteria...", opts:["Keakuratan","Kelengkapan","Kejelasan bahasa","Konjungsi temporal","Kata teknis"], correct:1},
    {lvl:"Sulit", q:"23. Manakah simpulan yang PALING TEPAT membedakan teks prosedur dan teks eksplanasi berdasarkan hasil yang diharapkan bagi pembaca?", opts:["Keduanya menghasilkan tindakan yang sama","Prosedur menghasilkan tindakan, eksplanasi menghasilkan pemahaman","Keduanya hanya menghasilkan hiburan","Eksplanasi selalu lebih pendek daripada prosedur","Prosedur tidak memiliki tujuan"], correct:1},
    {lvl:"Sulit", q:"24. Sebuah kelompok menyusun teks prosedur dengan langkah yang runtut, namun saat presentasi lisan, anggota kelompok berbicara terbata-bata dan tidak melakukan kontak mata. Aspek apa yang paling perlu diperbaiki?", opts:["Struktur teks tulisan","Kaidah kebahasaan teks","Keterampilan penyajian lisan","Ketepatan kata teknis","Penanda wacana"], correct:2},
    {lvl:"Sulit", q:"25. Perhatikan kalimat: \"Pastikan sakelar dalam posisi mati, lalu periksa kabel secara berkala agar tidak terjadi korsleting.\" Kalimat tersebut menggabungkan ciri kebahasaan...", opts:["Kalimat deklaratif dan konjungsi kausalitas","Kalimat perintah dan konjungsi temporal","Kalimat persuasif dan kata teknis","Kalimat interogatif dan penanda simpulan","Kalimat naratif dan konjungsi temporal"], correct:1}
  ];

  var optLabels = ["A","B","C","D","E"];
  var lvlColor = {"Mudah":"#6EC6CA","Sedang":"#F5A623","Sulit":"#D94E2A"};

  var container = document.getElementById("epbq-questions");
  questions.forEach(function(item, idx){
    var block = document.createElement("div");
    block.style.marginBottom = "20px";
    block.style.paddingBottom = "16px";
    block.style.borderBottom = "1px dashed rgba(234,242,245,0.16)";

    var tag = document.createElement("span");
    tag.textContent = item.lvl;
    tag.style.display = "inline-block";
    tag.style.fontFamily = "'IBM Plex Mono', monospace";
    tag.style.fontSize = "0.68rem";
    tag.style.letterSpacing = "0.08em";
    tag.style.textTransform = "uppercase";
    tag.style.color = lvlColor[item.lvl] || "#9FB4C2";
    tag.style.border = "1px solid " + (lvlColor[item.lvl] || "#9FB4C2");
    tag.style.padding = "2px 8px";
    tag.style.marginBottom = "6px";
    block.appendChild(tag);

    var qEl = document.createElement("p");
    qEl.style.color = "#EAF2F5";
    qEl.style.fontWeight = "600";
    qEl.style.margin = "6px 0 8px";
    qEl.textContent = item.q;
    block.appendChild(qEl);

    item.opts.forEach(function(opt, oi){
      var label = document.createElement("label");
      label.style.display = "block";
      label.style.color = "#DDE7EC";
      label.style.fontSize = "0.92rem";
      label.style.margin = "4px 0";
      label.style.cursor = "pointer";

      var radio = document.createElement("input");
      radio.type = "radio";
      radio.name = "epbq-q" + idx;
      radio.value = oi;
      radio.style.marginRight = "8px";

      label.appendChild(radio);
      label.appendChild(document.createTextNode(optLabels[oi] + ". " + opt));
      block.appendChild(label);
    });

    container.appendChild(block);
  });

  document.getElementById("epbq-submit").addEventListener("click", function(){
    var absen = document.getElementById("epbq-absen").value.trim();
    var nama = document.getElementById("epbq-nama").value.trim();
    var statusEl = document.getElementById("epbq-status");

    if(!absen || !nama){
      statusEl.textContent = "Isi No. Absen dan Nama terlebih dahulu.";
      statusEl.style.color = "#F5A623";
      return;
    }

    var belumDijawab = [];
    var benar = 0;
    questions.forEach(function(item, idx){
      var checked = document.querySelector('input[name="epbq-q' + idx + '"]:checked');
      if(!checked){
        belumDijawab.push(idx+1);
      } else if(parseInt(checked.value,10) === item.correct){
        benar++;
      }
    });

    if(belumDijawab.length &gt; 0){
      statusEl.textContent = "Pertanyaan belum dijawab: nomor " + belumDijawab.join(", ");
      statusEl.style.color = "#F5A623";
      return;
    }

    var skor = benar * 4;
    document.getElementById("epbq-score").textContent = skor;
    document.getElementById("epbq-detail").textContent = "Menjawab benar " + benar + " dari 25 pertanyaan.";
    document.getElementById("epbq-result").style.display = "block";
    statusEl.textContent = "Mengirim hasil...";
    statusEl.style.color = "#9FB4C2";

    var payload = new URLSearchParams();
    payload.append("noAbsen", absen);
    payload.append("nama", nama);
    payload.append("skor", skor);
    payload.append("materi", EPBQ_MATERI);
    payload.append("waktu", new Date().toISOString());

    fetch(EPBQ_ENDPOINT, {
      method: "POST",
      mode: "no-cors",
      headers: {"Content-Type":"application/x-www-form-urlencoded"},
      body: payload.toString()
    }).then(function(){
      statusEl.textContent = "Hasil berhasil dikirim ke guru.";
      statusEl.style.color = "#6EC6CA";
    }).catch(function(){
      statusEl.textContent = "Skor tercatat di halaman ini, namun pengiriman gagal. Tunjukkan skor ini ke guru.";
      statusEl.style.color = "#F5A623";
    });
  });
})();
&lt;/script&gt;

&lt;/main&gt;

&lt;footer&gt;
  &lt;div class="doc-code"&gt;DOK/B.INDO/XI/PROSEDUR-SAJIKAN — Fokus Tujuan Pembelajaran, Materi Inti, Tugas Kelompok &amp;amp; Reviu 25 Soal, 1× pertemuan (3 JP)&lt;/div&gt;
  &lt;p style="margin:0;"&gt;Referensi: Kurikulum Merdeka — Capaian Pembelajaran Bahasa Indonesia Fase F (Elemen Berbicara, Menulis, dan Memirsa); Buku Teks Bahasa Indonesia Kelas XI SMK/MAK Kemendikbudristek.&lt;/p&gt;
&lt;/footer&gt;
&lt;/div&gt;</description><link>http://kitab-investasi.blogspot.com/2026/08/menyajikan-teks-prosedur-rangkuman.html</link><thr:total>0</thr:total><author>nof_rizal07@yahoo.co.id (abang_cool)</author></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-9000860041661554971.post-3058660478422290104</guid><pubDate>Thu, 20 Aug 2026 03:08:59 +0000</pubDate><atom:updated>2026-08-20T10:10:03.035+07:00</atom:updated><title>SERTIFKAT KOMBEL KE 9</title><description>&lt;!DOCTYPE html&gt;
&lt;html lang="id"&gt;
&lt;head&gt;
&lt;meta charset="UTF-8"&gt;
&lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&gt;
&lt;title&gt;Generator Sertifikat&lt;/title&gt;

&lt;link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@700&amp;display=swap" rel="stylesheet"&gt;

&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"&gt;&lt;/script&gt;

&lt;style&gt;

body{
    font-family:Arial,sans-serif;
    background:#eef2f7;
    padding:20px;
    max-width:700px;
    margin:auto;
}

.card{
    background:white;
    padding:24px;
    border-radius:20px;
    box-shadow:0 10px 20px rgba(0,0,0,.1);
}

h2{
    text-align:center;
    color:#1e4668;
}

.confirm-box{
    background:#f0f6ff;
    border-left:5px solid #2c7da0;
    padding:16px;
    border-radius:16px;
    margin-bottom:20px;
    text-align:center;
}

.confirm-box p{
    margin-top:0;
    font-weight:bold;
    color:#1e4668;
}

.confirm-buttons{
    display:flex;
    gap:10px;
    margin-top:10px;
}

.confirm-buttons button{
    flex:1;
}

.yes-btn{
    background:#1f8a4c;
}

.yes-btn:hover{
    background:#166638;
}

.no-btn{
    background:#c0392b;
}

.no-btn:hover{
    background:#962d22;
}

input,select,button{
    width:100%;
    padding:12px;
    margin-top:10px;
    border-radius:12px;
    border:1px solid #ccc;
    font-size:16px;
}

button{
    background:#2c7da0;
    color:white;
    border:none;
    cursor:pointer;
    font-weight:bold;
}

button:hover{
    background:#1f5e7a;
}

button:disabled{
    background:#94a3b8;
    cursor:not-allowed;
}

input:disabled,
select:disabled{
    background:#f1f5f9;
}

#preview{
    width:100%;
    border-radius:12px;
    margin-top:10px;
}

.loading{
    display:none;
    margin-top:15px;
    color:#1e4668;
    font-weight:bold;
    text-align:center;
}

.status{
    margin-top:12px;
    font-weight:bold;
}

.success{
    color:#1f8a4c;
}

.error{
    color:#c0392b;
}

&lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;

&lt;div class="card"&gt;

&lt;h2&gt;&#128220; Generator Sertifikat&lt;/h2&gt;

&lt;!-- ================= KONFIRMASI ================= --&gt;

&lt;div class="confirm-box"&gt;

&lt;p&gt;&#128269; Apakah Anda mengikuti pelatihan?&lt;/p&gt;

&lt;div class="confirm-buttons"&gt;

&lt;button class="yes-btn" onclick="confirmIkut()"&gt;
✅ YA, IKUT
&lt;/button&gt;

&lt;button class="no-btn" onclick="confirmTidakIkut()"&gt;
❌ TIDAK
&lt;/button&gt;

&lt;/div&gt;

&lt;div id="statusKonfirmasi" class="status"&gt;&lt;/div&gt;

&lt;/div&gt;

&lt;!-- ================= FORM ================= --&gt;

&lt;label&gt;Nama Lengkap&lt;/label&gt;

&lt;input
type="text"
id="nama"
placeholder="Contoh: Ahmad Fauzi"
disabled&gt;

&lt;label&gt;Peran&lt;/label&gt;

&lt;select id="peran" disabled&gt;
    &lt;option&gt;Peserta&lt;/option&gt;
    &lt;option&gt;Narasumber&lt;/option&gt;
&lt;/select&gt;

&lt;img
id="preview"
src="https://lh3.googleusercontent.com/d/17OvHkbTI7cLyTZiZiL2gJykxyIQ1s44Z"
alt="Template"&gt;

&lt;button
id="downloadBtn"
onclick="generatePDF()"
disabled&gt;

⬇️ UNDUH PDF

&lt;/button&gt;

&lt;div class="loading" id="loading"&gt;
Memproses PDF...
&lt;/div&gt;

&lt;/div&gt;

&lt;script&gt;

// ================= TEMPLATE (DIUBAH) =================

const FILE_ID =
'17OvHkbTI7cLyTZiZiL2gJykxyIQ1s44Z';  // &lt;-- ID baru

const TEMPLATE_URL =
`https://lh3.googleusercontent.com/d/${FILE_ID}`;

// ================= UTIL =================

function showLoading(show){

    document.getElementById('loading').style.display =
        show ? 'block' : 'none';

}

function getRomanMonth(monthIndex){

    const romawi = [
        "I","II","III","IV","V","VI",
        "VII","VIII","IX","X","XI","XII"
    ];

    return romawi[monthIndex];

}

function capitalizeEachWord(text){

    return text
        .toLowerCase()
        .replace(/\b\w/g,c=&gt;c.toUpperCase());

}

// ================= KONFIRMASI =================

function confirmIkut(){

    document.getElementById('nama').disabled = false;

    document.getElementById('peran').disabled = false;

    document.getElementById('downloadBtn').disabled = false;

    document.getElementById('statusKonfirmasi').innerHTML =
        '&lt;span class="success"&gt;✅ Konfirmasi diterima. Anda dapat mengunduh sertifikat.&lt;/span&gt;';

}

function confirmTidakIkut(){

    document.getElementById('nama').disabled = true;

    document.getElementById('peran').disabled = true;

    document.getElementById('downloadBtn').disabled = true;

    document.getElementById('statusKonfirmasi').innerHTML =
        '&lt;span class="error"&gt;❌ Anda tidak dapat mengunduh sertifikat.&lt;/span&gt;';

}

// ================= LOAD IMAGE =================

function loadImage(url){

    return new Promise((resolve,reject)=&gt;{

        const img = new Image();

        img.crossOrigin = "anonymous";

        img.onload = ()=&gt;resolve(img);

        img.onerror = ()=&gt;{

            reject(
                new Error(
                    'Template Google Drive gagal dimuat'
                )
            );

        };

        img.src = url + '?t=' + Date.now();

    });

}

// ================= NOMOR =================

async function generateNomor(){

    const now = new Date();

    const bulan =
        getRomanMonth(now.getMonth());

    const tahun =
        now.getFullYear();

    const nomor =
        Math.floor(Math.random()*900)+100;

    return `${nomor}/K/${bulan}/${tahun}`;

}

// ================= PDF =================

async function generatePDF(){

    const namaInput =
        document.getElementById('nama');

    const peranSelect =
        document.getElementById('peran');

    let nama =
        namaInput.value.trim();

    const peran =
        peranSelect.value;

    if(!nama){

        alert('Nama wajib diisi');

        return;

    }

    nama =
        capitalizeEachWord(nama);

    showLoading(true);

    try{

        await document.fonts.ready;

        const img =
            await loadImage(TEMPLATE_URL);

        const canvas =
            document.createElement('canvas');

        canvas.width = img.width;
        canvas.height = img.height;

        const ctx =
            canvas.getContext('2d');

        ctx.drawImage(
            img,
            0,
            0,
            canvas.width,
            canvas.height
        );

        // ================= POSISI =================

        const nomorY =
            canvas.height * 0.235;

        const namaY =
            canvas.height * 0.3990;

        const peranY =
            canvas.height * 0.5420;

        // ================= STYLE =================

        ctx.textAlign = 'center';

        ctx.textBaseline = 'middle';

        ctx.fillStyle = '#000';

        // nomor
        const nomorSertifikat =
            await generateNomor();

        ctx.font =
            `bold ${canvas.width*0.0125}px Montserrat`;

        ctx.fillText(
            nomorSertifikat,
            canvas.width/2,
            nomorY
        );

        // nama auto shrink
        let fontSize =
            canvas.width * 0.031;

        ctx.font =
            `700 ${fontSize}px Montserrat`;

        let textWidth =
            ctx.measureText(nama).width;

        const maxWidth =
            canvas.width - 180;

        while(
            textWidth &gt; maxWidth &amp;&amp;
            fontSize &gt; 20
        ){

            fontSize -= 2;

            ctx.font =
                `700 ${fontSize}px Montserrat`;

            textWidth =
                ctx.measureText(nama).width;

        }

        ctx.fillText(
            nama,
            canvas.width/2,
            namaY
        );

        // peran
        ctx.font =
            `bold ${canvas.width*0.024}px Montserrat`;

        ctx.fillText(
            peran,
            canvas.width/2,
            peranY
        );

        // ================= PDF =================

        const imageData =
            canvas.toDataURL(
                'image/jpeg',
                1.0
            );

        const { jsPDF } =
            window.jspdf;

        const pdf =
            new jsPDF({

                orientation:
                    canvas.width &gt; canvas.height
                    ? 'landscape'
                    : 'portrait',

                unit:'px',

                format:[
                    canvas.width,
                    canvas.height
                ]

            });

        pdf.addImage(
            imageData,
            'JPEG',
            0,
            0,
            canvas.width,
            canvas.height
        );

        const safeName =
            nama.replace(/[^a-z0-9]/gi,'_');

        pdf.save(
            `Sertifikat_${safeName}.pdf`
        );

    }catch(error){

        console.error(error);

        alert(
            '❌ Gagal membuat PDF\n\n' +
            error.message +
            '\n\nPastikan file Google Drive bersifat PUBLIC.'
        );

    }finally{

        showLoading(false);

    }

}

&lt;/script&gt;

&lt;/body&gt;
&lt;/html&gt;</description><link>http://kitab-investasi.blogspot.com/2026/08/sertifkat-kombel-ke-9.html</link><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://lh3.googleusercontent.com/d/17OvHkbTI7cLyTZiZiL2gJykxyIQ1s44Z=s72-c" width="72"/><thr:total>0</thr:total><author>nof_rizal07@yahoo.co.id (abang_cool)</author></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-9000860041661554971.post-9087345521102818853</guid><pubDate>Wed, 19 Aug 2026 07:24:53 +0000</pubDate><atom:updated>2026-08-20T14:49:14.439+07:00</atom:updated><title>Jaringan Komputer, Internet, &amp; Keamanan Digital</title><description>&lt;!DOCTYPE html&gt;
&lt;html lang="id"&gt;
&lt;head&gt;
&lt;meta charset="UTF-8"&gt;
&lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&gt;
&lt;title&gt;Jaringan Komputer, Internet, &amp; Keamanan Digital — Informatika Kelas X&lt;/title&gt;
&lt;link rel="preconnect" href="https://fonts.googleapis.com"&gt;
&lt;link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500;600;700&amp;family=IBM+Plex+Sans:wght@400;500;600;700&amp;display=swap" rel="stylesheet"&gt;
&lt;style&gt;
  :root{
    --bg: #0B1B2B;
    --bg-deep: #071320;
    --node: #38BDF8;
    --node-dim: rgba(56,189,248,0.3);
    --secure: #22C55E;
    --alert: #F87171;
    --amber: #F2B84B;
    --paper: #FBFCFD;
    --ink: #16232E;
    --ink-soft: #4B5B6B;
    --line: #DCE3EA;
    --radius:6px;
  }
  *{box-sizing:border-box; margin:0; padding:0;}
  html{scroll-behavior:smooth;}
  body{ font-family:'IBM Plex Sans', sans-serif; background: var(--bg); color: var(--ink); line-height:1.6; }
  .mono{font-family:'IBM Plex Mono', monospace;}

  /* ===== Hero with network nodes ===== */
  header.hero{ position:relative; overflow:hidden; padding: 60px 6vw 56px; color:#EAF2FA; }
  header.hero::before{
    content:""; position:absolute; inset:0;
    background-image: radial-gradient(var(--node-dim) 1.5px, transparent 1.5px);
    background-size: 26px 26px;
    opacity:0.5;
  }
  header.hero .content{position:relative; z-index:1;}
  .eyebrow{
    font-family:'IBM Plex Mono', monospace; font-size:0.78rem; letter-spacing:0.16em; text-transform:uppercase;
    color: var(--node); display:flex; align-items:center; gap:10px; margin-bottom:20px;
  }
  .eyebrow::before{ content:""; width:10px; height:10px; border:1.5px solid var(--node); border-radius:50%; box-shadow:0 0 0 3px var(--node-dim); }
  h1.title{
    font-family:'IBM Plex Mono', monospace; font-weight:700;
    font-size: clamp(1.9rem, 4.2vw, 3.4rem); line-height:1.14; max-width: 19ch; color:#FFFFFF;
  }
  h1.title span{color: var(--node);}
  .hero-sub{ margin-top:18px; max-width: 64ch; font-size:1.04rem; color:#EAF2FA; }
  .meta-strip{
    margin-top:36px; display:grid; grid-template-columns: repeat(auto-fit,minmax(160px,1fr)); gap:1px;
    background: var(--node-dim); border:1px solid var(--node-dim); max-width: 940px;
  }
  .meta-cell{ background: var(--bg-deep); padding:14px 16px; }
  .meta-cell .k{ font-family:'IBM Plex Mono', monospace; font-size:0.66rem; letter-spacing:0.1em; text-transform:uppercase; color: var(--node); opacity:0.9; }
  .meta-cell .v{ margin-top:6px; font-size:0.94rem; font-weight:600; color:#F1F6FA; }

  /* ===== Content shell ===== */
  main{ background: var(--paper); border-radius:18px 18px 0 0; margin-top:-18px; position:relative; z-index:2; padding: 8px 0 0; }
  .section{ padding: 54px 6vw; max-width: 1180px; margin: 0 auto; border-bottom:1px solid #E7EAEE; }
  .section:last-of-type{border-bottom:none;}
  .section-tag{
    font-family:'IBM Plex Mono', monospace; font-size:0.72rem; letter-spacing:0.14em; text-transform:uppercase;
    color: var(--ink-soft); display:flex; align-items:center; gap:10px; margin-bottom:10px;
  }
  .section-tag .num{ color:#fff; background: var(--bg); padding:3px 8px; border-radius:3px; font-weight:600; }
  h2.section-title{ font-family:'IBM Plex Mono', monospace; font-size: clamp(1.35rem, 2.3vw, 1.9rem); font-weight:700; color: var(--bg); margin-bottom: 22px; max-width: 32ch; }
  h3.sub-title{ font-family:'IBM Plex Mono', monospace; font-size:1.06rem; font-weight:600; color: var(--bg); margin: 26px 0 12px; display:flex; align-items:center; gap:10px; }
  h3.sub-title::before{ content:""; width:8px;height:8px; background: var(--node); display:inline-block; border-radius:1px; }
  p{ color:#2C3B4A; max-width: 74ch; margin-bottom: 14px;}
  strong{color:var(--bg);}
  ul, ol{ margin: 8px 0 18px 1.3em; max-width: 74ch;}
  li{margin-bottom:8px; color:#2C3B4A;}

  .callout{ border-left: 3px solid var(--node); background: #EAF6FD; padding: 16px 20px; border-radius: 0 6px 6px 0; margin: 18px 0; max-width: 74ch; }
  .callout .lbl{ font-family:'IBM Plex Mono', monospace; font-size:0.7rem; letter-spacing:0.1em; text-transform:uppercase; color:#0E6E9C; font-weight:700; margin-bottom:6px; }
  .callout.warn{ border-left-color: var(--alert); background:#FDEEEC; }
  .callout.warn .lbl{ color:#B9392A; }
  .callout.secure{ border-left-color: var(--secure); background:#EBF9F0; }
  .callout.secure .lbl{ color:#177A43; }

  /* ===== Cards ===== */
  .card-grid{ display:grid; grid-template-columns: repeat(3, 1fr); gap: 16px; margin: 20px 0 8px; }
  @media (max-width: 860px){ .card-grid{grid-template-columns: 1fr;} }
  .card{ background: var(--paper); border: 1.5px solid var(--bg); border-radius: var(--radius); padding: 20px; }
  .card .tag{ font-family:'IBM Plex Mono', monospace; font-size:0.66rem; letter-spacing:0.1em; text-transform:uppercase; color:#fff; background: var(--bg); padding:3px 8px; border-radius:3px; display:inline-block; margin-bottom:12px; }
  .card h4{ font-family:'IBM Plex Mono', monospace; font-size:0.98rem; margin-bottom:8px; color:var(--bg); }
  .card p{font-size:0.89rem; margin-bottom:0;}

  table.compare{ width:100%; border-collapse:collapse; margin:18px 0; font-size:0.9rem; }
  table.compare th, table.compare td{ border:1px solid var(--line); padding:11px 14px; text-align:left; }
  table.compare th{ background: var(--bg); color:#fff; font-family:'IBM Plex Mono', monospace; font-size:0.74rem; letter-spacing:0.04em; text-transform:uppercase; }
  table.compare tr:nth-child(even) td{ background:#F4F6F8; }

  /* ===== Diagram ===== */
  .diagram-frame{ margin: 26px 0; background: var(--bg-deep); border-radius: 8px; padding: 18px; border: 1px solid var(--node-dim); }
  .diagram-frame svg{width:100%; height:auto; display:block;}
  .diagram-caption{ font-family:'IBM Plex Mono', monospace; font-size:0.72rem; color: var(--node); text-align:center; margin-top:10px; letter-spacing:0.03em; }
  .signal{ stroke-dasharray: 6 8; animation: flow 1.6s linear infinite; }
  @keyframes flow{ to{ stroke-dashoffset:-56; } }
  @media (prefers-reduced-motion: reduce){ .signal{animation:none;} }

  /* ===== Summary ===== */
  .summary-box{ background: var(--bg); color: #fff; border-radius: 8px; padding: 26px 28px; margin-top: 10px; }
  .summary-box h4{ font-family:'IBM Plex Mono', monospace; color: var(--node); font-size:0.85rem; letter-spacing:0.08em; text-transform:uppercase; margin-bottom:14px; }
  .summary-box ul{ margin:0 0 0 1.1em; max-width:none; }
  .summary-box li{ color:#DCEAF2; margin-bottom:8px; }

  /* ===== Tugas kelompok ===== */
  .task-panel{ border: 1.5px dashed var(--bg); border-radius: 8px; padding: 26px 28px; background: repeating-linear-gradient(135deg, #FBFCFD, #FBFCFD 18px, #EEF2F6 18px, #EEF2F6 19px); }
  .task-head{ display:flex; align-items:center; gap:12px; flex-wrap:wrap; margin-bottom:12px; }
  .task-head .badge{ font-family:'IBM Plex Mono', monospace; font-size:0.7rem; letter-spacing:0.08em; text-transform:uppercase; background: var(--node); color:#062230; padding:4px 10px; border-radius:3px; font-weight:700;}
  .task-panel h3{ font-family:'IBM Plex Mono', monospace; font-size:1.22rem; color: var(--bg); }
  .steps-num{ counter-reset: step; margin:16px 0; max-width:78ch; }
  .steps-num li{ counter-increment: step; list-style:none; position:relative; padding-left:34px; margin-bottom:14px; }
  .steps-num li::before{ content: counter(step); position:absolute; left:0; top:0; font-family:'IBM Plex Mono', monospace; font-weight:700; color:#fff; background: var(--bg); width:24px; height:24px; border-radius:50%; display:flex; align-items:center; justify-content:center; font-size:0.8rem; }
  table.rubrik{ width:100%; border-collapse:collapse; margin-top:18px; font-size:0.88rem; }
  table.rubrik th, table.rubrik td{ border:1px solid #C9CFD6; padding:10px 12px; text-align:left; }
  table.rubrik th{ background: var(--bg); color:#fff; font-family:'IBM Plex Mono', monospace; font-size:0.75rem; letter-spacing:0.04em; text-transform:uppercase; }
  table.rubrik tr:nth-child(even) td{ background:#EFF2F5; }

  .closing-task{ margin-top:22px; background: #FEF6EA; border:1.5px solid var(--amber); border-radius:8px; padding:20px 22px; }
  .closing-task .lbl{ font-family:'IBM Plex Mono', monospace; font-size:0.72rem; letter-spacing:0.1em; text-transform:uppercase; color:#8A5A0A; font-weight:700; margin-bottom:8px; }

  /* ===== Quiz ===== */
  .quiz-panel{ background: var(--bg-deep); border-radius: 10px; padding: 30px 28px; color:#EAF2FA; }
  .quiz-panel h3.sub-title{ color:#EAF2FA; }
  .quiz-panel h3.sub-title::before{ background: var(--node); }
  .quiz-note{ font-size:0.88rem; color:#9FB4C6; max-width:74ch; margin-bottom:18px;}
  .student-info{ display:grid; grid-template-columns: repeat(3, 1fr); gap:14px; margin: 18px 0 30px; }
  @media (max-width:700px){ .student-info{grid-template-columns:1fr;} }
  .field label{ display:block; font-family:'IBM Plex Mono', monospace; font-size:0.7rem; letter-spacing:0.06em; text-transform:uppercase; color: var(--node); margin-bottom:6px; }
  .field input, .field select{
    width:100%; padding:10px 12px; border-radius:5px; border:1px solid #2A4258; background:#0F2438; color:#EAF2FA; font-family:'IBM Plex Sans', sans-serif; font-size:0.94rem;
  }
  .field select{ cursor:pointer; }
  .field input:focus, .field select:focus{ outline:2px solid var(--node); }

  .q-card{ background:#0F2438; border:1px solid #23384B; border-radius:8px; padding:18px 20px; margin-bottom:14px; }
  .q-card .q-num{ font-family:'IBM Plex Mono', monospace; font-size:0.72rem; color: var(--node); letter-spacing:0.08em; margin-bottom:6px; }
  .q-card .q-text{ font-size:0.98rem; color:#F1F6FA; margin-bottom:12px; font-weight:500; }
  .options{ display:flex; flex-direction:column; gap:8px; }
  .opt{ display:flex; align-items:flex-start; gap:10px; padding:9px 12px; border:1px solid #23384B; border-radius:5px; cursor:pointer; transition: border-color .15s, background .15s; }
  .opt:hover{ border-color: var(--node); }
  .opt input{ margin-top:3px; accent-color: var(--node); }
  .opt span{ font-size:0.9rem; color:#DDE8F0; }
  .opt.selected{ border-color: var(--node); background: rgba(56,189,248,0.08); }

  .quiz-actions{ margin-top:24px; display:flex; align-items:center; gap:16px; flex-wrap:wrap; }
  #btnHitung, #btnKirim{
    font-family:'IBM Plex Mono', monospace; font-weight:600; font-size:0.85rem; letter-spacing:0.04em;
    padding: 12px 22px; border-radius:6px; border:none; cursor:pointer;
  }
  #btnHitung{ background: var(--node); color:#062230; }
  #btnHitung:hover{ filter:brightness(1.08); }
  #btnKirim{ background: var(--secure); color:#062230; display:none; }
  #btnKirim:hover{ filter:brightness(1.08); }
  #btnKirim:disabled{ opacity:0.6; cursor:not-allowed; }
  #quizMsg{ font-family:'IBM Plex Mono', monospace; font-size:0.85rem; color: var(--amber); }

  .result-panel{
    display:none; margin-top:22px; background:#0F2438; border:1.5px solid var(--secure); border-radius:8px; padding:22px 24px;
  }
  .result-panel .score{ font-family:'IBM Plex Mono', monospace; font-size:2.4rem; font-weight:700; color: var(--secure); }
  .result-panel .score-lbl{ font-family:'IBM Plex Mono', monospace; font-size:0.72rem; letter-spacing:0.1em; text-transform:uppercase; color:#9FB4C6; }
  .result-panel p{ color:#DDE8F0; font-size:0.9rem; margin-top:10px; margin-bottom:0; }

  footer{ background: var(--bg-deep); color:#7E93A6; text-align:center; padding: 30px 6vw 40px; font-family:'IBM Plex Mono', monospace; font-size:0.75rem; letter-spacing:0.04em; }

  @media (max-width: 700px){
    .card-grid{grid-template-columns:1fr;}
    header.hero{padding:44px 5vw 40px;}
    .section{padding:38px 5vw;}
  }
&lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;

&lt;header class="hero" style="background:#0B1B2A; border-radius:10px;"&gt;
  &lt;div class="content"&gt;
    &lt;div class="eyebrow"&gt;Informatika · Fase E · Kelas X SMK&lt;/div&gt;
    &lt;h1 class="title" style="color:#FFFFFF; text-shadow:0 2px 6px rgba(0,0,0,0.55);"&gt;Jaringan Komputer, Internet, &amp; Keamanan &lt;span style="color:#38BDF8;"&gt;Digital&lt;/span&gt;&lt;/h1&gt;
    &lt;p class="hero-sub" style="color:#EAF2FA; text-shadow:0 1px 4px rgba(0,0,0,0.45);"&gt;Materi ini membahas bagaimana perangkat saling terhubung membentuk jaringan, bagaimana internet bekerja menghubungkan jaringan-jaringan di seluruh dunia, serta bagaimana menerapkan keamanan dasar dan enkripsi agar aktivitas digital kita tetap aman.&lt;/p&gt;

    &lt;div class="meta-strip"&gt;
      &lt;div class="meta-cell"&gt;&lt;div class="k"&gt;Elemen CP&lt;/div&gt;&lt;div class="v"&gt;Jaringan &amp; Keamanan Digital&lt;/div&gt;&lt;/div&gt;
      &lt;div class="meta-cell"&gt;&lt;div class="k"&gt;Jenjang&lt;/div&gt;&lt;div class="v"&gt;SMK Kelas X&lt;/div&gt;&lt;/div&gt;
      &lt;div class="meta-cell"&gt;&lt;div class="k"&gt;Alokasi Waktu&lt;/div&gt;&lt;div class="v"&gt;1 Pertemuan · 4 JP (180 menit)&lt;/div&gt;&lt;/div&gt;
      &lt;div class="meta-cell"&gt;&lt;div class="k"&gt;Model&lt;/div&gt;&lt;div class="v"&gt;Diskusi, Kerja Kelompok &amp; Kuis&lt;/div&gt;&lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/header&gt;

&lt;main&gt;

  &lt;!-- ===================== TUJUAN ===================== --&gt;
  &lt;section class="section" id="tujuan"&gt;
    &lt;div class="section-tag"&gt;&lt;span class="num"&gt;00&lt;/span&gt; Capaian &amp; Tujuan Pembelajaran&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Ke Mana Materi Ini Menuju&lt;/h2&gt;

    &lt;h3 class="sub-title"&gt;Capaian Pembelajaran&lt;/h3&gt;
    &lt;p&gt;Murid mampu menjelaskan konsep jaringan komputer, konektivitas internet, perangkat jaringan, komunikasi data, serta menerapkan keamanan dasar dan enkripsi dalam penggunaan jaringan.&lt;/p&gt;

    &lt;h3 class="sub-title"&gt;Tujuan Pembelajaran&lt;/h3&gt;
    &lt;ol&gt;
      &lt;li&gt;Menjelaskan konsep dasar jaringan komputer dan jenis-jenisnya berdasarkan jangkauan (PAN, LAN, MAN, WAN).&lt;/li&gt;
      &lt;li&gt;Menjelaskan konektivitas internet: ISP, alamat IP, DNS, dan protokol dasar (TCP/IP, HTTP/HTTPS).&lt;/li&gt;
      &lt;li&gt;Mengidentifikasi perangkat jaringan (router, switch, modem, access point, firewall) beserta fungsinya.&lt;/li&gt;
      &lt;li&gt;Menjelaskan konsep komunikasi data, termasuk bandwidth dan latency.&lt;/li&gt;
      &lt;li&gt;Menerapkan prinsip keamanan dasar dan enkripsi dalam penggunaan jaringan sehari-hari.&lt;/li&gt;
    &lt;/ol&gt;

    &lt;h3 class="sub-title"&gt;Rincian Kegiatan (4 JP × 45 menit)&lt;/h3&gt;
    &lt;table class="compare"&gt;
      &lt;tr&gt;&lt;th&gt;Tahap&lt;/th&gt;&lt;th&gt;Kegiatan&lt;/th&gt;&lt;th&gt;Waktu&lt;/th&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Pendahuluan&lt;/td&gt;&lt;td&gt;Apersepsi ("Bagaimana pesan yang kamu kirim bisa sampai ke HP temanmu dalam hitungan detik?"), penyampaian tujuan pembelajaran&lt;/td&gt;&lt;td&gt;15 menit&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Inti — Eksplorasi Konsep&lt;/td&gt;&lt;td&gt;Penjelasan jaringan komputer, internet, perangkat jaringan, komunikasi data, dan keamanan digital&lt;/td&gt;&lt;td&gt;55 menit&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Inti — Kerja Kelompok&lt;/td&gt;&lt;td&gt;Diskusi dan pengerjaan tugas kelompok merancang skema jaringan&lt;/td&gt;&lt;td&gt;40 menit&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Inti — Presentasi&lt;/td&gt;&lt;td&gt;Presentasi singkat tiap kelompok dan tanggapan guru&lt;/td&gt;&lt;td&gt;20 menit&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Inti — Kuis Individu&lt;/td&gt;&lt;td&gt;Mengerjakan 15 soal pilihan ganda secara mandiri melalui halaman ini&lt;/td&gt;&lt;td&gt;30 menit&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Penutup&lt;/td&gt;&lt;td&gt;Refleksi, penguatan konsep, menulis kesimpulan ringkas di buku catatan&lt;/td&gt;&lt;td&gt;20 menit&lt;/td&gt;&lt;/tr&gt;
    &lt;/table&gt;
  &lt;/section&gt;

  &lt;!-- ===================== A. JARINGAN KOMPUTER ===================== --&gt;
  &lt;section class="section" id="jaringan"&gt;
    &lt;div class="section-tag"&gt;&lt;span class="num"&gt;01&lt;/span&gt; Konsep Dasar&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Apa Itu Jaringan Komputer?&lt;/h2&gt;
    &lt;p&gt;&lt;strong&gt;Jaringan komputer&lt;/strong&gt; adalah kumpulan dua atau lebih perangkat (komputer, laptop, HP, printer, dsb.) yang saling terhubung melalui media kabel atau nirkabel, sehingga dapat saling berbagi data, aplikasi, dan sumber daya seperti printer atau koneksi internet.&lt;/p&gt;

    &lt;h3 class="sub-title"&gt;Jenis Jaringan Berdasarkan Jangkauan&lt;/h3&gt;
    &lt;table class="compare"&gt;
      &lt;tr&gt;&lt;th&gt;Jenis&lt;/th&gt;&lt;th&gt;Kepanjangan&lt;/th&gt;&lt;th&gt;Cakupan&lt;/th&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;PAN&lt;/td&gt;&lt;td&gt;Personal Area Network&lt;/td&gt;&lt;td&gt;Sangat dekat, antar perangkat pribadi — mis. HP tersambung ke earphone via Bluetooth.&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;LAN&lt;/td&gt;&lt;td&gt;Local Area Network&lt;/td&gt;&lt;td&gt;Satu ruangan atau gedung — mis. jaringan komputer di lab sekolah.&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;MAN&lt;/td&gt;&lt;td&gt;Metropolitan Area Network&lt;/td&gt;&lt;td&gt;Satu kota — mis. jaringan yang menghubungkan beberapa kantor cabang dalam satu kota.&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;WAN&lt;/td&gt;&lt;td&gt;Wide Area Network&lt;/td&gt;&lt;td&gt;Sangat luas, antar kota bahkan antar negara — internet adalah contoh WAN terbesar.&lt;/td&gt;&lt;/tr&gt;
    &lt;/table&gt;

    &lt;h3 class="sub-title"&gt;Topologi Jaringan&lt;/h3&gt;
    &lt;p&gt;Topologi adalah pola bagaimana perangkat-perangkat dalam jaringan diatur dan dihubungkan satu sama lain.&lt;/p&gt;
    &lt;div class="diagram-frame"&gt;
      &lt;svg viewBox="0 0 800 230" xmlns="http://www.w3.org/2000/svg"&gt;
        &lt;text x="400" y="24" text-anchor="middle" fill="#38BDF8" font-family="IBM Plex Mono, monospace" font-size="12" letter-spacing="2"&gt;TOPOLOGI STAR (paling umum di lab sekolah)&lt;/text&gt;
        &lt;circle cx="400" cy="120" r="22" fill="none" stroke="#F2B84B" stroke-width="2"/&gt;
        &lt;text x="400" y="125" text-anchor="middle" fill="#F2B84B" font-family="IBM Plex Mono, monospace" font-size="10"&gt;SWITCH&lt;/text&gt;
        &lt;g stroke="#38BDF8" stroke-width="2"&gt;
          &lt;line class="signal" x1="400" y1="98" x2="400" y2="45"/&gt;
          &lt;line class="signal" x1="420" y1="105" x2="620" y2="70"/&gt;
          &lt;line class="signal" x1="420" y1="135" x2="620" y2="170"/&gt;
          &lt;line class="signal" x1="380" y1="135" x2="180" y2="170"/&gt;
          &lt;line class="signal" x1="380" y1="105" x2="180" y2="70"/&gt;
        &lt;/g&gt;
        &lt;g fill="none" stroke="#EAF2FA" stroke-width="1.5"&gt;
          &lt;rect x="375" y="15" width="50" height="30" rx="3"/&gt;
          &lt;rect x="600" y="55" width="55" height="30" rx="3"/&gt;
          &lt;rect x="600" y="155" width="55" height="30" rx="3"/&gt;
          &lt;rect x="150" y="55" width="55" height="30" rx="3"/&gt;
          &lt;rect x="150" y="155" width="55" height="30" rx="3"/&gt;
        &lt;/g&gt;
        &lt;g fill="#EAF2FA" font-family="IBM Plex Mono, monospace" font-size="9" text-anchor="middle"&gt;
          &lt;text x="400" y="34"&gt;PC 1&lt;/text&gt;
          &lt;text x="627" y="74"&gt;PC 2&lt;/text&gt;
          &lt;text x="627" y="174"&gt;PC 3&lt;/text&gt;
          &lt;text x="177" y="74"&gt;PC 4&lt;/text&gt;
          &lt;text x="177" y="174"&gt;PC 5&lt;/text&gt;
        &lt;/g&gt;
      &lt;/svg&gt;
      &lt;div class="diagram-caption"&gt;Semua perangkat terhubung ke satu titik pusat (switch) — mudah dipasang &amp; ditelusuri jika ada gangguan pada satu perangkat.&lt;/div&gt;
    &lt;/div&gt;
    &lt;p&gt;Selain &lt;em&gt;star&lt;/em&gt;, dikenal juga topologi &lt;strong&gt;bus&lt;/strong&gt; (semua perangkat berbagi satu jalur kabel utama), &lt;strong&gt;ring&lt;/strong&gt; (perangkat terhubung membentuk lingkaran), &lt;strong&gt;mesh&lt;/strong&gt; (setiap perangkat saling terhubung langsung satu sama lain), dan &lt;strong&gt;tree&lt;/strong&gt; (gabungan beberapa topologi star bertingkat).&lt;/p&gt;
  &lt;/section&gt;

  &lt;!-- ===================== B. PERANGKAT JARINGAN ===================== --&gt;
  &lt;section class="section" id="perangkat"&gt;
    &lt;div class="section-tag"&gt;&lt;span class="num"&gt;02&lt;/span&gt; Infrastruktur&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Perangkat Jaringan&lt;/h2&gt;
    &lt;p&gt;Sebuah jaringan membutuhkan beberapa perangkat keras khusus agar data dapat mengalir dengan benar antar perangkat.&lt;/p&gt;
    &lt;div class="card-grid"&gt;
      &lt;div class="card"&gt;&lt;span class="tag"&gt;Penghubung Internet&lt;/span&gt;&lt;h4&gt;Router&lt;/h4&gt;&lt;p&gt;Menghubungkan jaringan lokal (LAN) ke jaringan lain/internet, serta menentukan jalur terbaik pengiriman data.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;span class="tag"&gt;Penghubung Lokal&lt;/span&gt;&lt;h4&gt;Switch&lt;/h4&gt;&lt;p&gt;Menghubungkan banyak perangkat dalam satu LAN dan meneruskan data hanya ke perangkat tujuan yang tepat.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;span class="tag"&gt;Konversi Sinyal&lt;/span&gt;&lt;h4&gt;Modem&lt;/h4&gt;&lt;p&gt;Mengubah sinyal digital dari komputer menjadi sinyal yang dapat dikirim lewat jalur ISP, dan sebaliknya.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;span class="tag"&gt;Nirkabel&lt;/span&gt;&lt;h4&gt;Access Point&lt;/h4&gt;&lt;p&gt;Memancarkan sinyal Wi-Fi agar perangkat dapat terhubung ke jaringan tanpa kabel.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;span class="tag"&gt;Kartu Jaringan&lt;/span&gt;&lt;h4&gt;NIC (Network Interface Card)&lt;/h4&gt;&lt;p&gt;Komponen di dalam perangkat yang memungkinkannya terhubung secara fisik ke jaringan.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;span class="tag"&gt;Keamanan&lt;/span&gt;&lt;h4&gt;Firewall&lt;/h4&gt;&lt;p&gt;Menyaring dan mengendalikan lalu lintas data masuk/keluar jaringan berdasarkan aturan keamanan tertentu.&lt;/p&gt;&lt;/div&gt;
    &lt;/div&gt;
  &lt;/section&gt;

  &lt;!-- ===================== C. INTERNET &amp; KOMUNIKASI DATA ===================== --&gt;
  &lt;section class="section" id="internet"&gt;
    &lt;div class="section-tag"&gt;&lt;span class="num"&gt;03&lt;/span&gt; Konektivitas&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Internet &amp; Komunikasi Data&lt;/h2&gt;
    &lt;p&gt;&lt;strong&gt;Internet&lt;/strong&gt; adalah jaringan raksasa (WAN) yang menghubungkan jutaan jaringan komputer di seluruh dunia menggunakan aturan komunikasi yang sama, yaitu protokol &lt;strong&gt;TCP/IP&lt;/strong&gt;.&lt;/p&gt;

    &lt;h3 class="sub-title"&gt;Istilah Kunci Konektivitas&lt;/h3&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;strong&gt;ISP (Internet Service Provider)&lt;/strong&gt; — perusahaan penyedia layanan akses internet, mis. Telkom/IndiHome, Biznet, atau operator seluler.&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;IP Address&lt;/strong&gt; — alamat unik yang mengidentifikasi setiap perangkat dalam jaringan, seperti alamat rumah di dunia digital.&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;DNS (Domain Name System)&lt;/strong&gt; — sistem yang menerjemahkan nama domain (mis. &lt;span class="mono"&gt;www.contoh.com&lt;/span&gt;) menjadi alamat IP yang dipahami komputer.&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;HTTP/HTTPS&lt;/strong&gt; — protokol untuk mengakses halaman web; HTTPS menambahkan lapisan enkripsi agar data yang dikirim antara browser dan server lebih aman.&lt;/li&gt;
    &lt;/ul&gt;

    &lt;h3 class="sub-title"&gt;Bandwidth &amp; Latency&lt;/h3&gt;
    &lt;table class="compare"&gt;
      &lt;tr&gt;&lt;th&gt;Istilah&lt;/th&gt;&lt;th&gt;Penjelasan&lt;/th&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Bandwidth&lt;/td&gt;&lt;td&gt;Kapasitas maksimum data yang dapat ditransmisikan dalam jaringan pada waktu tertentu — makin besar, makin banyak data yang bisa mengalir sekaligus.&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Latency&lt;/td&gt;&lt;td&gt;Waktu tunda yang dibutuhkan data untuk berpindah dari satu titik ke titik lain — makin kecil, makin responsif koneksi terasa (penting untuk video call/game online).&lt;/td&gt;&lt;/tr&gt;
    &lt;/table&gt;
  &lt;/section&gt;

  &lt;!-- ===================== D. KEAMANAN DIGITAL ===================== --&gt;
  &lt;section class="section" id="keamanan"&gt;
    &lt;div class="section-tag"&gt;&lt;span class="num"&gt;04&lt;/span&gt; Perlindungan Data&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Keamanan Dasar &amp; Enkripsi&lt;/h2&gt;
    &lt;p&gt;Semakin banyak aktivitas dilakukan lewat jaringan, semakin penting pula memahami risiko dan cara melindungi data dari ancaman digital.&lt;/p&gt;

    &lt;h3 class="sub-title"&gt;Ancaman Umum di Jaringan&lt;/h3&gt;
    &lt;div class="callout warn"&gt;
      &lt;div class="lbl"&gt;Waspadai&lt;/div&gt;
      &lt;ul style="margin:0 0 0 1.1em;"&gt;
        &lt;li&gt;&lt;strong&gt;Malware&lt;/strong&gt; — perangkat lunak berbahaya (virus, ransomware) yang merusak atau mencuri data.&lt;/li&gt;
        &lt;li&gt;&lt;strong&gt;Phishing&lt;/strong&gt; — upaya menipu pengguna agar memberikan data pribadi (mis. password) lewat tautan atau pesan palsu.&lt;/li&gt;
        &lt;li&gt;&lt;strong&gt;DDoS (Distributed Denial of Service)&lt;/strong&gt; — serangan yang membanjiri server dengan lalu lintas palsu hingga layanan tidak bisa diakses.&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/div&gt;

    &lt;h3 class="sub-title"&gt;Praktik Keamanan Dasar&lt;/h3&gt;
    &lt;div class="callout secure"&gt;
      &lt;div class="lbl"&gt;Langkah Perlindungan&lt;/div&gt;
      &lt;ul style="margin:0 0 0 1.1em;"&gt;
        &lt;li&gt;Gunakan &lt;strong&gt;kata sandi (password) yang kuat&lt;/strong&gt; dan berbeda untuk setiap akun.&lt;/li&gt;
        &lt;li&gt;Aktifkan &lt;strong&gt;autentikasi dua faktor (2FA)&lt;/strong&gt; untuk lapisan keamanan tambahan.&lt;/li&gt;
        &lt;li&gt;Selalu &lt;strong&gt;perbarui (update)&lt;/strong&gt; sistem operasi dan aplikasi untuk menutup celah keamanan.&lt;/li&gt;
        &lt;li&gt;Aktifkan &lt;strong&gt;firewall&lt;/strong&gt; dan gunakan &lt;strong&gt;VPN&lt;/strong&gt; saat mengakses jaringan publik yang tidak terpercaya.&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/div&gt;

    &lt;h3 class="sub-title"&gt;Enkripsi&lt;/h3&gt;
    &lt;p&gt;&lt;strong&gt;Enkripsi&lt;/strong&gt; adalah proses mengubah data menjadi bentuk acak yang tidak dapat dibaca oleh pihak yang tidak berwenang, dan hanya dapat dikembalikan ke bentuk semula dengan kunci tertentu. Saat kalian mengakses situs dengan ikon gembok dan awalan &lt;span class="mono"&gt;https://&lt;/span&gt; di address bar, artinya data yang dikirim antara perangkat kalian dan server situs tersebut sudah dienkripsi.&lt;/p&gt;
  &lt;/section&gt;

  &lt;!-- ===================== E. HUBUNGAN ===================== --&gt;
  &lt;section class="section" id="hubungan"&gt;
    &lt;div class="section-tag"&gt;&lt;span class="num"&gt;05&lt;/span&gt; Keterkaitan&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Hubungan Antar Konsep&lt;/h2&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;strong&gt;Perangkat jaringan&lt;/strong&gt; (router, switch, modem, access point) adalah fondasi fisik yang membentuk jaringan komputer.&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Jaringan lokal&lt;/strong&gt; yang terhubung ke &lt;strong&gt;ISP&lt;/strong&gt; menjadi bagian dari &lt;strong&gt;internet&lt;/strong&gt; — jaringan global.&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Komunikasi data&lt;/strong&gt; antar perangkat diatur oleh protokol standar (TCP/IP, HTTP/HTTPS) agar semua perangkat "berbicara bahasa yang sama".&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Keamanan digital dan enkripsi&lt;/strong&gt; melindungi seluruh proses komunikasi data ini dari pihak yang tidak berwenang.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/section&gt;

  &lt;!-- ===================== F. RANGKUMAN ===================== --&gt;
  &lt;section class="section" id="rangkuman"&gt;
    &lt;div class="section-tag"&gt;&lt;span class="num"&gt;06&lt;/span&gt; Penguatan Konsep&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Rangkuman Materi&lt;/h2&gt;
    &lt;div class="summary-box"&gt;
      &lt;h4&gt;Poin-Poin Kunci&lt;/h4&gt;
      &lt;ul&gt;
        &lt;li&gt;Jaringan komputer menghubungkan dua atau lebih perangkat untuk berbagi data dan sumber daya, dengan jangkauan PAN, LAN, MAN, hingga WAN.&lt;/li&gt;
        &lt;li&gt;Topologi jaringan (star, bus, ring, mesh, tree) menentukan pola koneksi antar perangkat.&lt;/li&gt;
        &lt;li&gt;Perangkat jaringan utama meliputi router, switch, modem, access point, NIC, dan firewall.&lt;/li&gt;
        &lt;li&gt;Internet adalah WAN raksasa yang menghubungkan jaringan di seluruh dunia melalui protokol TCP/IP.&lt;/li&gt;
        &lt;li&gt;ISP menyediakan akses internet; IP address mengidentifikasi perangkat; DNS menerjemahkan nama domain menjadi IP.&lt;/li&gt;
        &lt;li&gt;Bandwidth menentukan kapasitas data, sedangkan latency menentukan kecepatan respons jaringan.&lt;/li&gt;
        &lt;li&gt;Ancaman digital meliputi malware, phishing, dan DDoS — dicegah dengan password kuat, 2FA, update rutin, firewall, dan VPN.&lt;/li&gt;
        &lt;li&gt;Enkripsi mengubah data menjadi bentuk aman, dan menjadi dasar dari koneksi HTTPS yang kita gunakan sehari-hari.&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/div&gt;
  &lt;/section&gt;

  &lt;!-- ===================== TUGAS KELOMPOK ===================== --&gt;
  &lt;section class="section" id="tugas"&gt;
    &lt;div class="section-tag"&gt;&lt;span class="num"&gt;07&lt;/span&gt; Aktivitas Belajar&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Tugas Kelompok&lt;/h2&gt;

    &lt;div class="task-panel"&gt;
      &lt;div class="task-head"&gt;
        &lt;span class="badge"&gt;Kerja Kelompok · 4–5 orang&lt;/span&gt;
        &lt;span class="badge" style="background:var(--bg); color:#fff;"&gt;40 menit diskusi + 20 menit presentasi&lt;/span&gt;
      &lt;/div&gt;
      &lt;h3&gt;Merancang Skema Jaringan LAN untuk Laboratorium Komputer Sekolah&lt;/h3&gt;
      &lt;p&gt;Setiap kelompok berperan sebagai "tim IT sekolah" yang ditugaskan merancang jaringan LAN sederhana dan aman untuk sebuah laboratorium komputer.&lt;/p&gt;

      &lt;ol class="steps-num"&gt;
        &lt;li&gt;&lt;strong&gt;Bentuk kelompok&lt;/strong&gt; beranggotakan 4–5 orang, tentukan skenario: jumlah komputer di lab (mis. 15 unit) dan kebutuhan aksesnya ke internet.&lt;/li&gt;
        &lt;li&gt;&lt;strong&gt;Pilih topologi jaringan&lt;/strong&gt; yang paling sesuai untuk skenario tersebut, dan jelaskan alasan pemilihannya.&lt;/li&gt;
        &lt;li&gt;&lt;strong&gt;Tentukan perangkat jaringan&lt;/strong&gt; yang dibutuhkan (router, switch, kabel/access point, dsb.) beserta perkiraan jumlahnya.&lt;/li&gt;
        &lt;li&gt;&lt;strong&gt;Gambarkan skema jaringan sederhana&lt;/strong&gt; yang menunjukkan bagaimana seluruh komputer, perangkat jaringan, dan sambungan internet terhubung.&lt;/li&gt;
        &lt;li&gt;&lt;strong&gt;Rancang langkah keamanan dasar&lt;/strong&gt; untuk jaringan tersebut, misalnya kebijakan password Wi-Fi, penggunaan firewall, dan pembatasan akses pengguna.&lt;/li&gt;
        &lt;li&gt;&lt;strong&gt;Presentasikan&lt;/strong&gt; rancangan di depan kelas selama maksimal 5 menit per kelompok.&lt;/li&gt;
      &lt;/ol&gt;

      &lt;h3 class="sub-title" style="margin-top:26px;"&gt;Format Laporan&lt;/h3&gt;
      &lt;p&gt;Laporan memuat: (1) skenario &amp; anggota kelompok, (2) topologi pilihan beserta alasan, (3) daftar perangkat jaringan yang dibutuhkan, (4) gambar skema jaringan, (5) rancangan langkah keamanan dasar.&lt;/p&gt;

      &lt;h3 class="sub-title"&gt;Rubrik Penilaian&lt;/h3&gt;
      &lt;table class="rubrik"&gt;
        &lt;tr&gt;&lt;th&gt;Aspek&lt;/th&gt;&lt;th&gt;Indikator&lt;/th&gt;&lt;th&gt;Skor Maks.&lt;/th&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td&gt;Ketepatan Topologi&lt;/td&gt;&lt;td&gt;Topologi yang dipilih sesuai skenario dan alasannya logis&lt;/td&gt;&lt;td&gt;25&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td&gt;Kelengkapan Perangkat&lt;/td&gt;&lt;td&gt;Perangkat jaringan yang disebutkan lengkap dan fungsinya tepat&lt;/td&gt;&lt;td&gt;25&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td&gt;Skema Jaringan&lt;/td&gt;&lt;td&gt;Gambar skema jelas dan menunjukkan hubungan antar komponen dengan benar&lt;/td&gt;&lt;td&gt;20&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td&gt;Aspek Keamanan&lt;/td&gt;&lt;td&gt;Langkah keamanan dasar relevan dan dapat diterapkan&lt;/td&gt;&lt;td&gt;15&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td&gt;Kerja Sama &amp; Presentasi&lt;/td&gt;&lt;td&gt;Seluruh anggota berkontribusi; presentasi jelas dan percaya diri&lt;/td&gt;&lt;td&gt;15&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td colspan="2" style="text-align:right; font-weight:600;"&gt;Total&lt;/td&gt;&lt;td&gt;100&lt;/td&gt;&lt;/tr&gt;
      &lt;/table&gt;
    &lt;/div&gt;

    &lt;div class="closing-task"&gt;
      &lt;div class="lbl"&gt;Penutup Pembelajaran · Tugas Individu&lt;/div&gt;
      &lt;p style="margin:0;"&gt;&lt;strong&gt;Tulislah satu kesimpulan ringkas (5–7 kalimat) di buku catatan kalian masing-masing&lt;/strong&gt;, yang merangkum keseluruhan materi hari ini: konsep jaringan komputer, perangkat jaringan, cara kerja internet, komunikasi data, serta pentingnya keamanan dasar dan enkripsi. Tulis dengan bahasa dan pemahaman kalian sendiri, bukan menyalin ulang materi.&lt;/p&gt;
    &lt;/div&gt;
  &lt;/section&gt;

  &lt;!-- ===================== KUIS INDIVIDU ===================== --&gt;
  &lt;section class="section" id="kuis"&gt;
    &lt;div class="section-tag"&gt;&lt;span class="num"&gt;08&lt;/span&gt; Evaluasi Individu&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Kuis Pilihan Ganda (15 Soal)&lt;/h2&gt;
    &lt;p&gt;Kerjakan seluruh soal berikut secara mandiri. Isi identitas kalian dengan benar sebelum mengirim jawaban — skor akan otomatis dihitung dan dikirim ke guru.&lt;/p&gt;

    &lt;div class="quiz-panel"&gt;
      &lt;h3 class="sub-title"&gt;Identitas Peserta&lt;/h3&gt;
      &lt;p class="quiz-note"&gt;Pastikan No. Absen, Nama, dan Kelas diisi sesuai data sekolah agar skor tercatat dengan benar.&lt;/p&gt;
      &lt;div class="student-info"&gt;
        &lt;div class="field"&gt;&lt;label for="noAbsen"&gt;No. Absen&lt;/label&gt;&lt;input type="number" id="noAbsen" min="1" placeholder="mis. 12"&gt;&lt;/div&gt;
        &lt;div class="field"&gt;&lt;label for="nama"&gt;Nama Lengkap&lt;/label&gt;&lt;input type="text" id="nama" placeholder="Nama sesuai absensi"&gt;&lt;/div&gt;
        &lt;div class="field"&gt;&lt;label for="kelas"&gt;Kelas&lt;/label&gt;
          &lt;select id="kelas"&gt;
            &lt;option value=""&gt;-- Pilih Kelas --&lt;/option&gt;
            &lt;option value="X TB1"&gt;X TB1&lt;/option&gt;
            &lt;option value="X TB2"&gt;X TB2&lt;/option&gt;
            &lt;option value="X TO1"&gt;X TO1&lt;/option&gt;
            &lt;option value="X TO2"&gt;X TO2&lt;/option&gt;
            &lt;option value="X TJKT1"&gt;X TJKT1&lt;/option&gt;
            &lt;option value="X TJKT2"&gt;X TJKT2&lt;/option&gt;
          &lt;/select&gt;
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;h3 class="sub-title"&gt;Soal&lt;/h3&gt;
      &lt;div id="quizContainer"&gt;&lt;/div&gt;

      &lt;div class="quiz-actions"&gt;
        &lt;button id="btnHitung"&gt;Hitung &amp; Lihat Skor&lt;/button&gt;
        &lt;button id="btnKirim"&gt;Kirim Ulang ke Guru&lt;/button&gt;
        &lt;span id="quizMsg"&gt;&lt;/span&gt;
      &lt;/div&gt;

      &lt;div class="result-panel" id="resultPanel"&gt;
        &lt;div class="score-lbl"&gt;Skor Kamu&lt;/div&gt;
        &lt;div class="score" id="scoreValue"&gt;0&lt;/div&gt;
        &lt;p id="resultDetail"&gt;&lt;/p&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/section&gt;

  &lt;!-- ===================== CONTOH JAWABAN TUGAS KELOMPOK ===================== --&gt;
  &lt;section class="section" id="jawaban-tugas"&gt;
    &lt;div class="section-tag"&gt;&lt;span class="num"&gt;09&lt;/span&gt; Referensi Diskusi Kelompok&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Contoh Jawaban: Skema Jaringan LAN Laboratorium Komputer&lt;/h2&gt;

    &lt;div class="callout secure"&gt;
      &lt;div class="lbl"&gt;Catatan&lt;/div&gt;
      &lt;p style="margin:0;"&gt;Bagian ini adalah &lt;strong&gt;contoh jawaban/kunci jawaban&lt;/strong&gt; untuk tugas kelompok di atas, disusun dari sudut pandang "Tim IT Sekolah" sebagai referensi Diskusi Kelompok hasil kerja murid. Skenario yang digunakan: laboratorium komputer dengan &lt;strong&gt;20 unit komputer siswa dan 1 unit komputer guru&lt;/strong&gt;, membutuhkan akses internet bersama dari satu sambungan ISP sekolah.&lt;/p&gt;
    &lt;/div&gt;

    &lt;h3 class="sub-title"&gt;1. Pemilihan Topologi Jaringan&lt;/h3&gt;
    &lt;p&gt;Topologi yang dipilih adalah &lt;strong&gt;topologi star&lt;/strong&gt;, dengan seluruh komputer terhubung ke satu switch pusat. Alasan pemilihan:&lt;/p&gt;
    &lt;ul&gt;
      &lt;li&gt;Jika satu kabel atau satu komputer bermasalah, komputer lain di lab tetap dapat terhubung ke jaringan — gangguan tidak menjalar ke seluruh jaringan seperti pada topologi bus.&lt;/li&gt;
      &lt;li&gt;Penambahan atau pengurangan komputer (mis. saat ada unit rusak/diganti) sangat mudah dilakukan tanpa mengganggu komputer lain.&lt;/li&gt;
      &lt;li&gt;Pelacakan gangguan (troubleshooting) lebih sederhana karena setiap jalur kabel dapat diperiksa satu per satu dari switch pusat.&lt;/li&gt;
      &lt;li&gt;Topologi ini paling umum dan paling sesuai untuk skala satu ruangan/lab dengan jumlah perangkat menengah (± 20 unit).&lt;/li&gt;
    &lt;/ul&gt;

    &lt;h3 class="sub-title"&gt;2. Perangkat Jaringan yang Dibutuhkan&lt;/h3&gt;
    &lt;table class="compare"&gt;
      &lt;tr&gt;&lt;th&gt;Perangkat&lt;/th&gt;&lt;th&gt;Perkiraan Jumlah&lt;/th&gt;&lt;th&gt;Fungsi dalam Skema&lt;/th&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Modem&lt;/td&gt;&lt;td&gt;1 unit&lt;/td&gt;&lt;td&gt;Menghubungkan jaringan sekolah ke jalur internet dari ISP.&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Router (dengan firewall &amp; DHCP)&lt;/td&gt;&lt;td&gt;1 unit&lt;/td&gt;&lt;td&gt;Membagi alamat IP otomatis ke seluruh perangkat dan menjadi lapisan keamanan pertama jaringan.&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Switch 24-port&lt;/td&gt;&lt;td&gt;1 unit&lt;/td&gt;&lt;td&gt;Menghubungkan seluruh 21 komputer (20 siswa + 1 guru) dalam satu jaringan lokal.&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Access Point&lt;/td&gt;&lt;td&gt;1 unit&lt;/td&gt;&lt;td&gt;Menyediakan akses Wi-Fi terbatas untuk perangkat guru/tamu tanpa perlu kabel tambahan.&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Kabel UTP Cat6 + konektor RJ45&lt;/td&gt;&lt;td&gt;± 21 jalur kabel&lt;/td&gt;&lt;td&gt;Media penghubung fisik dari switch ke setiap komputer.&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;UPS (Uninterruptible Power Supply)&lt;/td&gt;&lt;td&gt;1 unit&lt;/td&gt;&lt;td&gt;Menjaga router dan switch tetap menyala saat listrik padam mendadak, mencegah kerusakan perangkat.&lt;/td&gt;&lt;/tr&gt;
    &lt;/table&gt;

    &lt;h3 class="sub-title"&gt;3. Skema Jaringan&lt;/h3&gt;
    &lt;div class="diagram-frame"&gt;
      &lt;svg viewBox="0 0 800 380" xmlns="http://www.w3.org/2000/svg"&gt;
        &lt;text x="400" y="26" text-anchor="middle" fill="#38BDF8" font-family="IBM Plex Mono, monospace" font-size="12" letter-spacing="2"&gt;SKEMA JARINGAN LAN — LABORATORIUM KOMPUTER&lt;/text&gt;

        &lt;!-- internet cloud --&gt;
        &lt;g transform="translate(345,42)"&gt;
          &lt;path d="M28 46 a22 22 0 0 1 0-44 a27 27 0 0 1 52-8 a20 20 0 0 1 2 52 z" fill="none" stroke="#38BDF8" stroke-width="2"/&gt;
          &lt;text x="55" y="27" text-anchor="middle" fill="#38BDF8" font-family="IBM Plex Mono, monospace" font-weight="700" font-size="11"&gt;INTERNET&lt;/text&gt;
        &lt;/g&gt;

        &lt;line class="signal" x1="400" y1="100" x2="400" y2="122" stroke="#38BDF8" stroke-width="2"/&gt;

        &lt;!-- modem --&gt;
        &lt;rect x="335" y="122" width="130" height="34" rx="4" fill="none" stroke="#EAF2FA" stroke-width="1.5"/&gt;
        &lt;text x="400" y="143" text-anchor="middle" fill="#EAF2FA" font-family="IBM Plex Mono, monospace" font-size="11"&gt;MODEM&lt;/text&gt;

        &lt;line class="signal" x1="400" y1="156" x2="400" y2="178" stroke="#38BDF8" stroke-width="2"/&gt;

        &lt;!-- router --&gt;
        &lt;rect x="300" y="178" width="200" height="40" rx="4" fill="none" stroke="#F2B84B" stroke-width="1.5"/&gt;
        &lt;text x="400" y="199" text-anchor="middle" fill="#F2B84B" font-family="IBM Plex Mono, monospace" font-weight="700" font-size="11"&gt;ROUTER&lt;/text&gt;
        &lt;text x="400" y="212" text-anchor="middle" fill="#C3D3E0" font-family="IBM Plex Mono, monospace" font-size="8"&gt;Firewall aktif + DHCP&lt;/text&gt;

        &lt;line class="signal" x1="400" y1="218" x2="400" y2="240" stroke="#22C55E" stroke-width="2"/&gt;

        &lt;!-- switch --&gt;
        &lt;rect x="290" y="240" width="220" height="38" rx="4" fill="none" stroke="#22C55E" stroke-width="1.5"/&gt;
        &lt;text x="400" y="264" text-anchor="middle" fill="#22C55E" font-family="IBM Plex Mono, monospace" font-weight="700" font-size="11"&gt;SWITCH 24-PORT&lt;/text&gt;

        &lt;!-- fan out to PC siswa, PC guru, access point --&gt;
        &lt;line class="signal" x1="320" y1="278" x2="130" y2="330" stroke="#38BDF8" stroke-width="2"/&gt;
        &lt;line class="signal" x1="400" y1="278" x2="400" y2="330" stroke="#38BDF8" stroke-width="2"/&gt;
        &lt;line class="signal" x1="480" y1="278" x2="670" y2="330" stroke="#38BDF8" stroke-width="2"/&gt;

        &lt;rect x="45" y="330" width="170" height="38" rx="4" fill="none" stroke="#EAF2FA" stroke-width="1.5"/&gt;
        &lt;text x="130" y="350" text-anchor="middle" fill="#EAF2FA" font-family="IBM Plex Mono, monospace" font-size="10"&gt;PC SISWA (unit 1–20)&lt;/text&gt;
        &lt;text x="130" y="362" text-anchor="middle" fill="#9FB4C6" font-family="IBM Plex Mono, monospace" font-size="8"&gt;terhubung kabel UTP&lt;/text&gt;

        &lt;rect x="315" y="330" width="170" height="38" rx="4" fill="none" stroke="#EAF2FA" stroke-width="1.5"/&gt;
        &lt;text x="400" y="350" text-anchor="middle" fill="#EAF2FA" font-family="IBM Plex Mono, monospace" font-size="10"&gt;PC GURU&lt;/text&gt;
        &lt;text x="400" y="362" text-anchor="middle" fill="#9FB4C6" font-family="IBM Plex Mono, monospace" font-size="8"&gt;terhubung kabel UTP&lt;/text&gt;

        &lt;rect x="585" y="330" width="170" height="38" rx="4" fill="none" stroke="#EAF2FA" stroke-width="1.5"/&gt;
        &lt;text x="670" y="350" text-anchor="middle" fill="#EAF2FA" font-family="IBM Plex Mono, monospace" font-size="10"&gt;ACCESS POINT&lt;/text&gt;
        &lt;text x="670" y="362" text-anchor="middle" fill="#9FB4C6" font-family="IBM Plex Mono, monospace" font-size="8"&gt;Wi-Fi guru/tamu&lt;/text&gt;
      &lt;/svg&gt;
      &lt;div class="diagram-caption"&gt;Alur: Internet → Modem → Router (firewall &amp; DHCP) → Switch 24-port → seluruh PC siswa, PC guru, dan Access Point (Wi-Fi terbatas).&lt;/div&gt;
    &lt;/div&gt;

    &lt;h3 class="sub-title"&gt;4. Langkah Keamanan Dasar&lt;/h3&gt;
    &lt;div class="callout secure"&gt;
      &lt;div class="lbl"&gt;Kebijakan Keamanan Lab&lt;/div&gt;
      &lt;ul style="margin:0 0 0 1.1em;"&gt;
        &lt;li&gt;&lt;strong&gt;Password Wi-Fi kuat (WPA2/WPA3)&lt;/strong&gt; — kombinasi huruf, angka, dan simbol, diganti secara berkala tiap semester.&lt;/li&gt;
        &lt;li&gt;&lt;strong&gt;Firewall aktif di router&lt;/strong&gt; — memblokir port dan akses masuk yang tidak diperlukan dari luar jaringan sekolah.&lt;/li&gt;
        &lt;li&gt;&lt;strong&gt;Ganti kredensial admin default router/switch&lt;/strong&gt; — username dan password bawaan pabrik wajib diganti agar tidak mudah diretas.&lt;/li&gt;
        &lt;li&gt;&lt;strong&gt;Pembatasan akses pengguna&lt;/strong&gt; — akun/level akses PC guru dipisahkan dari PC siswa; siswa tidak diberi hak admin pada komputer lab.&lt;/li&gt;
        &lt;li&gt;&lt;strong&gt;Web filtering&lt;/strong&gt; — pembatasan akses ke situs yang tidak relevan dengan pembelajaran melalui pengaturan router atau software tambahan.&lt;/li&gt;
        &lt;li&gt;&lt;strong&gt;Update firmware &amp; software berkala&lt;/strong&gt; — router, switch, dan sistem operasi PC lab diperbarui rutin untuk menutup celah keamanan.&lt;/li&gt;
        &lt;li&gt;&lt;strong&gt;Backup data berkala&lt;/strong&gt; — file penting di komputer guru dicadangkan ke penyimpanan terpisah/cloud secara rutin.&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/div&gt;

    &lt;div class="callout"&gt;
      &lt;div class="lbl"&gt;Kesimpulan Tim IT Sekolah&lt;/div&gt;
      &lt;p style="margin:0;"&gt;Dengan topologi star, satu router berfirewall, satu switch 24-port, serta kebijakan password dan pembatasan akses yang jelas, laboratorium komputer sekolah dapat memiliki jaringan LAN yang sederhana untuk dikelola, mudah diperluas di masa depan, dan cukup aman untuk mendukung kegiatan belajar-mengajar sehari-hari.&lt;/p&gt;
    &lt;/div&gt;
  &lt;/section&gt;

&lt;/main&gt;

&lt;footer&gt;
  INFORMATIKA · JARINGAN KOMPUTER, INTERNET &amp; KEAMANAN DIGITAL · FASE E KELAS X SMK
&lt;/footer&gt;

&lt;script&gt;
  // ============================================================
  // KONFIGURASI PENGIRIMAN SKOR KE GOOGLE SHEETS
  // ------------------------------------------------------------
  // Google Sheets TIDAK bisa menerima data langsung dari halaman
  // web biasa. Guru WAJIB membuat Google Apps Script Web App yang
  // terhubung ke spreadsheet, lalu tempel URL Web App tersebut di
  // bawah ini menggantikan teks GANTI_DENGAN_URL_WEB_APP_ANDA.
  // Lihat instruksi lengkap yang diberikan terpisah dari file ini.
  // ============================================================
  const GAS_ENDPOINT = "https://script.google.com/macros/s/AKfycbwKp7DrBTALJMlw8crjK7RgXIO8LVcU4yVEd9WJNs_vgSXkVxfw7fwkGbOT2IBNOjg3uQ/exec";

  const QUESTIONS = [
    { q: "Jaringan komputer secara umum didefinisikan sebagai...",
      opts: ["Sekumpulan program yang berjalan otomatis di komputer",
             "Kumpulan dua atau lebih perangkat yang saling terhubung untuk berbagi data dan sumber daya",
             "Perangkat keras yang menyimpan data secara permanen",
             "Sistem operasi yang mengatur banyak pengguna sekaligus",
             "Aplikasi yang digunakan khusus untuk browsing internet"], correct: 1 },
    { q: "Jaringan yang mencakup area sangat luas seperti antar kota bahkan antar negara disebut...",
      opts: ["LAN", "PAN", "MAN", "WAN", "HAN"], correct: 3 },
    { q: "Jaringan yang biasa digunakan untuk menghubungkan perangkat dalam satu ruangan/gedung seperti lab komputer sekolah disebut...",
      opts: ["LAN", "WAN", "MAN", "Internet", "Cloud Network"], correct: 0 },
    { q: "Topologi jaringan di mana seluruh perangkat terhubung ke satu perangkat pusat (switch) disebut topologi...",
      opts: ["Bus", "Ring", "Star", "Mesh", "Tree"], correct: 2 },
    { q: "Perangkat yang menghubungkan jaringan lokal (LAN) dengan jaringan lain/internet serta menentukan jalur terbaik pengiriman data disebut...",
      opts: ["Switch", "Hub", "Modem", "Router", "Repeater"], correct: 3 },
    { q: "Perangkat atau perangkat lunak yang menyaring dan mengendalikan lalu lintas data masuk/keluar jaringan berdasarkan aturan keamanan disebut...",
      opts: ["Router", "Firewall", "Switch", "Modem", "Access Point"], correct: 1 },
    { q: "Perangkat yang mengubah sinyal digital menjadi sinyal yang dapat dikirim lewat jalur ISP (dan sebaliknya) disebut...",
      opts: ["Switch", "Modem", "Router", "Access Point", "NIC"], correct: 1 },
    { q: "Alamat unik yang digunakan untuk mengidentifikasi setiap perangkat dalam sebuah jaringan disebut...",
      opts: ["URL", "DNS", "IP Address", "MAC Studio", "Domain"], correct: 2 },
    { q: "Sistem yang menerjemahkan nama domain (misalnya www.contoh.com) menjadi alamat IP yang dipahami komputer disebut...",
      opts: ["HTTP", "DNS", "FTP", "ISP", "TCP"], correct: 1 },
    { q: "Perusahaan atau lembaga yang menyediakan layanan akses internet kepada pengguna disebut...",
      opts: ["Web Hosting", "Domain Provider", "ISP (Internet Service Provider)", "Data Center", "Cloud Provider"], correct: 2 },
    { q: "Protokol untuk mengakses halaman web dengan tambahan lapisan enkripsi ditandai dengan awalan...",
      opts: ["FTP", "HTTP", "HTTPS", "SMTP", "POP3"], correct: 2 },
    { q: "Ukuran kapasitas maksimum data yang dapat ditransmisikan dalam jaringan pada waktu tertentu disebut...",
      opts: ["Latency", "Bandwidth", "Ping", "Protokol", "Bit rate error"], correct: 1 },
    { q: "Waktu tunda yang dibutuhkan data untuk berpindah dari satu titik ke titik lain dalam jaringan disebut...",
      opts: ["Bandwidth", "Throughput", "Latency", "Uptime", "Frekuensi"], correct: 2 },
    { q: "Jenis serangan digital yang menipu pengguna agar memberikan data pribadi (seperti password) melalui tautan atau pesan palsu disebut...",
      opts: ["DDoS", "Malware", "Phishing", "Spoofing perangkat keras", "Brute force fisik"], correct: 2 },
    { q: "Proses mengubah data menjadi bentuk yang tidak dapat dibaca oleh pihak yang tidak berwenang, sehingga data tetap aman saat dikirim melalui jaringan, disebut...",
      opts: ["Kompresi", "Enkripsi", "Kalibrasi", "Sinkronisasi", "Virtualisasi"], correct: 1 }
  ];

  const LETTERS = ["A","B","C","D","E"];
  const container = document.getElementById('quizContainer');

  QUESTIONS.forEach((item, qi) =&gt; {
    const card = document.createElement('div');
    card.className = 'q-card';
    const num = document.createElement('div');
    num.className = 'q-num';
    num.textContent = 'SOAL ' + (qi+1) + ' / ' + QUESTIONS.length;
    const text = document.createElement('div');
    text.className = 'q-text';
    text.textContent = (qi+1) + '. ' + item.q;
    const opts = document.createElement('div');
    opts.className = 'options';

    item.opts.forEach((optText, oi) =&gt; {
      const label = document.createElement('label');
      label.className = 'opt';
      const input = document.createElement('input');
      input.type = 'radio';
      input.name = 'q' + qi;
      input.value = oi;
      input.addEventListener('change', () =&gt; {
        opts.querySelectorAll('.opt').forEach(o =&gt; o.classList.remove('selected'));
        label.classList.add('selected');
      });
      const span = document.createElement('span');
      span.textContent = LETTERS[oi] + '. ' + optText;
      label.appendChild(input);
      label.appendChild(span);
      opts.appendChild(label);
    });

    card.appendChild(num);
    card.appendChild(text);
    card.appendChild(opts);
    container.appendChild(card);
  });

  let finalScore = null;

  document.getElementById('btnHitung').addEventListener('click', () =&gt; {
    const noAbsen = document.getElementById('noAbsen').value.trim();
    const nama = document.getElementById('nama').value.trim();
    const kelas = document.getElementById('kelas').value.trim();
    const msg = document.getElementById('quizMsg');

    if (!noAbsen || !nama || !kelas) {
      msg.textContent = 'Lengkapi No. Absen, Nama, dan Kelas terlebih dahulu.';
      return;
    }

    let answered = 0, correct = 0;
    QUESTIONS.forEach((item, qi) =&gt; {
      const picked = document.querySelector('input[name="q' + qi + '"]:checked');
      if (picked) {
        answered++;
        if (parseInt(picked.value) === item.correct) correct++;
      }
    });

    if (answered &lt; QUESTIONS.length) {
      msg.textContent = 'Masih ada ' + (QUESTIONS.length - answered) + ' soal yang belum dijawab.';
      return;
    }

    msg.textContent = '';
    finalScore = Math.round((correct / QUESTIONS.length) * 100);

    document.getElementById('scoreValue').textContent = finalScore;
    document.getElementById('resultDetail').textContent =
      'Jawaban benar: ' + correct + ' dari ' + QUESTIONS.length + ' soal. Skor sedang dikirim ke guru...';
    document.getElementById('resultPanel').style.display = 'block';

    kirimSkor(noAbsen, nama, kelas, finalScore);
  });

  function kirimSkor(noAbsen, nama, kelas, skor) {
    const msg = document.getElementById('quizMsg');
    const btnKirim = document.getElementById('btnKirim');
    const resultDetail = document.getElementById('resultDetail');

    if (GAS_ENDPOINT.indexOf('GANTI_DENGAN_URL_WEB_APP_ANDA') !== -1) {
      msg.textContent = 'Pengiriman belum aktif — guru perlu memasang URL Apps Script terlebih dahulu.';
      btnKirim.style.display = 'inline-block';
      return;
    }

    btnKirim.disabled = true;
    msg.textContent = 'Mengirim skor...';

    fetch(GAS_ENDPOINT, {
      method: 'POST',
      mode: 'no-cors',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ noAbsen: noAbsen, nama: nama, kelas: kelas, skor: skor })
    }).then(() =&gt; {
      msg.textContent = 'Jawaban terkirim otomatis ke guru.';
      resultDetail.textContent = 'Jawaban benar: ' + Math.round(skor * QUESTIONS.length / 100) + ' dari ' + QUESTIONS.length + ' soal. Skor sudah terkirim ke guru.';
      btnKirim.style.display = 'none';
      btnKirim.disabled = false;
    }).catch(() =&gt; {
      msg.textContent = 'Gagal mengirim otomatis — klik "Kirim Ulang ke Guru", atau foto layar skor ini.';
      btnKirim.style.display = 'inline-block';
      btnKirim.disabled = false;
    });
  }

  document.getElementById('btnKirim').addEventListener('click', () =&gt; {
    const noAbsen = document.getElementById('noAbsen').value.trim();
    const nama = document.getElementById('nama').value.trim();
    const kelas = document.getElementById('kelas').value.trim();
    if (finalScore === null) return;
    kirimSkor(noAbsen, nama, kelas, finalScore);
  });
&lt;/script&gt;

&lt;/body&gt;
&lt;/html&gt;</description><link>http://kitab-investasi.blogspot.com/2026/08/jaringan-komputer-internet-keamanan.html</link><thr:total>0</thr:total><author>nof_rizal07@yahoo.co.id (abang_cool)</author></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-9000860041661554971.post-5361175741707973809</guid><pubDate>Fri, 14 Aug 2026 00:50:06 +0000</pubDate><atom:updated>2026-08-14T10:17:18.742+07:00</atom:updated><title>Pemetaan Profil Growth Mindset Murid</title><description>&lt;!DOCTYPE html&gt;
&lt;html lang="id"&gt;
&lt;head&gt;
&lt;meta charset="UTF-8"&gt;
&lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&gt;
&lt;title&gt;Pemetaan Growth Mindset Murid — SMKN 1 Tuntang&lt;/title&gt;
&lt;style&gt;
  :root{
    --navy:#152238;
    --navy-2:#1F3454;
    --steel:#3D5A80;
    --amber:#E8A33D;
    --amber-dark:#C97F1B;
    --paper:#F5F6F8;
    --card:#FFFFFF;
    --ink:#1B2333;
    --ink-soft:#5A6478;
    --line:#E1E4EA;
    --growth:#2E7D5B;
    --fixed:#B0532B;
    --radius:14px;
  }
  *{box-sizing:border-box;}
  body{
    margin:0;
    font-family:'Segoe UI',-apple-system,BlinkMacSystemFont,'Inter',Arial,sans-serif;
    background:var(--paper);
    color:var(--ink);
  }
  .topbar{
    background:linear-gradient(120deg,var(--navy) 0%,var(--navy-2) 100%);
    color:#fff;
    padding:36px 20px 90px;
    position:relative;
    overflow:hidden;
  }
  .topbar::after{
    content:"";
    position:absolute;
    right:-60px; top:-60px;
    width:220px; height:220px;
    border-radius:50%;
    background:radial-gradient(circle, rgba(232,163,61,0.25) 0%, rgba(232,163,61,0) 70%);
  }
  .topbar-inner{
    max-width:760px;
    margin:0 auto;
    position:relative;
    z-index:1;
  }
  .eyebrow{
    display:inline-block;
    font-size:12.5px;
    letter-spacing:.14em;
    text-transform:uppercase;
    color:var(--amber);
    font-weight:700;
    border:1px solid rgba(232,163,61,0.5);
    padding:5px 12px;
    border-radius:999px;
    margin-bottom:16px;
  }
  h1{
    font-size:clamp(24px,4vw,32px);
    line-height:1.25;
    margin:0 0 10px;
    font-weight:700;
  }
  .lede{
    color:#C9D2E3;
    font-size:15px;
    line-height:1.6;
    max-width:640px;
    margin:0;
  }
  .wrap{
    max-width:760px;
    margin:-56px auto 60px;
    padding:0 20px;
    position:relative;
    z-index:2;
  }
  .card{
    background:var(--card);
    border-radius:var(--radius);
    box-shadow:0 12px 30px rgba(21,34,56,0.10);
    padding:28px;
    margin-bottom:20px;
    border:1px solid var(--line);
  }
  .card h2{
    font-size:17px;
    margin:0 0 4px;
    color:var(--navy);
  }
  .card .sub{
    font-size:13px;
    color:var(--ink-soft);
    margin:0 0 18px;
  }
  label.field{
    display:block;
    font-size:13.5px;
    font-weight:600;
    color:var(--navy);
    margin-bottom:6px;
  }
  .field-wrap{margin-bottom:16px;}
  input[type=text], select{
    width:100%;
    padding:11px 13px;
    border-radius:9px;
    border:1.5px solid var(--line);
    font-size:14.5px;
    font-family:inherit;
    color:var(--ink);
    background:#fcfcfd;
  }
  input[type=text]:focus, select:focus{
    outline:none;
    border-color:var(--steel);
    box-shadow:0 0 0 3px rgba(61,90,128,0.15);
  }
  .progress-shell{
    position:sticky;
    top:0;
    z-index:20;
    background:rgba(245,246,248,0.94);
    backdrop-filter:blur(6px);
    padding:12px 20px;
    border-bottom:1px solid var(--line);
  }
  .progress-inner{
    max-width:760px;
    margin:0 auto;
    display:flex;
    align-items:center;
    gap:12px;
  }
  .progress-track{
    flex:1;
    height:7px;
    border-radius:999px;
    background:#E4E7EE;
    overflow:hidden;
  }
  .progress-fill{
    height:100%;
    width:0%;
    background:linear-gradient(90deg,var(--steel),var(--amber));
    border-radius:999px;
    transition:width .25s ease;
  }
  .progress-label{
    font-size:12.5px;
    font-weight:700;
    color:var(--navy);
    white-space:nowrap;
    min-width:64px;
    text-align:right;
  }
  .section-tag{
    display:inline-flex;
    align-items:center;
    gap:8px;
    font-size:11.5px;
    font-weight:700;
    letter-spacing:.06em;
    text-transform:uppercase;
    color:var(--steel);
    margin-bottom:14px;
  }
  .section-tag .dot{
    width:7px;height:7px;border-radius:50%;
    background:var(--amber);
  }
  .qitem{
    padding:18px 0;
    border-top:1px solid var(--line);
  }
  .qitem:first-of-type{border-top:none; padding-top:4px;}
  .qnum{
    font-size:12px;
    font-weight:700;
    color:#fff;
    background:var(--steel);
    width:22px;height:22px;
    border-radius:6px;
    display:inline-flex;
    align-items:center;
    justify-content:center;
    margin-right:8px;
    flex-shrink:0;
  }
  .qtext{
    font-size:14.5px;
    line-height:1.55;
    color:var(--ink);
    display:flex;
    margin-bottom:12px;
  }
  .qtext span.txt{padding-top:1px;}
  .opts{
    display:grid;
    grid-template-columns:repeat(4,1fr);
    gap:8px;
  }
  @media (max-width:520px){
    .opts{grid-template-columns:repeat(2,1fr);}
  }
  .opt{
    position:relative;
  }
  .opt input{
    position:absolute;
    opacity:0;
    width:100%;height:100%;
    cursor:pointer;
    margin:0;
  }
  .opt .pill{
    display:block;
    text-align:center;
    font-size:12.5px;
    font-weight:600;
    padding:10px 6px;
    border-radius:9px;
    border:1.5px solid var(--line);
    color:var(--ink-soft);
    transition:all .15s ease;
    background:#fcfcfd;
  }
  .opt input:checked + .pill{
    background:var(--navy);
    border-color:var(--navy);
    color:#fff;
  }
  .opt input:focus-visible + .pill{
    box-shadow:0 0 0 3px rgba(61,90,128,0.35);
  }
  .opt .pill:hover{border-color:var(--steel); color:var(--navy);}
  .submit-bar{
    display:flex;
    flex-direction:column;
    gap:12px;
    align-items:center;
    text-align:center;
  }
  button#submitBtn{
    width:100%;
    padding:15px;
    border:none;
    border-radius:11px;
    background:var(--amber-dark);
    color:#fff;
    font-size:15.5px;
    font-weight:700;
    cursor:pointer;
    transition:background .15s ease, transform .1s ease;
  }
  button#submitBtn:hover{background:#B06F16;}
  button#submitBtn:active{transform:scale(0.99);}
  button#submitBtn:disabled{background:#C7CCD6; cursor:not-allowed;}
  .hint{font-size:12.5px; color:var(--ink-soft);}
  .warn{
    font-size:13px;
    color:var(--fixed);
    font-weight:600;
    margin-top:6px;
    display:none;
  }
  .footer-note{
    text-align:center;
    font-size:12px;
    color:var(--ink-soft);
    margin-top:24px;
  }
  #successScreen{
    display:none;
    text-align:center;
    padding:40px 20px 70px;
    max-width:560px;
    margin:0 auto;
  }
  #successScreen .check{
    width:64px;height:64px;
    border-radius:50%;
    background:var(--growth);
    color:#fff;
    display:flex;
    align-items:center;
    justify-content:center;
    margin:0 auto 18px;
    font-size:30px;
  }
  #successScreen h2{color:var(--navy); font-size:22px; margin-bottom:8px;}
  #successScreen p{color:var(--ink-soft); font-size:14.5px; line-height:1.6;}
  #resultBox{
    margin-top:18px;
    background:var(--card);
    border:1px solid var(--line);
    border-radius:var(--radius);
    padding:20px;
    text-align:left;
  }
  #resultBox .scoreRow{display:flex; justify-content:space-between; font-size:14px; padding:6px 0; border-bottom:1px dashed var(--line);}
  #resultBox .scoreRow:last-child{border-bottom:none;}
  .catBadge{
    display:inline-block;
    padding:3px 10px;
    border-radius:999px;
    font-size:12.5px;
    font-weight:700;
    color:#fff;
  }
&lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;

&lt;div class="topbar"&gt;
  &lt;div class="topbar-inner"&gt;
    &lt;span class="eyebrow"&gt;SMKN 1 Tuntang · TJKT · Teknik Otomotif · Tata Busana&lt;/span&gt;
    &lt;h1&gt;Pemetaan Profil Growth Mindset Murid&lt;/h1&gt;
    &lt;p class="lede"&gt;Kuesioner ini diisi oleh Bapak/Ibu guru mata pelajaran untuk memetakan profil pola pikir (growth mindset) murid yang diajar, sebagai bagian dari siklus inkuiri kolaboratif identifikasi masalah pembelajaran di laboratorium/bengkel. Jawaban akan otomatis terkirim dan tersimpan.&lt;/p&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;div class="progress-shell" id="progressShell"&gt;
  &lt;div class="progress-inner"&gt;
    &lt;div class="progress-track"&gt;&lt;div class="progress-fill" id="progressFill"&gt;&lt;/div&gt;&lt;/div&gt;
    &lt;div class="progress-label" id="progressLabel"&gt;0 / 25&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;div class="wrap"&gt;

  &lt;form id="mindsetForm"&gt;

    &lt;div class="card" id="metaCard"&gt;
      &lt;h2&gt;Data Guru&lt;/h2&gt;
      &lt;p class="sub"&gt;Isi identitas Bapak/Ibu guru dan kelompok murid yang sedang dinilai.&lt;/p&gt;

      &lt;div class="field-wrap"&gt;
        &lt;label class="field"&gt;Nama Guru&lt;/label&gt;
        &lt;input type="text" id="namaGuru" required placeholder="Contoh: Nofrizal, S.Pd."&gt;
      &lt;/div&gt;

      &lt;div class="field-wrap"&gt;
        &lt;label class="field"&gt;Mata Pelajaran yang Diampu&lt;/label&gt;
        &lt;input type="text" id="mapel" required placeholder="Contoh: Produktif TJKT"&gt;
      &lt;/div&gt;

      &lt;div class="field-wrap" style="margin-bottom:0;"&gt;
        &lt;label class="field"&gt;Jurusan&lt;/label&gt;
        &lt;select id="jurusan" required&gt;
          &lt;option value="" disabled selected&gt;Pilih jurusan&lt;/option&gt;
          &lt;option value="TJKT"&gt;Teknik Jaringan Komputer dan Telekomunikasi (TJKT)&lt;/option&gt;
          &lt;option value="Teknik Otomotif"&gt;Teknik dan Bisnis Sepeda Motor (Teknik Otomotif)&lt;/option&gt;
          &lt;option value="Tata Busana"&gt;Tata Busana&lt;/option&gt;
          &lt;option value="Tata Busana"&gt;Semua Jurusan&lt;/option&gt;
        &lt;/select&gt;
      &lt;/div&gt;

      &lt;div class="field-wrap" style="margin-bottom:0; margin-top:16px;"&gt;
        &lt;label class="field"&gt;Jumlah Murid yang Dinilai (perkiraan, semua rombel di jurusan ini)&lt;/label&gt;
        &lt;input type="text" id="jumlahMurid" placeholder="Contoh: 96 murid"&gt;
      &lt;/div&gt;
    &lt;/div&gt;

    &lt;div id="questionsContainer"&gt;&lt;/div&gt;

    &lt;div class="card"&gt;
      &lt;div class="submit-bar"&gt;
        &lt;button type="submit" id="submitBtn"&gt;Kirim Jawaban&lt;/button&gt;
        &lt;div class="warn" id="warnMsg"&gt;Mohon lengkapi semua data dan jawab seluruh 25 pernyataan sebelum mengirim.&lt;/div&gt;
        &lt;div class="hint"&gt;Jawaban dikirim langsung ke rekap Google Sheet sekolah.&lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;

  &lt;/form&gt;

  &lt;div id="successScreen"&gt;
    &lt;div class="check"&gt;✓&lt;/div&gt;
    &lt;h2&gt;Jawaban Terkirim&lt;/h2&gt;
    &lt;p&gt;Terima kasih, Bapak/Ibu Guru. Pemetaan profil growth mindset murid yang diampu telah tercatat dan akan digunakan dalam siklus inkuiri kolaboratif SMKN 1 Tuntang.&lt;/p&gt;
    &lt;div id="resultBox"&gt;&lt;/div&gt;
  &lt;/div&gt;

  &lt;p class="footer-note"&gt;Presentasi Siklus Inkuiri Kolaboratif — SMKN 1 Tuntang&lt;/p&gt;
&lt;/div&gt;

&lt;script&gt;
/* ======================================================
   KONFIGURASI PENGIRIMAN DATA
   Ganti WEB_APP_URL dengan URL Web App Google Apps Script
   yang sudah di-deploy dan terhubung ke Google Sheet tujuan.
   Lihat panduan "Apps Script" yang disertakan terpisah.
====================================================== */
const WEB_APP_URL = "https://script.google.com/macros/s/AKfycbwntViLE98jkmp-xGIHAK8u13gdKyR4DY8dGMVfz77m9pqBHra7cc8bCOqlsmX3MtQadg/exec";

// type: "growth" -&gt; setuju mencerminkan growth mindset (skor SS=3..STS=0)
// type: "fixed"  -&gt; setuju mencerminkan fixed mindset (skor SS=0..STS=3)
const QUESTIONS = [
  { section:"Keyakinan tentang Kemampuan", items:[
    {t:"Murid yang saya ajar meyakini bahwa kemampuan mereka di mata pelajaran/praktik ini bisa terus berkembang melalui latihan.", type:"growth"},
    {t:"Murid yang saya ajar menganggap kemampuan praktiknya sudah menetap dan sulit untuk diubah.", type:"fixed"},
    {t:"Murid saya percaya bahwa kerja keras lebih menentukan keberhasilan dibanding bakat bawaan.", type:"growth"},
    {t:"Murid saya percaya hanya murid yang berbakat saja yang bisa unggul dalam praktik di jurusan ini.", type:"fixed"},
    {t:"Murid saya cepat puas dengan kemampuan yang sudah dimiliki dan enggan mempelajari hal baru.", type:"fixed"},
  ]},
  { section:"Sikap terhadap Tantangan &amp; Kegigihan", items:[
    {t:"Ketika menghadapi materi atau praktik yang sulit, murid saya cenderung terus mencoba hingga berhasil.", type:"growth"},
    {t:"Murid saya mudah menyerah ketika mengerjakan tugas praktik yang menantang.", type:"fixed"},
    {t:"Murid saya menganggap tantangan dalam tugas praktik sebagai kesempatan untuk berkembang.", type:"growth"},
    {t:"Murid saya menghindari tugas atau proyek praktik yang dirasa terlalu menantang.", type:"fixed"},
    {t:"Murid saya tetap berusaha semaksimal mungkin meski keterbatasan alat/bahan praktik di laboratorium atau bengkel.", type:"growth"},
    {t:"Murid saya mudah frustrasi dan berhenti berusaha ketika alat atau bahan praktik terbatas.", type:"fixed"},
  ]},
  { section:"Respon terhadap Kegagalan &amp; Kritik", items:[
    {t:"Murid saya menganggap kesalahan dalam praktik sebagai bagian wajar dari proses belajar.", type:"growth"},
    {t:"Murid saya merasa malu dan menghindar setelah melakukan kesalahan di depan teman-temannya.", type:"fixed"},
    {t:"Murid saya menunjukkan semangat yang lebih tinggi setelah mendapat kritik atau masukan dari saya.", type:"growth"},
    {t:"Murid saya bersikap defensif atau tidak senang saat menerima kritik terhadap hasil kerjanya.", type:"fixed"},
    {t:"Murid saya mau mencoba metode atau pendekatan baru saat cara sebelumnya gagal.", type:"growth"},
    {t:"Murid saya enggan mencoba cara baru karena takut gagal lagi.", type:"fixed"},
  ]},
  { section:"Rasa Ingin Tahu &amp; Motivasi Belajar", items:[
    {t:"Murid saya aktif bertanya ketika belum memahami suatu topik atau teknik praktik.", type:"growth"},
    {t:"Murid saya cenderung diam meski belum paham, karena takut dianggap tidak mampu.", type:"fixed"},
    {t:"Murid saya menunjukkan rasa ingin tahu terhadap teknik, alat, atau tren baru di bidang jurusannya.", type:"growth"},
    {t:"Secara umum, murid yang saya ajar memiliki motivasi belajar yang tinggi untuk berkembang di bidang keahliannya.", type:"growth"},
  ]},
  { section:"Kolaborasi &amp; Perkembangan Keterampilan", items:[
    {t:"Murid saya saling membantu dan berdiskusi dengan teman saat menghadapi kesulitan praktik.", type:"growth"},
    {t:"Murid saya lebih memilih bekerja sendiri dan enggan berkolaborasi saat praktik atau proyek kelompok.", type:"fixed"},
    {t:"Murid saya menunjukkan peningkatan keterampilan praktik dari waktu ke waktu selama saya ajar.", type:"growth"},
    {t:"Murid saya menunjukkan keterampilan praktik yang stagnan meski sudah diberi banyak latihan dan bimbingan.", type:"fixed"},
  ]},
];

const OPTIONS = [
  {label:"Sangat Setuju", key:"SS"},
  {label:"Setuju", key:"S"},
  {label:"Tidak Setuju", key:"TS"},
  {label:"Sangat Tidak Setuju", key:"STS"},
];

function scoreFor(type, key){
  const growthScale = {SS:3,S:2,TS:1,STS:0};
  const fixedScale  = {SS:0,S:1,TS:2,STS:3};
  return type === "growth" ? growthScale[key] : fixedScale[key];
}

const container = document.getElementById("questionsContainer");
let qCounter = 0;
let totalQuestions = 0;
QUESTIONS.forEach(sec =&gt; totalQuestions += sec.items.length);

QUESTIONS.forEach((sec) =&gt; {
  const card = document.createElement("div");
  card.className = "card";
  const tag = document.createElement("div");
  tag.className = "section-tag";
  tag.innerHTML = '&lt;span class="dot"&gt;&lt;/span&gt;' + sec.section;
  card.appendChild(tag);

  sec.items.forEach((item) =&gt; {
    qCounter++;
    const qid = "q" + qCounter;
    const qDiv = document.createElement("div");
    qDiv.className = "qitem";

    const qText = document.createElement("div");
    qText.className = "qtext";
    qText.innerHTML = '&lt;span class="qnum"&gt;' + qCounter + '&lt;/span&gt;&lt;span class="txt"&gt;' + item.t + '&lt;/span&gt;';
    qDiv.appendChild(qText);

    const opts = document.createElement("div");
    opts.className = "opts";
    OPTIONS.forEach((o) =&gt; {
      const optDiv = document.createElement("label");
      optDiv.className = "opt";
      optDiv.innerHTML =
        '&lt;input type="radio" name="' + qid + '" value="' + o.key + '" data-type="' + item.type + '" data-text="' + item.t.replace(/"/g,'&amp;quot;') + '" required&gt;' +
        '&lt;span class="pill"&gt;' + o.label + '&lt;/span&gt;';
      opts.appendChild(optDiv);
    });
    qDiv.appendChild(opts);
    card.appendChild(qDiv);
  });

  container.appendChild(card);
});

document.getElementById("progressLabel").textContent = "0 / " + totalQuestions;

function updateProgress(){
  const answered = new Set();
  document.querySelectorAll('#questionsContainer input[type=radio]:checked').forEach(r =&gt; answered.add(r.name));
  const n = answered.size;
  document.getElementById("progressLabel").textContent = n + " / " + totalQuestions;
  document.getElementById("progressFill").style.width = (n / totalQuestions * 100) + "%";
}
container.addEventListener("change", updateProgress);

function categorize(total, maxScore){
  const f1 = Math.round(maxScore * (20/60));
  const f2 = Math.round(maxScore * (33/60));
  const f3 = Math.round(maxScore * (44/60));
  if(total &lt;= f1) return {label:"Fixed Mindset (F)", color:"#B0532B"};
  if(total &lt;= f2) return {label:"Fixed-Growth (FG)", color:"#C97F1B"};
  if(total &lt;= f3) return {label:"Growth-Fixed (GF)", color:"#3D5A80"};
  return {label:"Growth Mindset (G)", color:"#2E7D5B"};
}

document.getElementById("mindsetForm").addEventListener("submit", function(e){
  e.preventDefault();

  const namaGuru = document.getElementById("namaGuru").value.trim();
  const mapel = document.getElementById("mapel").value.trim();
  const jurusan = document.getElementById("jurusan").value;
  const jumlahMurid = document.getElementById("jumlahMurid").value.trim();

  const checked = document.querySelectorAll('#questionsContainer input[type=radio]:checked');
  const warnMsg = document.getElementById("warnMsg");

  if(!namaGuru || !mapel || !jurusan || checked.length &lt; totalQuestions){
    warnMsg.style.display = "block";
    window.scrollTo({top:0, behavior:"smooth"});
    return;
  }
  warnMsg.style.display = "none";

  let total = 0;
  const answers = {};
  checked.forEach((r) =&gt; {
    const s = scoreFor(r.dataset.type, r.value);
    total += s;
    answers[r.name + "_jawaban"] = r.value;
    answers[r.name + "_skor"] = s;
  });
  const maxScore = totalQuestions * 3;
  const cat = categorize(total, maxScore);

  const payload = Object.assign({
    timestamp: new Date().toISOString(),
    namaGuru: namaGuru,
    mapel: mapel,
    jurusan: jurusan,
    jumlahMurid: jumlahMurid,
    totalSkor: total,
    skorMaksimal: maxScore,
    kategori: cat.label,
  }, answers);

  const submitBtn = document.getElementById("submitBtn");
  submitBtn.disabled = true;
  submitBtn.textContent = "Mengirim...";

  const formData = new URLSearchParams();
  Object.keys(payload).forEach(k =&gt; formData.append(k, payload[k]));

  fetch(WEB_APP_URL, {
    method: "POST",
    mode: "no-cors",
    body: formData
  }).catch(function(err){
    console.warn("Pengiriman ke Google Sheet gagal atau tidak dapat dikonfirmasi (mode no-cors):", err);
  }).finally(function(){
    document.getElementById("mindsetForm").style.display = "none";
    document.getElementById("progressShell").style.display = "none";
    const successScreen = document.getElementById("successScreen");
    successScreen.style.display = "block";
    document.getElementById("resultBox").innerHTML =
      '&lt;div class="scoreRow"&gt;&lt;span&gt;Guru&lt;/span&gt;&lt;b&gt;' + namaGuru + '&lt;/b&gt;&lt;/div&gt;' +
      '&lt;div class="scoreRow"&gt;&lt;span&gt;Jurusan&lt;/span&gt;&lt;b&gt;' + jurusan + '&lt;/b&gt;&lt;/div&gt;' +
      '&lt;div class="scoreRow"&gt;&lt;span&gt;Total Skor&lt;/span&gt;&lt;b&gt;' + total + ' / ' + maxScore + '&lt;/b&gt;&lt;/div&gt;' +
      '&lt;div class="scoreRow"&gt;&lt;span&gt;Kategori Mindset&lt;/span&gt;&lt;span class="catBadge" style="background:' + cat.color + '"&gt;' + cat.label + '&lt;/span&gt;&lt;/div&gt;';
    window.scrollTo({top:0, behavior:"smooth"});
  });
});
&lt;/script&gt;

&lt;/body&gt;
&lt;/html&gt;</description><link>http://kitab-investasi.blogspot.com/2026/08/pemetaan-growth-mindset-murid-smkn-1.html</link><thr:total>0</thr:total><author>nof_rizal07@yahoo.co.id (abang_cool)</author></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-9000860041661554971.post-575736118791912939</guid><pubDate>Wed, 12 Aug 2026 02:46:19 +0000</pubDate><atom:updated>2026-08-12T10:09:55.509+07:00</atom:updated><title>Kaidah Kebahasaan Teks Prosedur (Bagian 2) &amp; Menyusun Teks Prosedur</title><description>&lt;style&gt;
@import url('https://fonts.googleapis.com/css2?family=Oswald:wght@400;500;600;700&amp;family=Source+Sans+3:wght@400;500;600;700&amp;family=IBM+Plex+Mono:wght@400;500;600&amp;display=swap');
.epb{
  --blueprint:#0F2A3D;
  --blueprint-deep:#0A1E2C;
  --panel:#4A2E12;
  --paper:#F3F0E6;
  --ink:#132029;
  --amber:#F5A623;
  --amber-deep:#C97F12;
  --mint:#6EC6CA;
  --line:rgba(234,242,245,0.16);
  --off-white:#EAF2F5;
  --muted:#9FB4C2;
}
.epb *{box-sizing:border-box;}
.epb{scroll-behavior:smooth; background:#0A1F2E;}
.epb{
  margin:0;
  position:relative;
  overflow:hidden;
  background:var(--blueprint);
  color:var(--off-white);
  font-family:'Source Sans 3',sans-serif;
  line-height:1.65;
  background-image:
    linear-gradient(var(--line) 1px, transparent 1px),
    linear-gradient(90deg, var(--line) 1px, transparent 1px);
  background-size: 34px 34px;
}
.epb h1, .epb h2, .epb h3, .epb h4{font-family:'Oswald',sans-serif; text-transform:uppercase; letter-spacing:0.02em; margin:0 0 0.5em;}
.epb .mono{font-family:'IBM Plex Mono',monospace;}
.epb a{color:var(--amber);}
.epb .crop{position:absolute; width:22px; height:22px; z-index:5; opacity:.55; pointer-events:none;}
.epb .crop::before, .epb .crop::after{content:"";position:absolute;background:var(--mint);}
.epb .crop::before{width:100%;height:1px;top:50%;left:0;}
.epb .crop::after{width:1px;height:100%;left:50%;top:0;}
.epb .crop.tl{top:14px;left:14px;}
.epb .crop.tr{top:14px;right:14px;}
.epb .crop.bl{bottom:14px;left:14px;}
.epb .crop.br{bottom:14px;right:14px;}
.epb header.cover{
  position:relative;
  padding:40px 24px 36px;
  border-bottom:1px solid var(--line);
  overflow:hidden;
}
.epb .doc-code{font-family:'IBM Plex Mono',monospace; color:var(--amber); letter-spacing:0.15em; font-size:0.78rem; text-transform:uppercase; margin-bottom:18px; display:flex; gap:10px; align-items:center;}
.epb .doc-code::before{content:"◆"; color:var(--amber);}
.epb .cover h1{font-size:clamp(1.6rem,7vw,2.5rem); color:var(--off-white); max-width:16ch; line-height:1.05;}
.epb .cover .subtitle{color:var(--muted); font-size:1.05rem; max-width:60ch; margin-top:14px;}
.epb .meta-strip{
  margin-top:38px; display:grid; grid-template-columns:repeat(auto-fit,minmax(150px,1fr));
  border-top:1px dashed var(--line); border-bottom:1px dashed var(--line);
}
.epb .meta-strip div{padding:14px 16px; border-right:1px dashed var(--line);}
.epb .meta-strip div:last-child{border-right:none;}
.epb .meta-strip .k{font-family:'IBM Plex Mono',monospace; font-size:0.68rem; color:var(--amber); text-transform:uppercase; letter-spacing:0.1em;}
.epb .meta-strip .v{font-size:0.98rem; color:var(--off-white); margin-top:4px; font-weight:600;}
.epb .stamp{
  position:absolute; top:40px; right:20px; width:104px; height:104px;
  border:2.5px solid var(--amber); border-radius:50%;
  display:flex; align-items:center; justify-content:center;
  transform:rotate(-11deg);
  color:var(--amber); font-family:'IBM Plex Mono',monospace;
  text-align:center; font-size:0.62rem; letter-spacing:0.08em; text-transform:uppercase;
  opacity:0.9;
}
.epb .stamp .ring{position:absolute; inset:8px; border:1px dashed var(--amber); border-radius:50%;}
.epb .stamp b{display:block; font-family:'Oswald',sans-serif; font-size:1.05rem; letter-spacing:0.06em; margin-top:4px;}

@media (max-width:760px){.epb .stamp{display:none;}
.epb }


.epb main{max-width:920px; margin:0 auto; padding:0 20px 60px;}
.epb .section{padding-top:64px;}
.epb .eyebrow{font-family:'IBM Plex Mono',monospace; color:var(--amber); font-size:0.78rem; letter-spacing:0.14em; text-transform:uppercase; margin-bottom:10px; display:flex; align-items:center; gap:10px;}
.epb .eyebrow::after{content:""; flex:1; height:1px; background:var(--line);}
.epb h2.section-title{font-size:1.7rem; color:var(--off-white);}
.epb p{color:#DDE7EC;}
.epb .lead{color:var(--muted); font-size:1.02rem; max-width:72ch;}
.epb .panel{
  background:var(--panel); border:1px solid var(--line); border-radius:2px;
  padding:26px 28px; margin:22px 0;
}
.epb .panel.tp{border-left:4px solid var(--mint);}
.epb .panel.warn{border-left:4px solid var(--amber);}
.epb .tp-box{display:grid; gap:14px; margin-top:18px;}
.epb .tp-item{display:flex; gap:14px; align-items:flex-start;}
.epb .tp-item .idx{font-family:'IBM Plex Mono',monospace; color:var(--amber); font-weight:600; min-width:34px;}
.epb .flow{display:grid; grid-template-columns:repeat(auto-fit,minmax(220px,1fr)); gap:14px; margin-top:20px;}
.epb .flow .step{background:var(--blueprint-deep); border:1px solid var(--line); padding:18px; position:relative;}
.epb .flow .step .tag{font-family:'IBM Plex Mono',monospace; color:var(--amber); font-size:0.7rem; letter-spacing:0.1em; text-transform:uppercase;}
.epb .flow .step h4{font-size:1rem; margin-top:8px; color:var(--off-white);}
.epb .flow .step .time{position:absolute; top:16px; right:16px; font-family:'IBM Plex Mono',monospace; font-size:0.7rem; color:var(--amber);}
.epb .grid-3{display:grid; grid-template-columns:repeat(auto-fit,minmax(200px,1fr)); gap:14px; margin-top:16px;}
.epb .card{background:var(--blueprint-deep); border:1px solid var(--line); padding:18px;}
.epb .card h4{color:var(--amber); font-size:0.95rem;}
.epb .criteria{display:grid; gap:16px; margin-top:20px;}
.epb .crit{
  background:var(--blueprint-deep); border:1px solid var(--line);
  display:grid; grid-template-columns:64px 1fr; gap:0;
}
.epb .crit .num{
  background:var(--amber); color:var(--blueprint-deep); font-family:'IBM Plex Mono',monospace;
  font-weight:700; display:flex; align-items:center; justify-content:center; font-size:1.05rem;
}
.epb .crit .body{padding:18px 20px;}
.epb .crit h4{color:var(--off-white); font-size:1.02rem; margin-bottom:6px;}
.epb .crit .q{margin-top:10px; padding-top:10px; border-top:1px dashed var(--line); font-family:'IBM Plex Mono',monospace; font-size:0.86rem; color:var(--amber);}
.epb .timeline{margin-top:24px; position:relative; padding-left:34px;}
.epb .timeline::before{content:""; position:absolute; left:11px; top:6px; bottom:6px; width:2px; background:var(--line);}
.epb .tl-item{position:relative; padding-bottom:26px;}
.epb .tl-item:last-child{padding-bottom:0;}
.epb .tl-item::before{content:""; position:absolute; left:-34px; top:2px; width:22px; height:22px; border-radius:50%; background:var(--blueprint); border:2px solid var(--amber);}
.epb .tl-item h4{color:var(--off-white); font-size:1rem; margin-bottom:4px;}
.epb .doc-sample{
  background:var(--paper); color:var(--ink); border-radius:2px; padding:0; margin-top:22px;
  box-shadow:0 20px 45px rgba(0,0,0,0.35);
}
.epb .doc-sample .doc-head{background:var(--ink); color:var(--paper); padding:12px 22px; font-family:'IBM Plex Mono',monospace; font-size:0.75rem; letter-spacing:0.1em; text-transform:uppercase; display:flex; justify-content:space-between;}
.epb .doc-sample .doc-body{padding:26px 28px 30px;}
.epb .doc-sample h3{font-family:'Oswald',sans-serif; color:var(--ink); font-size:1.25rem; text-transform:none; letter-spacing:0;}
.epb .doc-sample ol{padding-left:22px;}
.epb .doc-sample li{margin-bottom:9px;}
.epb .flag{
  display:inline-block; font-family:'IBM Plex Mono',monospace; font-size:0.7rem; font-weight:600;
  background:#D94E2A; color:#fff; padding:1px 7px; border-radius:2px; margin-left:6px; vertical-align:middle;
}
.epb .doc-sample .note-margin{margin-top:6px; font-family:'IBM Plex Mono',monospace; font-size:0.78rem; color:#8A3A1F; padding-left:8px; border-left:2px solid #D94E2A;}
.epb .legend{display:flex; flex-wrap:wrap; gap:10px 20px; margin-top:16px;}
.epb .legend span{font-family:'IBM Plex Mono',monospace; font-size:0.78rem; color:var(--muted); display:flex; align-items:center; gap:8px;}
.epb .legend .dot{width:10px; height:10px; border-radius:50%; display:inline-block;}
.epb table{width:100%; border-collapse:collapse; margin-top:18px; font-size:0.94rem;}
.epb th, .epb td{border:1px solid var(--line); padding:10px 12px; text-align:left; vertical-align:top;}
.epb th{background:var(--blueprint-deep); font-family:'IBM Plex Mono',monospace; font-size:0.75rem; text-transform:uppercase; letter-spacing:0.06em; color:var(--amber);}
.epb .summary-box{
  border:1px solid var(--amber); background:linear-gradient(180deg, rgba(245,166,35,0.08), transparent);
  padding:24px 26px; margin-top:24px;
}
.epb .summary-box ul{margin:10px 0 0; padding-left:20px;}
.epb .summary-box li{margin-bottom:8px;}
.epb .task-header{
  background:var(--amber); color:var(--blueprint-deep); padding:22px 26px; margin-top:20px;
  display:flex; justify-content:space-between; align-items:center; flex-wrap:wrap; gap:10px;
}
.epb .task-header h2{color:var(--blueprint-deep); font-size:1.4rem; margin:0;}
.epb .task-header .badge{font-family:'IBM Plex Mono',monospace; font-size:0.8rem; background:var(--blueprint-deep); color:var(--amber); padding:6px 12px; border-radius:2px;}
.epb .steps-num{counter-reset:step; margin-top:18px; list-style:none; padding:0;}
.epb .steps-num li{counter-increment:step; position:relative; padding-left:44px; margin-bottom:16px;}
.epb .steps-num li::before{content:counter(step,decimal-leading-zero); position:absolute; left:0; top:0; font-family:'IBM Plex Mono',monospace; color:var(--amber); font-weight:600; font-size:0.95rem; border:1px solid var(--amber); width:30px; height:26px; display:flex; align-items:center; justify-content:center;}
.epb .rubric-scale{display:grid; grid-template-columns:repeat(4,1fr); gap:10px; margin-top:16px;}
.epb .rubric-scale div{background:var(--blueprint-deep); border:1px solid var(--line); padding:12px; text-align:center;}
.epb .rubric-scale .n{font-family:'IBM Plex Mono',monospace; color:var(--amber); font-size:1.3rem; font-weight:700;}
.epb .rubric-scale .l{font-size:0.78rem; color:var(--muted); text-transform:uppercase; letter-spacing:0.05em;}
.epb .notebook{
  background:repeating-linear-gradient(var(--paper), var(--paper) 33px, #D8D3C2 34px);
  color:var(--ink); border-radius:2px; padding:28px 30px; margin-top:20px; position:relative;
  box-shadow:0 20px 45px rgba(0,0,0,0.35);
}
.epb .notebook::before{content:""; position:absolute; left:46px; top:0; bottom:0; width:1.5px; background:#C0453A; opacity:0.5;}
.epb .notebook .content{padding-left:24px;}
.epb .notebook h3{color:var(--ink); font-family:'Oswald',sans-serif; letter-spacing:0.02em; margin-bottom:10px;}
.epb .notebook ul{padding-left:20px;}
.epb footer{border-top:1px solid var(--line); padding:24px 20px 40px; color:var(--muted); font-size:0.86rem;}
.epb footer .doc-code{margin-bottom:10px;}
.epb .divider-dash{border:none; border-top:1px dashed var(--line); margin:44px 0 0;}
.epb::selection{background:var(--amber); color:var(--blueprint-deep);}

&lt;/style&gt;
&lt;div class="epb"&gt;
&lt;div class="crop tl"&gt;&lt;/div&gt;&lt;div class="crop tr"&gt;&lt;/div&gt;&lt;div class="crop bl"&gt;&lt;/div&gt;&lt;div class="crop br"&gt;&lt;/div&gt;

&lt;header class="cover"&gt;
  &lt;div class="stamp"&gt;&lt;div class="ring"&gt;&lt;/div&gt;&lt;span&gt;Modul Ajar&lt;b&gt;Terverifikasi&lt;/b&gt;Fase F&lt;/span&gt;&lt;/div&gt;
  &lt;div class="doc-code"&gt;DOK/B.INDO/XI/PROSEDUR-KAIDAH-2 — 3 JP · 1 Pertemuan&lt;/div&gt;
  &lt;h1&gt;Kaidah Kebahasaan Teks Prosedur (Bagian 2) &amp;amp; Menyusun Teks Prosedur&lt;/h1&gt;
  &lt;p class="subtitle"&gt;Materi Bahasa Indonesia Kelas XI SMK/MAK — melatih murid menganalisis kalimat perintah, kata teknis, dan penanda wacana, serta menyusun teks prosedur secara logis dan sistematis.&lt;/p&gt;

  &lt;div class="meta-strip"&gt;
    &lt;div&gt;&lt;div class="k"&gt;Mata Pelajaran&lt;/div&gt;&lt;div class="v"&gt;Bahasa Indonesia&lt;/div&gt;&lt;/div&gt;
    &lt;div&gt;&lt;div class="k"&gt;Jenjang&lt;/div&gt;&lt;div class="v"&gt;SMK/MAK — Kelas XI&lt;/div&gt;&lt;/div&gt;
    &lt;div&gt;&lt;div class="k"&gt;Elemen&lt;/div&gt;&lt;div class="v"&gt;Membaca, Memirsa &amp;amp; Menulis&lt;/div&gt;&lt;/div&gt;
    &lt;div&gt;&lt;div class="k"&gt;Alokasi Waktu&lt;/div&gt;&lt;div class="v"&gt;3 JP (3 × 45 menit)&lt;/div&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/header&gt;

&lt;main&gt;

  &lt;!-- ============ TUJUAN PEMBELAJARAN ============ --&gt;
  &lt;section class="section" id="tujuan"&gt;
    &lt;div class="eyebrow"&gt;01 — Identitas Pembelajaran&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Capaian &amp;amp; Tujuan Pembelajaran&lt;/h2&gt;

    &lt;div class="panel tp"&gt;
      &lt;div class="eyebrow" style="margin-bottom:6px;"&gt;Capaian Pembelajaran (Elemen Membaca–Memirsa &amp;amp; Menulis)&lt;/div&gt;
      &lt;p&gt;Murid mampu menganalisis kaidah kebahasaan pada berbagai jenis teks, termasuk teks prosedur, serta menulis teks prosedur secara logis dan sistematis dengan memperhatikan struktur dan kaidah kebahasaan yang tepat.&lt;/p&gt;
    &lt;/div&gt;

    &lt;div class="panel"&gt;
      &lt;div class="eyebrow" style="margin-bottom:6px;"&gt;Tujuan Pembelajaran&lt;/div&gt;
      &lt;p style="font-size:1.05rem; color:var(--off-white); font-weight:600;"&gt;Murid mampu menganalisis penggunaan kalimat perintah, kata teknis, dan penanda wacana, serta menyusun teks prosedur secara logis dan sistematis.&lt;/p&gt;

      &lt;div class="tp-box"&gt;
        &lt;div class="tp-item"&gt;&lt;span class="idx mono"&gt;TP.1&lt;/span&gt;&lt;p&gt;Murid dapat menganalisis variasi bentuk dan fungsi kalimat perintah dalam teks prosedur.&lt;/p&gt;&lt;/div&gt;
        &lt;div class="tp-item"&gt;&lt;span class="idx mono"&gt;TP.2&lt;/span&gt;&lt;p&gt;Murid dapat mengidentifikasi kata teknis dalam teks prosedur beserta fungsinya.&lt;/p&gt;&lt;/div&gt;
        &lt;div class="tp-item"&gt;&lt;span class="idx mono"&gt;TP.3&lt;/span&gt;&lt;p&gt;Murid dapat mengidentifikasi penanda wacana dan menjelaskan fungsinya dalam menjaga keterpaduan teks.&lt;/p&gt;&lt;/div&gt;
        &lt;div class="tp-item"&gt;&lt;span class="idx mono"&gt;TP.4&lt;/span&gt;&lt;p&gt;Murid dapat menyusun teks prosedur baru secara logis dan sistematis dengan menerapkan ketiga kaidah kebahasaan tersebut.&lt;/p&gt;&lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;

    &lt;div class="eyebrow" style="margin-top:26px; margin-bottom:6px;"&gt;8 Profil Lulusan yang Dikembangkan&lt;/div&gt;
    &lt;div class="grid-3"&gt;
      &lt;div class="card"&gt;&lt;h4&gt;Penalaran Kritis&lt;/h4&gt;&lt;p style="font-size:0.9rem;"&gt;Menganalisis fungsi kalimat perintah, kata teknis, dan penanda wacana dalam teks.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;h4&gt;Kreativitas&lt;/h4&gt;&lt;p style="font-size:0.9rem;"&gt;Menyusun teks prosedur baru secara orisinal dan sistematis.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;h4&gt;Kolaborasi&lt;/h4&gt;&lt;p style="font-size:0.9rem;"&gt;Bekerja sama dalam kelompok saat menyusun teks prosedur.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;h4&gt;Komunikasi&lt;/h4&gt;&lt;p style="font-size:0.9rem;"&gt;Menyampaikan hasil analisis dan teks prosedur yang disusun secara jelas.&lt;/p&gt;&lt;/div&gt;
    &lt;/div&gt;
  &lt;/section&gt;

  &lt;hr class="divider-dash"&gt;

  &lt;!-- ============ MATERI A: RECAP BAGIAN 1 ============ --&gt;
  &lt;section class="section" id="materi-a"&gt;
    &lt;div class="eyebrow"&gt;02 — Materi Inti A&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Mengingat Kembali Kaidah Kebahasaan Teks Prosedur (Bagian 1)&lt;/h2&gt;
    &lt;p class="lead"&gt;Pada pertemuan sebelumnya, murid telah mempelajari empat ciri kebahasaan teks prosedur. Materi hari ini melanjutkan dengan tiga ciri kebahasaan tambahan, sekaligus mempelajari cara menyusun teks prosedur.&lt;/p&gt;

    &lt;div class="grid-3"&gt;
      &lt;div class="card"&gt;&lt;h4&gt;Kalimat Imperatif&lt;/h4&gt;&lt;p style="font-size:0.9rem;"&gt;Mengarahkan pembaca melakukan tindakan.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;h4&gt;Kalimat Deklaratif&lt;/h4&gt;&lt;p style="font-size:0.9rem;"&gt;Menyampaikan fakta atau informasi pendukung.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;h4&gt;Kalimat Persuasif&lt;/h4&gt;&lt;p style="font-size:0.9rem;"&gt;Membujuk pembaca mengikuti langkah dengan sungguh-sungguh.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;h4&gt;Konjungsi Temporal&lt;/h4&gt;&lt;p style="font-size:0.9rem;"&gt;Menandai urutan waktu antarlangkah.&lt;/p&gt;&lt;/div&gt;
    &lt;/div&gt;
  &lt;/section&gt;

  &lt;hr class="divider-dash"&gt;

  &lt;!-- ============ MATERI B: KALIMAT PERINTAH ============ --&gt;
  &lt;section class="section" id="materi-b"&gt;
    &lt;div class="eyebrow"&gt;03 — Materi Inti B&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Kalimat Perintah dalam Teks Prosedur&lt;/h2&gt;
    &lt;p class="lead"&gt;Kalimat perintah merupakan bentuk khusus kalimat imperatif yang memiliki beberapa variasi sesuai maksud penyampaiannya.&lt;/p&gt;

    &lt;div class="criteria"&gt;
      &lt;div class="crit"&gt;
        &lt;div class="num mono"&gt;1&lt;/div&gt;
        &lt;div class="body"&gt;
          &lt;h4&gt;Perintah Biasa&lt;/h4&gt;
          &lt;p style="margin:0;"&gt;Mengarahkan pembaca melakukan tindakan secara langsung.&lt;/p&gt;
          &lt;div class="q"&gt;Contoh: "Sambungkan kabel ke sumber listrik."&lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;
      &lt;div class="crit"&gt;
        &lt;div class="num mono"&gt;2&lt;/div&gt;
        &lt;div class="body"&gt;
          &lt;h4&gt;Perintah Larangan&lt;/h4&gt;
          &lt;p style="margin:0;"&gt;Melarang pembaca melakukan suatu tindakan tertentu.&lt;/p&gt;
          &lt;div class="q"&gt;Contoh: "Jangan sentuh permukaan yang masih panas."&lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;
      &lt;div class="crit"&gt;
        &lt;div class="num mono"&gt;3&lt;/div&gt;
        &lt;div class="body"&gt;
          &lt;h4&gt;Perintah Ajakan&lt;/h4&gt;
          &lt;p style="margin:0;"&gt;Mengajak pembaca melakukan tindakan dengan nada lebih halus.&lt;/p&gt;
          &lt;div class="q"&gt;Contoh: "Mari kita mulai dengan menyiapkan alat terlebih dahulu."&lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;
      &lt;div class="crit"&gt;
        &lt;div class="num mono"&gt;4&lt;/div&gt;
        &lt;div class="body"&gt;
          &lt;h4&gt;Perintah Permintaan&lt;/h4&gt;
          &lt;p style="margin:0;"&gt;Meminta pembaca melakukan sesuatu dengan nada sopan.&lt;/p&gt;
          &lt;div class="q"&gt;Contoh: "Tolong perhatikan indikator suhu sebelum melanjutkan."&lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/section&gt;

  &lt;hr class="divider-dash"&gt;

  &lt;!-- ============ MATERI C: KATA TEKNIS ============ --&gt;
  &lt;section class="section" id="materi-c"&gt;
    &lt;div class="eyebrow"&gt;04 — Materi Inti C&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Kata Teknis dalam Teks Prosedur&lt;/h2&gt;

    &lt;div class="panel"&gt;
      &lt;p&gt;&lt;b style="color:var(--off-white);"&gt;Kata teknis&lt;/b&gt; adalah istilah khusus yang digunakan dalam bidang keahlian tertentu, jarang dipakai dalam percakapan sehari-hari, dan berfungsi memberikan ketepatan serta presisi pada instruksi yang disampaikan.&lt;/p&gt;
    &lt;/div&gt;

    &lt;div class="grid-3"&gt;
      &lt;div class="card"&gt;&lt;h4&gt;Bidang Otomotif&lt;/h4&gt;&lt;p style="font-size:0.9rem;"&gt;karburator, velg, pentil, kampas rem&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;h4&gt;Bidang Tata Boga&lt;/h4&gt;&lt;p style="font-size:0.9rem;"&gt;mengocok, memfermentasi, mengukus, marinasi&lt;/p&gt;&lt;/div&gt;
      &lt;div class="card"&gt;&lt;h4&gt;Bidang Teknik Komputer&lt;/h4&gt;&lt;p style="font-size:0.9rem;"&gt;partisi, ekstensi file, restart, defrag&lt;/p&gt;&lt;/div&gt;
    &lt;/div&gt;
    &lt;p class="lead" style="margin-top:14px;"&gt;&lt;b style="color:var(--off-white);"&gt;Fungsi:&lt;/b&gt; memastikan pembaca yang memahami bidang tersebut dapat mengikuti instruksi secara akurat tanpa salah tafsir.&lt;/p&gt;
  &lt;/section&gt;

  &lt;hr class="divider-dash"&gt;

  &lt;!-- ============ MATERI D: PENANDA WACANA ============ --&gt;
  &lt;section class="section" id="materi-d"&gt;
    &lt;div class="eyebrow"&gt;05 — Materi Inti D&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Penanda Wacana dalam Teks Prosedur&lt;/h2&gt;

    &lt;div class="panel"&gt;
      &lt;p&gt;&lt;b style="color:var(--off-white);"&gt;Penanda wacana&lt;/b&gt; adalah kata atau frasa yang mengatur hubungan antarkalimat atau antarparagraf dalam sebuah teks, sehingga teks menjadi padu dan mudah dipahami. Penanda wacana tidak hanya menunjukkan urutan waktu, tetapi juga penambahan, penekanan, dan simpulan.&lt;/p&gt;
    &lt;/div&gt;

    &lt;table&gt;
      &lt;tr&gt;&lt;th style="width:24%;"&gt;Jenis Penanda Wacana&lt;/th&gt;&lt;th style="width:38%;"&gt;Contoh Kata/Frasa&lt;/th&gt;&lt;th&gt;Fungsi&lt;/th&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Penanda Urutan&lt;/td&gt;&lt;td&gt;pertama-tama, selanjutnya, berikutnya&lt;/td&gt;&lt;td&gt;Menunjukkan urutan langkah&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Penanda Penambahan&lt;/td&gt;&lt;td&gt;selain itu, di samping itu, lagi pula&lt;/td&gt;&lt;td&gt;Menambahkan informasi baru&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Penanda Penekanan&lt;/td&gt;&lt;td&gt;perlu diperhatikan, yang terpenting, perlu diingat&lt;/td&gt;&lt;td&gt;Menegaskan bagian penting&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Penanda Simpulan&lt;/td&gt;&lt;td&gt;dengan demikian, oleh karena itu, jadi&lt;/td&gt;&lt;td&gt;Menyimpulkan atau menegaskan hasil akhir&lt;/td&gt;&lt;/tr&gt;
    &lt;/table&gt;
  &lt;/section&gt;

  &lt;hr class="divider-dash"&gt;

  &lt;!-- ============ MATERI E: MENYUSUN TEKS PROSEDUR ============ --&gt;
  &lt;section class="section" id="materi-e"&gt;
    &lt;div class="eyebrow"&gt;06 — Materi Inti E&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Menyusun Teks Prosedur secara Logis dan Sistematis&lt;/h2&gt;

    &lt;div class="timeline"&gt;
      &lt;div class="tl-item"&gt;&lt;h4 class="mono"&gt;01 · Menentukan Tujuan&lt;/h4&gt;&lt;p&gt;Tentukan tujuan atau hasil akhir yang ingin dicapai dari prosedur yang akan disusun.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="tl-item"&gt;&lt;h4 class="mono"&gt;02 · Mendaftar Alat &amp;amp; Bahan&lt;/h4&gt;&lt;p&gt;Susun daftar alat dan bahan yang diperlukan, jika prosedur membutuhkannya.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="tl-item"&gt;&lt;h4 class="mono"&gt;03 · Merancang Langkah secara Berurutan&lt;/h4&gt;&lt;p&gt;Susun langkah-langkah sesuai urutan logis, tanpa ada langkah yang meloncat atau bertentangan.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="tl-item"&gt;&lt;h4 class="mono"&gt;04 · Menerapkan Kaidah Kebahasaan&lt;/h4&gt;&lt;p&gt;Gunakan kalimat perintah, kata teknis, dan penanda wacana yang tepat pada setiap bagian teks.&lt;/p&gt;&lt;/div&gt;
      &lt;div class="tl-item"&gt;&lt;h4 class="mono"&gt;05 · Merevisi Keruntutan Teks&lt;/h4&gt;&lt;p&gt;Baca ulang teks yang disusun untuk memastikan urutan sudah logis dan mudah diikuti pembaca.&lt;/p&gt;&lt;/div&gt;
    &lt;/div&gt;
  &lt;/section&gt;

  &lt;hr class="divider-dash"&gt;

  &lt;!-- ============ MATERI F: TABEL RANGKUMAN ============ --&gt;
  &lt;section class="section" id="materi-f"&gt;
    &lt;div class="eyebrow"&gt;07 — Materi Inti F&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Rangkuman Ciri Kebahasaan Bagian 2&lt;/h2&gt;

    &lt;table&gt;
      &lt;tr&gt;&lt;th style="width:20%;"&gt;Ciri Kebahasaan&lt;/th&gt;&lt;th style="width:30%;"&gt;Fungsi&lt;/th&gt;&lt;th&gt;Contoh&lt;/th&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Kalimat Perintah&lt;/td&gt;&lt;td&gt;Mengarahkan, melarang, mengajak, atau meminta pembaca melakukan tindakan&lt;/td&gt;&lt;td&gt;"Jangan sentuh permukaan yang masih panas."&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Kata Teknis&lt;/td&gt;&lt;td&gt;Memberikan ketepatan dan presisi sesuai bidang keahlian&lt;/td&gt;&lt;td&gt;"Periksa tekanan pada pentil ban."&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Penanda Wacana&lt;/td&gt;&lt;td&gt;Menjaga keterpaduan antarkalimat/paragraf dalam teks&lt;/td&gt;&lt;td&gt;"Selain itu, pastikan area kerja dalam keadaan bersih."&lt;/td&gt;&lt;/tr&gt;
    &lt;/table&gt;
  &lt;/section&gt;

  &lt;hr class="divider-dash"&gt;

  &lt;!-- ============ PEMODELAN ============ --&gt;
  &lt;section class="section" id="contoh"&gt;
    &lt;div class="eyebrow"&gt;08 — Pemodelan&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Contoh Penerapan: Menganalisis dan Menyusun Teks Prosedur&lt;/h2&gt;
    &lt;p class="lead"&gt;Guru membacakan dan membahas bersama contoh berikut sebagai model sebelum murid mengerjakan tugas kelompok.&lt;/p&gt;

    &lt;div class="doc-sample"&gt;
      &lt;div class="doc-head"&gt;&lt;span&gt;Lampiran · Teks Prosedur Contoh&lt;/span&gt;&lt;span&gt;Dokumen-01&lt;/span&gt;&lt;/div&gt;
      &lt;div class="doc-body"&gt;
        &lt;h3 style="color:#132029 !important;"&gt;Prosedur Memasang Kartu SIM dan Kartu Memori pada Smartphone&lt;/h3&gt;
        &lt;p style="margin-top:-4px; color:#4b5a63 !important;"&gt;&lt;i&gt;Tujuan: Memasang kartu SIM dan kartu memori dengan benar agar smartphone dapat digunakan secara optimal.&lt;/i&gt;&lt;/p&gt;
        &lt;ol style="color:#132029 !important;"&gt;
          &lt;li style="color:#132029 !important;"&gt;Matikan smartphone terlebih dahulu sebelum memasang kartu.&lt;span class="flag"&gt;PERINTAH&lt;/span&gt;&lt;/li&gt;
          &lt;li style="color:#132029 !important;"&gt;Gunakan ejector pin untuk membuka slot kartu SIM.&lt;span class="flag"&gt;KATA TEKNIS&lt;/span&gt;&lt;/li&gt;
          &lt;li style="color:#132029 !important;"&gt;Letakkan kartu SIM pada baki (tray) sesuai posisi yang tertera.&lt;span class="flag"&gt;KATA TEKNIS&lt;/span&gt;&lt;/li&gt;
          &lt;li style="color:#132029 !important;"&gt;Selain itu, pastikan kartu memori terpasang pada slot yang benar agar terbaca oleh sistem.&lt;span class="flag"&gt;PENANDA WACANA&lt;/span&gt;&lt;/li&gt;
          &lt;li style="color:#132029 !important;"&gt;Masukkan kembali baki ke dalam slot hingga terdengar bunyi klik.&lt;span class="flag"&gt;PERINTAH&lt;/span&gt;&lt;/li&gt;
          &lt;li style="color:#132029 !important;"&gt;Jangan memaksa memasukkan baki jika terasa tersendat.&lt;span class="flag"&gt;PERINTAH&lt;/span&gt;&lt;/li&gt;
        &lt;/ol&gt;
        &lt;div class="note-margin" style="margin-top:10px; color:#8A3A1F !important;"&gt;Dengan demikian, kartu SIM dan kartu memori siap digunakan setelah smartphone dinyalakan kembali. &lt;b&gt;(penanda simpulan)&lt;/b&gt;&lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;

    &lt;div class="panel" style="margin-top:22px;"&gt;
      &lt;p style="margin:0;"&gt;&lt;b style="color:var(--off-white);"&gt;Simpulan model analisis:&lt;/b&gt; Teks di atas menggunakan variasi kalimat perintah (perintah biasa dan larangan), kata teknis khas perangkat elektronik ("ejector pin", "baki/tray"), serta penanda wacana penambahan ("selain itu") dan simpulan ("dengan demikian") yang menjaga keterpaduan antarlangkah.&lt;/p&gt;
    &lt;/div&gt;
  &lt;/section&gt;

  &lt;hr class="divider-dash"&gt;

  &lt;!-- ============ RANGKUMAN ============ --&gt;
  &lt;section class="section" id="rangkuman"&gt;
    &lt;div class="eyebrow"&gt;09 — Ringkasan Materi&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Poin-Poin Penting&lt;/h2&gt;
    &lt;div class="summary-box"&gt;
      &lt;ul&gt;
        &lt;li&gt;Kalimat perintah memiliki variasi bentuk: perintah biasa, larangan, ajakan, dan permintaan.&lt;/li&gt;
        &lt;li&gt;Kata teknis adalah istilah khusus bidang keahlian yang memberi ketepatan pada instruksi.&lt;/li&gt;
        &lt;li&gt;Penanda wacana menjaga keterpaduan teks melalui penanda urutan, penambahan, penekanan, dan simpulan.&lt;/li&gt;
        &lt;li&gt;Teks prosedur disusun melalui lima langkah: menentukan tujuan → mendaftar alat/bahan → merancang langkah → menerapkan kaidah kebahasaan → merevisi keruntutan.&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/div&gt;
  &lt;/section&gt;

  &lt;hr class="divider-dash"&gt;

  &lt;!-- ============ TUGAS KELOMPOK ============ --&gt;
  &lt;section class="section" id="tugas-kelompok"&gt;
    &lt;div class="eyebrow"&gt;10 — Lembar Kerja&lt;/div&gt;
    &lt;div class="task-header"&gt;
      &lt;h2&gt;Tugas Kelompok: Menyusun Teks Prosedur Baru&lt;/h2&gt;
      &lt;span class="badge"&gt;Durasi ± 60 menit&lt;/span&gt;
    &lt;/div&gt;

    &lt;p style="margin-top:18px;"&gt;&lt;b style="color:var(--off-white);"&gt;Tujuan tugas:&lt;/b&gt; Murid secara berkelompok menyusun sebuah teks prosedur baru secara logis dan sistematis, dengan menerapkan kalimat perintah, kata teknis, dan penanda wacana yang telah dipelajari.&lt;/p&gt;

    &lt;div class="panel" style="margin-top:20px;"&gt;
      &lt;div class="eyebrow" style="margin-bottom:6px;"&gt;Pilihan Tema (boleh memilih salah satu atau mengusulkan tema lain sesuai bidang keahlian dengan persetujuan guru)&lt;/div&gt;
      &lt;p style="margin:0;"&gt;Mengisi Daya Ponsel dengan Aman · Membuat Mi Instan yang Lezat · Merawat Tanaman Hias di Dalam Ruangan · Membersihkan Keyboard Laptop · atau prosedur lain sesuai bidang keahlian kelompok.&lt;/p&gt;
    &lt;/div&gt;

    &lt;h4 style="color:var(--off-white); margin-top:24px;"&gt;Petunjuk Pengerjaan&lt;/h4&gt;
    &lt;ol class="steps-num"&gt;
      &lt;li&gt;&lt;b&gt;Bentuk kelompok&lt;/b&gt; beranggotakan 4–5 orang sesuai pembagian dari guru.&lt;/li&gt;
      &lt;li&gt;&lt;b&gt;Pilih satu tema&lt;/b&gt; teks prosedur yang akan disusun.&lt;/li&gt;
      &lt;li&gt;&lt;b&gt;Tentukan tujuan&lt;/b&gt; serta alat/bahan (jika ada) untuk prosedur tersebut.&lt;/li&gt;
      &lt;li&gt;&lt;b&gt;Susun langkah-langkah&lt;/b&gt; secara berurutan dan logis pada Lembar Kerja Penyusunan di bawah ini.&lt;/li&gt;
      &lt;li&gt;&lt;b&gt;Terapkan kaidah kebahasaan&lt;/b&gt;: gunakan minimal 5 kalimat perintah, 2 kata teknis, dan 2 penanda wacana, lalu isi tabel ceklis penggunaannya.&lt;/li&gt;
      &lt;li&gt;&lt;b&gt;Presentasikan hasil&lt;/b&gt; di depan kelas selama maksimal 5 menit per kelompok, dilanjutkan tanya jawab singkat.&lt;/li&gt;
    &lt;/ol&gt;

    &lt;h4 style="color:var(--off-white); margin-top:26px;"&gt;Lembar Kerja Penyusunan Teks Prosedur&lt;/h4&gt;
    &lt;table&gt;
      &lt;tr&gt;&lt;th style="width:22%;"&gt;Bagian&lt;/th&gt;&lt;th&gt;Isi yang Disusun Kelompok&lt;/th&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Judul&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Tujuan&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Alat &amp;amp; Bahan&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Langkah 1–3&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Langkah 4–6&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Penutup&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;/table&gt;

    &lt;h4 style="color:var(--off-white); margin-top:26px;"&gt;Ceklis Penggunaan Kaidah Kebahasaan&lt;/h4&gt;
    &lt;table&gt;
      &lt;tr&gt;&lt;th style="width:34%;"&gt;Kaidah Kebahasaan&lt;/th&gt;&lt;th style="width:20%;"&gt;Target Minimal&lt;/th&gt;&lt;th&gt;Jumlah yang Digunakan&lt;/th&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Kalimat Perintah&lt;/td&gt;&lt;td&gt;5 kalimat&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Kata Teknis&lt;/td&gt;&lt;td&gt;2 kata&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Penanda Wacana&lt;/td&gt;&lt;td&gt;2 kata/frasa&lt;/td&gt;&lt;td&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;
    &lt;/table&gt;

    &lt;h4 style="color:var(--off-white); margin-top:26px;"&gt;Rubrik Penilaian Kelompok&lt;/h4&gt;
    &lt;table&gt;
      &lt;tr&gt;&lt;th style="width:26%;"&gt;Aspek Penilaian&lt;/th&gt;&lt;th&gt;Skor 4 (Sangat Baik)&lt;/th&gt;&lt;th&gt;Skor 3 (Baik)&lt;/th&gt;&lt;th&gt;Skor 2 (Cukup)&lt;/th&gt;&lt;th&gt;Skor 1 (Kurang)&lt;/th&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Kelogisan urutan langkah&lt;/td&gt;&lt;td&gt;Seluruh langkah runtut dan logis&lt;/td&gt;&lt;td&gt;Sebagian besar runtut&lt;/td&gt;&lt;td&gt;Ada beberapa langkah tidak runtut&lt;/td&gt;&lt;td&gt;Urutan tidak logis&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Ketepatan kalimat perintah&lt;/td&gt;&lt;td&gt;Digunakan tepat dan bervariasi&lt;/td&gt;&lt;td&gt;Digunakan tepat&lt;/td&gt;&lt;td&gt;Kurang bervariasi&lt;/td&gt;&lt;td&gt;Tidak tepat/tidak digunakan&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Ketepatan kata teknis &amp;amp; penanda wacana&lt;/td&gt;&lt;td&gt;Digunakan tepat sesuai konteks&lt;/td&gt;&lt;td&gt;Sebagian besar tepat&lt;/td&gt;&lt;td&gt;Kurang tepat&lt;/td&gt;&lt;td&gt;Tidak digunakan&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Presentasi&lt;/td&gt;&lt;td&gt;Jelas, percaya diri, menjawab pertanyaan dengan baik&lt;/td&gt;&lt;td&gt;Jelas namun kurang percaya diri&lt;/td&gt;&lt;td&gt;Kurang jelas/terbata-bata&lt;/td&gt;&lt;td&gt;Tidak dapat menjelaskan hasil&lt;/td&gt;&lt;/tr&gt;
    &lt;/table&gt;
  &lt;/section&gt;

  &lt;hr class="divider-dash"&gt;

&lt;!-- ============ TUGAS INDIVIDU: KUIS INTERAKTIF 10 PERTANYAAN ============ --&gt;
  &lt;section class="section" id="tugas-individu"&gt;
    &lt;div class="eyebrow"&gt;11 — Penutup Pembelajaran&lt;/div&gt;
    &lt;div class="task-header"&gt;
      &lt;h2&gt;Tugas Individu: Menjawab 10 Pertanyaan tentang Materi&lt;/h2&gt;
      &lt;span class="badge"&gt;Dikerjakan Mandiri · Otomatis Bernilai&lt;/span&gt;
    &lt;/div&gt;

    &lt;p style="margin-top:18px;"&gt;&lt;b style="color:var(--off-white);"&gt;Petunjuk:&lt;/b&gt; Isi No. Absen dan Nama, lalu jawab 10 pertanyaan pilihan ganda berikut berdasarkan materi yang telah dipelajari hari ini. Skor akan muncul otomatis setelah menekan tombol "Kirim Jawaban", dan hasilnya (No. Absen, Nama, Skor) akan tercatat otomatis.&lt;/p&gt;

    &lt;div class="panel" id="epbq-form-wrap" style="margin-top:20px;"&gt;
      &lt;div style="display:grid; grid-template-columns:1fr 2fr; gap:14px; margin-bottom:22px;"&gt;
        &lt;div&gt;
          &lt;label class="mono" style="display:block; font-size:0.75rem; color:var(--amber); text-transform:uppercase; letter-spacing:0.08em; margin-bottom:6px;"&gt;No. Absen&lt;/label&gt;
          &lt;input id="epbq-absen" type="text" inputmode="numeric" placeholder="Contoh: 12" style="width:100%; padding:10px 12px; border-radius:2px; border:1px solid var(--line); background:var(--blueprint-deep); color:var(--off-white); font-family:'Source Sans 3',sans-serif; font-size:0.95rem;"&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;label class="mono" style="display:block; font-size:0.75rem; color:var(--amber); text-transform:uppercase; letter-spacing:0.08em; margin-bottom:6px;"&gt;Nama Lengkap&lt;/label&gt;
          &lt;input id="epbq-nama" type="text" placeholder="Tulis nama lengkap" style="width:100%; padding:10px 12px; border-radius:2px; border:1px solid var(--line); background:var(--blueprint-deep); color:var(--off-white); font-family:'Source Sans 3',sans-serif; font-size:0.95rem;"&gt;
        &lt;/div&gt;
      &lt;/div&gt;

      &lt;div id="epbq-questions"&gt;&lt;/div&gt;

      &lt;div style="margin-top:24px; display:flex; align-items:center; gap:16px; flex-wrap:wrap;"&gt;
        &lt;button id="epbq-submit" type="button" style="background:var(--amber); color:var(--blueprint-deep); border:none; padding:12px 26px; font-family:'Oswald',sans-serif; text-transform:uppercase; letter-spacing:0.05em; font-weight:600; border-radius:2px; cursor:pointer; font-size:0.95rem;"&gt;Kirim Jawaban&lt;/button&gt;
        &lt;span id="epbq-status" class="mono" style="font-size:0.85rem; color:var(--muted);"&gt;&lt;/span&gt;
      &lt;/div&gt;

      &lt;div id="epbq-result" style="display:none; margin-top:20px; padding:18px 20px; border:1px solid var(--amber); background:rgba(245,166,35,0.08);"&gt;
        &lt;p style="margin:0; font-size:1.05rem;"&gt;Skor kamu: &lt;b id="epbq-score" style="color:var(--amber); font-size:1.3rem;"&gt;&lt;/b&gt; / 100&lt;/p&gt;
        &lt;p id="epbq-detail" style="margin:8px 0 0; font-size:0.9rem; color:var(--muted);"&gt;&lt;/p&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/section&gt;

&lt;script&gt;
(function(){
  var EPBQ_ENDPOINT = "https://script.google.com/macros/s/AKfycbzM7t2qgAENzxQJXzSYJYL28R6nb3TxJVELLL3CopyEXb51t_gRtrkPOxTpI5mq6VCEKw/exec";

  var questions = [
    {q:"1. Kalimat yang berisi larangan kepada pembaca disebut...", opts:["Kalimat deklaratif","Kalimat perintah larangan","Kalimat persuasif","Kalimat interogatif"], correct:1},
    {q:"2. Manakah contoh kalimat perintah ajakan?", opts:["\"Jangan sentuh permukaan yang panas.\"","\"Mari kita mulai dengan menyiapkan alat.\"","\"Alat ini terbuat dari logam.\"","\"Sebaiknya gunakan alat ini secara rutin.\""], correct:1},
    {q:"3. Kata teknis dalam teks prosedur berfungsi untuk...", opts:["Membuat teks lebih panjang","Memberikan ketepatan dan presisi instruksi","Menghibur pembaca","Menambah jumlah kalimat persuasif"], correct:1},
    {q:"4. Manakah yang termasuk kata teknis bidang otomotif?", opts:["Mengocok","Partisi","Karburator","Marinasi"], correct:2},
    {q:"5. Penanda wacana \"selain itu\" termasuk jenis...", opts:["Penanda urutan","Penanda penambahan","Penanda penekanan","Penanda simpulan"], correct:1},
    {q:"6. Contoh penanda wacana penekanan adalah...", opts:["\"Pertama-tama...\"","\"Dengan demikian...\"","\"Perlu diperhatikan...\"","\"Selanjutnya...\""], correct:2},
    {q:"7. Langkah pertama dalam menyusun teks prosedur adalah...", opts:["Merevisi keruntutan teks","Menentukan tujuan","Menerapkan kaidah kebahasaan","Mendaftar alat dan bahan"], correct:1},
    {q:"8. Mengapa urutan langkah dalam teks prosedur tidak boleh diacak?", opts:["Karena akan membuat teks lebih pendek","Karena pembaca bisa gagal mencapai hasil yang diinginkan","Karena aturan tata bahasa mengharuskannya","Karena teks prosedur harus selalu memiliki 5 langkah"], correct:1},
    {q:"9. Manakah kalimat yang mengandung kata teknis?", opts:["\"Silakan duduk dengan nyaman.\"","\"Periksa tekanan pada pentil ban.\"","\"Semoga langkah ini bermanfaat.\"","\"Jangan lupa berdoa sebelum memulai.\""], correct:1},
    {q:"10. Penanda wacana yang menyimpulkan sebuah proses biasanya menggunakan kata...", opts:["\"Kemudian\"","\"Selain itu\"","\"Dengan demikian\"","\"Perlu diperhatikan\""], correct:2}
  ];

  var container = document.getElementById("epbq-questions");
  questions.forEach(function(item, idx){
    var block = document.createElement("div");
    block.style.marginBottom = "20px";
    block.style.paddingBottom = "16px";
    block.style.borderBottom = "1px dashed rgba(234,242,245,0.16)";

    var qEl = document.createElement("p");
    qEl.style.color = "#EAF2F5";
    qEl.style.fontWeight = "600";
    qEl.style.marginBottom = "8px";
    qEl.textContent = item.q;
    block.appendChild(qEl);

    item.opts.forEach(function(opt, oi){
      var label = document.createElement("label");
      label.style.display = "block";
      label.style.color = "#DDE7EC";
      label.style.fontSize = "0.92rem";
      label.style.margin = "4px 0";
      label.style.cursor = "pointer";

      var radio = document.createElement("input");
      radio.type = "radio";
      radio.name = "epbq-q" + idx;
      radio.value = oi;
      radio.style.marginRight = "8px";

      label.appendChild(radio);
      label.appendChild(document.createTextNode(opt));
      block.appendChild(label);
    });

    container.appendChild(block);
  });

  document.getElementById("epbq-submit").addEventListener("click", function(){
    var absen = document.getElementById("epbq-absen").value.trim();
    var nama = document.getElementById("epbq-nama").value.trim();
    var statusEl = document.getElementById("epbq-status");

    if(!absen || !nama){
      statusEl.textContent = "Isi No. Absen dan Nama terlebih dahulu.";
      statusEl.style.color = "#F5A623";
      return;
    }

    var belumDijawab = [];
    var benar = 0;
    questions.forEach(function(item, idx){
      var checked = document.querySelector('input[name="epbq-q' + idx + '"]:checked');
      if(!checked){
        belumDijawab.push(idx+1);
      } else if(parseInt(checked.value,10) === item.correct){
        benar++;
      }
    });

    if(belumDijawab.length &gt; 0){
      statusEl.textContent = "Pertanyaan belum dijawab: nomor " + belumDijawab.join(", ");
      statusEl.style.color = "#F5A623";
      return;
    }

    var skor = benar * 10;
    document.getElementById("epbq-score").textContent = skor;
    document.getElementById("epbq-detail").textContent = "Menjawab benar " + benar + " dari 10 pertanyaan.";
    document.getElementById("epbq-result").style.display = "block";
    statusEl.textContent = "Mengirim hasil...";
    statusEl.style.color = "#9FB4C2";

    var payload = new URLSearchParams();
    payload.append("noAbsen", absen);
    payload.append("nama", nama);
    payload.append("skor", skor);
    payload.append("waktu", new Date().toISOString());

    if(EPBQ_ENDPOINT.indexOf("PASTE_URL") === 0){
      statusEl.textContent = "Skor tercatat di halaman ini. (Pengiriman ke Google Sheets belum diaktifkan guru.)";
      return;
    }

    fetch(EPBQ_ENDPOINT, {
      method: "POST",
      mode: "no-cors",
      headers: {"Content-Type":"application/x-www-form-urlencoded"},
      body: payload.toString()
    }).then(function(){
      statusEl.textContent = "Hasil berhasil dikirim ke guru.";
      statusEl.style.color = "#6EC6CA";
    }).catch(function(){
      statusEl.textContent = "Skor tercatat di halaman ini, namun pengiriman gagal. Tunjukkan skor ini ke guru.";
      statusEl.style.color = "#F5A623";
    });
  });
})();
&lt;/script&gt;

&lt;/main&gt;

&lt;footer&gt;
  &lt;div class="doc-code"&gt;DOK/B.INDO/XI/PROSEDUR-KAIDAH-2 — Fokus Tujuan Pembelajaran, Materi Inti, Tugas Kelompok &amp;amp; Tugas Individu, 1× pertemuan (3 JP)&lt;/div&gt;
  &lt;p style="margin:0;"&gt;Referensi: Kurikulum Merdeka — Capaian Pembelajaran Bahasa Indonesia Fase F (Elemen Membaca, Memirsa, dan Menulis); Buku Teks Bahasa Indonesia Kelas XI SMK/MAK Kemendikbudristek.&lt;/p&gt;
&lt;/footer&gt;
&lt;/div&gt;</description><link>http://kitab-investasi.blogspot.com/2026/08/kaidah-kebahasaan-teks-prosedur-bagian.html</link><thr:total>0</thr:total><author>nof_rizal07@yahoo.co.id (abang_cool)</author></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-9000860041661554971.post-8699242951655968917</guid><pubDate>Fri, 07 Aug 2026 01:33:22 +0000</pubDate><atom:updated>2026-08-07T08:33:22.366+07:00</atom:updated><title>Sistem Operasi, Manajemen File, &amp; Penyimpanan Cloud</title><description>&lt;!DOCTYPE html&gt;
&lt;html lang="id"&gt;
&lt;head&gt;
&lt;meta charset="UTF-8"&gt;
&lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&gt;
&lt;title&gt;Sistem Operasi, Manajemen File &amp; Penyimpanan Cloud — Informatika Kelas X&lt;/title&gt;
&lt;link rel="preconnect" href="https://fonts.googleapis.com"&gt;
&lt;link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500;600;700&amp;family=IBM+Plex+Sans:wght@400;500;600;700&amp;display=swap" rel="stylesheet"&gt;
&lt;style&gt;
  :root{
    --chrome: #2E3440;
    --chrome-deep: #232833;
    --desktop: #E8ECF1;
    --window: #FFFFFF;
    --line: #C7D0DA;
    --folder: #F0A93F;
    --folder-dark: #C9820A;
    --cloud: #3B82C4;
    --cloud-dark: #2A5F8F;
    --file-gray: #7C8798;
    --ink: #1F2A36;
    --ink-soft: #55647A;
    --green: #3FAE72;
    --red: #E0604A;
    --radius: 6px;
  }
  *{box-sizing:border-box; margin:0; padding:0;}
  html{scroll-behavior:smooth;}
  body{
    font-family:'IBM Plex Sans', sans-serif;
    background: var(--desktop);
    color: var(--ink);
    line-height:1.6;
  }
  .mono{font-family:'IBM Plex Mono', monospace;}

  /* ===== Top window chrome hero ===== */
  .titlebar-hero{
    background: var(--chrome);
    color: #E8ECF1;
  }
  .titlebar{
    display:flex; align-items:center; gap:8px;
    padding: 14px 6vw;
    border-bottom: 1px solid rgba(255,255,255,0.08);
  }
  .dot{width:12px; height:12px; border-radius:50%;}
  .dot.r{background:#E0604A;}
  .dot.y{background:#F0A93F;}
  .dot.g{background:#3FAE72;}
  .path-bar{
    margin-left:14px;
    font-family:'IBM Plex Mono', monospace;
    font-size:0.78rem;
    background: rgba(255,255,255,0.07);
    padding:5px 12px;
    border-radius:4px;
    color:#B9C4D2;
    letter-spacing:0.02em;
  }
  .hero-body{
    padding: 40px 6vw 60px;
  }
  .eyebrow{
    font-family:'IBM Plex Mono', monospace;
    font-size:0.78rem;
    letter-spacing:0.14em;
    text-transform:uppercase;
    color: var(--folder);
    margin-bottom:18px;
  }
  h1.title{
    font-family:'IBM Plex Mono', monospace;
    font-weight:700;
    font-size: clamp(1.9rem, 4vw, 3.3rem);
    line-height:1.16;
    max-width: 20ch;
    color:#F4F6F9;
  }
  h1.title span{color: var(--cloud);}
  .hero-sub{
    margin-top:16px;
    max-width: 64ch;
    font-size:1.03rem;
    color: #C3CCD8;
  }
  .meta-strip{
    margin-top:36px;
    display:grid;
    grid-template-columns: repeat(auto-fit,minmax(160px,1fr));
    gap:1px;
    background: rgba(255,255,255,0.1);
    border:1px solid rgba(255,255,255,0.1);
    max-width: 920px;
  }
  .meta-cell{ background: var(--chrome-deep); padding:14px 16px; }
  .meta-cell .k{
    font-family:'IBM Plex Mono', monospace;
    font-size:0.66rem; letter-spacing:0.1em; text-transform:uppercase;
    color: var(--cloud); opacity:0.9;
  }
  .meta-cell .v{ margin-top:6px; font-size:0.94rem; font-weight:600; color:#F1F4F7; }

  /* ===== Content ===== */
  main{
    background: var(--desktop);
    padding: 8px 0 0;
  }
  .section{
    padding: 54px 6vw;
    max-width: 1180px;
    margin: 0 auto;
  }
  .section-tag{
    font-family:'IBM Plex Mono', monospace;
    font-size:0.72rem; letter-spacing:0.14em; text-transform:uppercase;
    color: var(--ink-soft);
    display:flex; align-items:center; gap:10px; margin-bottom:10px;
  }
  .section-tag .num{
    color:#fff; background: var(--chrome); padding:3px 8px; border-radius:3px; font-weight:600;
  }
  h2.section-title{
    font-family:'IBM Plex Mono', monospace;
    font-size: clamp(1.35rem, 2.3vw, 1.9rem);
    font-weight:700; color: var(--chrome); margin-bottom: 22px; max-width: 32ch;
  }
  h3.sub-title{
    font-family:'IBM Plex Mono', monospace;
    font-size:1.06rem; font-weight:600; color: var(--chrome);
    margin: 26px 0 12px; display:flex; align-items:center; gap:10px;
  }
  h3.sub-title::before{ content:""; width:8px;height:8px; background: var(--folder); display:inline-block; border-radius:1px; }
  p{ color:#33414F; max-width: 74ch; margin-bottom: 14px;}
  strong{color:var(--chrome);}
  ul, ol{ margin: 8px 0 18px 1.3em; max-width: 74ch;}
  li{margin-bottom:8px; color:#33414F;}

  .callout{
    border-left: 3px solid var(--cloud);
    background: #EAF2FA;
    padding: 16px 20px; border-radius: 0 6px 6px 0; margin: 18px 0; max-width: 74ch;
  }
  .callout .lbl{
    font-family:'IBM Plex Mono', monospace; font-size:0.7rem; letter-spacing:0.1em; text-transform:uppercase;
    color:#2A5F8F; font-weight:700; margin-bottom:6px;
  }

  /* ===== Window-style cards ===== */
  .win-card{
    background: var(--window);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    box-shadow: 0 2px 10px rgba(30,40,55,0.06);
    overflow:hidden;
  }
  .win-card .win-bar{
    background: #F3F5F8;
    border-bottom: 1px solid var(--line);
    padding: 8px 12px;
    display:flex; align-items:center; gap:6px;
  }
  .win-card .win-bar .d{width:9px;height:9px;border-radius:50%;}
  .win-card .win-bar .d.r{background:#E0604A;} .win-card .win-bar .d.y{background:#F0A93F;} .win-card .win-bar .d.g{background:#3FAE72;}
  .win-card .win-bar .win-title{
    margin-left:8px; font-family:'IBM Plex Mono', monospace; font-size:0.72rem; color: var(--ink-soft);
  }
  .win-card .win-content{ padding: 18px 20px; }

  .card-grid{ display:grid; grid-template-columns: repeat(3, 1fr); gap: 16px; margin: 20px 0 8px; }
  @media (max-width: 860px){ .card-grid{grid-template-columns: 1fr;} }
  .card-grid .win-card h4{ font-family:'IBM Plex Mono', monospace; font-size:0.98rem; color:var(--chrome); margin-bottom:6px;}
  .card-grid .win-card p{ font-size:0.88rem; margin-bottom:8px;}
  .card-grid .win-card ul{ margin:6px 0 0 1.1em; font-size:0.88rem;}
  .card-grid .win-card li{ margin-bottom:4px; color:#3C4C5B;}

  /* ===== Folder tree diagram ===== */
  .tree-frame{
    margin: 24px 0;
    background: var(--window);
    border:1px solid var(--line);
    border-radius: 8px;
    padding: 22px 24px;
  }
  .tree{ font-family:'IBM Plex Mono', monospace; font-size:0.88rem; line-height:2; color:#2C3947;}
  .tree .lvl0::before{ content:"&#128193; "; }
  .tree .lvl1{ padding-left:26px; position:relative;}
  .tree .lvl1::before{ content:"├─ &#128193; "; color: var(--ink-soft);}
  .tree .lvl2{ padding-left:52px; position:relative; color:#55647A;}
  .tree .lvl2::before{ content:"├─ &#128196; "; }
  .tree .lvl2.last::before{ content:"└─ &#128196; "; }
  .tree .folder-name{color:var(--folder-dark); font-weight:600;}
  .tree .file-name{color:var(--file-gray);}

  /* ===== Cloud sync diagram ===== */
  .diagram-frame{
    margin: 26px 0;
    background: var(--window);
    border-radius: 8px;
    padding: 18px;
    border: 1px solid var(--line);
  }
  .diagram-frame svg{width:100%; height:auto; display:block;}
  .diagram-caption{
    font-family:'IBM Plex Mono', monospace; font-size:0.72rem; color: var(--ink-soft);
    text-align:center; margin-top:10px; letter-spacing:0.03em;
  }
  .signal{ stroke-dasharray: 6 8; animation: flow 1.6s linear infinite; }
  @keyframes flow{ to{ stroke-dashoffset:-56; } }
  @media (prefers-reduced-motion: reduce){ .signal{animation:none;} }

  /* ===== Compare table ===== */
  table.compare{ width:100%; border-collapse:collapse; margin:18px 0; font-size:0.9rem; background:var(--window); }
  table.compare th, table.compare td{ border:1px solid var(--line); padding:11px 14px; text-align:left; }
  table.compare th{ background: var(--chrome); color:#fff; font-family:'IBM Plex Mono', monospace; font-size:0.74rem; letter-spacing:0.04em; text-transform:uppercase; }
  table.compare tr:nth-child(even) td{ background:#F3F5F8; }

  /* ===== Summary ===== */
  .summary-box{ background: var(--chrome); color: #fff; border-radius: 8px; padding: 26px 28px; margin-top: 10px; }
  .summary-box h4{ font-family:'IBM Plex Mono', monospace; color: var(--folder); font-size:0.85rem; letter-spacing:0.08em; text-transform:uppercase; margin-bottom:14px; }
  .summary-box ul{ margin:0 0 0 1.1em; max-width:none; }
  .summary-box li{ color:#E4EAF0; margin-bottom:8px; }

  /* ===== Tugas kelompok ===== */
  .task-panel{
    border: 1.5px dashed var(--chrome);
    border-radius: 8px; padding: 26px 28px;
    background: repeating-linear-gradient(135deg, #FFFFFF, #FFFFFF 18px, #EEF1F5 18px, #EEF1F5 19px);
  }
  .task-head{ display:flex; align-items:center; gap:12px; flex-wrap:wrap; margin-bottom:12px; }
  .task-head .badge{
    font-family:'IBM Plex Mono', monospace; font-size:0.7rem; letter-spacing:0.08em; text-transform:uppercase;
    background: var(--cloud); color:#fff; padding:4px 10px; border-radius:3px;
  }
  .task-panel h3{ font-family:'IBM Plex Mono', monospace; font-size:1.22rem; color: var(--chrome); }
  .steps-num{ counter-reset: step; margin:16px 0; max-width:78ch; }
  .steps-num li{ counter-increment: step; list-style:none; position:relative; padding-left:34px; margin-bottom:14px; }
  .steps-num li::before{
    content: counter(step); position:absolute; left:0; top:0;
    font-family:'IBM Plex Mono', monospace; font-weight:700; color:#fff; background: var(--chrome);
    width:24px; height:24px; border-radius:50%; display:flex; align-items:center; justify-content:center; font-size:0.8rem;
  }
  table.rubrik{ width:100%; border-collapse:collapse; margin-top:18px; font-size:0.88rem; }
  table.rubrik th, table.rubrik td{ border:1px solid #C9C4B4; padding:10px 12px; text-align:left; }
  table.rubrik th{ background: var(--chrome); color:#fff; font-family:'IBM Plex Mono', monospace; font-size:0.75rem; letter-spacing:0.04em; text-transform:uppercase; }
  table.rubrik tr:nth-child(even) td{ background:#F1F0E8; }

  .closing-task{
    margin-top:22px; background: #FFF6E8; border:1.5px solid var(--folder); border-radius:8px; padding:20px 22px;
  }
  .closing-task .lbl{ font-family:'IBM Plex Mono', monospace; font-size:0.72rem; letter-spacing:0.1em; text-transform:uppercase; color:#8A5A0A; font-weight:700; margin-bottom:8px; }

  footer{
    background: var(--chrome-deep); color:#9FAEC0; text-align:center; padding: 30px 6vw 40px;
    font-family:'IBM Plex Mono', monospace; font-size:0.75rem; letter-spacing:0.04em;
  }

  @media (max-width: 700px){
    .card-grid{grid-template-columns:1fr;}
    .hero-body{padding:32px 5vw 44px;}
    .section{padding:38px 5vw;}
  }
&lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;

&lt;div class="titlebar-hero"&gt;
  &lt;div class="titlebar"&gt;
    &lt;span class="dot r"&gt;&lt;/span&gt;&lt;span class="dot y"&gt;&lt;/span&gt;&lt;span class="dot g"&gt;&lt;/span&gt;
    &lt;span class="path-bar"&gt;C:\Informatika\Kelas-X\Sistem-Operasi-File-Cloud&lt;/span&gt;
  &lt;/div&gt;
  &lt;div class="hero-body"&gt;
    &lt;div class="eyebrow"&gt;Informatika · Fase E · Kelas X SMK&lt;/div&gt;
    &lt;h1 class="title"&gt;Sistem Operasi, Manajemen File, &amp; Penyimpanan &lt;span&gt;Cloud&lt;/span&gt;&lt;/h1&gt;
    &lt;p class="hero-sub"&gt;Materi ini membahas bagaimana sistem operasi mengatur seluruh sumber daya komputer, bagaimana file dan folder dikelola secara sistematis, serta bagaimana layanan penyimpanan cloud mendukung pekerjaan digital masa kini.&lt;/p&gt;

    &lt;div class="meta-strip"&gt;
      &lt;div class="meta-cell"&gt;&lt;div class="k"&gt;Elemen CP&lt;/div&gt;&lt;div class="v"&gt;Sistem Operasi &amp; File&lt;/div&gt;&lt;/div&gt;
      &lt;div class="meta-cell"&gt;&lt;div class="k"&gt;Jenjang&lt;/div&gt;&lt;div class="v"&gt;SMK Kelas X&lt;/div&gt;&lt;/div&gt;
      &lt;div class="meta-cell"&gt;&lt;div class="k"&gt;Alokasi Waktu&lt;/div&gt;&lt;div class="v"&gt;1 Pertemuan · 4 JP (180 menit)&lt;/div&gt;&lt;/div&gt;
      &lt;div class="meta-cell"&gt;&lt;div class="k"&gt;Model&lt;/div&gt;&lt;div class="v"&gt;Praktik &amp; Kerja Kelompok&lt;/div&gt;&lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;main&gt;

  &lt;!-- ===================== TUJUAN ===================== --&gt;
  &lt;section class="section" id="tujuan"&gt;
    &lt;div class="section-tag"&gt;&lt;span class="num"&gt;00&lt;/span&gt; Capaian &amp; Tujuan Pembelajaran&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Ke Mana Materi Ini Menuju&lt;/h2&gt;

    &lt;h3 class="sub-title"&gt;Capaian Pembelajaran&lt;/h3&gt;
    &lt;p&gt;Murid mampu mengelola sistem operasi, file, folder, media penyimpanan, serta memanfaatkan layanan cloud storage untuk mendukung pekerjaan digital.&lt;/p&gt;

    &lt;h3 class="sub-title"&gt;Tujuan Pembelajaran&lt;/h3&gt;
    &lt;ol&gt;
      &lt;li&gt;Menjelaskan pengertian dan fungsi sistem operasi dalam mengelola sumber daya komputer.&lt;/li&gt;
      &lt;li&gt;Mengidentifikasi jenis-jenis sistem operasi yang umum digunakan.&lt;/li&gt;
      &lt;li&gt;Mengelola file dan folder: membuat, menamai, menyalin, memindahkan, dan menghapus dengan struktur yang rapi.&lt;/li&gt;
      &lt;li&gt;Membedakan jenis media penyimpanan (internal, removable, dan cloud) beserta karakteristiknya.&lt;/li&gt;
      &lt;li&gt;Memanfaatkan layanan penyimpanan cloud untuk menyimpan, mengelola, dan berbagi berkas pekerjaan digital.&lt;/li&gt;
    &lt;/ol&gt;

    &lt;h3 class="sub-title"&gt;Rincian Kegiatan (4 JP × 45 menit)&lt;/h3&gt;
    &lt;table class="compare"&gt;
      &lt;tr&gt;&lt;th&gt;Tahap&lt;/th&gt;&lt;th&gt;Kegiatan&lt;/th&gt;&lt;th&gt;Waktu&lt;/th&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Pendahuluan&lt;/td&gt;&lt;td&gt;Apersepsi ("Ke mana perginya file yang kamu simpan?"), penyampaian tujuan pembelajaran&lt;/td&gt;&lt;td&gt;15 menit&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Inti — Eksplorasi Konsep&lt;/td&gt;&lt;td&gt;Penjelasan sistem operasi, manajemen file/folder, media penyimpanan, dan cloud storage&lt;/td&gt;&lt;td&gt;55 menit&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Inti — Praktik Mandiri&lt;/td&gt;&lt;td&gt;Murid mempraktikkan membuat struktur folder dan mengunggah file ke akun cloud storage&lt;/td&gt;&lt;td&gt;30 menit&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Inti — Kerja Kelompok&lt;/td&gt;&lt;td&gt;Diskusi dan pengerjaan tugas kelompok&lt;/td&gt;&lt;td&gt;45 menit&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Inti — Presentasi&lt;/td&gt;&lt;td&gt;Presentasi singkat tiap kelompok dan tanggapan guru&lt;/td&gt;&lt;td&gt;25 menit&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Penutup&lt;/td&gt;&lt;td&gt;Refleksi, penguatan konsep, menulis kesimpulan ringkas di buku catatan&lt;/td&gt;&lt;td&gt;10 menit&lt;/td&gt;&lt;/tr&gt;
    &lt;/table&gt;
  &lt;/section&gt;

  &lt;!-- ===================== A. SISTEM OPERASI ===================== --&gt;
  &lt;section class="section" id="sistem-operasi"&gt;
    &lt;div class="section-tag"&gt;&lt;span class="num"&gt;01&lt;/span&gt; Konsep Dasar&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Apa Itu Sistem Operasi?&lt;/h2&gt;
    &lt;p&gt;&lt;strong&gt;Sistem operasi (operating system/OS)&lt;/strong&gt; adalah perangkat lunak utama yang menjembatani antara pengguna, aplikasi, dan perangkat keras komputer. OS dijalankan pertama kali saat komputer dinyalakan dan terus bekerja di latar belakang selama komputer digunakan.&lt;/p&gt;

    &lt;h3 class="sub-title"&gt;Fungsi Utama Sistem Operasi&lt;/h3&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;strong&gt;Manajemen proses&lt;/strong&gt; — mengatur program apa saja yang sedang berjalan dan membagi waktu pemrosesan CPU untuk masing-masing program.&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Manajemen memori&lt;/strong&gt; — mengalokasikan RAM untuk setiap program agar dapat berjalan tanpa saling bertabrakan.&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Manajemen perangkat keras&lt;/strong&gt; — mengatur komunikasi dengan printer, keyboard, mouse, dan perangkat lain melalui driver.&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Manajemen file&lt;/strong&gt; — mengatur bagaimana data disimpan, disusun dalam folder, dan diakses kembali.&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Antarmuka pengguna (User Interface)&lt;/strong&gt; — menyediakan tampilan (GUI) atau baris perintah (CLI) agar manusia dapat berinteraksi dengan komputer.&lt;/li&gt;
    &lt;/ul&gt;

    &lt;h3 class="sub-title"&gt;Jenis-Jenis Sistem Operasi&lt;/h3&gt;
    &lt;div class="card-grid"&gt;
      &lt;div class="win-card"&gt;
        &lt;div class="win-bar"&gt;&lt;span class="d r"&gt;&lt;/span&gt;&lt;span class="d y"&gt;&lt;/span&gt;&lt;span class="d g"&gt;&lt;/span&gt;&lt;span class="win-title"&gt;desktop-os.exe&lt;/span&gt;&lt;/div&gt;
        &lt;div class="win-content"&gt;
          &lt;h4&gt;Windows&lt;/h4&gt;
          &lt;p&gt;OS paling umum di komputer perkantoran dan sekolah, dikembangkan oleh Microsoft, dikenal luas kompatibel dengan berbagai aplikasi.&lt;/p&gt;
        &lt;/div&gt;
      &lt;/div&gt;
      &lt;div class="win-card"&gt;
        &lt;div class="win-bar"&gt;&lt;span class="d r"&gt;&lt;/span&gt;&lt;span class="d y"&gt;&lt;/span&gt;&lt;span class="d g"&gt;&lt;/span&gt;&lt;span class="win-title"&gt;macos.app&lt;/span&gt;&lt;/div&gt;
        &lt;div class="win-content"&gt;
          &lt;h4&gt;macOS&lt;/h4&gt;
          &lt;p&gt;OS buatan Apple untuk perangkat Mac, dikenal dengan antarmuka yang halus dan integrasi kuat dengan perangkat Apple lainnya.&lt;/p&gt;
        &lt;/div&gt;
      &lt;/div&gt;
      &lt;div class="win-card"&gt;
        &lt;div class="win-bar"&gt;&lt;span class="d r"&gt;&lt;/span&gt;&lt;span class="d y"&gt;&lt;/span&gt;&lt;span class="d g"&gt;&lt;/span&gt;&lt;span class="win-title"&gt;~/linux&lt;/span&gt;&lt;/div&gt;
        &lt;div class="win-content"&gt;
          &lt;h4&gt;Linux&lt;/h4&gt;
          &lt;p&gt;OS open-source yang fleksibel dan banyak dipakai di server, perangkat pengembangan, hingga superkomputer. Contoh: Ubuntu, Debian.&lt;/p&gt;
        &lt;/div&gt;
      &lt;/div&gt;
      &lt;div class="win-card"&gt;
        &lt;div class="win-bar"&gt;&lt;span class="d r"&gt;&lt;/span&gt;&lt;span class="d y"&gt;&lt;/span&gt;&lt;span class="d g"&gt;&lt;/span&gt;&lt;span class="win-title"&gt;mobile.apk&lt;/span&gt;&lt;/div&gt;
        &lt;div class="win-content"&gt;
          &lt;h4&gt;Android&lt;/h4&gt;
          &lt;p&gt;OS berbasis Linux untuk perangkat mobile, dikembangkan Google, digunakan oleh mayoritas smartphone di dunia.&lt;/p&gt;
        &lt;/div&gt;
      &lt;/div&gt;
      &lt;div class="win-card"&gt;
        &lt;div class="win-bar"&gt;&lt;span class="d r"&gt;&lt;/span&gt;&lt;span class="d y"&gt;&lt;/span&gt;&lt;span class="d g"&gt;&lt;/span&gt;&lt;span class="win-title"&gt;mobile.ipa&lt;/span&gt;&lt;/div&gt;
        &lt;div class="win-content"&gt;
          &lt;h4&gt;iOS&lt;/h4&gt;
          &lt;p&gt;OS buatan Apple khusus untuk iPhone, dikenal dengan ekosistem tertutup namun stabil dan aman.&lt;/p&gt;
        &lt;/div&gt;
      &lt;/div&gt;
      &lt;div class="win-card"&gt;
        &lt;div class="win-bar"&gt;&lt;span class="d r"&gt;&lt;/span&gt;&lt;span class="d y"&gt;&lt;/span&gt;&lt;span class="d g"&gt;&lt;/span&gt;&lt;span class="win-title"&gt;chrome.os&lt;/span&gt;&lt;/div&gt;
        &lt;div class="win-content"&gt;
          &lt;h4&gt;Chrome OS&lt;/h4&gt;
          &lt;p&gt;OS ringan berbasis cloud dari Google, banyak digunakan di Chromebook untuk kebutuhan belajar dan kerja ringan berbasis internet.&lt;/p&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/section&gt;

  &lt;!-- ===================== B. MANAJEMEN FILE ===================== --&gt;
  &lt;section class="section" id="manajemen-file"&gt;
    &lt;div class="section-tag"&gt;&lt;span class="num"&gt;02&lt;/span&gt; Pengelolaan Data&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Manajemen File dan Folder&lt;/h2&gt;
    &lt;p&gt;Salah satu tugas penting sistem operasi adalah mengatur &lt;strong&gt;file&lt;/strong&gt; (berkas data) dan &lt;strong&gt;folder/direktori&lt;/strong&gt; (wadah untuk mengelompokkan file) agar data dapat disimpan dan ditemukan kembali dengan mudah.&lt;/p&gt;

    &lt;h3 class="sub-title"&gt;Anatomi Sebuah File&lt;/h3&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;strong&gt;Nama file&lt;/strong&gt; — identitas unik dalam satu folder, sebaiknya deskriptif dan konsisten.&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Ekstensi file&lt;/strong&gt; — akhiran nama yang menandakan jenis/format file, misalnya &lt;span class="mono"&gt;.docx&lt;/span&gt; (dokumen), &lt;span class="mono"&gt;.xlsx&lt;/span&gt; (spreadsheet), &lt;span class="mono"&gt;.jpg&lt;/span&gt; (gambar), &lt;span class="mono"&gt;.pdf&lt;/span&gt; (dokumen portabel), &lt;span class="mono"&gt;.mp4&lt;/span&gt; (video).&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Ukuran file&lt;/strong&gt; — kapasitas ruang yang dipakai, diukur dalam KB, MB, atau GB.&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Path (alamat file)&lt;/strong&gt; — lokasi lengkap file dalam struktur folder, misalnya &lt;span class="mono"&gt;D:\Tugas\Informatika\laporan.docx&lt;/span&gt;.&lt;/li&gt;
    &lt;/ul&gt;

    &lt;h3 class="sub-title"&gt;Struktur Folder (Hierarki)&lt;/h3&gt;
    &lt;p&gt;Folder disusun secara berjenjang seperti pohon terbalik — satu folder utama dapat memiliki banyak subfolder, dan setiap subfolder dapat menyimpan file maupun subfolder lain di dalamnya.&lt;/p&gt;
    &lt;div class="tree-frame"&gt;
      &lt;div class="tree"&gt;
        &lt;div class="lvl0"&gt;&lt;span class="folder-name"&gt;Tugas Sekolah&lt;/span&gt;&lt;/div&gt;
        &lt;div class="lvl1"&gt;&lt;span class="folder-name"&gt;Informatika&lt;/span&gt;&lt;/div&gt;
        &lt;div class="lvl2"&gt;&lt;span class="file-name"&gt;materi-sistem-operasi.pdf&lt;/span&gt;&lt;/div&gt;
        &lt;div class="lvl2 last"&gt;&lt;span class="file-name"&gt;tugas-kelompok.docx&lt;/span&gt;&lt;/div&gt;
        &lt;div class="lvl1"&gt;&lt;span class="folder-name"&gt;Matematika&lt;/span&gt;&lt;/div&gt;
        &lt;div class="lvl2 last"&gt;&lt;span class="file-name"&gt;latihan-soal.pdf&lt;/span&gt;&lt;/div&gt;
        &lt;div class="lvl1"&gt;&lt;span class="folder-name"&gt;Bahasa Indonesia&lt;/span&gt;&lt;/div&gt;
        &lt;div class="lvl2 last"&gt;&lt;span class="file-name"&gt;esai-argumentatif.docx&lt;/span&gt;&lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;

    &lt;h3 class="sub-title"&gt;Operasi Dasar Pengelolaan File&lt;/h3&gt;
    &lt;ul style="columns:2;"&gt;
      &lt;li&gt;&lt;strong&gt;Create&lt;/strong&gt; — membuat file/folder baru&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Rename&lt;/strong&gt; — mengganti nama&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Copy&lt;/strong&gt; — menggandakan&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Move&lt;/strong&gt; — memindahkan lokasi&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Delete&lt;/strong&gt; — menghapus&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Compress&lt;/strong&gt; — memampatkan (mis. .zip)&lt;/li&gt;
    &lt;/ul&gt;

    &lt;div class="callout"&gt;
      &lt;div class="lbl"&gt;Praktik Baik&lt;/div&gt;
      &lt;p style="margin:0;"&gt;Gunakan penamaan file yang konsisten dan deskriptif, misalnya &lt;span class="mono"&gt;Laporan_Praktikum_Bab3_v1.docx&lt;/span&gt;, serta kelompokkan file ke dalam folder bertema agar mudah ditemukan kembali — bukan menumpuk semua file langsung di Desktop.&lt;/p&gt;
    &lt;/div&gt;
  &lt;/section&gt;

  &lt;!-- ===================== C. MEDIA PENYIMPANAN ===================== --&gt;
  &lt;section class="section" id="penyimpanan"&gt;
    &lt;div class="section-tag"&gt;&lt;span class="num"&gt;03&lt;/span&gt; Perangkat Simpan&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Media Penyimpanan&lt;/h2&gt;
    &lt;p&gt;File dan folder yang dikelola sistem operasi pada akhirnya disimpan secara fisik maupun virtual pada media penyimpanan berikut.&lt;/p&gt;

    &lt;table class="compare"&gt;
      &lt;tr&gt;&lt;th&gt;Jenis&lt;/th&gt;&lt;th&gt;Contoh&lt;/th&gt;&lt;th&gt;Karakteristik&lt;/th&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Penyimpanan Internal&lt;/td&gt;&lt;td&gt;HDD (Hard Disk Drive), SSD (Solid State Drive)&lt;/td&gt;&lt;td&gt;Terpasang permanen di dalam perangkat; SSD jauh lebih cepat namun lebih mahal per GB dibanding HDD.&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Penyimpanan Removable&lt;/td&gt;&lt;td&gt;Flashdisk, memory card (microSD), HDD eksternal&lt;/td&gt;&lt;td&gt;Portabel, mudah dipindah antar perangkat, namun rawan hilang atau rusak fisik.&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Penyimpanan Cloud&lt;/td&gt;&lt;td&gt;Google Drive, OneDrive, Dropbox, iCloud&lt;/td&gt;&lt;td&gt;Data tersimpan di server internet, dapat diakses dari mana saja selama terhubung internet.&lt;/td&gt;&lt;/tr&gt;
    &lt;/table&gt;
  &lt;/section&gt;

  &lt;!-- ===================== D. CLOUD STORAGE ===================== --&gt;
  &lt;section class="section" id="cloud"&gt;
    &lt;div class="section-tag"&gt;&lt;span class="num"&gt;04&lt;/span&gt; Penyimpanan Modern&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Penyimpanan Cloud (Cloud Storage)&lt;/h2&gt;
    &lt;p&gt;&lt;strong&gt;Cloud storage&lt;/strong&gt; adalah layanan penyimpanan data yang menempatkan file pada server jarak jauh milik penyedia layanan, bukan pada perangkat milik pengguna sendiri. File yang disimpan di cloud dapat diakses, diedit, dan dibagikan dari perangkat mana pun yang terhubung ke internet.&lt;/p&gt;

    &lt;h3 class="sub-title"&gt;Cara Kerja Cloud Storage&lt;/h3&gt;
    &lt;div class="diagram-frame"&gt;
      &lt;svg viewBox="0 0 800 300" xmlns="http://www.w3.org/2000/svg"&gt;
        &lt;text x="400" y="28" text-anchor="middle" fill="#55647A" font-family="IBM Plex Mono, monospace" font-size="12" letter-spacing="2"&gt;SINKRONISASI PERANGKAT LOKAL &amp;amp; CLOUD&lt;/text&gt;

        &lt;!-- laptop --&gt;
        &lt;rect x="60" y="90" width="150" height="95" rx="6" fill="none" stroke="#2E3440" stroke-width="1.5"/&gt;
        &lt;text x="135" y="122" text-anchor="middle" fill="#2E3440" font-family="IBM Plex Mono, monospace" font-weight="700" font-size="12"&gt;Laptop&lt;/text&gt;
        &lt;text x="135" y="145" text-anchor="middle" fill="#55647A" font-family="IBM Plex Mono, monospace" font-size="9"&gt;file lokal&lt;/text&gt;
        &lt;rect x="85" y="155" width="100" height="16" fill="none" stroke="#7C8798" stroke-width="1"/&gt;

        &lt;!-- smartphone --&gt;
        &lt;rect x="60" y="205" width="150" height="70" rx="6" fill="none" stroke="#2E3440" stroke-width="1.5"/&gt;
        &lt;text x="135" y="232" text-anchor="middle" fill="#2E3440" font-family="IBM Plex Mono, monospace" font-weight="700" font-size="12"&gt;Smartphone&lt;/text&gt;
        &lt;text x="135" y="252" text-anchor="middle" fill="#55647A" font-family="IBM Plex Mono, monospace" font-size="9"&gt;app cloud storage&lt;/text&gt;

        &lt;!-- cloud --&gt;
        &lt;g transform="translate(430,60)"&gt;
          &lt;path d="M50 90 a40 40 0 0 1 0-80 a50 50 0 0 1 96-14 a36 36 0 0 1 4 94 z" fill="none" stroke="#3B82C4" stroke-width="2"/&gt;
          &lt;text x="90" y="52" text-anchor="middle" fill="#2A5F8F" font-family="IBM Plex Mono, monospace" font-weight="700" font-size="13"&gt;CLOUD&lt;/text&gt;
          &lt;text x="90" y="70" text-anchor="middle" fill="#3B82C4" font-family="IBM Plex Mono, monospace" font-size="9"&gt;server penyedia layanan&lt;/text&gt;
        &lt;/g&gt;

        &lt;!-- arrows --&gt;
        &lt;line class="signal" x1="210" y1="130" x2="440" y2="110" stroke="#3B82C4" stroke-width="2"/&gt;
        &lt;line class="signal" x1="210" y1="240" x2="440" y2="150" stroke="#3B82C4" stroke-width="2"/&gt;

        &lt;text x="580" y="235" text-anchor="middle" fill="#55647A" font-family="IBM Plex Mono, monospace" font-size="10"&gt;Sinkron otomatis via internet —&lt;/text&gt;
        &lt;text x="580" y="252" text-anchor="middle" fill="#55647A" font-family="IBM Plex Mono, monospace" font-size="10"&gt;perubahan di satu perangkat&lt;/text&gt;
        &lt;text x="580" y="269" text-anchor="middle" fill="#55647A" font-family="IBM Plex Mono, monospace" font-size="10"&gt;otomatis muncul di perangkat lain&lt;/text&gt;
      &lt;/svg&gt;
      &lt;div class="diagram-caption"&gt;File yang diunggah dari satu perangkat langsung tersinkronisasi ke semua perangkat lain yang masuk ke akun cloud yang sama.&lt;/div&gt;
    &lt;/div&gt;

    &lt;h3 class="sub-title"&gt;Contoh Layanan Cloud Storage&lt;/h3&gt;
    &lt;div class="card-grid"&gt;
      &lt;div class="win-card"&gt;&lt;div class="win-bar"&gt;&lt;span class="d r"&gt;&lt;/span&gt;&lt;span class="d y"&gt;&lt;/span&gt;&lt;span class="d g"&gt;&lt;/span&gt;&lt;span class="win-title"&gt;drive.google.com&lt;/span&gt;&lt;/div&gt;&lt;div class="win-content"&gt;&lt;h4&gt;Google Drive&lt;/h4&gt;&lt;p&gt;Terintegrasi dengan akun Google dan Google Docs/Sheets/Slides untuk kolaborasi real-time.&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;
      &lt;div class="win-card"&gt;&lt;div class="win-bar"&gt;&lt;span class="d r"&gt;&lt;/span&gt;&lt;span class="d y"&gt;&lt;/span&gt;&lt;span class="d g"&gt;&lt;/span&gt;&lt;span class="win-title"&gt;onedrive.live.com&lt;/span&gt;&lt;/div&gt;&lt;div class="win-content"&gt;&lt;h4&gt;OneDrive&lt;/h4&gt;&lt;p&gt;Layanan cloud dari Microsoft, terhubung erat dengan Windows dan aplikasi Office.&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;
      &lt;div class="win-card"&gt;&lt;div class="win-bar"&gt;&lt;span class="d r"&gt;&lt;/span&gt;&lt;span class="d y"&gt;&lt;/span&gt;&lt;span class="d g"&gt;&lt;/span&gt;&lt;span class="win-title"&gt;dropbox.com&lt;/span&gt;&lt;/div&gt;&lt;div class="win-content"&gt;&lt;h4&gt;Dropbox&lt;/h4&gt;&lt;p&gt;Salah satu pionir cloud storage, dikenal dengan fitur sinkronisasi dan berbagi file yang sederhana.&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;
    &lt;/div&gt;

    &lt;h3 class="sub-title"&gt;Kelebihan &amp; Tantangan Cloud Storage&lt;/h3&gt;
    &lt;table class="compare"&gt;
      &lt;tr&gt;&lt;th&gt;Kelebihan&lt;/th&gt;&lt;th&gt;Tantangan&lt;/th&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Dapat diakses dari mana saja dan kapan saja selama ada internet&lt;/td&gt;&lt;td&gt;Membutuhkan koneksi internet untuk sinkronisasi&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Memudahkan kolaborasi dan berbagi file dengan orang lain&lt;/td&gt;&lt;td&gt;Kapasitas gratis terbatas, perlu berlangganan untuk kapasitas lebih besar&lt;/td&gt;&lt;/tr&gt;
      &lt;tr&gt;&lt;td&gt;Berfungsi sebagai cadangan (backup) jika perangkat lokal rusak/hilang&lt;/td&gt;&lt;td&gt;Perlu diperhatikan pengaturan privasi dan keamanan berbagi file&lt;/td&gt;&lt;/tr&gt;
    &lt;/table&gt;
  &lt;/section&gt;

  &lt;!-- ===================== E. HUBUNGAN ===================== --&gt;
  &lt;section class="section" id="hubungan"&gt;
    &lt;div class="section-tag"&gt;&lt;span class="num"&gt;05&lt;/span&gt; Keterkaitan&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Hubungan Antar Konsep&lt;/h2&gt;
    &lt;p&gt;Sistem operasi, manajemen file, media penyimpanan, dan cloud storage bekerja sebagai satu rangkaian yang saling melengkapi:&lt;/p&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;strong&gt;Sistem operasi&lt;/strong&gt; menyediakan alat (file manager) untuk mengelola file dan folder.&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;File dan folder&lt;/strong&gt; yang dikelola tersebut pada akhirnya disimpan secara fisik pada &lt;strong&gt;media penyimpanan&lt;/strong&gt; — baik internal, removable, maupun cloud.&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;Cloud storage&lt;/strong&gt; memperluas kapasitas dan fleksibilitas penyimpanan, memungkinkan file yang sama diakses dari berbagai perangkat dan sistem operasi yang berbeda.&lt;/li&gt;
      &lt;li&gt;Ketiganya membentuk fondasi produktivitas digital: tanpa manajemen file yang baik, kapasitas penyimpanan sebesar apa pun akan sulit dimanfaatkan secara efektif.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/section&gt;

  &lt;!-- ===================== F. RANGKUMAN ===================== --&gt;
  &lt;section class="section" id="rangkuman"&gt;
    &lt;div class="section-tag"&gt;&lt;span class="num"&gt;06&lt;/span&gt; Penguatan Konsep&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Rangkuman Materi&lt;/h2&gt;
    &lt;div class="summary-box"&gt;
      &lt;h4&gt;Poin-Poin Kunci&lt;/h4&gt;
      &lt;ul&gt;
        &lt;li&gt;Sistem operasi mengatur proses, memori, perangkat keras, file, dan antarmuka pengguna.&lt;/li&gt;
        &lt;li&gt;Contoh sistem operasi: Windows, macOS, Linux, Android, iOS, dan Chrome OS.&lt;/li&gt;
        &lt;li&gt;File memiliki nama, ekstensi, ukuran, dan path; folder menyusun file dalam struktur hierarki.&lt;/li&gt;
        &lt;li&gt;Operasi dasar pengelolaan file meliputi create, rename, copy, move, delete, dan compress.&lt;/li&gt;
        &lt;li&gt;Media penyimpanan terbagi atas internal (HDD/SSD), removable (flashdisk, HDD eksternal), dan cloud.&lt;/li&gt;
        &lt;li&gt;Cloud storage menyimpan file di server internet dan mensinkronkannya ke seluruh perangkat pengguna.&lt;/li&gt;
        &lt;li&gt;Cloud storage memudahkan akses dan kolaborasi, namun bergantung pada koneksi internet dan kuota penyimpanan.&lt;/li&gt;
        &lt;li&gt;Sistem operasi, manajemen file, dan cloud storage saling melengkapi dalam mendukung pekerjaan digital.&lt;/li&gt;
      &lt;/ul&gt;
    &lt;/div&gt;
  &lt;/section&gt;

  &lt;!-- ===================== TUGAS KELOMPOK ===================== --&gt;
  &lt;section class="section" id="tugas"&gt;
    &lt;div class="section-tag"&gt;&lt;span class="num"&gt;07&lt;/span&gt; Aktivitas Belajar&lt;/div&gt;
    &lt;h2 class="section-title"&gt;Tugas Kelompok&lt;/h2&gt;

    &lt;div class="task-panel"&gt;
      &lt;div class="task-head"&gt;
        &lt;span class="badge"&gt;Kerja Kelompok · 4–5 orang&lt;/span&gt;
        &lt;span class="badge" style="background:var(--chrome);"&gt;45 menit diskusi + 25 menit presentasi&lt;/span&gt;
      &lt;/div&gt;
      &lt;h3&gt;Membangun Struktur Folder &amp; Ekosistem Cloud Storage Kelompok&lt;/h3&gt;
      &lt;p&gt;Setiap kelompok merancang struktur folder digital untuk sebuah proyek belajar, kemudian mengimplementasikannya pada salah satu layanan cloud storage dan mempraktikkan cara berbagi file antar anggota.&lt;/p&gt;

      &lt;ol class="steps-num"&gt;
        &lt;li&gt;&lt;strong&gt;Bentuk kelompok&lt;/strong&gt; beranggotakan 4–5 orang dan pilih satu layanan cloud storage yang akan digunakan (Google Drive, OneDrive, atau Dropbox).&lt;/li&gt;
        &lt;li&gt;&lt;strong&gt;Rancang struktur folder&lt;/strong&gt; untuk proyek "Portofolio Belajar Semester Ini" dengan minimal 1 folder utama dan 3 subfolder bertema (mis. per mata pelajaran atau per jenis tugas).&lt;/li&gt;
        &lt;li&gt;&lt;strong&gt;Buat struktur folder tersebut&lt;/strong&gt; di akun cloud storage kelompok, lalu unggah minimal 3 contoh file ke dalamnya.&lt;/li&gt;
        &lt;li&gt;&lt;strong&gt;Atur pengaturan berbagi (sharing)&lt;/strong&gt; agar seluruh anggota kelompok dapat mengakses dan mengedit folder bersama.&lt;/li&gt;
        &lt;li&gt;&lt;strong&gt;Dokumentasikan prosesnya&lt;/strong&gt; dalam bentuk tangkapan layar (screenshot) struktur folder dan pengaturan berbagi.&lt;/li&gt;
        &lt;li&gt;&lt;strong&gt;Diskusikan dan tuliskan perbandingan&lt;/strong&gt;: kelebihan dan kekurangan menyimpan tugas di penyimpanan lokal (flashdisk/laptop) dibandingkan di cloud storage untuk skenario kerja kelompok.&lt;/li&gt;
        &lt;li&gt;&lt;strong&gt;Presentasikan&lt;/strong&gt; struktur folder, hasil dokumentasi, dan kesimpulan perbandingan di depan kelas selama maksimal 5 menit per kelompok.&lt;/li&gt;
      &lt;/ol&gt;

      &lt;h3 class="sub-title" style="margin-top:26px;"&gt;Format Laporan&lt;/h3&gt;
      &lt;p&gt;Laporan memuat: (1) nama layanan cloud &amp; anggota kelompok, (2) skema/daftar struktur folder yang dirancang, (3) tangkapan layar folder dan pengaturan berbagi di cloud, (4) tabel perbandingan penyimpanan lokal vs cloud.&lt;/p&gt;

      &lt;h3 class="sub-title"&gt;Rubrik Penilaian&lt;/h3&gt;
      &lt;table class="rubrik"&gt;
        &lt;tr&gt;&lt;th&gt;Aspek&lt;/th&gt;&lt;th&gt;Indikator&lt;/th&gt;&lt;th&gt;Skor Maks.&lt;/th&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td&gt;Struktur Folder&lt;/td&gt;&lt;td&gt;Struktur folder logis, bertingkat, dan sesuai tema proyek&lt;/td&gt;&lt;td&gt;25&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td&gt;Implementasi di Cloud&lt;/td&gt;&lt;td&gt;Folder dan file berhasil dibuat serta diunggah ke layanan cloud yang dipilih&lt;/td&gt;&lt;td&gt;25&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td&gt;Pengaturan Berbagi&lt;/td&gt;&lt;td&gt;Pengaturan sharing tepat sehingga seluruh anggota dapat mengakses&lt;/td&gt;&lt;td&gt;20&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td&gt;Analisis Perbandingan&lt;/td&gt;&lt;td&gt;Perbandingan lokal vs cloud logis, relevan, dan didukung alasan yang jelas&lt;/td&gt;&lt;td&gt;15&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td&gt;Kerja Sama &amp; Presentasi&lt;/td&gt;&lt;td&gt;Seluruh anggota berkontribusi; presentasi jelas dan percaya diri&lt;/td&gt;&lt;td&gt;15&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td colspan="2" style="text-align:right; font-weight:600;"&gt;Total&lt;/td&gt;&lt;td&gt;100&lt;/td&gt;&lt;/tr&gt;
      &lt;/table&gt;
    &lt;/div&gt;

    &lt;div class="closing-task"&gt;
      &lt;div class="lbl"&gt;Penutup Pembelajaran · Tugas Individu&lt;/div&gt;
      &lt;p style="margin:0;"&gt;&lt;strong&gt;Tulislah satu kesimpulan ringkas (5–7 kalimat) di buku catatan kalian masing-masing&lt;/strong&gt;, yang merangkum keseluruhan materi hari ini: fungsi sistem operasi, cara mengelola file dan folder, jenis-jenis media penyimpanan, serta peran dan cara kerja cloud storage dalam mendukung pekerjaan digital. Tulis dengan bahasa dan pemahaman kalian sendiri, bukan menyalin ulang materi.&lt;/p&gt;
    &lt;/div&gt;
  &lt;/section&gt;

&lt;/main&gt;

&lt;footer&gt;
  INFORMATIKA · SISTEM OPERASI, MANAJEMEN FILE &amp; PENYIMPANAN CLOUD · FASE E KELAS X SMK
&lt;/footer&gt;

&lt;/body&gt;
&lt;/html&gt;</description><link>http://kitab-investasi.blogspot.com/2026/08/sistem-operasi-manajemen-file.html</link><thr:total>0</thr:total><author>nof_rizal07@yahoo.co.id (abang_cool)</author></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-9000860041661554971.post-4375210522487967607</guid><pubDate>Tue, 04 Aug 2026 02:25:41 +0000</pubDate><atom:updated>2026-08-04T09:25:41.044+07:00</atom:updated><title>sertifikat kombel</title><description>&lt;!DOCTYPE html&gt;
&lt;html lang="id"&gt;
&lt;head&gt;
&lt;meta charset="UTF-8"&gt;
&lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&gt;
&lt;title&gt;Generator Sertifikat&lt;/title&gt;

&lt;link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@700&amp;display=swap" rel="stylesheet"&gt;

&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"&gt;&lt;/script&gt;

&lt;style&gt;

body{
    font-family:Arial,sans-serif;
    background:#eef2f7;
    padding:20px;
    max-width:700px;
    margin:auto;
}

.card{
    background:white;
    padding:24px;
    border-radius:20px;
    box-shadow:0 10px 20px rgba(0,0,0,.1);
}

h2{
    text-align:center;
    color:#1e4668;
}

.confirm-box{
    background:#f0f6ff;
    border-left:5px solid #2c7da0;
    padding:16px;
    border-radius:16px;
    margin-bottom:20px;
    text-align:center;
}

.confirm-box p{
    margin-top:0;
    font-weight:bold;
    color:#1e4668;
}

.confirm-buttons{
    display:flex;
    gap:10px;
    margin-top:10px;
}

.confirm-buttons button{
    flex:1;
}

.yes-btn{
    background:#1f8a4c;
}

.yes-btn:hover{
    background:#166638;
}

.no-btn{
    background:#c0392b;
}

.no-btn:hover{
    background:#962d22;
}

input,select,button{
    width:100%;
    padding:12px;
    margin-top:10px;
    border-radius:12px;
    border:1px solid #ccc;
    font-size:16px;
}

button{
    background:#2c7da0;
    color:white;
    border:none;
    cursor:pointer;
    font-weight:bold;
}

button:hover{
    background:#1f5e7a;
}

button:disabled{
    background:#94a3b8;
    cursor:not-allowed;
}

input:disabled,
select:disabled{
    background:#f1f5f9;
}

#preview{
    width:100%;
    border-radius:12px;
    margin-top:10px;
}

.loading{
    display:none;
    margin-top:15px;
    color:#1e4668;
    font-weight:bold;
    text-align:center;
}

.status{
    margin-top:12px;
    font-weight:bold;
}

.success{
    color:#1f8a4c;
}

.error{
    color:#c0392b;
}

&lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;

&lt;div class="card"&gt;

&lt;h2&gt;&#128220; Generator Sertifikat&lt;/h2&gt;

&lt;!-- ================= KONFIRMASI ================= --&gt;

&lt;div class="confirm-box"&gt;

&lt;p&gt;&#128269; Apakah Anda mengikuti pelatihan?&lt;/p&gt;

&lt;div class="confirm-buttons"&gt;

&lt;button class="yes-btn" onclick="confirmIkut()"&gt;
✅ YA, IKUT
&lt;/button&gt;

&lt;button class="no-btn" onclick="confirmTidakIkut()"&gt;
❌ TIDAK
&lt;/button&gt;

&lt;/div&gt;

&lt;div id="statusKonfirmasi" class="status"&gt;&lt;/div&gt;

&lt;/div&gt;

&lt;!-- ================= FORM ================= --&gt;

&lt;label&gt;Nama Lengkap&lt;/label&gt;

&lt;input
type="text"
id="nama"
placeholder="Contoh: Ahmad Fauzi"
disabled&gt;

&lt;label&gt;Peran&lt;/label&gt;

&lt;select id="peran" disabled&gt;
    &lt;option&gt;Peserta&lt;/option&gt;
    &lt;option&gt;Narasumber&lt;/option&gt;
&lt;/select&gt;

&lt;img
id="preview"
src="https://lh3.googleusercontent.com/d/1uGWwV5s0sYXgquBcnrH5_jyIFYnyMTHz"
alt="Template"&gt;

&lt;button
id="downloadBtn"
onclick="generatePDF()"
disabled&gt;

⬇️ UNDUH PDF

&lt;/button&gt;

&lt;div class="loading" id="loading"&gt;
Memproses PDF...
&lt;/div&gt;

&lt;/div&gt;

&lt;script&gt;

// ================= TEMPLATE (DIUBAH) =================

const FILE_ID =
'1uGWwV5s0sYXgquBcnrH5_jyIFYnyMTHz';  // &lt;-- ID baru

const TEMPLATE_URL =
`https://lh3.googleusercontent.com/d/${FILE_ID}`;

// ================= UTIL =================

function showLoading(show){

    document.getElementById('loading').style.display =
        show ? 'block' : 'none';

}

function getRomanMonth(monthIndex){

    const romawi = [
        "I","II","III","IV","V","VI",
        "VII","VIII","IX","X","XI","XII"
    ];

    return romawi[monthIndex];

}

function capitalizeEachWord(text){

    return text
        .toLowerCase()
        .replace(/\b\w/g,c=&gt;c.toUpperCase());

}

// ================= KONFIRMASI =================

function confirmIkut(){

    document.getElementById('nama').disabled = false;

    document.getElementById('peran').disabled = false;

    document.getElementById('downloadBtn').disabled = false;

    document.getElementById('statusKonfirmasi').innerHTML =
        '&lt;span class="success"&gt;✅ Konfirmasi diterima. Anda dapat mengunduh sertifikat.&lt;/span&gt;';

}

function confirmTidakIkut(){

    document.getElementById('nama').disabled = true;

    document.getElementById('peran').disabled = true;

    document.getElementById('downloadBtn').disabled = true;

    document.getElementById('statusKonfirmasi').innerHTML =
        '&lt;span class="error"&gt;❌ Anda tidak dapat mengunduh sertifikat.&lt;/span&gt;';

}

// ================= LOAD IMAGE =================

function loadImage(url){

    return new Promise((resolve,reject)=&gt;{

        const img = new Image();

        img.crossOrigin = "anonymous";

        img.onload = ()=&gt;resolve(img);

        img.onerror = ()=&gt;{

            reject(
                new Error(
                    'Template Google Drive gagal dimuat'
                )
            );

        };

        img.src = url + '?t=' + Date.now();

    });

}

// ================= NOMOR =================

async function generateNomor(){

    const now = new Date();

    const bulan =
        getRomanMonth(now.getMonth());

    const tahun =
        now.getFullYear();

    const nomor =
        Math.floor(Math.random()*900)+100;

    return `${nomor}/K/${bulan}/${tahun}`;

}

// ================= PDF =================

async function generatePDF(){

    const namaInput =
        document.getElementById('nama');

    const peranSelect =
        document.getElementById('peran');

    let nama =
        namaInput.value.trim();

    const peran =
        peranSelect.value;

    if(!nama){

        alert('Nama wajib diisi');

        return;

    }

    nama =
        capitalizeEachWord(nama);

    showLoading(true);

    try{

        await document.fonts.ready;

        const img =
            await loadImage(TEMPLATE_URL);

        const canvas =
            document.createElement('canvas');

        canvas.width = img.width;
        canvas.height = img.height;

        const ctx =
            canvas.getContext('2d');

        ctx.drawImage(
            img,
            0,
            0,
            canvas.width,
            canvas.height
        );

        // ================= POSISI =================

        const nomorY =
            canvas.height * 0.235;

        const namaY =
            canvas.height * 0.3990;

        const peranY =
            canvas.height * 0.5420;

        // ================= STYLE =================

        ctx.textAlign = 'center';

        ctx.textBaseline = 'middle';

        ctx.fillStyle = '#000';

        // nomor
        const nomorSertifikat =
            await generateNomor();

        ctx.font =
            `bold ${canvas.width*0.0125}px Montserrat`;

        ctx.fillText(
            nomorSertifikat,
            canvas.width/2,
            nomorY
        );

        // nama auto shrink
        let fontSize =
            canvas.width * 0.031;

        ctx.font =
            `700 ${fontSize}px Montserrat`;

        let textWidth =
            ctx.measureText(nama).width;

        const maxWidth =
            canvas.width - 180;

        while(
            textWidth &gt; maxWidth &amp;&amp;
            fontSize &gt; 20
        ){

            fontSize -= 2;

            ctx.font =
                `700 ${fontSize}px Montserrat`;

            textWidth =
                ctx.measureText(nama).width;

        }

        ctx.fillText(
            nama,
            canvas.width/2,
            namaY
        );

        // peran
        ctx.font =
            `bold ${canvas.width*0.024}px Montserrat`;

        ctx.fillText(
            peran,
            canvas.width/2,
            peranY
        );

        // ================= PDF =================

        const imageData =
            canvas.toDataURL(
                'image/jpeg',
                1.0
            );

        const { jsPDF } =
            window.jspdf;

        const pdf =
            new jsPDF({

                orientation:
                    canvas.width &gt; canvas.height
                    ? 'landscape'
                    : 'portrait',

                unit:'px',

                format:[
                    canvas.width,
                    canvas.height
                ]

            });

        pdf.addImage(
            imageData,
            'JPEG',
            0,
            0,
            canvas.width,
            canvas.height
        );

        const safeName =
            nama.replace(/[^a-z0-9]/gi,'_');

        pdf.save(
            `Sertifikat_${safeName}.pdf`
        );

    }catch(error){

        console.error(error);

        alert(
            '❌ Gagal membuat PDF\n\n' +
            error.message +
            '\n\nPastikan file Google Drive bersifat PUBLIC.'
        );

    }finally{

        showLoading(false);

    }

}

&lt;/script&gt;

&lt;/body&gt;
&lt;/html&gt;</description><link>http://kitab-investasi.blogspot.com/2026/08/sertifikat-kombel.html</link><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://lh3.googleusercontent.com/d/1uGWwV5s0sYXgquBcnrH5_jyIFYnyMTHz=s72-c" width="72"/><thr:total>0</thr:total><author>nof_rizal07@yahoo.co.id (abang_cool)</author></item></channel></rss>