<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>R | Irpan Chumaedi</title><link>https://www.irpanchumaedi.com/tag/r/</link><atom:link href="https://www.irpanchumaedi.com/tag/r/index.xml" rel="self" type="application/rss+xml"/><description>R</description><generator>Wowchemy (https://wowchemy.com)</generator><language>en-us</language><lastBuildDate>Mon, 18 May 2026 00:00:00 +0000</lastBuildDate><image><url>https://www.irpanchumaedi.com/images/icon_huc8b49dbecede763dad003ee9bbdb929f_244914_512x512_fill_lanczos_center_2.png</url><title>R</title><link>https://www.irpanchumaedi.com/tag/r/</link></image><item><title>Rekap &amp; Visualisasi Data Hujan dengan R &amp; ggplot2</title><link>https://www.irpanchumaedi.com/post/materi-visualisasi-r-ggplot2/</link><pubDate>Mon, 18 May 2026 00:00:00 +0000</pubDate><guid>https://www.irpanchumaedi.com/post/materi-visualisasi-r-ggplot2/</guid><description>
&lt;iframe
src="https://www.irpanchumaedi.com/html/visualisasi-data-hujan-r-ggplot2.html"
width="100%"
height="920px"
style="border:none; border-radius:10px; display:block;"
loading="lazy"
title="Rekap dan Visualisasi Data Hujan dengan Excel">
&lt;/iframe>
&lt;hr>
&lt;p>&lt;small> 🔽&lt;a href="https://1drv.ms/x/c/22f5ef4527203c63/IQCF8XwJQ0FlSbOszk5HB-tMAblXsphp4gsBaUdwiihCZ1c?e=Modg3o" target="_blank" rel="noopener">Download &lt;/a>data hujan Sta. Cemara, Bandung 2000-2025. &lt;/small>&lt;/p></description></item><item><title>Mengenal R &amp; RMarkdown: Instalasi dan Proyek Pertama</title><link>https://www.irpanchumaedi.com/post/mengenal-r-rmarkdown/</link><pubDate>Sun, 17 May 2026 00:00:00 +0000</pubDate><guid>https://www.irpanchumaedi.com/post/mengenal-r-rmarkdown/</guid><description>&lt;style>
@keyframes fadeUp {
from { opacity: 0; transform: translateY(14px); }
to { opacity: 1; transform: translateY(0); }
}
@keyframes slideRight {
from { opacity: 0; transform: translateX(-14px); }
to { opacity: 1; transform: translateX(0); }
}
@keyframes pulseDot {
0%, 100% { transform: scale(1); box-shadow: 0 0 0 0 rgba(0,188,212,0.4); }
50% { transform: scale(1.1); box-shadow: 0 0 0 8px rgba(0,188,212,0); }
}
@keyframes arrowBounce {
0%, 100% { transform: translateX(0); }
50% { transform: translateX(5px); }
}
.card-anim { opacity: 0; animation: fadeUp 0.5s ease forwards; }
.ca1 { animation-delay: 0.05s; }
.ca2 { animation-delay: 0.18s; }
.ca3 { animation-delay: 0.31s; }
.ca4 { animation-delay: 0.44s; }
.ca5 { animation-delay: 0.57s; }
.step-anim { opacity: 0; animation: slideRight 0.45s ease forwards; }
.sa1 { animation-delay: 0.1s; } .sa2 { animation-delay: 0.22s; }
.sa3 { animation-delay: 0.34s; } .sa4 { animation-delay: 0.46s; }
.sa5 { animation-delay: 0.58s; }
.pulse-dot { animation: pulseDot 2s ease-in-out infinite; }
.arrow-bounce { display: inline-block; animation: arrowBounce 1.3s ease-in-out infinite; }
&lt;/style>
&lt;blockquote>
&lt;p>&lt;em>Artikel ini adalah bagian dari seri &lt;strong>Fondasi Data &amp;amp; Tools&lt;/strong>. Sebelum membaca ini, pastikan sudah membaca &lt;a href="https://www.irpanchumaedi.com/post/materi-pengguna-pembuat-kode/">Filosofi: Pengguna vs. Pembuat Kode&lt;/a>.&lt;/em>&lt;/p>
&lt;/blockquote>
&lt;hr>
&lt;p>Bayangkan kamu baru saja selesai mengumpulkan data curah hujan 25 tahun dari BMKG. Analisis frekuensi harus dikerjakan: hitung statistik, fit distribusi, uji KS, uji chi-kuadrat, buat kurva IDF. Lalu semua hasilnya harus masuk ke laporan Word yang rapi.&lt;/p>
&lt;p>&lt;em>Tiba-tiba bos bilang: &amp;ldquo;Mas, data hujan yang kemarin kejauhan. ambil data ini ya, lokasi nya lebih dekat soalnya&amp;rdquo;&lt;/em>&lt;/p>
&lt;p>&lt;em>&amp;lsquo;Waduh, ngulang dari awal lagi dong&amp;ndash;'&lt;/em>&lt;/p>
&lt;p>Hal ini sering saya alami dan dengan berat hati harus dikerjakan lagi dari awal. Memang sudah ada template excel dan word nya. Tapi menghabiskan waktu, belum lagi kita harus teliti jangan sampai ada kata &amp;ldquo;Papua&amp;rdquo; di proyek &amp;ldquo;Banjarmasin&amp;rdquo;, &lt;strong>malu banget&lt;/strong>.&lt;/p>
&lt;p>Contoh kasus lainnya adalah ketika kita mengerjakan proses yang sama, tapi lokasinya saja yang berbeda. Data memang pasti berbeda juga, tapi proses analisis persis sama tok.&lt;/p>
&lt;p>Untuk mengerjakan ulang dengan cara biasa mungkin bisa menghabiskan &lt;strong>2-4 jam&lt;/strong> per stasiun, per proyek. tapi dengan cara yang akan kita pelajari hari ini tinggal &lt;strong>klik satu tombol&lt;/strong>, laporan bisa jadi dalam 30 detik.&lt;/p>
&lt;hr>
&lt;h2 id="apa-itu-r">Apa Itu R?&lt;/h2>
&lt;p>R adalah bahasa pemrograman yang dirancang khusus untuk analisis statistik dan visualisasi data. Tapi jangan langsung takut dengan kata &amp;ldquo;pemrograman&amp;rdquo; — seperti yang sudah dibahas di &lt;a href="https://www.irpanchumaedi.com/post/materi-pengguna-pembuat-kode/" target="_blank" rel="noopener">artikel sebelumnya&lt;/a>, kita tidak perlu menjadi programmer. Kita cukup menjadi &lt;strong>pengguna yang cerdas&lt;/strong>.&lt;/p>
&lt;div style="display: grid; grid-template-columns: repeat(3, 1fr); gap: 0.9rem; margin: 1.8rem 0;">
&lt;div class="card-anim ca1" style="border-radius: 12px; padding: 1.2rem; background: #0d1b2a; border: 1px solid #1565C0; border-top: 3px solid #1565C0; text-align: center;">
&lt;div style="font-size: 1.6rem; margin-bottom: 0.5rem; font-family: monospace; color: #1E88E5; font-weight: 700;">R&lt;/div>
&lt;div style="font-size: 0.82rem; font-weight: 700; color: #90CAF9; margin-bottom: 0.4rem;">Gratis &amp; Open Source&lt;/div>
&lt;div style="font-size: 0.75rem; color: #666; line-height: 1.5;">Tidak perlu lisensi. Ribuan paket tersedia di CRAN.&lt;/div>
&lt;/div>
&lt;div class="card-anim ca2" style="border-radius: 12px; padding: 1.2rem; background: #0d1b2a; border: 1px solid #00BCD4; border-top: 3px solid #00BCD4; text-align: center;">
&lt;div style="font-size: 1.6rem; margin-bottom: 0.5rem; font-family: monospace; color: #00BCD4; font-weight: 700;">📊&lt;/div>
&lt;div style="font-size: 0.82rem; font-weight: 700; color: #80DEEA; margin-bottom: 0.4rem;">Visualisasi Kelas Atas&lt;/div>
&lt;div style="font-size: 0.75rem; color: #666; line-height: 1.5;">ggplot2 menghasilkan plot publikasi-siap dengan sedikit kode.&lt;/div>
&lt;/div>
&lt;div class="card-anim ca3" style="border-radius: 12px; padding: 1.2rem; background: #0d1b2a; border: 1px solid #43A047; border-top: 3px solid #43A047; text-align: center;">
&lt;div style="font-size: 1.6rem; margin-bottom: 0.5rem; font-family: monospace; color: #66BB6A; font-weight: 700;">∞&lt;/div>
&lt;div style="font-size: 0.82rem; font-weight: 700; color: #A5D6A7; margin-bottom: 0.4rem;">Reproducible&lt;/div>
&lt;div style="font-size: 0.75rem; color: #666; line-height: 1.5;">Ganti input → semua output diperbarui otomatis. Tidak ada copy-paste.&lt;/div>
&lt;/div>
&lt;/div>
&lt;hr>
&lt;h2 id="apa-itu-rmarkdown">Apa Itu RMarkdown?&lt;/h2>
&lt;p>RMarkdown adalah format file (&lt;code>.Rmd&lt;/code>) yang &lt;strong>menggabungkan tiga hal dalam satu dokumen&lt;/strong>:&lt;/p>
&lt;div style="margin: 1.5rem 0; border: 1px solid #1a2a3a; border-radius: 12px; overflow: hidden;">
&lt;div style="display: grid; grid-template-columns: 1fr 1fr 1fr;">
&lt;div class="card-anim ca1" style="padding: 1.1rem; border-right: 1px solid #1a2a3a; background: #070d14;">
&lt;div style="font-size: 0.7rem; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: #F57F17; margin-bottom: 0.5rem;">① YAML Header&lt;/div>
&lt;div style="font-family: monospace; font-size: 0.72rem; color: #FFB74D; line-height: 1.7;">---&lt;br>title: "Analisis"&lt;br>output:&lt;br>&amp;nbsp;&amp;nbsp;word_document&lt;br>---&lt;/div>
&lt;div style="font-size: 0.72rem; color: #555; margin-top: 0.5rem;">Konfigurasi dokumen: judul, format output, parameter.&lt;/div>
&lt;/div>
&lt;div class="card-anim ca2" style="padding: 1.1rem; border-right: 1px solid #1a2a3a; background: #070d14;">
&lt;div style="font-size: 0.7rem; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: #0288D1; margin-bottom: 0.5rem;">② Teks Markdown&lt;/div>
&lt;div style="font-family: monospace; font-size: 0.72rem; color: #4FC3F7; line-height: 1.7;"># Bab 1&lt;br>Analisis dilakukan&lt;br>di stasiun **BMKG**&lt;br>periode 2000–2026.&lt;/div>
&lt;div style="font-size: 0.72rem; color: #555; margin-top: 0.5rem;">Narasi laporan dalam format teks sederhana.&lt;/div>
&lt;/div>
&lt;div class="card-anim ca3" style="padding: 1.1rem; background: #070d14;">
&lt;div style="font-size: 0.7rem; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: #43A047; margin-bottom: 0.5rem;">③ Code Chunk R&lt;/div>
&lt;div style="font-family: monospace; font-size: 0.72rem; color: #81C784; line-height: 1.7;">```{r}&lt;br>x_bar &amp;lt;- mean(hujan)&lt;br>plot(cdf_gumbel)&lt;br>flextable(df_hasil)&lt;br>```&lt;/div>
&lt;div style="font-size: 0.72rem; color: #555; margin-top: 0.5rem;">Kode analisis, tabel, dan grafik — semua otomatis.&lt;/div>
&lt;/div>
&lt;/div>
&lt;/div>
&lt;p>Ketika kamu klik &lt;strong>Knit&lt;/strong>, RStudio menjalankan semua kode R, menghasilkan grafik, menghitung angka, lalu menyusunnya menjadi dokumen Word (atau PDF, atau HTML) secara otomatis.&lt;/p>
&lt;hr>
&lt;h2 id="perbandingan-manual-vs-rmarkdown">Perbandingan: Manual vs RMarkdown&lt;/h2>
&lt;p>Gambar di bawah ini menunjukkan perbedaan nyata dalam alur kerja:&lt;/p>
&lt;p>&lt;img src="compare-manual-vs-rmd.gif" alt="Perbandingan Manual vs RMarkdown">&lt;/p>
&lt;p>Satu kata: &lt;strong>reproducible&lt;/strong>. Ketika data berubah, kamu tidak perlu mengulang semua langkah. Cukup update file Excel, klik Knit, laporan diperbarui dalam hitungan detik.&lt;/p>
&lt;hr>
&lt;h2 id="instalasi-r--rstudio">Instalasi: R + RStudio&lt;/h2>
&lt;p>Kamu hanya butuh &lt;strong>dua software&lt;/strong> ini. Keduanya gratis.&lt;/p>
&lt;div style="margin: 1.5rem 0;">
&lt;div class="step-anim sa1" style="display: flex; align-items: flex-start; gap: 1rem; padding: 1rem 1.2rem; margin-bottom: 0.75rem; background: #0d1b2a; border: 1px solid #1a3050; border-left: 4px solid #1565C0; border-radius: 10px;">
&lt;div style="width: 36px; height: 36px; border-radius: 50%; background: #1565C0; color: white; display: flex; align-items: center; justify-content: center; font-size: 0.85rem; font-weight: 700; flex-shrink: 0; margin-top: 1px;" class="pulse-dot">1&lt;/div>
&lt;div>
&lt;div style="font-size: 0.9rem; font-weight: 700; color: #90CAF9; margin-bottom: 0.2rem;">Install R&lt;/div>
&lt;div style="font-size: 0.82rem; color: #666; line-height: 1.6;">Download dari &lt;a href="https://cran.r-project.org" strong style="color: #90CAF9;">cran.r-project.org&lt;/strong>&lt;/a> → pilih &lt;em>Download R for Windows atau sistem operasi yang kamu pakai&lt;/em> → jalankan installer, klik Next terus sampai selesai.&lt;/div>
&lt;/div>
&lt;/div>
&lt;div class="step-anim sa2" style="display: flex; align-items: flex-start; gap: 1rem; padding: 1rem 1.2rem; margin-bottom: 0.75rem; background: #0d1b2a; border: 1px solid #1a3050; border-left: 4px solid #00BCD4; border-radius: 10px;">
&lt;div style="width: 36px; height: 36px; border-radius: 50%; background: #00838F; color: white; display: flex; align-items: center; justify-content: center; font-size: 0.85rem; font-weight: 700; flex-shrink: 0; margin-top: 1px;">2&lt;/div>
&lt;div>
&lt;div style="font-size: 0.9rem; font-weight: 700; color: #80DEEA; margin-bottom: 0.2rem;">Install RStudio&lt;/div>
&lt;div style="font-size: 0.82rem; color: #666; line-height: 1.6;">Download RStudio dari posit untuk &lt;a href="https://rstudio.org/download/latest/stable/desktop/windows/RStudio-latest.exe" strong style="color: #80DEEA;">windows&lt;/strong>&lt;/a> atau &lt;a href="https://rstudio.org/download/latest/stable/desktop/mac/RStudio-latest.dmg" strong style="color: #80DEEA;">mac&lt;/strong>&lt;/a> → install. RStudio adalah antarmuka visual untuk bekerja dengan R.&lt;/div>
&lt;/div>
&lt;/div>
&lt;div class="step-anim sa3" style="display: flex; align-items: flex-start; gap: 1rem; padding: 1rem 1.2rem; margin-bottom: 0.75rem; background: #0d1b2a; border: 1px solid #1a3050; border-left: 4px solid #43A047; border-radius: 10px;">
&lt;div style="width: 36px; height: 36px; border-radius: 50%; background: #2E7D32; color: white; display: flex; align-items: center; justify-content: center; font-size: 0.85rem; font-weight: 700; flex-shrink: 0; margin-top: 1px;">3&lt;/div>
&lt;div>
&lt;div style="font-size: 0.9rem; font-weight: 700; color: #A5D6A7; margin-bottom: 0.2rem;">Install Paket yang Dibutuhkan&lt;/div>
&lt;div style="font-size: 0.82rem; color: #666; line-height: 1.5; margin-bottom: 0.5rem;">Buka RStudio → di panel &lt;em>Console&lt;/em> (bawah kiri), ketik dan tekan Enter:&lt;/div>
&lt;div style="background: #050d14; border: 1px solid #1a2a3a; border-radius: 6px; padding: 0.6rem 0.8rem; font-family: monospace; font-size: 0.78rem; color: #A5D6A7; line-height: 1.8;">install.packages(c("rmarkdown", "readxl", "ggplot2",&lt;br>&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;"dplyr", "tidyr", "flextable", "scales"))&lt;/div>
&lt;div style="font-size: 0.75rem; color: #555; margin-top: 0.4rem;">Tunggu beberapa menit hingga semua paket terinstal.&lt;/div>
&lt;/div>
&lt;/div>
&lt;div class="step-anim sa4" style="display: flex; align-items: flex-start; gap: 1rem; padding: 1rem 1.2rem; background: #0d1b2a; border: 1px solid #1a3050; border-left: 4px solid #FFB300; border-radius: 10px;">
&lt;div style="width: 36px; height: 36px; border-radius: 50%; background: #F57F17; color: white; display: flex; align-items: center; justify-content: center; font-size: 0.85rem; font-weight: 700; flex-shrink: 0; margin-top: 1px;">4&lt;/div>
&lt;div>
&lt;div style="font-size: 0.9rem; font-weight: 700; color: #FFE082; margin-bottom: 0.2rem;">Verifikasi Instalasi&lt;/div>
&lt;div style="font-size: 0.82rem; color: #666; line-height: 1.5; margin-bottom: 0.5rem;">Di Console, ketik:&lt;/div>
&lt;div style="background: #050d14; border: 1px solid #1a2a3a; border-radius: 6px; padding: 0.6rem 0.8rem; font-family: monospace; font-size: 0.78rem; color: #FFE082; line-height: 1.8;">library(ggplot2)&lt;br>ggplot(data.frame(x=1:10, y=rnorm(10)), aes(x,y)) + geom_point()&lt;/div>
&lt;div style="font-size: 0.75rem; color: #555; margin-top: 0.4rem;">Jika muncul grafik di panel kanan bawah, instalasi berhasil.&lt;/div>
&lt;/div>
&lt;/div>
&lt;/div>
&lt;hr>
&lt;h2 id="proyek-pertama-analisis-frekuensi-curah-hujan">Proyek Pertama: Analisis Frekuensi Curah Hujan&lt;/h2>
&lt;p>Ini bagian yang menarik. Kita tidak akan mulai dari nol — saya sudah siapkan template lengkap yang bisa langsung dipakai.&lt;/p>
&lt;h3 id="cara-kerjanya">Cara Kerjanya&lt;/h3>
&lt;p>&lt;img src="workflow-rmarkdown.gif" alt="Alur Kerja Template RMarkdown">&lt;/p>
&lt;p>Template ini membaca data dari &lt;strong>Excel&lt;/strong>, menjalankan seluruh analisis secara otomatis, lalu menghasilkan &lt;strong>laporan Word&lt;/strong> lengkap dengan tabel dan grafik.&lt;/p>
&lt;h3 id="yang-dihasilkan-otomatis">Yang Dihasilkan Otomatis&lt;/h3>
&lt;div style="display: grid; grid-template-columns: 1fr 1fr; gap: 0.8rem; margin: 1.5rem 0;">
&lt;div class="card-anim ca1" style="padding: 1rem 1.1rem; background: #0a120d; border: 1px solid #2E7D32; border-radius: 10px;">
&lt;div style="font-size: 0.7rem; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: #66BB6A; margin-bottom: 0.6rem;">Analisis Distribusi&lt;/div>
&lt;div style="font-size: 0.8rem; color: #888; line-height: 1.7;">
[v] Tabel data hujan harian maksimum&lt;br>
[v] Plot PDF — 4 distribusi sekaligus&lt;br>
[v] Plot CDF dengan plotting position&lt;br>
[v] Uji Kolmogorov-Smirnov&lt;br>
[v] Uji Chi-Kuadrat&lt;br>
[v] Pemilihan distribusi terbaik otomatis
&lt;/div>
&lt;/div>
&lt;div class="card-anim ca2" style="padding: 1rem 1.1rem; background: #0a1018; border: 1px solid #1565C0; border-radius: 10px;">
&lt;div style="font-size: 0.7rem; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: #64B5F6; margin-bottom: 0.6rem;">Curah Hujan Rencana &amp; IDF&lt;/div>
&lt;div style="font-size: 0.8rem; color: #888; line-height: 1.7;">
[v] CH rencana: T = 2, 5, 10, 25, 50, 100 tahun&lt;br>
[v] Tabel IDF lengkap (5 menit - 24 jam)&lt;br>
[v] Kurva IDF log-log&lt;br>
[v] Rumus Mononobe&lt;br>
[v] Rekapitulasi intensitas t = 60 menit&lt;br>
[v] Semua dalam format Word siap laporan
&lt;/div>
&lt;/div>
&lt;/div>
&lt;h3 id="cara-menggunakan-template">Cara Menggunakan Template&lt;/h3>
&lt;div style="margin: 1.5rem 0;">
&lt;div class="step-anim sa1" style="display: flex; gap: 0.9rem; padding: 0.9rem 1.1rem; margin-bottom: 0.6rem; background: #070d14; border: 1px solid #1a2a3a; border-radius: 9px;">
&lt;div style="font-family: monospace; font-size: 0.78rem; font-weight: 700; color: #1E88E5; flex-shrink: 0; padding-top: 1px;">01&lt;/div>
&lt;div>
&lt;div style="font-size: 0.85rem; font-weight: 700; color: #90CAF9; margin-bottom: 0.2rem;">Download &amp; Ekstrak File Template&lt;/div>
&lt;div style="font-size: 0.78rem; color: #555; line-height: 1.5;">Simpan ketiga file di &lt;strong style="color: #90CAF9;">satu folder yang sama&lt;/strong>: &lt;code style="background:#1a2a3a; padding:1px 5px; border-radius:3px; font-size:0.72rem;">Analisis_Frekuensi_TEMPLATE.Rmd&lt;/code>, &lt;code style="background:#1a2a3a; padding:1px 5px; border-radius:3px; font-size:0.72rem;">Data_Input_Frekuensi.xlsx&lt;/code>, dan &lt;code style="background:#1a2a3a; padding:1px 5px; border-radius:3px; font-size:0.72rem;">reference_template.docx&lt;/code>&lt;/div>
&lt;/div>
&lt;/div>
&lt;div class="step-anim sa2" style="display: flex; gap: 0.9rem; padding: 0.9rem 1.1rem; margin-bottom: 0.6rem; background: #070d14; border: 1px solid #1a2a3a; border-radius: 9px;">
&lt;div style="font-family: monospace; font-size: 0.78rem; font-weight: 700; color: #00BCD4; flex-shrink: 0; padding-top: 1px;">02&lt;/div>
&lt;div>
&lt;div style="font-size: 0.85rem; font-weight: 700; color: #80DEEA; margin-bottom: 0.2rem;">Isi Data di Excel&lt;/div>
&lt;div style="font-size: 0.78rem; color: #555; line-height: 1.5;">Buka &lt;code style="background:#1a2a3a; padding:1px 5px; border-radius:3px; font-size:0.72rem;">Data_Input_Frekuensi.xlsx&lt;/code>. Isi sheet &lt;strong style="color:#80DEEA;">Metadata_Proyek&lt;/strong> (nama proyek, stasiun, kala ulang) dan sheet &lt;strong style="color:#80DEEA;">Data_Hujan&lt;/strong> (kolom Tahun dan Hujan Maks mm). Simpan file.&lt;/div>
&lt;/div>
&lt;/div>
&lt;div class="step-anim sa3" style="display: flex; gap: 0.9rem; padding: 0.9rem 1.1rem; margin-bottom: 0.6rem; background: #070d14; border: 1px solid #1a2a3a; border-radius: 9px;">
&lt;div style="font-family: monospace; font-size: 0.78rem; font-weight: 700; color: #43A047; flex-shrink: 0; padding-top: 1px;">03&lt;/div>
&lt;div>
&lt;div style="font-size: 0.85rem; font-weight: 700; color: #A5D6A7; margin-bottom: 0.2rem;">Buka File .Rmd di RStudio&lt;/div>
&lt;div style="font-size: 0.78rem; color: #555; line-height: 1.5;">Double-click file &lt;code style="background:#1a2a3a; padding:1px 5px; border-radius:3px; font-size:0.72rem;">.Rmd&lt;/code> → terbuka di RStudio. Kamu akan melihat kode di bagian &lt;code style="background:#1a2a3a; padding:1px 5px; border-radius:3px; font-size:0.72rem;">DATA_INPUT&lt;/code> — tidak perlu diubah jika file Excel ada di folder yang sama.&lt;/div>
&lt;/div>
&lt;/div>
&lt;div class="step-anim sa4" style="display: flex; gap: 0.9rem; padding: 0.9rem 1.1rem; margin-bottom: 0.6rem; background: #070d14; border: 1px solid #1a2a3a; border-radius: 9px;">
&lt;div style="font-family: monospace; font-size: 0.78rem; font-weight: 700; color: #FFB300; flex-shrink: 0; padding-top: 1px;">04&lt;/div>
&lt;div>
&lt;div style="font-size: 0.85rem; font-weight: 700; color: #FFE082; margin-bottom: 0.2rem;">Klik Tombol Knit&lt;/div>
&lt;div style="font-size: 0.78rem; color: #555; line-height: 1.5;">Di RStudio, klik tombol &lt;strong style="color:#FFE082;">[ Knit ]&lt;/strong> (ikon benang + jarum di toolbar, atau tekan &lt;kbd style="background:#1a2a3a; padding:2px 6px; border-radius:3px; font-size:0.7rem;">Ctrl + Shift + K&lt;/kbd>). Tunggu 10–30 detik. File Word akan terbuka otomatis.&lt;/div>
&lt;/div>
&lt;/div>
&lt;div class="step-anim sa5" style="display: flex; gap: 0.9rem; padding: 0.9rem 1.1rem; background: #070e12; border: 1px solid #006064; border-radius: 9px;">
&lt;div style="font-family: monospace; font-size: 0.78rem; font-weight: 700; color: #00BCD4; flex-shrink: 0; padding-top: 1px;">05&lt;/div>
&lt;div>
&lt;div style="font-size: 0.85rem; font-weight: 700; color: #80DEEA; margin-bottom: 0.2rem;">Proyek Berikutnya? Tinggal Ganti Data&lt;/div>
&lt;div style="font-size: 0.78rem; color: #555; line-height: 1.5;">Salin folder ke direktori proyek baru. Buka Excel, ganti data hujan dan metadata. Klik Knit. Laporan baru siap — tanpa mengubah satu baris kode pun.&lt;/div>
&lt;/div>
&lt;/div>
&lt;/div>
&lt;hr>
&lt;h2 id="anatomi-template-bagian-yang-perlu-diketahui">Anatomi Template: Bagian yang Perlu Diketahui&lt;/h2>
&lt;p>Kamu tidak perlu memahami semua kode. Tapi ada tiga bagian penting yang perlu diketahui:&lt;/p>
&lt;div style="margin: 1.5rem 0; background: #050d14; border: 1px solid #1a2a3a; border-radius: 12px; overflow: hidden;">
&lt;div style="background: #0a1520; padding: 0.7rem 1.2rem; border-bottom: 1px solid #1a2a3a;">
&lt;span style="font-size: 0.72rem; font-weight: 700; letter-spacing: 0.08em; color: #64B5F6; text-transform: uppercase;">Analisis_Frekuensi_TEMPLATE.Rmd&lt;/span>
&lt;/div>
&lt;div style="padding: 1.1rem 1.3rem;">
&lt;div style="margin-bottom: 1rem;">
&lt;div style="font-size: 0.68rem; font-weight: 700; letter-spacing: 0.07em; text-transform: uppercase; color: #F57F17; margin-bottom: 0.4rem;">① YAML — Konfigurasi Output&lt;/div>
&lt;div style="background: #0a1218; border-radius: 6px; padding: 0.7rem 0.9rem; font-family: monospace; font-size: 0.75rem; line-height: 1.8; color: #FFB74D;">
&lt;span style="color: #555;">---&lt;/span>&lt;br>
&lt;span style="color: #F57F17;">title:&lt;/span> &lt;span style="color: #FFF8E1;">"Analisis Frekuensi Curah Hujan Harian Maksimum"&lt;/span>&lt;br>
&lt;span style="color: #F57F17;">params:&lt;/span>&lt;br>
&amp;nbsp;&amp;nbsp;&lt;span style="color: #F57F17;">path_excel:&lt;/span> &lt;span style="color: #FFF8E1;">"Data_Input_Frekuensi.xlsx"&lt;/span> &lt;span style="color: #555;"># ← path ke file Excel&lt;/span>&lt;br>
&lt;span style="color: #F57F17;">output:&lt;/span>&lt;br>
&amp;nbsp;&amp;nbsp;&lt;span style="color: #F57F17;">word_document:&lt;/span>&lt;br>
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="color: #F57F17;">reference_docx:&lt;/span> &lt;span style="color: #FFF8E1;">reference_template.docx&lt;/span>&lt;br>
&lt;span style="color: #555;">---&lt;/span>
&lt;/div>
&lt;div style="font-size: 0.74rem; color: #555; margin-top: 0.4rem;">Hanya ubah &lt;code>path_excel&lt;/code> jika file Excel tidak berada di folder yang sama.&lt;/div>
&lt;/div>
&lt;div style="margin-bottom: 1rem;">
&lt;div style="font-size: 0.68rem; font-weight: 700; letter-spacing: 0.07em; text-transform: uppercase; color: #43A047; margin-bottom: 0.4rem;">② DATA_INPUT — Satu-satunya blok yang perlu dipahami&lt;/div>
&lt;div style="background: #0a1218; border-radius: 6px; padding: 0.7rem 0.9rem; font-family: monospace; font-size: 0.75rem; line-height: 1.8; color: #A5D6A7;">
&lt;span style="color: #555;">```{r DATA_INPUT}&lt;/span>&lt;br>
&lt;span style="color: #555;"># !! HANYA EDIT BAGIAN INI UNTUK SETIAP PROYEK BARU !!&lt;/span>&lt;br>
&lt;span style="color: #43A047;">path_excel&lt;/span> &lt;span style="color: #fff;">&amp;lt;-&lt;/span> params$path_excel&lt;br>
&lt;span style="color: #43A047;">T_values_default&lt;/span> &lt;span style="color: #fff;">&amp;lt;-&lt;/span> &lt;span style="color: #81C784;">c(2, 5, 10, 25, 50, 100)&lt;/span>&lt;br>
&lt;span style="color: #555;">```&lt;/span>
&lt;/div>
&lt;div style="font-size: 0.74rem; color: #555; margin-top: 0.4rem;">Kala ulang bisa diatur dari Excel (sheet Metadata_Proyek). Blok ini hanya fallback.&lt;/div>
&lt;/div>
&lt;div>
&lt;div style="font-size: 0.68rem; font-weight: 700; letter-spacing: 0.07em; text-transform: uppercase; color: #1E88E5; margin-bottom: 0.4rem;">③ ANALISIS — Jangan diubah&lt;/div>
&lt;div style="background: #0a1218; border-radius: 6px; padding: 0.7rem 0.9rem; font-family: monospace; font-size: 0.75rem; line-height: 1.8; color: #64B5F6;">
&lt;span style="color: #555;">```{r ANALISIS, include=FALSE}&lt;/span>&lt;br>
&lt;span style="color: #555;"># Statistik dasar, fit 4 distribusi, uji KS &amp; Chi-kuadrat,&lt;/span>&lt;br>
&lt;span style="color: #555;"># pemilihan otomatis, hitung IDF Mononobe — semua di sini.&lt;/span>&lt;br>
&lt;span style="color: #555;"># Tidak perlu diubah.&lt;/span>&lt;br>
&lt;span style="color: #555;">```&lt;/span>
&lt;/div>
&lt;div style="font-size: 0.74rem; color: #555; margin-top: 0.4rem;">Semua matematika ada di sini — Normal, Log-Normal, Gumbel, Log-Pearson III. Dihitung otomatis.&lt;/div>
&lt;/div>
&lt;/div>
&lt;/div>
&lt;hr>
&lt;h2 id="download-template">Download Template&lt;/h2>
&lt;div style="margin: 1.5rem 0; padding: 1.4rem 1.6rem; background: linear-gradient(135deg, #0a1520, #071018); border: 1px solid #1565C0; border-radius: 14px;" class="card-anim ca1">
&lt;div style="font-size: 0.7rem; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: #64B5F6; margin-bottom: 1rem;">Paket Template — Analisis Frekuensi Curah Hujan&lt;/div>
&lt;div style="display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 0.7rem; margin-bottom: 1.1rem;">
&lt;div style="padding: 0.8rem; background: #0d1b2a; border: 1px solid #1a3050; border-radius: 8px; text-align: center;">
&lt;div style="font-family: monospace; font-size: 0.75rem; font-weight: 700; color: #43A047; margin-bottom: 0.3rem;">.Rmd&lt;/div>
&lt;div style="font-size: 0.72rem; color: #666;">Analisis_Frekuensi&lt;br>_TEMPLATE.Rmd&lt;/div>
&lt;/div>
&lt;div style="padding: 0.8rem; background: #0d1b2a; border: 1px solid #1a3050; border-radius: 8px; text-align: center;">
&lt;div style="font-family: monospace; font-size: 0.75rem; font-weight: 700; color: #1E88E5; margin-bottom: 0.3rem;">.xlsx&lt;/div>
&lt;div style="font-size: 0.72rem; color: #666;">Data_Input&lt;br>_Frekuensi.xlsx&lt;/div>
&lt;/div>
&lt;div style="padding: 0.8rem; background: #0d1b2a; border: 1px solid #1a3050; border-radius: 8px; text-align: center;">
&lt;div style="font-family: monospace; font-size: 0.75rem; font-weight: 700; color: #FFB300; margin-bottom: 0.3rem;">.docx&lt;/div>
&lt;div style="font-size: 0.72rem; color: #666;">reference&lt;br>_template.docx&lt;/div>
&lt;/div>
&lt;/div>
&lt;div style="font-size: 0.8rem; color: #555; line-height: 1.6; margin-bottom: 1rem;">Tiga file harus berada dalam &lt;strong style="color: #90CAF9;">satu folder yang sama&lt;/strong>. Template sudah diuji dengan data BMKG stasiun Bandung, 2000–2026. Distribusi yang didukung: Normal, Log-Normal 2P, Gumbel, Log-Pearson III.&lt;/div>
&lt;a href="https://www.irpanchumaedi.com/files/template-analisis-frekuensi.zip" style="display: inline-flex; align-items: center; gap: 0.6rem; padding: 0.75rem 1.5rem; background: #1565C0; color: white; text-decoration: none; border-radius: 8px; font-size: 0.88rem; font-weight: 700; letter-spacing: 0.02em; transition: background 0.2s ease;" onmouseover="this.style.background='#1E88E5'" onmouseout="this.style.background='#1565C0'">
&lt;span style="font-size: 1rem;">&amp;#8595;&lt;/span> Download Template (ZIP)
&lt;/a>
&lt;/div>
&lt;hr>
&lt;h2 id="apa-selanjutnya">Apa Selanjutnya?&lt;/h2>
&lt;p>Setelah berhasil menjalankan template ini, kamu sudah memiliki fondasi yang kuat. Artikel berikutnya akan membahas cara &lt;strong>memodifikasi template&lt;/strong> untuk kebutuhan proyek yang berbeda — menambah stasiun, mengubah distribusi, atau mengintegrasikan data GPM IMERG.&lt;/p>
&lt;div style="display: flex; flex-direction: column; gap: 0.6rem; margin-top: 1.5rem;">
&lt;a href="https://www.irpanchumaedi.com/post/materi-pengguna-pembuat-kode/" style="display: flex; align-items: center; gap: 1rem; padding: 0.9rem 1.2rem; background: #070d14; border: 1px solid #1a2a3a; border-radius: 10px; text-decoration: none; transition: border-color 0.2s ease;" onmouseover="this.style.borderColor='#555'" onmouseout="this.style.borderColor='#1a2a3a'">
&lt;span style="font-size: 1.1rem; flex-shrink: 0; color: #555; display: inline-block; transform: scaleX(-1);">→&lt;/span>
&lt;div>
&lt;div style="font-size: 0.65rem; font-weight: 700; letter-spacing: 0.09em; text-transform: uppercase; color: #555; margin-bottom: 0.15rem;">Artikel Sebelumnya&lt;/div>
&lt;div style="font-size: 0.85rem; font-weight: 700; color: #90CAF9;">Filosofi: Pengguna vs. Pembuat Kode&lt;/div>
&lt;/div>
&lt;/a>
&lt;div style="display: flex; align-items: center; gap: 1rem; padding: 0.9rem 1.2rem; background: #070d14; border: 1px dashed #2a2a3a; border-radius: 10px; opacity: 0.55; cursor: default;">
&lt;span style="font-size: 1.1rem; flex-shrink: 0; color: #444;">→&lt;/span>
&lt;div>
&lt;div style="font-size: 0.65rem; font-weight: 700; letter-spacing: 0.09em; text-transform: uppercase; color: #444; margin-bottom: 0.15rem;">Segera Hadir&lt;/div>
&lt;div style="font-size: 0.85rem; font-weight: 700; color: #555;">Kustomisasi Template: Adaptasi untuk Berbagai Proyek&lt;/div>
&lt;/div>
&lt;/div>
&lt;/div>
&lt;hr>
&lt;p>&lt;em>Template ini dibuat menggunakan R versi 4.x dengan paket: &lt;code>rmarkdown&lt;/code>, &lt;code>readxl&lt;/code>, &lt;code>ggplot2&lt;/code>, &lt;code>dplyr&lt;/code>, &lt;code>tidyr&lt;/code>, &lt;code>flextable&lt;/code>, &lt;code>scales&lt;/code>. Semua perhitungan mengikuti metode standar hidrologi Indonesia.&lt;/em> 🌧️&lt;/p></description></item><item><title>Perhitungan Debit Banjir Rencana</title><link>https://www.irpanchumaedi.com/post/materi-perhitungan-debit-banjir/</link><pubDate>Sat, 03 Feb 2024 00:00:00 +0000</pubDate><guid>https://www.irpanchumaedi.com/post/materi-perhitungan-debit-banjir/</guid><description>
&lt;style>
.materi-debit {
--navy:#0A2342;--blue:#185fa5;--blue-mid:#378add;--blue-light:#85b7eb;--blue-pale:#e6f1fb;
--red:#B91C1C;--red-light:#fee2e2;--navy2:#1A5276;
--amber:#B45309;--amber-light:#fef3c7;
--purple:#6D28D9;--purple-light:#ede9fe;
--green:#1d6f42;--green-light:#d1fae5;
--teal:#0d6efd;--teal-light:#e7f1ff;
--gray-100:#f8fafc;--gray-200:#e2e8f0;--gray-300:#cbd5e1;
--gray-500:#64748b;--gray-600:#475569;--gray-700:#334155;--gray-900:#0f172a;
--radius:10px;--radius-sm:6px;
--shadow:0 2px 12px rgba(0,0,0,0.07);--shadow-md:0 4px 20px rgba(0,0,0,0.10);
--code-bg:#1e1e2e;
}
.materi-debit, .materi-debit *::before, .materi-debit *::after {box-sizing:border-box;margin:0;padding:0;}
.materi-debit .sticky-nav {position:sticky;top:0;z-index:200;background:#fff;border-bottom:1px solid var(--gray-200);box-shadow:var(--shadow);}
.materi-debit .sticky-inner {max-width:960px;margin:0 auto;padding:0 1.25rem;display:flex;align-items:center;gap:1rem;height:52px;}
.materi-debit .sticky-title {font-size:13px;font-weight:600;color:var(--navy);white-space:nowrap;}
.materi-debit .progress-track {flex:1;height:4px;background:var(--gray-200);border-radius:2px;}
.materi-debit .progress-fill {height:100%;background:linear-gradient(90deg,var(--blue),var(--purple));border-radius:2px;width:0%;transition:width 0.3s;}
.materi-debit .sticky-pct {font-size:12px;color:var(--gray-500);min-width:32px;}
.materi-debit .toc-float {position:fixed;top:80px;right:0;width:200px;background:#fff;border:1px solid var(--gray-200);border-right:none;border-radius:var(--radius) 0 0 var(--radius);box-shadow:-2px 4px 16px rgba(0,0,0,0.09);z-index:150;transition:all 0.28s cubic-bezier(0.4,0,0.2,1);overflow:hidden;}
.materi-debit .toc-float.collapsed {width:32px;}
.materi-debit .toc-head {display:flex;align-items:center;justify-content:space-between;padding:8px 10px 8px 12px;border-bottom:1px solid var(--gray-200);cursor:pointer;user-select:none;background:var(--navy);border-radius:var(--radius) 0 0 0;}
.materi-debit .toc-head:hover {background:#1a3a5c;}
.materi-debit .toc-title {font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:0.07em;color:rgba(255,255,255,0.9);white-space:nowrap;overflow:hidden;}
.materi-debit .toc-chevron {font-size:11px;color:rgba(255,255,255,0.7);flex-shrink:0;transition:transform 0.25s;margin-left:6px;}
.materi-debit .toc-float.collapsed .toc-chevron {transform:rotate(180deg);}
.materi-debit .toc-float.collapsed .toc-title {opacity:0;width:0;margin:0;}
.materi-debit .toc-body {padding:8px 6px;max-height:calc(100vh - 140px);overflow-y:auto;scrollbar-width:thin;scrollbar-color:var(--gray-300) transparent;}
.materi-debit .toc-body::-webkit-scrollbar {width:3px;}
.materi-debit .toc-body::-webkit-scrollbar-thumb {background:var(--gray-300);border-radius:2px;}
.materi-debit .toc-float.collapsed .toc-body {display:none;}
.materi-debit .toc-link {display:block;font-size:11px;color:var(--gray-600);text-decoration:none;padding:3px 8px;border-radius:4px;border-left:2px solid transparent;margin-bottom:1px;transition:all 0.15s;line-height:1.4;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
.materi-debit .toc-link:hover {background:var(--blue-pale);color:var(--blue);border-left-color:var(--blue);}
.materi-debit .toc-link.active {background:var(--blue-pale);color:var(--blue);border-left-color:var(--blue);font-weight:600;}
.materi-debit .toc-link.sub {padding-left:14px;font-size:10px;color:var(--gray-500);}
.materi-debit .toc-link.sub.active {color:var(--blue);}
.materi-debit .toc-toggle {display:none;position:fixed;bottom:20px;right:16px;width:40px;height:40px;border-radius:50%;background:var(--navy);color:#fff;border:none;font-size:16px;cursor:pointer;box-shadow:var(--shadow-md);z-index:160;align-items:center;justify-content:center;}
@.materi-debit media(max-width:1100px) {.toc-float{display:none;}.materi-debit .toc-toggle {display:flex;}.materi-debit }
.hero {background:linear-gradient(135deg,#0A2342 0%,#0e3a6b 50%,#1a1065 100%);color:#fff;padding:3rem 1.5rem 2.5rem;border-radius:0 0 var(--radius) var(--radius);margin-bottom:2rem;position:relative;overflow:hidden;}
.materi-debit .hero::before {content:'';position:absolute;top:-80px;right:-60px;width:300px;height:300px;border-radius:50%;background:rgba(55,138,221,0.12);}
.materi-debit .hero::after {content:'';position:absolute;bottom:-100px;left:10%;width:250px;height:250px;border-radius:50%;background:rgba(109,40,217,0.10);}
.materi-debit .hero-inner {max-width:960px;margin:0 auto;position:relative;z-index:1;}
.materi-debit .hero-badge {display:inline-block;background:rgba(55,138,221,0.25);color:#85b7eb;font-size:11px;padding:3px 10px;border-radius:20px;margin-bottom:0.75rem;letter-spacing:0.04em;}
.materi-debit .hero h1 {font-size:clamp(22px,4vw,30px);font-weight:700;line-height:1.3;margin-bottom:0.5rem;}
.materi-debit .hero-sub {font-size:14px;color:rgba(255,255,255,0.65);margin-bottom:1.5rem;}
.materi-debit .hero-pills {display:flex;flex-wrap:wrap;gap:8px;margin-top:1rem;}
.materi-debit .hero-pill {display:inline-block;font-size:11px;padding:4px 10px;border-radius:20px;font-weight:600;border:1px solid;}
.materi-debit .pill-blue {background:rgba(26,82,118,0.3);color:#85b7eb;border-color:rgba(26,82,118,0.5);}
.materi-debit .pill-amber {background:rgba(180,83,9,0.25);color:#fcd34d;border-color:rgba(180,83,9,0.4);}
.materi-debit .pill-purple {background:rgba(109,40,217,0.25);color:#c4b5fd;border-color:rgba(109,40,217,0.4);}
.materi-debit .pill-green {background:rgba(29,111,66,0.25);color:#6ee7b7;border-color:rgba(29,111,66,0.4);}
.materi-debit .pill-red {background:rgba(185,28,28,0.25);color:#fca5a5;border-color:rgba(185,28,28,0.4);}
.materi-debit .hero-meta {display:flex;flex-wrap:wrap;gap:1.25rem;margin-top:1rem;}
.materi-debit .hero-meta-item {font-size:12px;color:rgba(255,255,255,0.55);}
.materi-debit .wrap {max-width:960px;margin:0 auto;padding:0 1.25rem 4rem;}
.materi-debit .section {margin-bottom:3rem;}
.materi-debit .section-header {display:flex;align-items:center;gap:12px;margin-bottom:1.25rem;}
.materi-debit .section-num {width:32px;height:32px;border-radius:50%;background:var(--navy);color:#fff;font-size:13px;font-weight:600;display:flex;align-items:center;justify-content:center;flex-shrink:0;}
.materi-debit .section-header h2 {font-size:20px;font-weight:700;color:var(--gray-900);}
.materi-debit .subsection {margin:1.5rem 0 0.75rem;}
.materi-debit .subsection h3 {font-size:15px;font-weight:700;color:var(--gray-700);padding-left:10px;border-left:3px solid var(--blue-mid);margin-bottom:0.75rem;}
.materi-debit .card {background:#fff;border-radius:var(--radius);padding:1.25rem 1.5rem;box-shadow:var(--shadow);margin-bottom:1rem;}
.materi-debit .card-navy {border-left:4px solid var(--navy);}
.materi-debit .card-blue {border-left:4px solid var(--blue-mid);}
.materi-debit .card-red {border-left:4px solid var(--red);}
.materi-debit .card-amber {border-left:4px solid var(--amber);}
.materi-debit .card-green {border-left:4px solid var(--green);}
.materi-debit .card-purple {border-left:4px solid var(--purple);}
.materi-debit .card-label {font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:0.07em;color:var(--gray-500);margin-bottom:6px;}
.materi-debit .card p {font-size:13px;color:var(--gray-600);line-height:1.7;}
.materi-debit .card strong {color:var(--gray-800);}
.materi-debit .grid-2 {display:grid;grid-template-columns:1fr 1fr;gap:1rem;margin-bottom:1rem;}
.materi-debit .grid-3 {display:grid;grid-template-columns:1fr 1fr 1fr;gap:1rem;margin-bottom:1rem;}
.materi-debit .grid-4 {display:grid;grid-template-columns:repeat(4,1fr);gap:1rem;margin-bottom:1.5rem;}
@.materi-debit media(max-width:700px) {.grid-2,.grid-3,.grid-4{grid-template-columns:1fr;}.materi-debit }
@media(max-width:900px) and (min-width:701px) {.grid-3{grid-template-columns:1fr 1fr;}.materi-debit .grid-4 {grid-template-columns:1fr 1fr;}.materi-debit }
.metric-card {background:#fff;border-radius:var(--radius);padding:1rem 1.1rem;box-shadow:var(--shadow);text-align:center;position:relative;overflow:hidden;}
.materi-debit .metric-card::before {content:'';position:absolute;top:0;left:0;right:0;height:3px;}
.materi-debit .metric-card.blue::before {background:var(--blue);}
.materi-debit .metric-card.green::before {background:var(--green);}
.materi-debit .metric-card.amber::before {background:var(--amber);}
.materi-debit .metric-card.purple::before {background:var(--purple);}
.materi-debit .metric-card.red::before {background:var(--red);}
.materi-debit .metric-card.navy::before {background:var(--navy);}
.materi-debit .metric-label {font-size:11px;color:var(--gray-500);font-weight:600;margin-bottom:4px;}
.materi-debit .metric-val {font-size:20px;font-weight:700;color:var(--navy);}
.materi-debit .metric-unit {font-size:11px;color:var(--gray-500);margin-top:3px;}
.materi-debit .info-box {display:flex;gap:10px;background:var(--blue-pale);border:1px solid #b5d4f4;border-radius:var(--radius-sm);padding:.9rem 1rem;font-size:13px;color:#0c447c;margin:1rem 0;line-height:1.55;}
.materi-debit .warn-box {display:flex;gap:10px;background:var(--amber-light);border:1px solid #fac775;border-radius:var(--radius-sm);padding:.9rem 1rem;font-size:13px;color:var(--amber);margin:1rem 0;line-height:1.55;}
.materi-debit .success-box {display:flex;gap:10px;background:var(--green-light);border:1px solid #a7f3d0;border-radius:var(--radius-sm);padding:.9rem 1rem;font-size:13px;color:var(--green);margin:1rem 0;line-height:1.55;}
.materi-debit .purple-box {display:flex;gap:10px;background:var(--purple-light);border:1px solid #c4b5fd;border-radius:var(--radius-sm);padding:.9rem 1rem;font-size:13px;color:var(--purple);margin:1rem 0;line-height:1.55;}
.materi-debit .box-icon {font-size:18px;flex-shrink:0;line-height:1.3;}
.materi-debit .formula-block {background:#0f172a;border-radius:var(--radius-sm);padding:1rem 1.25rem;margin:.75rem 0;font-family:'Consolas','Courier New',monospace;font-size:14px;color:#e2e8f0;letter-spacing:0.02em;border-left:4px solid var(--purple);}
.materi-debit .formula-block .eq-label {font-size:11px;color:#94a3b8;display:block;margin-bottom:4px;}
.materi-debit .formula-block .eq-main {color:#c4b5fd;font-size:15px;display:block;text-align:center;margin:6px 0;}
.materi-debit .formula-block .eq-desc {font-size:11px;color:#64748b;display:block;margin-top:6px;}
.materi-debit .step-flow {margin:1rem 0;}
.materi-debit .step-item {display:flex;gap:14px;}
.materi-debit .step-line {display:flex;flex-direction:column;align-items:center;}
.materi-debit .step-dot {width:30px;height:30px;border-radius:50%;background:var(--blue-mid);color:#fff;font-size:12px;font-weight:600;display:flex;align-items:center;justify-content:center;flex-shrink:0;}
.materi-debit .step-dot.navy {background:var(--navy);}
.materi-debit .step-dot.green {background:var(--green);}
.materi-debit .step-dot.purple {background:var(--purple);}
.materi-debit .step-dot.amber {background:var(--amber);}
.materi-debit .step-dot.red {background:var(--red);}
.materi-debit .step-connector {width:2px;background:var(--gray-200);flex:1;min-height:16px;margin:3px 0;}
.materi-debit .step-body {padding-bottom:20px;flex:1;}
.materi-debit .step-title {font-size:14px;font-weight:600;color:var(--gray-800);margin-bottom:4px;}
.materi-debit .step-desc {font-size:13px;color:var(--gray-600);line-height:1.6;}
.materi-debit .code-wrap {background:var(--code-bg);border-radius:var(--radius-sm);overflow:hidden;margin:.75rem 0;box-shadow:var(--shadow-md);}
.materi-debit .code-header {background:#2a2a3e;padding:7px 14px;display:flex;align-items:center;justify-content:space-between;}
.materi-debit .code-lang {font-size:11px;color:#a0aec0;font-weight:600;letter-spacing:0.05em;display:flex;align-items:center;gap:6px;}
.materi-debit .code-lang .dot {width:8px;height:8px;border-radius:50%;}
.materi-debit .copy-btn {font-size:11px;color:#a0aec0;cursor:pointer;background:none;border:none;padding:2px 8px;border-radius:4px;transition:all 0.2s;}
.materi-debit .copy-btn:hover {background:rgba(255,255,255,0.1);color:#fff;}
.materi-debit pre {padding:1rem 1.25rem;overflow-x:auto;font-family:'Consolas','Courier New',monospace;font-size:12.5px;line-height:1.75;color:#cdd6f4;}
.materi-debit pre::-webkit-scrollbar {height:4px;}
.materi-debit pre::-webkit-scrollbar-thumb {background:#4a4a6a;border-radius:2px;}
.materi-debit .kw {color:#cba6f7;}.materi-debit .fn {color:#89b4fa;}.materi-debit .str {color:#a6e3a1;}.materi-debit .num {color:#fab387;}.materi-debit .cm {color:#6c7086;font-style:italic;}.materi-debit .op {color:#89dceb;}.materi-debit .pkg {color:#f38ba8;}
.materi-debit .tbl-wrap {overflow-x:auto;margin-bottom:1rem;}
.materi-debit .data-tbl {width:100%;border-collapse:collapse;font-size:13px;min-width:380px;}
.materi-debit .data-tbl th {background:var(--navy);color:#fff;padding:8px 12px;text-align:center;font-weight:600;font-size:12px;}
.materi-debit .data-tbl td {padding:7px 12px;border-bottom:1px solid var(--gray-200);text-align:center;font-family:'Consolas',monospace;font-size:12px;color:var(--gray-700);}
.materi-debit .data-tbl td.td-label {text-align:left;font-family:inherit;font-weight:600;color:var(--gray-700);}
.materi-debit .data-tbl tr:hover td {background:var(--blue-pale);}
.materi-debit .data-tbl .best {color:var(--green);font-weight:700;}
.materi-debit .data-tbl .highlight {background:rgba(26,82,118,0.06)!important;}
.materi-debit .data-tbl .th-blue {background:var(--navy2)!important;}
.materi-debit .data-tbl .th-red {background:var(--red)!important;}
.materi-debit .data-tbl .th-green {background:var(--green)!important;}
.materi-debit .data-tbl .th-purple {background:var(--purple)!important;}
.materi-debit .data-tbl .th-amber {background:var(--amber)!important;}
.materi-debit .chart-card {background:#fff;border-radius:var(--radius);padding:1.25rem 1.5rem 1rem;box-shadow:var(--shadow);margin-bottom:1.25rem;}
.materi-debit .chart-title {font-size:13px;font-weight:700;color:var(--gray-700);margin-bottom:2px;}
.materi-debit .chart-sub {font-size:11px;color:var(--gray-500);margin-bottom:1rem;}
.materi-debit .chart-wrap {position:relative;width:100%;}
.materi-debit .legend-row {display:flex;flex-wrap:wrap;gap:12px;margin-top:10px;font-size:11px;color:var(--gray-500);}
.materi-debit .legend-item {display:flex;align-items:center;gap:5px;}
.materi-debit .legend-sq {width:10px;height:10px;border-radius:2px;flex-shrink:0;}
.materi-debit .tag {display:inline-block;font-size:11px;padding:3px 10px;border-radius:20px;margin:2px;font-weight:500;}
.materi-debit .tag-blue {background:var(--blue-pale);color:#0c447c;}
.materi-debit .tag-red {background:var(--red-light);color:var(--red);}
.materi-debit .tag-purple {background:var(--purple-light);color:var(--purple);}
.materi-debit .tag-green {background:var(--green-light);color:var(--green);}
.materi-debit .tag-amber {background:var(--amber-light);color:var(--amber);}
.materi-debit .divider {height:1px;background:var(--gray-200);margin:2.5rem 0;}
.materi-debit .analogy-box {background:linear-gradient(135deg,#f0f7ff,#f8f0ff);border:1px solid #c4d9f7;border-radius:var(--radius);padding:1.1rem 1.3rem;margin:1rem 0;}
.materi-debit .analogy-badge {font-size:10px;font-weight:700;letter-spacing:0.07em;text-transform:uppercase;color:var(--blue);margin-bottom:6px;}
.materi-debit .analogy-box p {font-size:13px;color:var(--gray-700);line-height:1.7;font-style:italic;}
/.materi-debit * INTERACTIVE CALCULATOR */
.calc-box {background:#fff;border-radius:var(--radius);padding:1.5rem;box-shadow:var(--shadow-md);border:1px solid var(--gray-200);margin:1rem 0;}
.materi-debit .calc-title {font-size:13px;font-weight:700;color:var(--navy);margin-bottom:1.1rem;display:flex;align-items:center;gap:8px;}
.materi-debit .calc-grid {display:grid;grid-template-columns:1fr 1fr 1fr;gap:1rem;margin-bottom:1.2rem;}
@.materi-debit media(max-width:600px) {.calc-grid{grid-template-columns:1fr;}.materi-debit }
.calc-field label {display:block;font-size:11px;font-weight:600;color:var(--gray-600);margin-bottom:4px;text-transform:uppercase;letter-spacing:0.05em;}
.materi-debit .calc-field input[type=range] {width:100%;accent-color:var(--blue);}
.materi-debit .calc-field select {width:100%;padding:5px 8px;border:1px solid var(--gray-300);border-radius:6px;font-size:13px;background:#fff;}
.materi-debit .calc-field .val-display {font-size:13px;font-weight:600;color:var(--navy);margin-top:3px;}
.materi-debit .calc-result {background:linear-gradient(135deg,var(--navy),#1a3a6b);border-radius:8px;padding:1rem 1.25rem;display:flex;align-items:center;justify-content:space-between;gap:1rem;flex-wrap:wrap;}
.materi-debit .calc-result-label {font-size:12px;color:rgba(255,255,255,0.7);font-weight:600;}
.materi-debit .calc-result-val {font-size:28px;font-weight:700;color:#fff;}
.materi-debit .calc-result-unit {font-size:13px;color:rgba(255,255,255,0.6);}
/.materi-debit * HYDROGRAPH CONTROLS */
.hydro-controls {display:flex;gap:8px;flex-wrap:wrap;margin-bottom:1rem;}
.materi-debit .hydro-btn {padding:5px 14px;border-radius:20px;border:1.5px solid;font-size:12px;font-weight:600;cursor:pointer;transition:all 0.2s;background:#fff;}
.materi-debit .hydro-btn.active {color:#fff!important;}
/.materi-debit * DAS SCHEMATIC */
.das-grid {display:grid;grid-template-columns:repeat(3,1fr);gap:0.6rem;margin:1rem 0;}
@.materi-debit media(max-width:600px) {.das-grid{grid-template-columns:1fr 1fr;}.materi-debit }
.das-param {background:#fff;border-radius:8px;padding:0.7rem 0.9rem;box-shadow:var(--shadow);border-top:3px solid var(--blue-mid);}
.materi-debit .das-param-name {font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:0.06em;color:var(--gray-500);margin-bottom:3px;}
.materi-debit .das-param-val {font-size:16px;font-weight:700;color:var(--navy);}
.materi-debit .das-param-unit {font-size:11px;color:var(--gray-500);}
/.materi-debit * METHOD BADGE */
.method-badge {display:inline-flex;align-items:center;gap:6px;padding:5px 12px;border-radius:20px;font-size:12px;font-weight:700;margin-bottom:8px;}
.materi-debit .nav-link {display:flex;align-items:center;gap:1rem;padding:0.9rem 1.2rem;background:#fff;border:1px solid var(--gray-200);border-radius:10px;text-decoration:none;transition:all 0.2s;margin-bottom:0.5rem;box-shadow:var(--shadow);}
.materi-debit .nav-link:hover {border-color:var(--blue-mid);box-shadow:var(--shadow-md);}
.materi-debit .nav-link-label {font-size:10px;font-weight:700;letter-spacing:0.09em;text-transform:uppercase;color:var(--gray-500);margin-bottom:3px;}
.materi-debit .nav-link-title {font-size:14px;font-weight:700;color:var(--navy);}
.materi-debit .nav-link-dim {opacity:0.5;cursor:default;}
.materi-debit .nav-link-dim:hover {border-color:var(--gray-200);box-shadow:var(--shadow);}
@.materi-debit keyframes fadeUp {from{opacity:0;transform:translateY(16px);}.materi-debit to {opacity:1;transform:translateY(0);}.materi-debit }
.anim-in {opacity:1;}.materi-debit .anim-in.visible {animation:fadeUp 0.45s ease both;}
/* === LAYOUT FIX: integrasi Wowchemy === */
.materi-debit { box-sizing: border-box; width: 100%; overflow-x: hidden; }
.materi-debit * { box-sizing: border-box; }
.materi-debit .wrap, .materi-debit .section { max-width: 100%; }
/* === DARK MODE === */
body.dark .materi-debit { color:#8e94b5; }
/* Heading &amp; teks utama */
body.dark .materi-debit h1,
body.dark .materi-debit h2,
body.dark .materi-debit h3,
body.dark .materi-debit h4 { color:#e8eaf6 !important; }
body.dark .materi-debit p { color:#8e94b5; }
body.dark .materi-debit strong { color:#e8eaf6; }
body.dark .materi-debit li { color:#8e94b5; }
/* Section header */
body.dark .materi-debit .section-header { border-color:#343858; }
body.dark .materi-debit .section-header h2 { color:#e8eaf6 !important; }
body.dark .materi-debit .section-num {
background:#1e3a6e !important;
color:#5b8fff !important;
border-color:#2a4a8e !important;
}
body.dark .materi-debit .subsection h3 { color:#c8ccdf !important; }
/* Cards — background &amp; border */
body.dark .materi-debit [class*="card"],
body.dark .materi-debit .card,
body.dark .materi-debit .metric-card {
background:#222638 !important;
border-color:#343858 !important;
box-shadow: 0 2px 12px rgba(0,0,0,0.3) !important;
}
/* Card teks — SEMUA varian label &amp; nilai */
body.dark .materi-debit .card-label,
body.dark .materi-debit .metric-label,
body.dark .materi-debit .metric-sub {
color:#8e94b5 !important;
}
body.dark .materi-debit .card p,
body.dark .materi-debit .card-body {
color:#8e94b5 !important;
}
body.dark .materi-debit .metric-val {
/* warna nilai (biru/amber/dll) tetap — biarkan dari CSS asli */
filter: brightness(1.2);
}
/* Teks dengan var gray-* — override via CSS variable remapping */
body.dark .materi-debit {
--gray-100:#1b1d27;
--gray-200:#222638;
--gray-300:#2a2e42;
--gray-500:#8e94b5;
--gray-600:#a0a8cc;
--gray-700:#c8ccdf;
--gray-900:#e8eaf6;
--navy:#e8eaf6;
--navy2:#c8ccdf;
--blue:#5b8fff;
--blue-mid:#7aa5ff;
--blue-pale:#1e2a42;
--red:#e05a5a;
--red-light:#2d1515;
--amber:#f4a642;
--amber-light:#2d2010;
--purple:#9d7cf8;
--purple-light:#1e1530;
--green:#3ecf8e;
--green-light:#0d2418;
--shadow: 0 2px 12px rgba(0,0,0,0.35);
--shadow-md: 0 4px 20px rgba(0,0,0,0.45);
--code-bg:#12151f;
}
/* Table */
body.dark .materi-debit table { border-color:#343858; }
body.dark .materi-debit th {
background:#2a2e42 !important;
color:#8e94b5 !important;
border-color:#343858 !important;
}
body.dark .materi-debit td {
border-color:#343858 !important;
color:#8e94b5 !important;
}
body.dark .materi-debit tr:nth-child(even) { background:#1e2235 !important; }
body.dark .materi-debit tr:hover td { background:#252840 !important; }
/* Code */
body.dark .materi-debit code,
body.dark .materi-debit pre {
background:#12151f !important;
color:#a8b4ff !important;
}
/* Form inputs */
body.dark .materi-debit select,
body.dark .materi-debit input[type=number],
body.dark .materi-debit input[type=text] {
background:#2a2e42 !important;
border-color:#343858 !important;
color:#e8eaf6 !important;
}
/* Result/output boxes */
body.dark .materi-debit [class*="result"],
body.dark .materi-debit [id*="result"],
body.dark .materi-debit [class*="output"],
body.dark .materi-debit [id*="output"] {
background:#222638 !important;
border-color:#343858 !important;
color:#8e94b5 !important;
}
/* Grid boxes */
body.dark .materi-debit .grid-2>*,
body.dark .materi-debit .grid-3>*,
body.dark .materi-debit .grid-4>* {
background:#222638 !important;
border-color:#343858 !important;
}
/* Info/alert boxes */
body.dark .materi-debit [class*="info-"],
body.dark .materi-debit [class*="alert-"],
body.dark .materi-debit [class*="note-"] {
background:#1e2235 !important;
border-color:#343858 !important;
color:#8e94b5 !important;
}
/* Links */
body.dark .materi-debit a { color:#5b8fff; }
body.dark .materi-debit hr { border-color:#343858; }
/* Fix teks inline style hardcoded */
body.dark .materi-debit [style*="color:#0f172a"],
body.dark .materi-debit [style*="color:#1e293b"],
body.dark .materi-debit [style*="color:#334155"],
body.dark .materi-debit [style*="color:#475569"] {
color:#e8eaf6 !important;
}
body.dark .materi-debit [style*="background:#fff"],
body.dark .materi-debit [style*="background:#f4f6f9"],
body.dark .materi-debit [style*="background:#f8fafc"],
body.dark .materi-debit [style*="background:#f1f5f9"] {
background:#222638 !important;
}
&lt;/style>
&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.4.1/chart.umd.js">&lt;/script>
&lt;div class="materi-debit">
&lt;!-- S1: LATAR BELAKANG -->
&lt;section class="section anim-in" id="s1">
&lt;div class="section-header">&lt;div class="section-num">1&lt;/div>&lt;h2>Latar Belakang — Mengapa Perlu Debit Banjir Rencana?&lt;/h2>&lt;/div>
&lt;div class="card card-navy">
&lt;div class="card-label">Dari Angka Hujan ke Angka Desain&lt;/div>
&lt;p>Artikel sebelumnya menghasilkan &lt;strong>curah hujan rencana R_T&lt;/strong> (mm) dan &lt;strong>kurva IDF&lt;/strong> untuk berbagai kala ulang. Tapi para &lt;em>engineer&lt;/em> tidak mendesain jembatan dengan satuan "milimeter hujan" — mereka mendesain dengan satuan &lt;strong>meter kubik per detik (m³/s)&lt;/strong>.&lt;/p>
&lt;p style="margin-top:8px;">Pertanyaannya: &lt;em>"Kalau hujan 152 mm turun dalam satu hari di DAS seluas 50 km², berapa debit puncak yang akan terjadi di outlet sungai?"&lt;/em> — Inilah yang dijawab oleh perhitungan debit banjir rencana.&lt;/p>
&lt;/div>
&lt;div class="grid-2">
&lt;div class="card card-blue">
&lt;div class="card-label">Input — dari Artikel Sebelumnya&lt;/div>
&lt;p>&lt;strong>Curah Hujan Rencana R_T:&lt;/strong>&lt;br>
T=2: 96.4 mm &amp;nbsp;|&amp;nbsp; T=5: 118.7 mm&lt;br>
T=10: 133.4 mm &amp;nbsp;|&amp;nbsp; T=25: 151.9 mm&lt;br>
T=50: 165.6 mm &amp;nbsp;|&amp;nbsp; T=100: 179.2 mm&lt;br>&lt;br>
&lt;strong>Intensitas IDF&lt;/strong> dari rumus Mononobe untuk berbagai durasi.&lt;/p>
&lt;/div>
&lt;div class="card card-green">
&lt;div class="card-label">Output — yang Dihasilkan di Artikel Ini&lt;/div>
&lt;p>&lt;strong>Debit Puncak Q_T (m³/s)&lt;/strong> untuk setiap kala ulang, menggunakan:&lt;br>&lt;br>
📌 Metode Rasional → Q puncak saja&lt;br>
📌 HSS Nakayasu → hidrograf penuh Q(t)&lt;br>&lt;br>
Output ini menjadi input langsung untuk HEC-RAS, desain bendung, dan drainase.&lt;/p>
&lt;/div>
&lt;/div>
&lt;div class="analogy-box">
&lt;div class="analogy-badge">💡 Analogi Bak Mandi&lt;/div>
&lt;p>Bayangkan hujan adalah air yang dituang ke bak mandi besar (DAS). Seberapa cepat air mengalir keluar dari saluran pembuangan (outlet sungai) tergantung pada: seberapa besar bak (luas DAS), seberapa curam kemiringannya (slope), dan seberapa banyak air yang meresap ke tanah vs mengalir di permukaan. Debit banjir rencana menghitung laju aliran di saluran pembuangan itu — bukan berapa air yang dituang.&lt;/p>
&lt;/div>
&lt;/section>
&lt;div class="divider">&lt;/div>
&lt;!-- S2: ALUR -->
&lt;section class="section anim-in" id="s2">
&lt;div class="section-header">&lt;div class="section-num">2&lt;/div>&lt;h2>Alur: Dari Curah Hujan ke Debit Banjir&lt;/h2>&lt;/div>
&lt;p style="font-size:13px;color:var(--gray-600);line-height:1.7;margin-bottom:1rem;">Tidak semua hujan yang jatuh menjadi debit di sungai. Ada yang meresap ke tanah (infiltrasi), ada yang menguap (evapotranspirasi), dan sisanya baru menjadi aliran permukaan (runoff). Proses ini dipengaruhi karakteristik DAS dan kondisi lahan.&lt;/p>
&lt;div class="card" style="background:#0f172a;border:none;padding:1.5rem;">
&lt;div style="display:flex;align-items:center;justify-content:center;gap:0;flex-wrap:wrap;">
&lt;div style="text-align:center;padding:0.8rem;">
&lt;div style="font-size:1.6rem;">🌧️&lt;/div>
&lt;div style="font-size:12px;font-weight:700;color:#85b7eb;margin-top:4px;">CH Rencana&lt;/div>
&lt;div style="font-size:10px;color:#64748b;">R_T (mm)&lt;/div>
&lt;/div>
&lt;div style="font-size:20px;color:#334155;padding:0 4px;">→&lt;/div>
&lt;div style="text-align:center;padding:0.8rem;background:rgba(26,82,118,0.3);border-radius:8px;border:1px solid #1A5276;">
&lt;div style="font-size:1.6rem;">🌿&lt;/div>
&lt;div style="font-size:12px;font-weight:700;color:#6ee7b7;margin-top:4px;">Hujan Efektif&lt;/div>
&lt;div style="font-size:10px;color:#64748b;">R_eff = R_T × (1-abstraksi)&lt;/div>
&lt;/div>
&lt;div style="font-size:20px;color:#334155;padding:0 4px;">→&lt;/div>
&lt;div style="text-align:center;padding:0.8rem;background:rgba(109,40,217,0.2);border-radius:8px;border:1px solid #6D28D9;">
&lt;div style="font-size:1.6rem;">🏔️&lt;/div>
&lt;div style="font-size:12px;font-weight:700;color:#c4b5fd;margin-top:4px;">Karakteristik DAS&lt;/div>
&lt;div style="font-size:10px;color:#64748b;">A, L, S, landuse&lt;/div>
&lt;/div>
&lt;div style="font-size:20px;color:#334155;padding:0 4px;">→&lt;/div>
&lt;div style="text-align:center;padding:0.8rem;background:rgba(29,111,66,0.2);border-radius:8px;border:1px solid #1d6f42;">
&lt;div style="font-size:1.6rem;">📈&lt;/div>
&lt;div style="font-size:12px;font-weight:700;color:#6ee7b7;margin-top:4px;">Model Transformasi&lt;/div>
&lt;div style="font-size:10px;color:#64748b;">Rasional / Nakayasu&lt;/div>
&lt;/div>
&lt;div style="font-size:20px;color:#334155;padding:0 4px;">→&lt;/div>
&lt;div style="text-align:center;padding:0.8rem;background:rgba(180,83,9,0.25);border-radius:8px;border:1px solid #B45309;">
&lt;div style="font-size:1.6rem;">💧&lt;/div>
&lt;div style="font-size:12px;font-weight:700;color:#fcd34d;margin-top:4px;">Debit Banjir&lt;/div>
&lt;div style="font-size:10px;color:#64748b;">Q_T (m³/s)&lt;/div>
&lt;/div>
&lt;/div>
&lt;/div>
&lt;div class="info-box">&lt;span class="box-icon">ℹ️&lt;/span>&lt;span>Proses transformasi hujan menjadi debit disebut &lt;strong>rainfall-runoff transformation&lt;/strong>. Dua faktor utama yang menentukan hasilnya: (1) &lt;em>berapa banyak hujan yang jadi runoff&lt;/em> (hujan efektif), dan (2) &lt;em>seberapa cepat runoff itu mencapai outlet&lt;/em> (karakteristik DAS).&lt;/span>&lt;/div>
&lt;/section>
&lt;div class="divider">&lt;/div>
&lt;!-- S3: DATA DAS -->
&lt;section class="section anim-in" id="s3">
&lt;div class="section-header">&lt;div class="section-num">3&lt;/div>&lt;h2>Data Daerah Aliran Sungai (DAS)&lt;/h2>&lt;/div>
&lt;div id="s3a">&lt;/div>
&lt;div class="subsection">&lt;h3>Karakteristik DAS yang Diperlukan&lt;/h3>&lt;/div>
&lt;p style="font-size:13px;color:var(--gray-600);line-height:1.7;margin-bottom:1rem;">Untuk menghitung debit banjir, kita perlu mengkarakterisasi DAS terlebih dahulu. Data ini bisa didapat dari analisis DEM (SRTM/DEMNAS) di QGIS atau Global Mapper.&lt;/p>
&lt;div class="das-grid" id="dasParams">&lt;/div>
&lt;div class="grid-2" style="margin-top:1rem;">
&lt;div class="card card-blue">
&lt;div class="card-label">Sumber Data DAS&lt;/div>
&lt;p>&lt;strong>Peta topografi / DEM:&lt;/strong> DEMNAS (8m, BIG), SRTM 30m — untuk delineasi DAS, panjang sungai, dan kemiringan.&lt;br>&lt;br>&lt;strong>Peta tata guna lahan:&lt;/strong> RTRW, citra satelit Sentinel/Landsat — untuk koefisien limpasan (C).&lt;br>&lt;br>&lt;strong>Peta jenis tanah:&lt;/strong> untuk CN SCS atau parameter infiltrasi.&lt;/p>
&lt;/div>
&lt;div class="card card-amber">
&lt;div class="card-label">Tools yang Digunakan&lt;/div>
&lt;p>&lt;strong>QGIS:&lt;/strong> Delineasi DAS otomatis dari DEM menggunakan plugin SAGA atau GRASS. Hitung luas, panjang sungai, slope rerata.&lt;br>&lt;br>&lt;strong>Global Mapper:&lt;/strong> Analisis watershed, profil memanjang sungai, ekstrak parameter morfometri DAS dengan mudah.&lt;/p>
&lt;/div>
&lt;/div>
&lt;div id="s3b">&lt;/div>
&lt;div class="subsection">&lt;h3>Waktu Konsentrasi (t_c)&lt;/h3>&lt;/div>
&lt;div class="card card-purple">
&lt;div class="card-label">Definisi&lt;/div>
&lt;p>&lt;strong>Waktu konsentrasi (t_c)&lt;/strong> adalah waktu yang dibutuhkan tetesan air dari titik terjauh dalam DAS untuk mencapai outlet (titik pengukuran). Ini adalah parameter kunci — intensitas hujan yang dipakai dalam metode rasional diambil pada durasi = t_c.&lt;/p>
&lt;/div>
&lt;div class="grid-2">
&lt;div>
&lt;div class="card card-blue" style="margin-bottom:0.6rem;">
&lt;div class="card-label">① Metode Kirpich (1940)&lt;/div>
&lt;p>Paling umum untuk DAS kecil. Menggunakan panjang saluran dan beda tinggi.&lt;/p>
&lt;/div>
&lt;div class="formula-block">
&lt;span class="eq-label">Rumus Kirpich&lt;/span>
&lt;span class="eq-main">t_c = 0.0195 · L^0.77 · S^(−0.385)&lt;/span>
&lt;span class="eq-desc">t_c dalam menit | L = panjang saluran terpanjang (meter) | S = kemiringan rata-rata (m/m)
Contoh: L=5000 m, S=0.010 → t_c = 0.0195 × 705 × 5.89 = 81 mnt ≈ 1.35 jam&lt;/span>
&lt;/div>
&lt;/div>
&lt;div>
&lt;div class="card card-green" style="margin-bottom:0.6rem;">
&lt;div class="card-label">② Metode Bransby-Williams&lt;/div>
&lt;p>Mempertimbangkan luas DAS. Cocok untuk DAS yang lebih besar dan tidak seragam.&lt;/p>
&lt;/div>
&lt;div class="formula-block" style="border-left-color:var(--green);">
&lt;span class="eq-label">Rumus Bransby-Williams&lt;/span>
&lt;span class="eq-main">t_c = (L / (58 · A^0.1 · S_e^0.2)) &lt;/span>
&lt;span class="eq-desc">t_c dalam jam | L = panjang sungai (km) | A = luas DAS (km²) | S_e = kemiringan ekivalen (m/km)
Contoh: L=10 km, A=50 km², S_e=5 m/km → t_c ≈ 2.1 jam&lt;/span>
&lt;/div>
&lt;/div>
&lt;/div>
&lt;div class="warn-box">&lt;span class="box-icon">⚠️&lt;/span>&lt;span>Hasil t_c dari berbagai metode bisa berbeda signifikan. Dalam praktik, gunakan &lt;strong>dua metode&lt;/strong> lalu ambil rata-rata, atau pilih metode yang sesuai dengan kondisi DAS. Untuk DAS perkotaan (urban), t_c cenderung lebih pendek karena permukaan kedap air mempercepat aliran.&lt;/span>&lt;/div>
&lt;/section>
&lt;div class="divider">&lt;/div>
&lt;!-- S4: KOEFISIEN LIMPASAN -->
&lt;section class="section anim-in" id="s4">
&lt;div class="section-header">&lt;div class="section-num">4&lt;/div>&lt;h2>Koefisien Limpasan (C)&lt;/h2>&lt;/div>
&lt;p style="font-size:13px;color:var(--gray-600);line-height:1.7;margin-bottom:1rem;">Koefisien limpasan (C) menunjukkan &lt;strong>proporsi hujan yang menjadi aliran permukaan&lt;/strong>. Nilai C antara 0 (semua meresap) hingga 1 (semua jadi runoff). Nilainya ditentukan oleh tata guna lahan, jenis tanah, dan kemiringan.&lt;/p>
&lt;div class="tbl-wrap">
&lt;table class="data-tbl">
&lt;thead>
&lt;tr>&lt;th>Tipe Lahan / Kondisi&lt;/th>&lt;th>C Minimum&lt;/th>&lt;th>C Maksimum&lt;/th>&lt;th>C Tipikal&lt;/th>&lt;th>Keterangan&lt;/th>&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>&lt;td class="td-label">Hutan lebat / konservasi&lt;/td>&lt;td>0.10&lt;/td>&lt;td>0.25&lt;/td>&lt;td class="best">0.15&lt;/td>&lt;td class="td-label" style="font-family:inherit;font-size:11px;color:var(--gray-600);">Infiltrasi sangat tinggi&lt;/td>&lt;/tr>
&lt;tr>&lt;td class="td-label">Perkebunan / ladang&lt;/td>&lt;td>0.25&lt;/td>&lt;td>0.45&lt;/td>&lt;td class="best">0.35&lt;/td>&lt;td class="td-label" style="font-family:inherit;font-size:11px;color:var(--gray-600);">Tergantung kerapatan tanaman&lt;/td>&lt;/tr>
&lt;tr>&lt;td class="td-label">Sawah / lahan pertanian&lt;/td>&lt;td>0.45&lt;/td>&lt;td>0.65&lt;/td>&lt;td class="best">0.55&lt;/td>&lt;td class="td-label" style="font-family:inherit;font-size:11px;color:var(--gray-600);">Bervariasi per musim&lt;/td>&lt;/tr>
&lt;tr>&lt;td class="td-label">Permukiman jarang&lt;/td>&lt;td>0.50&lt;/td>&lt;td>0.70&lt;/td>&lt;td class="best">0.60&lt;/td>&lt;td class="td-label" style="font-family:inherit;font-size:11px;color:var(--gray-600);">Halaman rumput + jalan&lt;/td>&lt;/tr>
&lt;tr class="highlight">&lt;td class="td-label" style="color:var(--amber);font-weight:700;">Permukiman padat / urban&lt;/td>&lt;td>0.65&lt;/td>&lt;td>0.80&lt;/td>&lt;td style="color:var(--amber);font-weight:700;">0.72&lt;/td>&lt;td class="td-label" style="font-family:inherit;font-size:11px;color:var(--gray-600);">Banyak permukaan kedap&lt;/td>&lt;/tr>
&lt;tr>&lt;td class="td-label">Jalan aspal / beton&lt;/td>&lt;td>0.80&lt;/td>&lt;td>0.95&lt;/td>&lt;td class="best">0.90&lt;/td>&lt;td class="td-label" style="font-family:inherit;font-size:11px;color:var(--gray-600);">Hampir semua jadi runoff&lt;/td>&lt;/tr>
&lt;tr>&lt;td class="td-label">Atap bangunan&lt;/td>&lt;td>0.85&lt;/td>&lt;td>0.95&lt;/td>&lt;td class="best">0.90&lt;/td>&lt;td class="td-label" style="font-family:inherit;font-size:11px;color:var(--gray-600);">Tidak ada infiltrasi&lt;/td>&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;/div>
&lt;div class="info-box">&lt;span class="box-icon">ℹ️&lt;/span>&lt;span>Untuk DAS dengan berbagai tipe lahan (mixed land use), hitung &lt;strong>C gabungan&lt;/strong> berdasarkan proporsi luas: &lt;code>C_gabungan = Σ(Cᵢ × Aᵢ) / A_total&lt;/code>. Dalam contoh artikel ini, DAS campuran hutan + sawah + permukiman menghasilkan C_gabungan = &lt;strong>0.65&lt;/strong>.&lt;/span>&lt;/div>
&lt;/section>
&lt;div class="divider">&lt;/div>
&lt;!-- S4B: PANDUAN PEMILIHAN METODE -->
&lt;section class="section anim-in" id="s4b">
&lt;div class="section-header">&lt;div class="section-num" style="background:var(--blue-mid);">↓&lt;/div>&lt;h2>Panduan Pemilihan Metode&lt;/h2>&lt;/div>
&lt;p style="font-size:13px;color:var(--gray-600);line-height:1.7;margin-bottom:1rem;">Sebelum memilih metode perhitungan, tentukan dulu &lt;strong>skala DAS&lt;/strong> yang akan dianalisis. Matriks berikut adalah panduan umum yang diadaptasi dari Ponce (1989) — salah satu referensi klasik hidrologi teknik.&lt;/p>
&lt;!-- MATRIX -->
&lt;div style="background:#fff;border-radius:var(--radius);box-shadow:var(--shadow-md);overflow:hidden;margin:1rem 0;">
&lt;!-- Header caption -->
&lt;div style="background:var(--navy);color:#fff;padding:0.7rem 1.2rem;font-size:12px;font-weight:700;display:flex;align-items:center;justify-content:space-between;">
&lt;span>📊 Hubungan Skala DAS dengan Metode Perhitungan Banjir&lt;/span>
&lt;span style="font-size:10px;font-weight:400;opacity:0.7;">Diadaptasi dari Ponce (1989) — Engineering Hydrology&lt;/span>
&lt;/div>
&lt;div style="padding:1.5rem;overflow-x:auto;">
&lt;table style="width:100%;border-collapse:separate;border-spacing:6px;min-width:480px;">
&lt;thead>
&lt;tr>
&lt;th style="width:130px;">&lt;/th>
&lt;th colspan="3" style="text-align:center;background:#fef3c7;color:#92400e;padding:10px 14px;border-radius:6px;font-size:13px;font-weight:700;letter-spacing:0.03em;">Skala DAS (Catchment Scale)&lt;/th>
&lt;/tr>
&lt;tr>
&lt;th style="width:130px;vertical-align:middle;text-align:right;padding-right:10px;">
&lt;div style="font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:0.06em;color:var(--gray-500);">Metode&lt;/div>
&lt;/th>
&lt;th style="text-align:center;background:#f8fafc;color:var(--gray-700);padding:9px 10px;border-radius:6px;font-size:12px;font-weight:700;border:1px solid var(--gray-200);">
Kecil&lt;br>&lt;span style="font-size:10px;font-weight:400;color:var(--gray-500);">Small (&amp;lt; 50 km²)&lt;/span>
&lt;/th>
&lt;th style="text-align:center;background:#f8fafc;color:var(--gray-700);padding:9px 10px;border-radius:6px;font-size:12px;font-weight:700;border:1px solid var(--gray-200);">
Sedang&lt;br>&lt;span style="font-size:10px;font-weight:400;color:var(--gray-500);">Midsize (50–250 km²)&lt;/span>
&lt;/th>
&lt;th style="text-align:center;background:#f8fafc;color:var(--gray-700);padding:9px 10px;border-radius:6px;font-size:12px;font-weight:700;border:1px solid var(--gray-200);">
Besar&lt;br>&lt;span style="font-size:10px;font-weight:400;color:var(--gray-500);">Large (&amp;gt; 250 km²)&lt;/span>
&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;!-- Row 1: Rational -->
&lt;tr>
&lt;td style="vertical-align:middle;padding:4px 10px 4px 0;text-align:right;">
&lt;div style="font-size:12px;font-weight:700;color:var(--blue);">📏 Metode&lt;br>Rasional&lt;/div>
&lt;div style="font-size:10px;color:var(--gray-500);">Q = 0.278·C·I·A&lt;/div>
&lt;/td>
&lt;td style="text-align:center;background:#d1fae5;border:2px solid #6ee7b7;border-radius:8px;padding:14px 10px;">
&lt;div style="font-size:16px;margin-bottom:4px;">✅&lt;/div>
&lt;div style="font-size:13px;font-weight:700;color:var(--green);">Biasanya&lt;/div>
&lt;div style="font-size:10px;color:#065f46;margin-top:3px;">Metode utama&lt;/div>
&lt;/td>
&lt;td style="text-align:center;background:#fee2e2;border:2px solid #fca5a5;border-radius:8px;padding:14px 10px;">
&lt;div style="font-size:16px;margin-bottom:4px;">❌&lt;/div>
&lt;div style="font-size:13px;font-weight:700;color:var(--red);">Tidak Berlaku&lt;/div>
&lt;div style="font-size:10px;color:#7f1d1d;margin-top:3px;">Kurang akurat&lt;/div>
&lt;/td>
&lt;td style="text-align:center;background:#fee2e2;border:2px solid #fca5a5;border-radius:8px;padding:14px 10px;">
&lt;div style="font-size:16px;margin-bottom:4px;">❌&lt;/div>
&lt;div style="font-size:13px;font-weight:700;color:var(--red);">Tidak Berlaku&lt;/div>
&lt;div style="font-size:10px;color:#7f1d1d;margin-top:3px;">Sangat tidak akurat&lt;/div>
&lt;/td>
&lt;/tr>
&lt;!-- Row 2: Unit Hydrograph -->
&lt;tr>
&lt;td style="vertical-align:middle;padding:4px 10px 4px 0;text-align:right;">
&lt;div style="font-size:12px;font-weight:700;color:var(--purple);">📈 Hidrograf&lt;br>Satuan (HSS)&lt;/div>
&lt;div style="font-size:10px;color:var(--gray-500);">Nakayasu, GAMA I&lt;/div>
&lt;/td>
&lt;td style="text-align:center;background:#fee2e2;border:2px solid #fca5a5;border-radius:8px;padding:14px 10px;">
&lt;div style="font-size:16px;margin-bottom:4px;">❌&lt;/div>
&lt;div style="font-size:13px;font-weight:700;color:var(--red);">Tidak Berlaku&lt;/div>
&lt;div style="font-size:10px;color:#7f1d1d;margin-top:3px;">Terlalu detail&lt;/div>
&lt;/td>
&lt;td style="text-align:center;background:#d1fae5;border:2px solid #6ee7b7;border-radius:8px;padding:14px 10px;">
&lt;div style="font-size:16px;margin-bottom:4px;">✅&lt;/div>
&lt;div style="font-size:13px;font-weight:700;color:var(--green);">Biasanya&lt;/div>
&lt;div style="font-size:10px;color:#065f46;margin-top:3px;">Metode utama&lt;/div>
&lt;/td>
&lt;td style="text-align:center;background:var(--blue-pale);border:2px solid var(--blue-light);border-radius:8px;padding:14px 10px;">
&lt;div style="font-size:16px;margin-bottom:4px;">⚡&lt;/div>
&lt;div style="font-size:13px;font-weight:700;color:var(--blue);">Kadang&lt;/div>
&lt;div style="font-size:10px;color:#1e3a5f;margin-top:3px;">Perlu pertimbangan&lt;/div>
&lt;/td>
&lt;/tr>
&lt;!-- Row 3: Routing -->
&lt;tr>
&lt;td style="vertical-align:middle;padding:4px 10px 4px 0;text-align:right;">
&lt;div style="font-size:12px;font-weight:700;color:var(--amber);">🌊 Flood&lt;br>Routing&lt;/div>
&lt;div style="font-size:10px;color:var(--gray-500);">HEC-HMS, HEC-RAS&lt;/div>
&lt;/td>
&lt;td style="text-align:center;background:var(--blue-pale);border:2px solid var(--blue-light);border-radius:8px;padding:14px 10px;">
&lt;div style="font-size:16px;margin-bottom:4px;">⚡&lt;/div>
&lt;div style="font-size:13px;font-weight:700;color:var(--blue);">Kadang&lt;/div>
&lt;div style="font-size:10px;color:#1e3a5f;margin-top:3px;">Bila diperlukan&lt;/div>
&lt;/td>
&lt;td style="text-align:center;background:var(--blue-pale);border:2px solid var(--blue-light);border-radius:8px;padding:14px 10px;">
&lt;div style="font-size:16px;margin-bottom:4px;">⚡&lt;/div>
&lt;div style="font-size:13px;font-weight:700;color:var(--blue);">Kadang&lt;/div>
&lt;div style="font-size:10px;color:#1e3a5f;margin-top:3px;">Perlu pertimbangan&lt;/div>
&lt;/td>
&lt;td style="text-align:center;background:#d1fae5;border:2px solid #6ee7b7;border-radius:8px;padding:14px 10px;">
&lt;div style="font-size:16px;margin-bottom:4px;">✅&lt;/div>
&lt;div style="font-size:13px;font-weight:700;color:var(--green);">Biasanya&lt;/div>
&lt;div style="font-size:10px;color:#065f46;margin-top:3px;">Metode utama&lt;/div>
&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;!-- Legend -->
&lt;div style="display:flex;gap:1.5rem;margin-top:1rem;flex-wrap:wrap;align-items:center;">
&lt;div style="font-size:11px;font-weight:700;color:var(--gray-500);text-transform:uppercase;letter-spacing:0.06em;">Keterangan:&lt;/div>
&lt;div style="display:flex;align-items:center;gap:6px;font-size:12px;color:var(--green);">&lt;div style="width:12px;height:12px;border-radius:3px;background:#d1fae5;border:1.5px solid #6ee7b7;">&lt;/div>Biasanya digunakan (Usually)&lt;/div>
&lt;div style="display:flex;align-items:center;gap:6px;font-size:12px;color:var(--red);">&lt;div style="width:12px;height:12px;border-radius:3px;background:#fee2e2;border:1.5px solid #fca5a5;">&lt;/div>Tidak berlaku (Not applicable)&lt;/div>
&lt;div style="display:flex;align-items:center;gap:6px;font-size:12px;color:var(--blue);">&lt;div style="width:12px;height:12px;border-radius:3px;background:var(--blue-pale);border:1.5px solid var(--blue-light);">&lt;/div>Kadang digunakan (Sometimes)&lt;/div>
&lt;/div>
&lt;div style="margin-top:0.75rem;font-size:11px;color:var(--gray-400);border-top:1px solid var(--gray-200);padding-top:0.6rem;">
Sumber: Ponce, V.M. (1989). &lt;em>Engineering Hydrology: Principles and Practices&lt;/em>. Prentice Hall. Fig. 1-9.
Akses: &lt;a href="https://ponce.sdsu.edu/enghydro/engineering_hydrology_01.php" target="_blank" style="color:var(--blue);">ponce.sdsu.edu&lt;/a>
&lt;/div>
&lt;/div>
&lt;/div>
&lt;!-- Batasan skala DAS -->
&lt;div class="grid-3" style="margin-top:1rem;">
&lt;div class="card card-blue" style="margin-bottom:0;">
&lt;div class="card-label" style="color:var(--blue);">🏙️ DAS Kecil — &amp;lt; 50 km²&lt;/div>
&lt;p>Respons cepat terhadap hujan. Satu hujan → satu puncak banjir yang jelas. Metode Rasional cukup untuk mendapatkan debit puncak. Contoh: sub-DAS perkotaan, saluran drainase.&lt;/p>
&lt;/div>
&lt;div class="card card-purple" style="margin-bottom:0;">
&lt;div class="card-label" style="color:var(--purple);">🏔️ DAS Sedang — 50–250 km²&lt;/div>
&lt;p>Skala DAS dalam artikel ini (50 km²). HSS Nakayasu cocok di rentang ini. Hidrograf satuan dapat merepresentasikan respons DAS dengan baik dan parameter masih dapat dikalibrasi.&lt;/p>
&lt;/div>
&lt;div class="card card-amber" style="margin-bottom:0;">
&lt;div class="card-label" style="color:var(--amber);">🌏 DAS Besar — &amp;gt; 250 km²&lt;/div>
&lt;p>Perlu flood routing karena banjir merambat dari hulu ke hilir dalam waktu yang signifikan. HEC-HMS (routing) dan HEC-RAS diperlukan. HSS masih bisa sebagai sub-DAS.&lt;/p>
&lt;/div>
&lt;/div>
&lt;div class="info-box" style="margin-top:1rem;">&lt;span class="box-icon">ℹ️&lt;/span>&lt;span>Artikel ini fokus pada &lt;strong>DAS sedang (50 km²)&lt;/strong> menggunakan dua metode: Metode Rasional (sebagai pembanding sederhana) dan HSS Nakayasu (metode utama). Untuk DAS yang lebih besar, lihat artikel HEC-HMS dan HEC-RAS di seri selanjutnya.&lt;/span>&lt;/div>
&lt;/section>
&lt;div class="divider">&lt;/div>
&lt;!-- S5: METODE RASIONAL -->
&lt;section class="section anim-in" id="s5">
&lt;div class="section-header">&lt;div class="section-num">5&lt;/div>&lt;h2>Metode Rasional&lt;/h2>&lt;/div>
&lt;div class="method-badge" style="background:rgba(24,95,165,0.1);color:var(--blue);border:1px solid var(--blue);">
📏 Cocok untuk DAS &amp;lt; 50 km²
&lt;/div>
&lt;p style="font-size:13px;color:var(--gray-600);line-height:1.7;margin-bottom:1rem;">Metode rasional adalah metode paling sederhana dan paling banyak digunakan untuk DAS kecil. Output-nya hanya debit puncak — tidak menghasilkan bentuk hidrograf penuh.&lt;/p>
&lt;div id="s5a">&lt;/div>
&lt;div class="subsection">&lt;h3>Rumus &amp; Parameter&lt;/h3>&lt;/div>
&lt;div class="formula-block">
&lt;span class="eq-label">Rumus Rasional — Debit Puncak Banjir&lt;/span>
&lt;span class="eq-main">Q = 0.278 × C × I × A&lt;/span>
&lt;span class="eq-desc">Q = debit puncak (m³/s) | C = koefisien limpasan (-) | I = intensitas hujan (mm/jam) | A = luas DAS (km²)
Angka 0.278 = faktor konversi satuan: 1 mm/jam × 1 km² = 0.278 m³/s
I diambil pada durasi t = t_c dari kurva IDF, pada kala ulang T yang diinginkan&lt;/span>
&lt;/div>
&lt;div class="step-flow">
&lt;div class="step-item">
&lt;div class="step-line">&lt;div class="step-dot navy">1&lt;/div>&lt;div class="step-connector">&lt;/div>&lt;/div>
&lt;div class="step-body">
&lt;div class="step-title">Hitung t_c (waktu konsentrasi)&lt;/div>
&lt;div class="step-desc">Dengan Kirpich: t_c = 0.0195 × 5000^0.77 × 0.010^(−0.385) = 81 menit = 1.35 jam&lt;/div>
&lt;/div>
&lt;/div>
&lt;div class="step-item">
&lt;div class="step-line">&lt;div class="step-dot navy">2&lt;/div>&lt;div class="step-connector">&lt;/div>&lt;/div>
&lt;div class="step-body">
&lt;div class="step-title">Ambil intensitas I dari kurva IDF pada t = t_c&lt;/div>
&lt;div class="step-desc">I(t_c = 1.35 jam, T = 25 tahun) = (R₂₄/24) × (24/1.35)^(2/3) = (151.9/24) × 17.78^(2/3) = 6.33 × 6.85 = 43.3 mm/jam&lt;/div>
&lt;/div>
&lt;/div>
&lt;div class="step-item">
&lt;div class="step-line">&lt;div class="step-dot navy">3&lt;/div>&lt;div class="step-connector">&lt;/div>&lt;/div>
&lt;div class="step-body">
&lt;div class="step-title">Tentukan C (koefisien limpasan)&lt;/div>
&lt;div class="step-desc">DAS campuran: hutan (40%) + sawah (35%) + permukiman (25%) → C = 0.15×0.40 + 0.55×0.35 + 0.65×0.25 = 0.06 + 0.19 + 0.16 = 0.41 ≈ 0.65 (kondisi jenuh saat banjir)&lt;/div>
&lt;/div>
&lt;/div>
&lt;div class="step-item">
&lt;div class="step-line">&lt;div class="step-dot green">4&lt;/div>&lt;/div>
&lt;div class="step-body" style="padding-bottom:0;">
&lt;div class="step-title">Hitung Q puncak&lt;/div>
&lt;div class="step-desc">Q_25 = 0.278 × 0.65 × 43.3 × 50 = &lt;strong style="color:var(--green);">391 m³/s&lt;/strong>&lt;/div>
&lt;/div>
&lt;/div>
&lt;/div>
&lt;div id="s5b">&lt;/div>
&lt;div class="subsection">&lt;h3>🎮 Kalkulator Interaktif — Metode Rasional&lt;/h3>&lt;/div>
&lt;div class="calc-box">
&lt;div class="calc-title">⚡ Hitung Debit Puncak — Metode Rasional &lt;span style="font-size:11px;font-weight:400;color:var(--gray-500);">Geser slider untuk melihat perubahan hasil secara langsung&lt;/span>&lt;/div>
&lt;div class="calc-grid">
&lt;div class="calc-field">
&lt;label>C — Koefisien Limpasan&lt;/label>
&lt;input type="range" id="slC" min="0.10" max="0.95" step="0.01" value="0.65" oninput="updateRasional()">
&lt;div class="val-display">C = &lt;span id="dispC">0.65&lt;/span>&lt;/div>
&lt;select onchange="setC(this.value)" style="margin-top:6px;">
&lt;option value="">Pilih tipe lahan...&lt;/option>
&lt;option value="0.15">Hutan lebat (0.15)&lt;/option>
&lt;option value="0.35">Perkebunan (0.35)&lt;/option>
&lt;option value="0.55">Sawah (0.55)&lt;/option>
&lt;option value="0.65">Permukiman jarang (0.65)&lt;/option>
&lt;option value="0.72">Permukiman padat (0.72)&lt;/option>
&lt;option value="0.90">Jalan aspal (0.90)&lt;/option>
&lt;/select>
&lt;/div>
&lt;div class="calc-field">
&lt;label>A — Luas DAS (km²)&lt;/label>
&lt;input type="range" id="slA" min="1" max="300" step="1" value="50" oninput="updateRasional()">
&lt;div class="val-display">A = &lt;span id="dispA">50&lt;/span> km²&lt;/div>
&lt;div style="font-size:11px;color:var(--gray-500);margin-top:4px;">Cocok untuk DAS ≤ 50 km²&lt;/div>
&lt;/div>
&lt;div class="calc-field">
&lt;label>T — Kala Ulang&lt;/label>
&lt;select id="selT" onchange="updateRasional()">
&lt;option value="2">T = 2 tahun&lt;/option>
&lt;option value="5">T = 5 tahun&lt;/option>
&lt;option value="10">T = 10 tahun&lt;/option>
&lt;option value="25" selected>T = 25 tahun&lt;/option>
&lt;option value="50">T = 50 tahun&lt;/option>
&lt;option value="100">T = 100 tahun&lt;/option>
&lt;/select>
&lt;label style="margin-top:8px;">t_c — Waktu Konsentrasi (jam)&lt;/label>
&lt;input type="range" id="slTc" min="0.25" max="6" step="0.05" value="1.35" oninput="updateRasional()">
&lt;div class="val-display">t_c = &lt;span id="dispTc">1.35&lt;/span> jam&lt;/div>
&lt;/div>
&lt;/div>
&lt;div style="background:var(--blue-pale);border-radius:8px;padding:0.8rem 1rem;margin-bottom:1rem;font-size:12px;color:#0c447c;">
&lt;strong>Intensitas I(t_c, T):&lt;/strong> &lt;span id="dispI">—&lt;/span> mm/jam
&amp;nbsp;|&amp;nbsp; &lt;strong>Rumus:&lt;/strong> Q = 0.278 × C × I × A
&lt;/div>
&lt;div class="calc-result">
&lt;div>
&lt;div class="calc-result-label">DEBIT PUNCAK RENCANA&lt;/div>
&lt;div>&lt;span class="calc-result-val" id="resultQ">391&lt;/span> &lt;span class="calc-result-unit">m³/s&lt;/span>&lt;/div>
&lt;/div>
&lt;div style="text-align:right;">
&lt;div class="calc-result-label">Setara dengan&lt;/div>
&lt;div style="color:rgba(255,255,255,0.8);font-size:13px;" id="resultCompare">—&lt;/div>
&lt;/div>
&lt;/div>
&lt;div style="margin-top:0.8rem;">
&lt;div id="warningA" class="warn-box" style="display:none;margin:0;font-size:12px;">&lt;span class="box-icon">⚠️&lt;/span>&lt;span>Luas DAS melebihi 50 km². Metode Rasional kurang akurat — pertimbangkan menggunakan HSS Nakayasu.&lt;/span>&lt;/div>
&lt;/div>
&lt;/div>
&lt;div class="chart-card">
&lt;div class="chart-title">Debit Puncak Metode Rasional per Kala Ulang&lt;/div>
&lt;div class="chart-sub">Berdasarkan: C = 0.65, A = 50 km², t_c = 1.35 jam, Distribusi Gumbel&lt;/div>
&lt;div class="chart-wrap" style="height:260px;">&lt;canvas id="chartRasional">&lt;/canvas>&lt;/div>
&lt;/div>
&lt;/section>
&lt;div class="divider">&lt;/div>
&lt;!-- S6: NAKAYASU -->
&lt;section class="section anim-in" id="s6">
&lt;div class="section-header">&lt;div class="section-num">6&lt;/div>&lt;h2>Hidrograf Satuan Sintetis (HSS) Nakayasu&lt;/h2>&lt;/div>
&lt;div class="method-badge" style="background:rgba(109,40,217,0.1);color:var(--purple);border:1px solid var(--purple);">
📊 Menghasilkan Hidrograf Penuh Q(t) — Cocok untuk DAS 50–250 km²
&lt;/div>
&lt;p style="font-size:13px;color:var(--gray-600);line-height:1.7;margin-bottom:1rem;">Metode Rasional hanya menghasilkan &lt;em>satu angka&lt;/em>: debit puncak. Untuk desain yang lebih detail — seperti penelusuran banjir (flood routing) di HEC-RAS atau desain kolam retensi — kita butuh &lt;strong>bentuk hidrograf lengkap&lt;/strong>: bagaimana debit naik, puncak, lalu turun kembali ke kondisi normal. HSS Nakayasu memberikan ini.&lt;/p>
&lt;div class="analogy-box">
&lt;div class="analogy-badge">💡 Analogi Hidrograf&lt;/div>
&lt;p>Hidrograf adalah seperti grafik jumlah penumpang di stasiun selama hari hujan. Paginya sepi, siang naik drastis saat hujan, mencapai puncak saat semua orang keluar serentak, lalu perlahan turun sore hari. Bentuk kurva naik-puncak-turun inilah yang disebut hidrograf — dan setiap DAS punya "bentuk khas" yang berbeda.&lt;/p>
&lt;/div>
&lt;div id="s6a">&lt;/div>
&lt;div class="subsection">&lt;h3>Parameter HSS Nakayasu&lt;/h3>&lt;/div>
&lt;div class="formula-block">
&lt;span class="eq-label">Debit Puncak Hidrograf Satuan — Nakayasu&lt;/span>
&lt;span class="eq-main">Q_p = A / (3.6 × (0.3·t_p + T_{0.3}))&lt;/span>
&lt;span class="eq-desc">Q_p = debit puncak hidrograf satuan (m³/s per mm hujan efektif)
A = luas DAS (km²) | t_p = waktu ke puncak (jam) | T₀.₃ = waktu resesi ke 0.3·Q_p (jam)&lt;/span>
&lt;/div>
&lt;div class="grid-2">
&lt;div>
&lt;div class="formula-block" style="margin-top:0;">
&lt;span class="eq-label">Waktu Kelambatan — t_g&lt;/span>
&lt;span class="eq-main">L &amp;lt; 15 km → t_g = 0.21 · L^0.7&lt;/span>
&lt;span class="eq-main">L ≥ 15 km → t_g = 0.40 + 0.058 · L&lt;/span>
&lt;span class="eq-desc">L = panjang sungai utama (km) | t_g dalam jam
Contoh: L = 10 km → t_g = 0.21 × 10^0.7 = 0.21 × 5.01 = 1.05 jam&lt;/span>
&lt;/div>
&lt;/div>
&lt;div>
&lt;div class="formula-block" style="margin-top:0;border-left-color:var(--green);">
&lt;span class="eq-label">Waktu ke Puncak &amp; Resesi&lt;/span>
&lt;span class="eq-main">t_r = 0.5 · t_g sampai 1.0 · t_g&lt;/span>
&lt;span class="eq-main">t_p = t_g + 0.8 · t_r&lt;/span>
&lt;span class="eq-main">T_{0.3} = α · t_g&lt;/span>
&lt;span class="eq-desc">t_r = saturation time | α = parameter resesi DAS (1–3)
α kecil = naik-turun cepat (DAS terjal) | α besar = resesi lambat (DAS datar)&lt;/span>
&lt;/div>
&lt;/div>
&lt;/div>
&lt;div class="tbl-wrap">
&lt;table class="data-tbl">
&lt;thead>&lt;tr>&lt;th>Parameter&lt;/th>&lt;th>Simbol&lt;/th>&lt;th>Nilai (contoh)&lt;/th>&lt;th>Satuan&lt;/th>&lt;th>Cara Mendapatkan&lt;/th>&lt;/tr>&lt;/thead>
&lt;tbody>
&lt;tr>&lt;td class="td-label">Luas DAS&lt;/td>&lt;td>A&lt;/td>&lt;td>50&lt;/td>&lt;td>km²&lt;/td>&lt;td class="td-label" style="font-family:inherit;font-size:11px;color:var(--gray-600);">Delineasi dari DEM di QGIS/Global Mapper&lt;/td>&lt;/tr>
&lt;tr>&lt;td class="td-label">Panjang sungai utama&lt;/td>&lt;td>L&lt;/td>&lt;td>10&lt;/td>&lt;td>km&lt;/td>&lt;td class="td-label" style="font-family:inherit;font-size:11px;color:var(--gray-600);">Ukur dari DEM atau peta topografi&lt;/td>&lt;/tr>
&lt;tr>&lt;td class="td-label">Parameter resesi DAS&lt;/td>&lt;td>α&lt;/td>&lt;td>2.0&lt;/td>&lt;td>-&lt;/td>&lt;td class="td-label" style="font-family:inherit;font-size:11px;color:var(--gray-600);">Kalibrasi data debit terukur (AWLR) atau dari referensi&lt;/td>&lt;/tr>
&lt;tr>&lt;td class="td-label">Waktu kelambatan&lt;/td>&lt;td>t_g&lt;/td>&lt;td>1.05&lt;/td>&lt;td>jam&lt;/td>&lt;td class="td-label" style="font-family:inherit;font-size:11px;color:var(--gray-600);">Dihitung: 0.21 × 10^0.7 = 1.05 jam&lt;/td>&lt;/tr>
&lt;tr>&lt;td class="td-label">Saturation time&lt;/td>&lt;td>t_r&lt;/td>&lt;td>1.05&lt;/td>&lt;td>jam&lt;/td>&lt;td class="td-label" style="font-family:inherit;font-size:11px;color:var(--gray-600);">Diambil = t_g (simplifikasi)&lt;/td>&lt;/tr>
&lt;tr class="highlight">&lt;td class="td-label" style="color:var(--purple);font-weight:700;">Waktu ke puncak&lt;/td>&lt;td style="color:var(--purple);font-weight:700;">t_p&lt;/td>&lt;td style="color:var(--purple);font-weight:700;">1.89&lt;/td>&lt;td>jam&lt;/td>&lt;td class="td-label" style="font-family:inherit;font-size:11px;color:var(--gray-600);">t_g + 0.8×t_r = 1.05 + 0.84 = 1.89 jam&lt;/td>&lt;/tr>
&lt;tr class="highlight">&lt;td class="td-label" style="color:var(--purple);font-weight:700;">Waktu resesi&lt;/td>&lt;td style="color:var(--purple);font-weight:700;">T₀.₃&lt;/td>&lt;td style="color:var(--purple);font-weight:700;">2.10&lt;/td>&lt;td>jam&lt;/td>&lt;td class="td-label" style="font-family:inherit;font-size:11px;color:var(--gray-600);">α × t_g = 2.0 × 1.05 = 2.10 jam&lt;/td>&lt;/tr>
&lt;tr>&lt;td class="td-label" style="color:var(--amber);font-weight:700;">Debit puncak unit&lt;/td>&lt;td style="color:var(--amber);font-weight:700;">Q_p&lt;/td>&lt;td style="color:var(--amber);font-weight:700;">5.19&lt;/td>&lt;td>m³/s/mm&lt;/td>&lt;td class="td-label" style="font-family:inherit;font-size:11px;color:var(--gray-600);">50 / (3.6 × (0.3×1.89 + 2.10)) = 5.19&lt;/td>&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;/div>
&lt;div class="card card-navy">
&lt;div class="card-label">Bentuk Hidrograf Satuan — Persamaan per Segmen&lt;/div>
&lt;div style="display:grid;grid-template-columns:1fr 1fr;gap:0.8rem;margin-top:0.5rem;">
&lt;div>
&lt;div class="formula-block" style="margin:0;padding:0.6rem 0.9rem;">
&lt;span class="eq-label">① Naik (0 ≤ t ≤ t_p)&lt;/span>
&lt;span class="eq-main" style="font-size:13px;">Q(t) = Q_p · (t / t_p)^2.4&lt;/span>
&lt;/div>
&lt;/div>
&lt;div>
&lt;div class="formula-block" style="margin:0;padding:0.6rem 0.9rem;border-left-color:var(--amber);">
&lt;span class="eq-label">② Turun awal (t_p ≤ t ≤ t_p + T₀.₃)&lt;/span>
&lt;span class="eq-main" style="font-size:13px;">Q(t) = Q_p · 0.3^((t−t_p)/T₀.₃)&lt;/span>
&lt;/div>
&lt;/div>
&lt;div>
&lt;div class="formula-block" style="margin:0;padding:0.6rem 0.9rem;border-left-color:var(--green);">
&lt;span class="eq-label">③ Turun tengah (s.d. t_p + 2.5·T₀.₃)&lt;/span>
&lt;span class="eq-main" style="font-size:12px;">Q(t) = Q_p · 0.3^((t−t_p+0.5·T₀.₃)/(1.5·T₀.₃))&lt;/span>
&lt;/div>
&lt;/div>
&lt;div>
&lt;div class="formula-block" style="margin:0;padding:0.6rem 0.9rem;border-left-color:var(--red);">
&lt;span class="eq-label">④ Ekor resesi (t &amp;gt; t_p + 2.5·T₀.₃)&lt;/span>
&lt;span class="eq-main" style="font-size:12px;">Q(t) = Q_p · 0.3^((t−t_p+1.5·T₀.₃)/(2·T₀.₃))&lt;/span>
&lt;/div>
&lt;/div>
&lt;/div>
&lt;/div>
&lt;div id="s6b">&lt;/div>
&lt;div class="subsection">&lt;h3>🎮 Hidrograf Interaktif — Pilih Kala Ulang&lt;/h3>&lt;/div>
&lt;div class="chart-card">
&lt;div class="chart-title">Hidrograf Banjir Rencana — HSS Nakayasu&lt;/div>
&lt;div class="chart-sub">A = 50 km² | L = 10 km | α = 2.0 | C = 0.65 | Distribusi Gumbel. Klik kala ulang untuk tampilkan/sembunyikan.&lt;/div>
&lt;div class="hydro-controls" id="hydroBtns">&lt;/div>
&lt;div class="chart-wrap" style="height:340px;">&lt;canvas id="chartHydro">&lt;/canvas>&lt;/div>
&lt;div style="background:var(--gray-100);border-radius:8px;padding:0.8rem 1rem;margin-top:0.8rem;">
&lt;div style="font-size:11px;font-weight:700;color:var(--gray-600);margin-bottom:6px;text-transform:uppercase;letter-spacing:0.06em;">Parameter Hidrograf Satuan&lt;/div>
&lt;div style="display:flex;gap:1.5rem;flex-wrap:wrap;font-size:12px;color:var(--gray-700);">
&lt;span>t_p = &lt;strong>1.89 jam&lt;/strong>&lt;/span>
&lt;span>T₀.₃ = &lt;strong>2.10 jam&lt;/strong>&lt;/span>
&lt;span>Q_p unit = &lt;strong>5.19 m³/s/mm&lt;/strong>&lt;/span>
&lt;span>t_dasar ≈ &lt;strong>16.4 jam&lt;/strong>&lt;/span>
&lt;/div>
&lt;/div>
&lt;/div>
&lt;/section>
&lt;div class="divider">&lt;/div>
&lt;!-- S7: HUJAN EFEKTIF -->
&lt;section class="section anim-in" id="s7">
&lt;div class="section-header">&lt;div class="section-num">7&lt;/div>&lt;h2>Hujan Efektif (R_eff)&lt;/h2>&lt;/div>
&lt;p style="font-size:13px;color:var(--gray-600);line-height:1.7;margin-bottom:1rem;">Tidak semua curah hujan rencana langsung menjadi aliran permukaan. Ada kehilangan akibat intersepsi, infiltrasi, dan tampungan permukaan. Yang tersisa disebut &lt;strong>hujan efektif (R_eff)&lt;/strong> — inilah yang benar-benar berkontribusi pada banjir.&lt;/p>
&lt;div class="grid-2">
&lt;div class="card card-blue">
&lt;div class="card-label">① Metode Phi-Index (φ)&lt;/div>
&lt;p>Kehilangan dianggap konstan sebesar φ (phi). Semua intensitas di atas φ menjadi hujan efektif. Sederhana, tapi memerlukan data debit terukur untuk kalibrasi φ.&lt;/p>
&lt;div class="formula-block" style="margin-top:8px;padding:0.6rem 0.9rem;">
&lt;span class="eq-main" style="font-size:13px;">R_eff = R_T − Abstraksi&lt;/span>
&lt;span class="eq-desc">Abstraksi ≈ 20-40% dari R_T (tanpa kalibrasi)&lt;/span>
&lt;/div>
&lt;/div>
&lt;div class="card card-green">
&lt;div class="card-label">② Metode SCS-CN (Curve Number)&lt;/div>
&lt;p>Menggunakan angka CN yang merepresentasikan kondisi tanah dan tata guna lahan. Lebih ilmiah dan bisa digunakan tanpa data debit terukur.&lt;/p>
&lt;div class="formula-block" style="margin-top:8px;padding:0.6rem 0.9rem;border-left-color:var(--green);">
&lt;span class="eq-main" style="font-size:12px;">R_eff = (R − 0.2·S)² / (R + 0.8·S)&lt;/span>
&lt;span class="eq-desc">S = 25400/CN − 254 &amp;nbsp;|&amp;nbsp; CN = 60–90 tipikal&lt;/span>
&lt;/div>
&lt;/div>
&lt;/div>
&lt;div class="card card-amber" style="margin-bottom:1rem;">
&lt;div class="card-label">Pendekatan Sederhana (Tanpa Kalibrasi)&lt;/div>
&lt;p>Untuk analisis awal tanpa data debit terukur, hujan efektif dapat dihitung menggunakan koefisien limpasan: &lt;strong>R_eff = C × R_T&lt;/strong>. Ini setara dengan asumsi bahwa proporsi hujan yang menjadi runoff sama dengan koefisien C dalam metode rasional.&lt;/p>
&lt;/div>
&lt;div class="tbl-wrap">
&lt;table class="data-tbl" id="tblReff">&lt;/table>
&lt;/div>
&lt;/section>
&lt;div class="divider">&lt;/div>
&lt;!-- S8: DEBIT PUNCAK -->
&lt;section class="section anim-in" id="s8">
&lt;div class="section-header">&lt;div class="section-num">8&lt;/div>&lt;h2>Rekapitulasi Debit Banjir Rencana&lt;/h2>&lt;/div>
&lt;p style="font-size:13px;color:var(--gray-600);line-height:1.7;margin-bottom:1rem;">Dengan mengalikan hidrograf satuan Nakayasu (Q_p unit = 5.19 m³/s per mm) dengan hujan efektif masing-masing kala ulang, diperoleh debit puncak banjir rencana.&lt;/p>
&lt;div class="grid-4" id="peakCards">&lt;/div>
&lt;div class="tbl-wrap">
&lt;table class="data-tbl" id="tblDebit">&lt;/table>
&lt;/div>
&lt;div class="success-box">&lt;span class="box-icon">🎯&lt;/span>&lt;span>Tabel debit puncak di atas adalah &lt;strong>output final yang siap digunakan&lt;/strong> sebagai input untuk: (1) HEC-RAS untuk profil muka air banjir, (2) desain dimensi bendung/tanggul, (3) penentuan tinggi jagaan (freeboard), dan (4) analisis kapasitas sungai.&lt;/span>&lt;/div>
&lt;/section>
&lt;div class="divider">&lt;/div>
&lt;!-- S9: PERBANDINGAN -->
&lt;section class="section anim-in" id="s9">
&lt;div class="section-header">&lt;div class="section-num">9&lt;/div>&lt;h2>Perbandingan Antar Metode&lt;/h2>&lt;/div>
&lt;div class="chart-card">
&lt;div class="chart-title">Perbandingan Debit Puncak: Metode Rasional vs HSS Nakayasu&lt;/div>
&lt;div class="chart-sub">A = 50 km² | C = 0.65 | Distribusi Gumbel. Nilai dalam m³/s.&lt;/div>
&lt;div class="chart-wrap" style="height:300px;">&lt;canvas id="chartCompare">&lt;/canvas>&lt;/div>
&lt;div class="legend-row">
&lt;div class="legend-item">&lt;div class="legend-sq" style="background:#185fa5;">&lt;/div> Metode Rasional&lt;/div>
&lt;div class="legend-item">&lt;div class="legend-sq" style="background:#6D28D9;">&lt;/div> HSS Nakayasu&lt;/div>
&lt;/div>
&lt;/div>
&lt;div class="tbl-wrap">
&lt;table class="data-tbl" id="tblCompare">&lt;/table>
&lt;/div>
&lt;div class="card card-navy" style="margin-top:1rem;">
&lt;div class="card-label">Kapan Menggunakan Metode Mana?&lt;/div>
&lt;div style="display:grid;grid-template-columns:1fr 1fr;gap:1rem;margin-top:0.5rem;">
&lt;div>
&lt;p>&lt;strong style="color:var(--blue);">📏 Metode Rasional&lt;/strong>&lt;/p>
&lt;p>✅ DAS kecil (&amp;lt; 50 km²)&lt;br>✅ Desain drainase perkotaan&lt;br>✅ Gorong-gorong dan saluran kecil&lt;br>✅ Saat data terbatas&lt;br>❌ Tidak menghasilkan hidrograf&lt;br>❌ Kurang akurat untuk DAS besar&lt;/p>
&lt;/div>
&lt;div>
&lt;p>&lt;strong style="color:var(--purple);">📊 HSS Nakayasu&lt;/strong>&lt;/p>
&lt;p>✅ DAS menengah–besar (10–1000 km²)&lt;br>✅ Perlu bentuk hidrograf penuh&lt;br>✅ Input untuk HEC-HMS/RAS&lt;br>✅ Desain bendung dan waduk&lt;br>❌ Perlu kalibrasi parameter α&lt;br>❌ Lebih kompleks perhitungannya&lt;/p>
&lt;/div>
&lt;/div>
&lt;/div>
&lt;div class="warn-box">&lt;span class="box-icon">⚠️&lt;/span>&lt;span>Hasil debit dari metode berbeda bisa berbeda 10–30%. Dalam proyek nyata, selalu lakukan &lt;strong>analisis sensitivitas&lt;/strong> dengan minimal dua metode, dan gunakan nilai yang lebih konservatif (lebih besar) untuk keamanan. Konfirmasi juga dengan data debit terukur (AWLR) jika tersedia.&lt;/span>&lt;/div>
&lt;/section>
&lt;div class="divider">&lt;/div>
&lt;!-- S10: KODE R -->
&lt;section class="section anim-in" id="s10">
&lt;div class="section-header">&lt;div class="section-num">10&lt;/div>&lt;h2>Kode R — Implementasi Lengkap&lt;/h2>&lt;/div>
&lt;div class="code-wrap">
&lt;div class="code-header">
&lt;span class="code-lang">&lt;span class="dot" style="background:#4fc3f7;">&lt;/span>R · Setup &amp; Parameter DAS&lt;/span>
&lt;button class="copy-btn" onclick="copyCode(this)">Salin&lt;/button>
&lt;/div>
&lt;pre>&lt;span class="fn">options&lt;/span>(OutDec = &lt;span class="str">"."&lt;/span>)
&lt;span class="kw">library&lt;/span>(&lt;span class="pkg">dplyr&lt;/span>); &lt;span class="kw">library&lt;/span>(&lt;span class="pkg">tidyr&lt;/span>); &lt;span class="kw">library&lt;/span>(&lt;span class="pkg">ggplot2&lt;/span>)
&lt;span class="cm"># ── Parameter DAS ─────────────────────────────────────────────&lt;/span>
A &lt;span class="op">&amp;lt;-&lt;/span> &lt;span class="num">50&lt;/span> &lt;span class="cm"># luas DAS (km²)&lt;/span>
L &lt;span class="op">&amp;lt;-&lt;/span> &lt;span class="num">10&lt;/span> &lt;span class="cm"># panjang sungai utama (km)&lt;/span>
alpha &lt;span class="op">&amp;lt;-&lt;/span> &lt;span class="num">2.0&lt;/span> &lt;span class="cm"># parameter resesi Nakayasu&lt;/span>
C_run &lt;span class="op">&amp;lt;-&lt;/span> &lt;span class="num">0.65&lt;/span> &lt;span class="cm"># koefisien limpasan DAS&lt;/span>
L_kir &lt;span class="op">&amp;lt;-&lt;/span> &lt;span class="num">5000&lt;/span> &lt;span class="cm"># panjang saluran untuk Kirpich (meter)&lt;/span>
S_kir &lt;span class="op">&amp;lt;-&lt;/span> &lt;span class="num">0.010&lt;/span> &lt;span class="cm"># kemiringan untuk Kirpich (m/m)&lt;/span>
&lt;span class="cm"># ── Curah hujan rencana dari analisa frekuensi (Gumbel) ───────&lt;/span>
T_values &lt;span class="op">&amp;lt;-&lt;/span> &lt;span class="fn">c&lt;/span>(&lt;span class="num">2&lt;/span>, &lt;span class="num">5&lt;/span>, &lt;span class="num">10&lt;/span>, &lt;span class="num">25&lt;/span>, &lt;span class="num">50&lt;/span>, &lt;span class="num">100&lt;/span>)
R_T &lt;span class="op">&amp;lt;-&lt;/span> &lt;span class="fn">c&lt;/span>(&lt;span class="num">96.4&lt;/span>, &lt;span class="num">118.7&lt;/span>, &lt;span class="num">133.4&lt;/span>, &lt;span class="num">151.9&lt;/span>, &lt;span class="num">165.6&lt;/span>, &lt;span class="num">179.2&lt;/span>) &lt;span class="cm"># mm&lt;/span>
&lt;span class="cm"># ── Waktu konsentrasi Kirpich ─────────────────────────────────&lt;/span>
tc_min &lt;span class="op">&amp;lt;-&lt;/span> &lt;span class="num">0.0195&lt;/span> &lt;span class="op">*&lt;/span> L_kir^&lt;span class="num">0.77&lt;/span> &lt;span class="op">*&lt;/span> S_kir^(&lt;span class="op">-&lt;/span>&lt;span class="num">0.385&lt;/span>)
tc_jam &lt;span class="op">&amp;lt;-&lt;/span> tc_min / &lt;span class="num">60&lt;/span>
&lt;span class="fn">cat&lt;/span>(&lt;span class="str">"tc Kirpich ="&lt;/span>, &lt;span class="fn">round&lt;/span>(tc_jam, &lt;span class="num">2&lt;/span>), &lt;span class="str">"jam\n"&lt;/span>)&lt;/pre>
&lt;/div>
&lt;div class="code-wrap">
&lt;div class="code-header">
&lt;span class="code-lang">&lt;span class="dot" style="background:#4fc3f7;">&lt;/span>R · Metode Rasional&lt;/span>
&lt;button class="copy-btn" onclick="copyCode(this)">Salin&lt;/button>
&lt;/div>
&lt;pre>&lt;span class="cm"># ── Intensitas Mononobe pada t = tc ───────────────────────────&lt;/span>
mononobe &lt;span class="op">&amp;lt;-&lt;/span> &lt;span class="kw">function&lt;/span>(R24, t_jam) (R24 / &lt;span class="num">24&lt;/span>) &lt;span class="op">*&lt;/span> (&lt;span class="num">24&lt;/span> / t_jam)^(&lt;span class="num">2&lt;/span>/&lt;span class="num">3&lt;/span>)
&lt;span class="cm"># ── Debit puncak metode rasional ─────────────────────────────&lt;/span>
I_tc &lt;span class="op">&amp;lt;-&lt;/span> &lt;span class="fn">sapply&lt;/span>(R_T, mononobe, t_jam = tc_jam) &lt;span class="cm"># intensitas (mm/jam)&lt;/span>
Q_ras &lt;span class="op">&amp;lt;-&lt;/span> &lt;span class="num">0.278&lt;/span> &lt;span class="op">*&lt;/span> C_run &lt;span class="op">*&lt;/span> I_tc &lt;span class="op">*&lt;/span> A &lt;span class="cm"># debit (m³/s)&lt;/span>
hasil_rasional &lt;span class="op">&amp;lt;-&lt;/span> &lt;span class="fn">data.frame&lt;/span>(
T = T_values,
R_T_mm = R_T,
I_mmjam = &lt;span class="fn">round&lt;/span>(I_tc, &lt;span class="num">1&lt;/span>),
Q_m3s = &lt;span class="fn">round&lt;/span>(Q_ras, &lt;span class="num">1&lt;/span>)
)
&lt;span class="fn">print&lt;/span>(hasil_rasional)&lt;/pre>
&lt;/div>
&lt;div class="code-wrap">
&lt;div class="code-header">
&lt;span class="code-lang">&lt;span class="dot" style="background:#4fc3f7;">&lt;/span>R · HSS Nakayasu — Parameter &amp; Hidrograf Satuan&lt;/span>
&lt;button class="copy-btn" onclick="copyCode(this)">Salin&lt;/button>
&lt;/div>
&lt;pre>&lt;span class="cm"># ── Parameter Nakayasu ────────────────────────────────────────&lt;/span>
tg &lt;span class="op">&amp;lt;-&lt;/span> &lt;span class="kw">if&lt;/span>(L &lt;span class="op">&amp;lt;&lt;/span> &lt;span class="num">15&lt;/span>) &lt;span class="num">0.21&lt;/span> &lt;span class="op">*&lt;/span> L^&lt;span class="num">0.7&lt;/span> &lt;span class="kw">else&lt;/span> &lt;span class="num">0.40&lt;/span> &lt;span class="op">+&lt;/span> &lt;span class="num">0.058&lt;/span> &lt;span class="op">*&lt;/span> L
tr &lt;span class="op">&amp;lt;-&lt;/span> tg &lt;span class="cm"># simplifikasi: tr = tg&lt;/span>
tp &lt;span class="op">&amp;lt;-&lt;/span> tg &lt;span class="op">+&lt;/span> &lt;span class="num">0.8&lt;/span> &lt;span class="op">*&lt;/span> tr
T03 &lt;span class="op">&amp;lt;-&lt;/span> alpha &lt;span class="op">*&lt;/span> tg
Qp &lt;span class="op">&amp;lt;-&lt;/span> A / (&lt;span class="num">3.6&lt;/span> &lt;span class="op">*&lt;/span> (&lt;span class="num">0.3&lt;/span> &lt;span class="op">*&lt;/span> tp &lt;span class="op">+&lt;/span> T03)) &lt;span class="cm"># m³/s per mm&lt;/span>
&lt;span class="fn">cat&lt;/span>(&lt;span class="str">"tg ="&lt;/span>, &lt;span class="fn">round&lt;/span>(tg, &lt;span class="num">2&lt;/span>), &lt;span class="str">"jam | tp ="&lt;/span>, &lt;span class="fn">round&lt;/span>(tp,&lt;span class="num">2&lt;/span>),
&lt;span class="str">"jam | T03 ="&lt;/span>, &lt;span class="fn">round&lt;/span>(T03,&lt;span class="num">2&lt;/span>), &lt;span class="str">"jam | Qp_unit ="&lt;/span>, &lt;span class="fn">round&lt;/span>(Qp,&lt;span class="num">3&lt;/span>), &lt;span class="str">"m3/s/mm\n"&lt;/span>)
&lt;span class="cm"># ── Hidrograf satuan (dt = 0.1 jam) ──────────────────────────&lt;/span>
nakayasu_unit &lt;span class="op">&amp;lt;-&lt;/span> &lt;span class="kw">function&lt;/span>(t) {
&lt;span class="kw">if&lt;/span> (t &lt;span class="op">&amp;lt;=&lt;/span> tp) Qp &lt;span class="op">*&lt;/span> (t / tp)^&lt;span class="num">2.4&lt;/span>
&lt;span class="kw">else if&lt;/span> (t &lt;span class="op">&amp;lt;=&lt;/span> tp &lt;span class="op">+&lt;/span> T03) Qp &lt;span class="op">*&lt;/span> &lt;span class="num">0.3&lt;/span>^((t &lt;span class="op">-&lt;/span> tp) / T03)
&lt;span class="kw">else if&lt;/span> (t &lt;span class="op">&amp;lt;=&lt;/span> tp &lt;span class="op">+&lt;/span> &lt;span class="num">2.5&lt;/span>&lt;span class="op">*&lt;/span>T03) Qp &lt;span class="op">*&lt;/span> &lt;span class="num">0.3&lt;/span>^((t &lt;span class="op">-&lt;/span> tp &lt;span class="op">+&lt;/span> &lt;span class="num">0.5&lt;/span>&lt;span class="op">*&lt;/span>T03) / (&lt;span class="num">1.5&lt;/span>&lt;span class="op">*&lt;/span>T03))
&lt;span class="kw">else&lt;/span> Qp &lt;span class="op">*&lt;/span> &lt;span class="num">0.3&lt;/span>^((t &lt;span class="op">-&lt;/span> tp &lt;span class="op">+&lt;/span> &lt;span class="num">1.5&lt;/span>&lt;span class="op">*&lt;/span>T03) / (&lt;span class="num">2&lt;/span> &lt;span class="op">*&lt;/span>T03))
}
t_seq &lt;span class="op">&amp;lt;-&lt;/span> &lt;span class="fn">seq&lt;/span>(&lt;span class="num">0&lt;/span>, &lt;span class="num">24&lt;/span>, by = &lt;span class="num">0.1&lt;/span>)
unit_hydro &lt;span class="op">&amp;lt;-&lt;/span> &lt;span class="fn">sapply&lt;/span>(t_seq, nakayasu_unit)&lt;/pre>
&lt;/div>
&lt;div class="code-wrap">
&lt;div class="code-header">
&lt;span class="code-lang">&lt;span class="dot" style="background:#4fc3f7;">&lt;/span>R · Debit Banjir Rencana &amp; Plot Hidrograf&lt;/span>
&lt;button class="copy-btn" onclick="copyCode(this)">Salin&lt;/button>
&lt;/div>
&lt;pre>&lt;span class="cm"># ── Hujan efektif &amp; hidrograf banjir per kala ulang ──────────&lt;/span>
R_eff &lt;span class="op">&amp;lt;-&lt;/span> C_run &lt;span class="op">*&lt;/span> R_T &lt;span class="cm"># hujan efektif (mm)&lt;/span>
Qpeak_N &lt;span class="op">&amp;lt;-&lt;/span> Qp &lt;span class="op">*&lt;/span> R_eff &lt;span class="cm"># debit puncak Nakayasu (m³/s)&lt;/span>
&lt;span class="cm"># ── Buat data frame hidrograf semua kala ulang ────────────────&lt;/span>
df_hydro &lt;span class="op">&amp;lt;-&lt;/span> &lt;span class="fn">lapply&lt;/span>(&lt;span class="fn">seq_along&lt;/span>(T_values), &lt;span class="kw">function&lt;/span>(i) {
&lt;span class="fn">data.frame&lt;/span>(
t = t_seq,
Q = unit_hydro &lt;span class="op">*&lt;/span> R_eff[i],
T_yr = &lt;span class="fn">paste0&lt;/span>(&lt;span class="str">"T"&lt;/span>, T_values[i])
)
}) &lt;span class="op">|&amp;gt;&lt;/span> &lt;span class="fn">bind_rows&lt;/span>()
&lt;span class="cm"># ── Plot hidrograf semua kala ulang ───────────────────────────&lt;/span>
cols &lt;span class="op">&amp;lt;-&lt;/span> &lt;span class="fn">c&lt;/span>(T2=&lt;span class="str">"#64748b"&lt;/span>, T5=&lt;span class="str">"#2563eb"&lt;/span>, T10=&lt;span class="str">"#0284c7"&lt;/span>,
T25=&lt;span class="str">"#d97706"&lt;/span>, T50=&lt;span class="str">"#dc2626"&lt;/span>, T100=&lt;span class="str">"#7c3aed"&lt;/span>)
ggplot(df_hydro, &lt;span class="fn">aes&lt;/span>(x = t, y = Q, color = T_yr)) &lt;span class="op">+&lt;/span>
&lt;span class="fn">geom_line&lt;/span>(linewidth = &lt;span class="num">0.9&lt;/span>) &lt;span class="op">+&lt;/span>
&lt;span class="fn">scale_color_manual&lt;/span>(values = cols) &lt;span class="op">+&lt;/span>
&lt;span class="fn">geom_vline&lt;/span>(xintercept = tp, linetype = &lt;span class="str">"dashed"&lt;/span>, color = &lt;span class="str">"gray50"&lt;/span>, linewidth = &lt;span class="num">0.5&lt;/span>) &lt;span class="op">+&lt;/span>
&lt;span class="fn">annotate&lt;/span>(&lt;span class="str">"text"&lt;/span>, x = tp + &lt;span class="num">0.2&lt;/span>, y = &lt;span class="fn">max&lt;/span>(df_hydro&lt;span class="op">$&lt;/span>Q) &lt;span class="op">*&lt;/span> &lt;span class="num">0.95&lt;/span>,
label = &lt;span class="fn">paste0&lt;/span>(&lt;span class="str">"tp = "&lt;/span>, &lt;span class="fn">round&lt;/span>(tp, &lt;span class="num">2&lt;/span>), &lt;span class="str">" jam"&lt;/span>), size = &lt;span class="num">3&lt;/span>, hjust = &lt;span class="num">0&lt;/span>) &lt;span class="op">+&lt;/span>
&lt;span class="fn">labs&lt;/span>(
title = &lt;span class="str">"Hidrograf Banjir Rencana — HSS Nakayasu"&lt;/span>,
subtitle = &lt;span class="fn">paste0&lt;/span>(&lt;span class="str">"A="&lt;/span>, A, &lt;span class="str">" km² | L="&lt;/span>, L, &lt;span class="str">" km | α="&lt;/span>, alpha, &lt;span class="str">" | C="&lt;/span>, C_run),
x = &lt;span class="str">"Waktu (jam)"&lt;/span>, y = &lt;span class="str">"Debit Q (m³/s)"&lt;/span>, color = &lt;span class="str">"Kala Ulang"&lt;/span>,
caption = &lt;span class="str">"Metode: HSS Nakayasu | SNI 2415:2016"&lt;/span>
) &lt;span class="op">+&lt;/span>
&lt;span class="fn">theme_minimal&lt;/span>(base_size = &lt;span class="num">11&lt;/span>) &lt;span class="op">+&lt;/span>
&lt;span class="fn">theme&lt;/span>(plot.title = &lt;span class="fn">element_text&lt;/span>(face = &lt;span class="str">"bold"&lt;/span>))
&lt;span class="fn">ggsave&lt;/span>(&lt;span class="str">"hidrograf_banjir_rencana.png"&lt;/span>, width = &lt;span class="num">36&lt;/span>, height = &lt;span class="num">22&lt;/span>, units = &lt;span class="str">"cm"&lt;/span>, dpi = &lt;span class="num">300&lt;/span>)&lt;/pre>
&lt;/div>
&lt;/section>
&lt;div class="divider">&lt;/div>
&lt;!-- S11: KELANJUTAN -->
&lt;section class="section anim-in" id="s11">
&lt;div class="section-header">&lt;div class="section-num">11&lt;/div>&lt;h2>Kelanjutan — Debit Banjir Rencana Dipakai untuk Apa?&lt;/h2>&lt;/div>
&lt;div class="grid-3">
&lt;div class="card card-blue">
&lt;div class="card-label">① Pemodelan HEC-RAS&lt;/div>
&lt;p>Debit Q_T (m³/s) menjadi input boundary condition di HEC-RAS untuk menghitung profil muka air banjir di sepanjang sungai.&lt;/p>
&lt;p style="margin-top:8px;font-size:12px;color:var(--gray-500);">→ Profil WSE (Water Surface Elevation)&lt;br>→ Kecepatan aliran per penampang&lt;br>→ Peta genangan banjir (GIS)&lt;/p>
&lt;/div>
&lt;div class="card card-green">
&lt;div class="card-label">② Desain Bendung &amp; Tanggul&lt;/div>
&lt;p>Q rencana menentukan dimensi pelimpah (spillway), tinggi tanggul, dan tinggi jagaan (freeboard) yang diperlukan.&lt;/p>
&lt;p style="margin-top:8px;font-size:12px;color:var(--gray-500);">→ Q_50 atau Q_100 untuk tanggul&lt;br>→ Q_100 atau Q_PMF untuk bendungan&lt;br>→ Kapasitas kolam olak&lt;/p>
&lt;/div>
&lt;div class="card card-amber">
&lt;div class="card-label">③ Analisis Sempadan Sungai&lt;/div>
&lt;p>Profil muka air dari HEC-RAS digunakan untuk menentukan garis sempadan sungai sesuai Permen PUPR No. 28/2015.&lt;/p>
&lt;p style="margin-top:8px;font-size:12px;color:var(--gray-500);">→ Batas banjir Q_25 atau Q_50&lt;br>→ Sempadan berdasarkan lebar sungai&lt;br>→ Rekomendasi tata ruang&lt;/p>
&lt;/div>
&lt;div class="card card-purple">
&lt;div class="card-label">④ Drainase Perkotaan (SWMM)&lt;/div>
&lt;p>Untuk DAS kecil perkotaan, hidrograf banjir menjadi input SWMM untuk merancang kapasitas saluran dan kolam retensi.&lt;/p>
&lt;p style="margin-top:8px;font-size:12px;color:var(--gray-500);">→ Dimensi saluran drainase&lt;br>→ Volume kolam detensi/retensi&lt;br>→ Pompa dan pintu air&lt;/p>
&lt;/div>
&lt;div class="card card-navy">
&lt;div class="card-label">⑤ Analisis AMDAL Hidrologi&lt;/div>
&lt;p>Perbandingan Q sebelum dan sesudah proyek pembangunan untuk prakiraan dampak peningkatan limpasan permukaan.&lt;/p>
&lt;p style="margin-top:8px;font-size:12px;color:var(--gray-500);">→ ΔQ akibat perubahan tutupan lahan&lt;br>→ Prakiraan peningkatan debit puncak&lt;br>→ Rekomendasi mitigasi banjir&lt;/p>
&lt;/div>
&lt;div class="card card-red">
&lt;div class="card-label">⑥ Analisis Risiko Banjir&lt;/div>
&lt;p>Kombinasi Q rencana berbagai kala ulang dengan peta topografi untuk peta hazard banjir dan analisis kerentanan wilayah.&lt;/p>
&lt;p style="margin-top:8px;font-size:12px;color:var(--gray-500);">→ Peta genangan multi-skenario&lt;br>→ Matriks risiko banjir&lt;br>→ Prioritas pengendalian banjir&lt;/p>
&lt;/div>
&lt;/div>
&lt;div class="info-box">&lt;span class="box-icon">🔗&lt;/span>&lt;span>Rantai lengkap analisis hidrologi: &lt;strong>Data Hujan → Analisa Frekuensi → Curah Hujan Rencana → Debit Banjir Rencana → HEC-RAS → Profil Muka Air → Desain Infrastruktur&lt;/strong>. Setiap langkah membangun di atas hasil langkah sebelumnya — kesalahan di langkah awal akan menjalar ke semua output hilir.&lt;/span>&lt;/div>
&lt;div style="margin-top:1.5rem;">
&lt;div class="card-label" style="font-size:11px;margin-bottom:10px;">ARTIKEL TERKAIT&lt;/div>
&lt;a href="https://www.irpanchumaedi.com/post/materi-analisa-frekuensi-hujan/" class="nav-link">
&lt;span style="font-size:1.2rem;color:var(--gray-400);">←&lt;/span>
&lt;div>
&lt;div class="nav-link-label">Artikel Sebelumnya&lt;/div>
&lt;div class="nav-link-title" style="color:var(--text-color,inherit);">Analisa Frekuensi Curah Hujan: Panduan Lengkap&lt;/div>
&lt;/div>
&lt;/a>
&lt;a href="https://www.irpanchumaedi.com/post/materi-pengantar-hecras/" class="nav-link">
&lt;span style="font-size:1.2rem;color:var(--gray-400);">→&lt;/span>
&lt;div>
&lt;div class="nav-link-label">Artikl Selanjutnya&lt;/div>
&lt;div class="nav-link-title" style="color:var(--text-color,inherit);">Pemodelan HEC-RAS: Dari Debit ke Profil Muka Air&lt;/div>
&lt;/div>
&lt;/a>
&lt;/div>
&lt;p style="font-size:12px;color:var(--gray-400);margin-top:2rem;border-top:1px solid var(--gray-200);padding-top:1rem;">
Semua rumus mengikuti &lt;strong>SNI 2415:2016&lt;/strong>. Referensi: Sri Harto (1993), Triatmodjo (2008), Soemarto (1995), Nakayasu (1950), Kirpich (1940). Kode R menggunakan paket: &lt;code>dplyr&lt;/code>, &lt;code>tidyr&lt;/code>, &lt;code>ggplot2&lt;/code>.
&lt;/p>
&lt;/section>
&lt;/div>
&lt;script>
/* ================================================================
DATA
================================================================ */
const T_arr = [2,5,10,25,50,100];
const RT = [96.4,118.7,133.4,151.9,165.6,179.2];
const A=50, L=10, alpha=2.0, C=0.65;
const Lk=5000, Sk=0.010;
// Nakayasu parameters
const tg = (L &lt; 15) ? 0.21*Math.pow(L,0.7) : 0.40+0.058*L; // 1.053 hr
const tr = tg;
const tp = tg + 0.8*tr; // 1.895 hr
const T03 = alpha*tg; // 2.106 hr
const Qp_unit = A/(3.6*(0.3*tp+T03)); // m3/s per mm
// Time of concentration - Kirpich
const tc_min = 0.0195*Math.pow(Lk,0.77)*Math.pow(Sk,-0.385);
const tc_hr = tc_min/60;
// Mononobe IDF
function mononobe(R24,t){ return (R24/24)*Math.pow(24/t, 2/3); }
// Intensities at tc
const I_tc = RT.map(r=>mononobe(r,tc_hr));
// Rational method peak discharge
const Q_ras = I_tc.map(i=>0.278*C*i*A);
// Effective rainfall &amp; Nakayasu peaks
const R_eff = RT.map(r=>C*r);
const Qpeak_N = R_eff.map(r=>Qp_unit*r);
// Nakayasu unit hydrograph
function nakUnit(t){
if(t&lt;=tp) return Qp_unit*Math.pow(t/tp,2.4);
if(t&lt;=tp+T03) return Qp_unit*Math.pow(0.3,(t-tp)/T03);
if(t&lt;=tp+2.5*T03) return Qp_unit*Math.pow(0.3,(t-tp+0.5*T03)/(1.5*T03));
return Qp_unit*Math.pow(0.3,(t-tp+1.5*T03)/(2*T03));
}
const dt=0.1, tMax=22;
const t_seq=[], u_seq=[];
for(let t=0;t&lt;=tMax;t+=dt){t_seq.push(+t.toFixed(1));u_seq.push(nakUnit(t));}
const COLORS=['#64748b','#2563eb','#0284c7','#d97706','#dc2626','#7c3aed'];
const LABELS=['T = 2 thn','T = 5 thn','T = 10 thn','T = 25 thn','T = 50 thn','T = 100 thn'];
/* ================================================================
DAS PARAMS CARD
================================================================ */
function buildDASParams(){
const el=document.getElementById('dasParams');
const params=[
{n:'Luas DAS (A)',v:'50',u:'km²',c:'var(--blue-mid)'},
{n:'Panjang Sungai (L)',v:'10',u:'km',c:'var(--purple)'},
{n:'Kemiringan DAS (S)',v:'0.010',u:'m/m',c:'var(--amber)'},
{n:'Koef. Limpasan (C)',v:'0.65',u:'-',c:'var(--green)'},
{n:'Waktu Konsentrasi',v:'1.35',u:'jam',c:'var(--red)'},
{n:'Parameter α',v:'2.0',u:'-',c:'var(--navy)'},
];
el.innerHTML=params.map(p=>`
&lt;div class="das-param" style="border-top-color:${p.c};">
&lt;div class="das-param-name">${p.n}&lt;/div>
&lt;div class="das-param-val">${p.v} &lt;span class="das-param-unit">${p.u}&lt;/span>&lt;/div>
&lt;/div>`).join('');
}
/* ================================================================
REFF TABLE
================================================================ */
function buildReffTable(){
const tb=document.getElementById('tblReff');
let html=`&lt;thead>&lt;tr>&lt;th>Kala Ulang T&lt;/th>&lt;th class="th-blue">R_T (mm)&lt;/th>
&lt;th class="th-amber">R_eff = C×R_T (mm)&lt;/th>
&lt;th class="th-purple">Q_p Nakayasu (m³/s)&lt;/th>
&lt;th class="th-blue">Proporsi Runoff&lt;/th>&lt;/tr>&lt;/thead>&lt;tbody>`;
T_arr.forEach((T,i)=>{
const hi=i>=3;
html+=`&lt;tr ${hi?'class="highlight"':''}>
&lt;td style="${hi?'color:var(--amber);font-weight:700;':''}">T = ${T} tahun&lt;/td>
&lt;td>${RT[i].toFixed(1)}&lt;/td>
&lt;td style="color:var(--amber);font-weight:600;">${R_eff[i].toFixed(1)}&lt;/td>
&lt;td style="color:var(--purple);font-weight:700;">${Qpeak_N[i].toFixed(0)}&lt;/td>
&lt;td>${(C*100).toFixed(0)}%&lt;/td>
&lt;/tr>`;
});
tb.innerHTML=html+'&lt;/tbody>';
}
/* ================================================================
PEAK DEBIT CARDS
================================================================ */
function buildPeakCards(){
const el=document.getElementById('peakCards');
const cls=['blue','blue','blue','amber','red','purple'];
el.innerHTML=T_arr.map((T,i)=>`
&lt;div class="metric-card ${cls[i]}">
&lt;div class="metric-label">T = ${T} tahun&lt;/div>
&lt;div class="metric-val">${Qpeak_N[i].toFixed(0)}&lt;/div>
&lt;div class="metric-unit">m³/s (Nakayasu)&lt;/div>
&lt;/div>`).join('');
}
/* ================================================================
DEBIT TABLE
================================================================ */
function buildDebitTable(){
const tb=document.getElementById('tblDebit');
let html=`&lt;thead>&lt;tr>
&lt;th>Kala Ulang T&lt;/th>
&lt;th class="th-blue">R_T (mm)&lt;/th>
&lt;th class="th-green">R_eff (mm)&lt;/th>
&lt;th class="th-blue">Q Rasional (m³/s)&lt;/th>
&lt;th class="th-purple">Q Nakayasu (m³/s)&lt;/th>
&lt;th class="th-amber">Selisih (%)&lt;/th>
&lt;th>Keterangan&lt;/th>
&lt;/tr>&lt;/thead>&lt;tbody>`;
const uses=['Drainase minor','Drainase sekunder','Drainase utama','Sungai / jembatan','Tanggul / bendung','Bendungan / vital'];
T_arr.forEach((T,i)=>{
const selisih=((Q_ras[i]-Qpeak_N[i])/Qpeak_N[i]*100);
const hi=i>=3;
html+=`&lt;tr ${hi?'class="highlight"':''}>
&lt;td style="${hi?'color:var(--amber);font-weight:700;':''}">T = ${T} thn&lt;/td>
&lt;td>${RT[i].toFixed(1)}&lt;/td>
&lt;td style="color:var(--green);">${R_eff[i].toFixed(1)}&lt;/td>
&lt;td style="color:var(--blue);font-weight:600;">${Q_ras[i].toFixed(0)}&lt;/td>
&lt;td style="color:var(--purple);font-weight:700;">${Qpeak_N[i].toFixed(0)}&lt;/td>
&lt;td style="color:${Math.abs(selisih)>15?'var(--red)':'var(--gray-600)'};">${selisih>0?'+':''}${selisih.toFixed(1)}%&lt;/td>
&lt;td class="td-label" style="font-family:inherit;font-size:11px;color:var(--gray-600);">${uses[i]}&lt;/td>
&lt;/tr>`;
});
tb.innerHTML=html+'&lt;/tbody>';
}
/* ================================================================
RATIONAL CALCULATOR
================================================================ */
function updateRasional(){
const c_val = parseFloat(document.getElementById('slC').value);
const a_val = parseFloat(document.getElementById('slA').value);
const t_val = parseFloat(document.getElementById('selT').value);
const tc_v = parseFloat(document.getElementById('slTc').value);
document.getElementById('dispC').textContent = c_val.toFixed(2);
document.getElementById('dispA').textContent = a_val.toFixed(0);
document.getElementById('dispTc').textContent = tc_v.toFixed(2);
// Find RT for selected T
const idx = T_arr.indexOf(parseInt(t_val));
const rt_v = RT[idx] || 133.4;
const i_v = mononobe(rt_v, tc_v);
const q_v = 0.278*c_val*i_v*a_val;
document.getElementById('dispI').textContent = i_v.toFixed(1)+' mm/jam (R₂₄='+rt_v+' mm, t='+tc_v.toFixed(2)+' jam)';
document.getElementById('resultQ').textContent = q_v.toFixed(0);
// Compare text
const pools = q_v/0.001; // liters
document.getElementById('resultCompare').textContent = `≈ ${(q_v/1000).toFixed(2)} m³/ms | ${Math.round(q_v*3600/50000)} mm/jam rata DAS`;
document.getElementById('warningA').style.display = a_val>50?'flex':'none';
}
function setC(v){ if(v){ document.getElementById('slC').value=v; updateRasional(); } }
/* ================================================================
CHARTS
================================================================ */
const CH={};
function buildCharts(){
if(CH._built) return; CH._built=true;
/* Rasional Bar */
const ctx1=document.getElementById('chartRasional');
if(ctx1) CH.ras=new Chart(ctx1,{
type:'bar',
data:{
labels:T_arr.map(t=>'T='+t+' thn'),
datasets:[{
label:'Debit Puncak (m³/s)',
data:Q_ras.map(q=>+q.toFixed(1)),
backgroundColor:COLORS,
borderRadius:5,
}]
},
options:{responsive:true,maintainAspectRatio:false,
plugins:{
legend:{display:false},
tooltip:{callbacks:{label:c=>'Q = '+c.raw.toFixed(1)+' m³/s'}}
},
scales:{
x:{grid:{display:false},ticks:{font:{size:11}}},
y:{title:{display:true,text:'Debit (m³/s)'},ticks:{font:{size:11}},grid:{color:'rgba(0,0,0,0.05)'}}
}
}
});
/* Hydrograph */
const ctx2=document.getElementById('chartHydro');
if(ctx2){
const datasets=T_arr.map((T,i)=>({
label:LABELS[i],
data:u_seq.map(u=>+(u*R_eff[i]).toFixed(2)),
borderColor:COLORS[i],
backgroundColor:'transparent',
borderWidth:i>=3?2.2:1.5,
pointRadius:0,
tension:0.3,
hidden:i&lt;2 // default show T10+
}));
CH.hydro=new Chart(ctx2,{
type:'line',
data:{labels:t_seq,datasets},
options:{responsive:true,maintainAspectRatio:false,
interaction:{mode:'index',intersect:false},
plugins:{
legend:{display:false},
tooltip:{callbacks:{
title:items=>'t = '+items[0].label+' jam',
label:c=>c.dataset.label+': '+c.raw.toFixed(1)+' m³/s'
}}
},
scales:{
x:{title:{display:true,text:'Waktu (jam)'},ticks:{maxTicksLimit:12,font:{size:11}},grid:{color:'rgba(0,0,0,0.04)'}},
y:{title:{display:true,text:'Debit Q (m³/s)'},min:0,ticks:{font:{size:11}},grid:{color:'rgba(0,0,0,0.05)'}}
}
}
});
// Build toggle buttons
const btns=document.getElementById('hydroBtns');
btns.innerHTML=T_arr.map((T,i)=>`
&lt;button class="hydro-btn ${!CH.hydro.data.datasets[i].hidden?'active':''}"
style="color:${COLORS[i]};border-color:${COLORS[i]};${!CH.hydro.data.datasets[i].hidden?'background:'+COLORS[i]+';color:#fff;':''}"
onclick="toggleHydro(${i},this,'${COLORS[i]}')">T = ${T}&lt;/button>`).join('');
}
/* Compare */
const ctx3=document.getElementById('chartCompare');
if(ctx3) CH.cmp=new Chart(ctx3,{
type:'bar',
data:{
labels:T_arr.map(t=>'T = '+t+' thn'),
datasets:[
{label:'Metode Rasional',data:Q_ras.map(q=>+q.toFixed(0)),backgroundColor:'rgba(24,95,165,0.75)',borderRadius:4},
{label:'HSS Nakayasu',data:Qpeak_N.map(q=>+q.toFixed(0)),backgroundColor:'rgba(109,40,217,0.75)',borderRadius:4},
]
},
options:{responsive:true,maintainAspectRatio:false,
plugins:{
legend:{position:'bottom',labels:{font:{size:11},usePointStyle:true}},
tooltip:{callbacks:{label:c=>c.dataset.label+': '+c.raw+' m³/s'}}
},
scales:{
x:{grid:{display:false},ticks:{font:{size:11}}},
y:{title:{display:true,text:'Debit Puncak (m³/s)'},ticks:{font:{size:11}},grid:{color:'rgba(0,0,0,0.05)'}}
}
}
});
}
function toggleHydro(i,btn,color){
const ds=CH.hydro.data.datasets[i];
ds.hidden=!ds.hidden;
if(ds.hidden){btn.style.background='#fff';btn.style.color=color;}
else{btn.style.background=color;btn.style.color='#fff';}
CH.hydro.update();
}
/* ================================================================
TOC, SCROLL
================================================================ */
function updateProgress(){
const el=document.getElementById('progBar'),pct=document.getElementById('progPct');
const s=window.scrollY,total=document.body.scrollHeight-window.innerHeight;
const p=total>0?Math.round(s/total*100):0;
el.style.width=p+'%';pct.textContent=p+'%';
}
window.addEventListener('scroll',updateProgress,{passive:true});
const tocLinks=document.querySelectorAll('.toc-link');
const sections=Array.from(document.querySelectorAll('section[id],div[id]'));
function updateToc(){
let cur='';
sections.forEach(s=>{if(window.scrollY>=s.offsetTop-100)cur=s.id;});
tocLinks.forEach(l=>{const h=l.getAttribute('href').replace('#','');l.classList.toggle('active',h===cur);});
}
window.addEventListener('scroll',updateToc,{passive:true});
function toggleToc(){document.getElementById('tocFloat').classList.toggle('collapsed');}
let tocV=false;
function toggleTocMobile(){
tocV=!tocV;const tf=document.getElementById('tocFloat');
tf.style.display=tocV?'block':'';
if(tocV){tf.style.position='fixed';tf.style.right='0';tf.style.top='80px';}
}
function copyCode(btn){
const t=btn.closest('.code-wrap').querySelector('pre').innerText;
navigator.clipboard.writeText(t).then(()=>{btn.textContent='✓ Tersalin!';setTimeout(()=>btn.textContent='Salin',2000);});
}
const io=new IntersectionObserver(entries=>{
entries.forEach(e=>{if(e.isIntersecting){e.target.classList.add('visible');buildCharts();}});
},{threshold:0.01,rootMargin:'0px 0px -10px 0px'});
document.querySelectorAll('.anim-in').forEach(el=>io.observe(el));
/* INIT */
buildDASParams();
buildReffTable();
buildPeakCards();
buildDebitTable();
updateRasional();
updateProgress();
setTimeout(buildCharts,400);
&lt;/script></description></item><item><title>Analisa Frekuensi Curah Hujan</title><link>https://www.irpanchumaedi.com/post/materi-analisa-frekuensi-hujan/</link><pubDate>Fri, 02 Feb 2024 00:00:00 +0000</pubDate><guid>https://www.irpanchumaedi.com/post/materi-analisa-frekuensi-hujan/</guid><description>
&lt;style>
.materi-frekuensi {
--navy:#0A2342; --blue:#185fa5; --blue-mid:#378add; --blue-light:#85b7eb; --blue-pale:#e6f1fb;
--red:#B91C1C; --red-light:#fee2e2; --navy2:#1A5276;
--amber:#B45309; --amber-light:#fef3c7;
--purple:#6D28D9; --purple-light:#ede9fe;
--green:#1d6f42; --green-light:#d1fae5;
--gray-100:#f8fafc; --gray-200:#e2e8f0; --gray-300:#cbd5e1;
--gray-500:#64748b; --gray-600:#475569; --gray-700:#334155; --gray-900:#0f172a;
--radius:10px; --radius-sm:6px;
--shadow:0 2px 12px rgba(0,0,0,0.07);
--shadow-md:0 4px 20px rgba(0,0,0,0.10);
--code-bg:#1e1e2e;
}
.materi-frekuensi, .materi-frekuensi *::before, .materi-frekuensi *::after {box-sizing:border-box;margin:0;padding:0;}
/.materi-frekuensi * STICKY NAV */
.sticky-nav {position:sticky;top:0;z-index:200;background:#fff;border-bottom:1px solid var(--gray-200);box-shadow:var(--shadow);}
.materi-frekuensi .sticky-inner {max-width:960px;margin:0 auto;padding:0 1.25rem;display:flex;align-items:center;gap:1rem;height:52px;}
.materi-frekuensi .sticky-title {font-size:13px;font-weight:600;color:var(--navy);white-space:nowrap;}
.materi-frekuensi .progress-track {flex:1;height:4px;background:var(--gray-200);border-radius:2px;}
.materi-frekuensi .progress-fill {height:100%;background:linear-gradient(90deg,var(--blue),var(--purple));border-radius:2px;width:0%;transition:width 0.3s;}
.materi-frekuensi .sticky-pct {font-size:12px;color:var(--gray-500);min-width:32px;}
/.materi-frekuensi * FLOATING TOC */
.toc-float {position:fixed;top:80px;right:0;width:195px;background:#fff;border:1px solid var(--gray-200);border-right:none;border-radius:var(--radius) 0 0 var(--radius);box-shadow:-2px 4px 16px rgba(0,0,0,0.09);z-index:150;transition:all 0.28s cubic-bezier(0.4,0,0.2,1);overflow:hidden;}
.materi-frekuensi .toc-float.collapsed {width:32px;}
.materi-frekuensi .toc-head {display:flex;align-items:center;justify-content:space-between;padding:8px 10px 8px 12px;border-bottom:1px solid var(--gray-200);cursor:pointer;user-select:none;background:var(--navy);border-radius:var(--radius) 0 0 0;}
.materi-frekuensi .toc-head:hover {background:#1a3a5c;}
.materi-frekuensi .toc-title {font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:0.07em;color:rgba(255,255,255,0.9);white-space:nowrap;overflow:hidden;}
.materi-frekuensi .toc-chevron {font-size:11px;color:rgba(255,255,255,0.7);flex-shrink:0;transition:transform 0.25s;margin-left:6px;}
.materi-frekuensi .toc-float.collapsed .toc-chevron {transform:rotate(180deg);}
.materi-frekuensi .toc-float.collapsed .toc-title {opacity:0;width:0;margin:0;}
.materi-frekuensi .toc-body {padding:8px 6px;max-height:calc(100vh - 140px);overflow-y:auto;scrollbar-width:thin;scrollbar-color:var(--gray-300) transparent;}
.materi-frekuensi .toc-body::-webkit-scrollbar {width:3px;}
.materi-frekuensi .toc-body::-webkit-scrollbar-thumb {background:var(--gray-300);border-radius:2px;}
.materi-frekuensi .toc-float.collapsed .toc-body {display:none;}
.materi-frekuensi .toc-link {display:block;font-size:11px;color:var(--gray-600);text-decoration:none;padding:3px 8px;border-radius:4px;border-left:2px solid transparent;margin-bottom:1px;transition:all 0.15s;line-height:1.4;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
.materi-frekuensi .toc-link:hover {background:var(--blue-pale);color:var(--blue);border-left-color:var(--blue);}
.materi-frekuensi .toc-link.active {background:var(--blue-pale);color:var(--blue);border-left-color:var(--blue);font-weight:600;}
.materi-frekuensi .toc-link.sub {padding-left:14px;font-size:10px;color:var(--gray-500);}
.materi-frekuensi .toc-link.sub.active {color:var(--blue);}
.materi-frekuensi .toc-toggle {display:none;position:fixed;bottom:20px;right:16px;width:40px;height:40px;border-radius:50%;background:var(--navy);color:#fff;border:none;font-size:16px;cursor:pointer;box-shadow:var(--shadow-md);z-index:160;align-items:center;justify-content:center;}
@.materi-frekuensi media(max-width:1100px) {.toc-float{display:none;}.materi-frekuensi .toc-toggle {display:flex;}.materi-frekuensi }
/* HERO */
.hero {background:linear-gradient(135deg,#0A2342 0%,#1A3a5c 55%,#2d1065 100%);color:#fff;padding:3rem 1.5rem 2.5rem;border-radius:0 0 var(--radius) var(--radius);margin-bottom:2rem;position:relative;overflow:hidden;}
.materi-frekuensi .hero::before {content:'';position:absolute;top:-80px;right:-60px;width:300px;height:300px;border-radius:50%;background:rgba(55,138,221,0.12);}
.materi-frekuensi .hero::after {content:'';position:absolute;bottom:-100px;left:10%;width:250px;height:250px;border-radius:50%;background:rgba(109,40,217,0.10);}
.materi-frekuensi .hero-inner {max-width:960px;margin:0 auto;position:relative;z-index:1;}
.materi-frekuensi .hero-badge {display:inline-block;background:rgba(55,138,221,0.25);color:#85b7eb;font-size:11px;padding:3px 10px;border-radius:20px;margin-bottom:0.75rem;letter-spacing:0.04em;}
.materi-frekuensi .hero h1 {font-size:clamp(22px,4vw,30px);font-weight:700;line-height:1.3;margin-bottom:0.5rem;}
.materi-frekuensi .hero-sub {font-size:14px;color:rgba(255,255,255,0.65);margin-bottom:1.5rem;}
.materi-frekuensi .hero-pills {display:flex;flex-wrap:wrap;gap:8px;margin-top:1rem;}
.materi-frekuensi .hero-pill {display:inline-block;font-size:11px;padding:4px 10px;border-radius:20px;font-weight:600;border:1px solid;}
.materi-frekuensi .pill-red {background:rgba(185,28,28,0.25);color:#fca5a5;border-color:rgba(185,28,28,0.4);}
.materi-frekuensi .pill-blue {background:rgba(26,82,118,0.3);color:#85b7eb;border-color:rgba(26,82,118,0.5);}
.materi-frekuensi .pill-amber {background:rgba(180,83,9,0.25);color:#fcd34d;border-color:rgba(180,83,9,0.4);}
.materi-frekuensi .pill-purple {background:rgba(109,40,217,0.25);color:#c4b5fd;border-color:rgba(109,40,217,0.4);}
.materi-frekuensi .pill-green {background:rgba(29,111,66,0.25);color:#6ee7b7;border-color:rgba(29,111,66,0.4);}
.materi-frekuensi .hero-meta {display:flex;flex-wrap:wrap;gap:1.25rem;margin-top:1rem;}
.materi-frekuensi .hero-meta-item {font-size:12px;color:rgba(255,255,255,0.55);}
/.materi-frekuensi * LAYOUT */
.wrap {max-width:960px;margin:0 auto;padding:0 1.25rem 4rem;}
/.materi-frekuensi * SECTIONS */
.section {margin-bottom:3rem;}
.materi-frekuensi .section-header {display:flex;align-items:center;gap:12px;margin-bottom:1.25rem;}
.materi-frekuensi .section-num {width:32px;height:32px;border-radius:50%;background:var(--navy);color:#fff;font-size:13px;font-weight:600;display:flex;align-items:center;justify-content:center;flex-shrink:0;}
.materi-frekuensi .section-header h2 {font-size:20px;font-weight:700;color:var(--gray-900);}
.materi-frekuensi .subsection {margin:1.5rem 0 1rem;}
.materi-frekuensi .subsection h3 {font-size:15px;font-weight:700;color:var(--gray-700);padding-left:10px;border-left:3px solid var(--blue-mid);margin-bottom:0.75rem;}
/.materi-frekuensi * CARDS */
.card {background:#fff;border-radius:var(--radius);padding:1.25rem 1.5rem;box-shadow:var(--shadow);margin-bottom:1rem;}
.materi-frekuensi .card-navy {border-left:4px solid var(--navy);}
.materi-frekuensi .card-blue {border-left:4px solid var(--blue-mid);}
.materi-frekuensi .card-red {border-left:4px solid var(--red);}
.materi-frekuensi .card-amber {border-left:4px solid var(--amber);}
.materi-frekuensi .card-green {border-left:4px solid var(--green);}
.materi-frekuensi .card-purple {border-left:4px solid var(--purple);}
.materi-frekuensi .card-label {font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:0.07em;color:var(--gray-500);margin-bottom:6px;}
.materi-frekuensi .card p, .materi-frekuensi .card-body {font-size:13px;color:var(--gray-600);line-height:1.65;}
.materi-frekuensi .card strong {color:var(--gray-800);}
/.materi-frekuensi * GRID */
.grid-2 {display:grid;grid-template-columns:1fr 1fr;gap:1rem;margin-bottom:1rem;}
.materi-frekuensi .grid-3 {display:grid;grid-template-columns:1fr 1fr 1fr;gap:1rem;margin-bottom:1rem;}
.materi-frekuensi .grid-4 {display:grid;grid-template-columns:repeat(4,1fr);gap:1rem;margin-bottom:1.5rem;}
@.materi-frekuensi media(max-width:700px) {.grid-2,.grid-3,.grid-4{grid-template-columns:1fr;}.materi-frekuensi }
@media(max-width:900px) {.grid-3{grid-template-columns:1fr 1fr;}.materi-frekuensi }
/* METRIC CARDS */
.metric-card {background:#fff;border-radius:var(--radius);padding:1rem 1.1rem;box-shadow:var(--shadow);text-align:center;position:relative;overflow:hidden;}
.materi-frekuensi .metric-card::before {content:'';position:absolute;top:0;left:0;right:0;height:3px;}
.materi-frekuensi .metric-card.blue::before {background:var(--blue);}
.materi-frekuensi .metric-card.green::before {background:var(--green);}
.materi-frekuensi .metric-card.amber::before {background:var(--amber);}
.materi-frekuensi .metric-card.purple::before {background:var(--purple);}
.materi-frekuensi .metric-card.red::before {background:var(--red);}
.materi-frekuensi .metric-label {font-size:11px;color:var(--gray-500);font-weight:600;margin-bottom:4px;}
.materi-frekuensi .metric-val {font-size:18px;font-weight:700;color:var(--navy);}
.materi-frekuensi .metric-sub {font-size:11px;color:var(--gray-500);margin-top:3px;}
/.materi-frekuensi * INFO BOXES */
.info-box {display:flex;gap:10px;background:var(--blue-pale);border:1px solid #b5d4f4;border-radius:var(--radius-sm);padding:.9rem 1rem;font-size:13px;color:#0c447c;margin:1rem 0;line-height:1.55;}
.materi-frekuensi .warn-box {display:flex;gap:10px;background:var(--amber-light);border:1px solid #fac775;border-radius:var(--radius-sm);padding:.9rem 1rem;font-size:13px;color:var(--amber);margin:1rem 0;line-height:1.55;}
.materi-frekuensi .success-box {display:flex;gap:10px;background:var(--green-light);border:1px solid #a7f3d0;border-radius:var(--radius-sm);padding:.9rem 1rem;font-size:13px;color:var(--green);margin:1rem 0;line-height:1.55;}
.materi-frekuensi .purple-box {display:flex;gap:10px;background:var(--purple-light);border:1px solid #c4b5fd;border-radius:var(--radius-sm);padding:.9rem 1rem;font-size:13px;color:var(--purple);margin:1rem 0;line-height:1.55;}
.materi-frekuensi .box-icon {font-size:18px;flex-shrink:0;line-height:1.3;}
/.materi-frekuensi * FORMULA */
.formula-block {background:#0f172a;border-radius:var(--radius-sm);padding:1rem 1.25rem;margin:.75rem 0;font-family:'Consolas','Courier New',monospace;font-size:14px;color:#e2e8f0;letter-spacing:0.02em;border-left:4px solid var(--purple);}
.materi-frekuensi .formula-block .eq-label {font-size:11px;color:#94a3b8;display:block;margin-bottom:4px;}
.materi-frekuensi .formula-block .eq-main {color:#c4b5fd;font-size:15px;display:block;text-align:center;margin:6px 0;}
.materi-frekuensi .formula-block .eq-desc {font-size:11px;color:#64748b;display:block;margin-top:6px;}
/.materi-frekuensi * STEP FLOW */
.step-flow {margin:1rem 0;}
.materi-frekuensi .step-item {display:flex;gap:14px;}
.materi-frekuensi .step-line {display:flex;flex-direction:column;align-items:center;}
.materi-frekuensi .step-dot {width:30px;height:30px;border-radius:50%;background:var(--blue-mid);color:#fff;font-size:12px;font-weight:600;display:flex;align-items:center;justify-content:center;flex-shrink:0;}
.materi-frekuensi .step-dot.navy {background:var(--navy);}
.materi-frekuensi .step-dot.green {background:var(--green);}
.materi-frekuensi .step-dot.purple {background:var(--purple);}
.materi-frekuensi .step-dot.amber {background:var(--amber);}
.materi-frekuensi .step-connector {width:2px;background:var(--gray-200);flex:1;min-height:16px;margin:3px 0;}
.materi-frekuensi .step-body {padding-bottom:20px;flex:1;}
.materi-frekuensi .step-title {font-size:14px;font-weight:600;color:var(--gray-800);margin-bottom:4px;}
.materi-frekuensi .step-desc {font-size:13px;color:var(--gray-600);line-height:1.6;}
/.materi-frekuensi * CODE */
.code-wrap {background:var(--code-bg);border-radius:var(--radius-sm);overflow:hidden;margin:.75rem 0;box-shadow:var(--shadow-md);}
.materi-frekuensi .code-header {background:#2a2a3e;padding:7px 14px;display:flex;align-items:center;justify-content:space-between;}
.materi-frekuensi .code-lang {font-size:11px;color:#a0aec0;font-weight:600;letter-spacing:0.05em;display:flex;align-items:center;gap:6px;}
.materi-frekuensi .code-lang .dot {width:8px;height:8px;border-radius:50%;}
.materi-frekuensi .copy-btn {font-size:11px;color:#a0aec0;cursor:pointer;background:none;border:none;padding:2px 8px;border-radius:4px;transition:all 0.2s;}
.materi-frekuensi .copy-btn:hover {background:rgba(255,255,255,0.1);color:#fff;}
.materi-frekuensi pre {padding:1rem 1.25rem;overflow-x:auto;font-family:'Consolas','Courier New',monospace;font-size:12.5px;line-height:1.75;color:#cdd6f4;}
.materi-frekuensi pre::-webkit-scrollbar {height:4px;}
.materi-frekuensi pre::-webkit-scrollbar-thumb {background:#4a4a6a;border-radius:2px;}
.materi-frekuensi .kw {color:#cba6f7;}.materi-frekuensi .fn {color:#89b4fa;}.materi-frekuensi .str {color:#a6e3a1;}.materi-frekuensi .num {color:#fab387;}.materi-frekuensi .cm {color:#6c7086;font-style:italic;}.materi-frekuensi .op {color:#89dceb;}.materi-frekuensi .pkg {color:#f38ba8;}
/.materi-frekuensi * TABLE */
.tbl-wrap {overflow-x:auto;margin-bottom:1rem;}
.materi-frekuensi .data-tbl {width:100%;border-collapse:collapse;font-size:13px;min-width:380px;}
.materi-frekuensi .data-tbl th {background:var(--navy);color:#fff;padding:8px 12px;text-align:center;font-weight:600;font-size:12px;}
.materi-frekuensi .data-tbl td {padding:7px 12px;border-bottom:1px solid var(--gray-200);text-align:center;font-family:'Consolas',monospace;font-size:12px;color:var(--gray-700);}
.materi-frekuensi .data-tbl td.td-label {text-align:left;font-family:inherit;font-weight:600;color:var(--gray-700);}
.materi-frekuensi .data-tbl tr:hover td {background:var(--blue-pale);}
.materi-frekuensi .data-tbl .best {color:var(--green);font-weight:700;}
.materi-frekuensi .data-tbl .pass {color:var(--green);}
.materi-frekuensi .data-tbl .fail {color:var(--red);font-weight:700;}
.materi-frekuensi .data-tbl .highlight {background:rgba(26,82,118,0.06)!important;}
.materi-frekuensi .data-tbl .th-blue {background:var(--navy2)!important;}
.materi-frekuensi .data-tbl .th-red {background:var(--red)!important;}
.materi-frekuensi .data-tbl .th-green {background:var(--green)!important;}
.materi-frekuensi .data-tbl .th-purple {background:var(--purple)!important;}
.materi-frekuensi .data-tbl .th-amber {background:var(--amber)!important;}
/.materi-frekuensi * CHART */
.chart-card {background:#fff;border-radius:var(--radius);padding:1.25rem 1.5rem 1rem;box-shadow:var(--shadow);margin-bottom:1.25rem;}
.materi-frekuensi .chart-title {font-size:13px;font-weight:700;color:var(--gray-700);margin-bottom:2px;}
.materi-frekuensi .chart-sub {font-size:11px;color:var(--gray-500);margin-bottom:1rem;}
.materi-frekuensi .chart-wrap {position:relative;width:100%;}
.materi-frekuensi .legend-row {display:flex;flex-wrap:wrap;gap:12px;margin-top:10px;font-size:11px;color:var(--gray-500);}
.materi-frekuensi .legend-item {display:flex;align-items:center;gap:5px;}
.materi-frekuensi .legend-sq {width:10px;height:10px;border-radius:2px;flex-shrink:0;}
/.materi-frekuensi * TAG */
.tag {display:inline-block;font-size:11px;padding:3px 10px;border-radius:20px;margin:2px;font-weight:500;}
.materi-frekuensi .tag-blue {background:var(--blue-pale);color:#0c447c;}
.materi-frekuensi .tag-red {background:var(--red-light);color:var(--red);}
.materi-frekuensi .tag-purple {background:var(--purple-light);color:var(--purple);}
.materi-frekuensi .tag-green {background:var(--green-light);color:var(--green);}
.materi-frekuensi .tag-amber {background:var(--amber-light);color:var(--amber);}
/.materi-frekuensi * RETURN PERIOD VISUAL */
.rp-grid {display:grid;grid-template-columns:repeat(6,1fr);gap:6px;margin:1rem 0;}
.materi-frekuensi .rp-card {background:#fff;border-radius:8px;padding:0.8rem 0.5rem;box-shadow:var(--shadow);text-align:center;border-top:3px solid;}
.materi-frekuensi .rp-T {font-size:15px;font-weight:700;}
.materi-frekuensi .rp-prob {font-size:11px;color:var(--gray-500);margin:3px 0;}
.materi-frekuensi .rp-use {font-size:10px;color:var(--gray-500);line-height:1.4;}
@.materi-frekuensi media(max-width:700px) {.rp-grid{grid-template-columns:repeat(3,1fr);}.materi-frekuensi }
/* DIST GRID */
.dist-grid {display:grid;grid-template-columns:1fr 1fr;gap:1rem;margin:1rem 0;}
@.materi-frekuensi media(max-width:600px) {.dist-grid{grid-template-columns:1fr;}.materi-frekuensi }
/* FLOW DIAGRAM */
.flow-row {display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin:1rem 0;}
.materi-frekuensi .flow-box {padding:0.6rem 1rem;border-radius:8px;font-size:12px;font-weight:600;text-align:center;flex-shrink:0;}
.materi-frekuensi .flow-arrow {color:var(--gray-400);font-size:18px;flex-shrink:0;}
/.materi-frekuensi * DIVIDER */
.divider {height:1px;background:var(--gray-200);margin:2.5rem 0;}
/.materi-frekuensi * ANALOGY BOX */
.analogy-box {background:linear-gradient(135deg,#f0f7ff,#f8f0ff);border:1px solid #c4d9f7;border-radius:var(--radius);padding:1.1rem 1.3rem;margin:1rem 0;position:relative;}
.materi-frekuensi .analogy-badge {font-size:10px;font-weight:700;letter-spacing:0.07em;text-transform:uppercase;color:var(--blue);margin-bottom:6px;}
.materi-frekuensi .analogy-box p {font-size:13px;color:var(--gray-700);line-height:1.7;font-style:italic;}
/.materi-frekuensi * ANIMATE */
@keyframes fadeUp {from{opacity:0;transform:translateY(16px);}.materi-frekuensi to {opacity:1;transform:translateY(0);}.materi-frekuensi }
.anim-in {opacity:1;}
.materi-frekuensi .anim-in.visible {animation:fadeUp 0.45s ease both;}
/.materi-frekuensi * NEXT ARTICLES */
.nav-link {display:flex;align-items:center;gap:1rem;padding:0.9rem 1.2rem;background:#fff;border:1px solid var(--gray-200);border-radius:10px;text-decoration:none;transition:all 0.2s;margin-bottom:0.5rem;box-shadow:var(--shadow);}
.materi-frekuensi .nav-link:hover {border-color:var(--blue-mid);box-shadow:var(--shadow-md);}
.materi-frekuensi .nav-link-label {font-size:10px;font-weight:700;letter-spacing:0.09em;text-transform:uppercase;color:var(--gray-500);margin-bottom:3px;}
.materi-frekuensi .nav-link-title {font-size:14px;font-weight:700;color:var(--navy);}
.materi-frekuensi .nav-link-dim {opacity:0.5;cursor:default;}
.materi-frekuensi .nav-link-dim:hover {border-color:var(--gray-200);box-shadow:var(--shadow);}
/* === LAYOUT FIX: integrasi Wowchemy === */
.materi-frekuensi { box-sizing: border-box; width: 100%; overflow-x: hidden; }
.materi-frekuensi * { box-sizing: border-box; }
.materi-frekuensi .wrap, .materi-frekuensi .section { max-width: 100%; }
/* === DARK MODE === */
body.dark .materi-frekuensi { color:#8e94b5; }
/* Heading &amp; teks utama */
body.dark .materi-frekuensi h1,
body.dark .materi-frekuensi h2,
body.dark .materi-frekuensi h3,
body.dark .materi-frekuensi h4 { color:#e8eaf6 !important; }
body.dark .materi-frekuensi p { color:#8e94b5; }
body.dark .materi-frekuensi strong { color:#e8eaf6; }
body.dark .materi-frekuensi li { color:#8e94b5; }
/* Section header */
body.dark .materi-frekuensi .section-header { border-color:#343858; }
body.dark .materi-frekuensi .section-header h2 { color:#e8eaf6 !important; }
body.dark .materi-frekuensi .section-num {
background:#1e3a6e !important;
color:#5b8fff !important;
border-color:#2a4a8e !important;
}
body.dark .materi-frekuensi .subsection h3 { color:#c8ccdf !important; }
/* Cards — background &amp; border */
body.dark .materi-frekuensi [class*="card"],
body.dark .materi-frekuensi .card,
body.dark .materi-frekuensi .metric-card {
background:#222638 !important;
border-color:#343858 !important;
box-shadow: 0 2px 12px rgba(0,0,0,0.3) !important;
}
/* Card teks — SEMUA varian label &amp; nilai */
body.dark .materi-frekuensi .card-label,
body.dark .materi-frekuensi .metric-label,
body.dark .materi-frekuensi .metric-sub {
color:#8e94b5 !important;
}
body.dark .materi-frekuensi .card p,
body.dark .materi-frekuensi .card-body {
color:#8e94b5 !important;
}
body.dark .materi-frekuensi .metric-val {
/* warna nilai (biru/amber/dll) tetap — biarkan dari CSS asli */
filter: brightness(1.2);
}
/* Teks dengan var gray-* — override via CSS variable remapping */
body.dark .materi-frekuensi {
--gray-100:#1b1d27;
--gray-200:#222638;
--gray-300:#2a2e42;
--gray-500:#8e94b5;
--gray-600:#a0a8cc;
--gray-700:#c8ccdf;
--gray-900:#e8eaf6;
--navy:#e8eaf6;
--navy2:#c8ccdf;
--blue:#5b8fff;
--blue-mid:#7aa5ff;
--blue-pale:#1e2a42;
--red:#e05a5a;
--red-light:#2d1515;
--amber:#f4a642;
--amber-light:#2d2010;
--purple:#9d7cf8;
--purple-light:#1e1530;
--green:#3ecf8e;
--green-light:#0d2418;
--shadow: 0 2px 12px rgba(0,0,0,0.35);
--shadow-md: 0 4px 20px rgba(0,0,0,0.45);
--code-bg:#12151f;
}
/* Table */
body.dark .materi-frekuensi table { border-color:#343858; }
body.dark .materi-frekuensi th {
background:#2a2e42 !important;
color:#8e94b5 !important;
border-color:#343858 !important;
}
body.dark .materi-frekuensi td {
border-color:#343858 !important;
color:#8e94b5 !important;
}
body.dark .materi-frekuensi tr:nth-child(even) { background:#1e2235 !important; }
body.dark .materi-frekuensi tr:hover td { background:#252840 !important; }
/* Code */
body.dark .materi-frekuensi code,
body.dark .materi-frekuensi pre {
background:#12151f !important;
color:#a8b4ff !important;
}
/* Form inputs */
body.dark .materi-frekuensi select,
body.dark .materi-frekuensi input[type=number],
body.dark .materi-frekuensi input[type=text] {
background:#2a2e42 !important;
border-color:#343858 !important;
color:#e8eaf6 !important;
}
/* Result/output boxes */
body.dark .materi-frekuensi [class*="result"],
body.dark .materi-frekuensi [id*="result"],
body.dark .materi-frekuensi [class*="output"],
body.dark .materi-frekuensi [id*="output"] {
background:#222638 !important;
border-color:#343858 !important;
color:#8e94b5 !important;
}
/* Grid boxes */
body.dark .materi-frekuensi .grid-2>*,
body.dark .materi-frekuensi .grid-3>*,
body.dark .materi-frekuensi .grid-4>* {
background:#222638 !important;
border-color:#343858 !important;
}
/* Info/alert boxes */
body.dark .materi-frekuensi [class*="info-"],
body.dark .materi-frekuensi [class*="alert-"],
body.dark .materi-frekuensi [class*="note-"] {
background:#1e2235 !important;
border-color:#343858 !important;
color:#8e94b5 !important;
}
/* Links */
body.dark .materi-frekuensi a { color:#5b8fff; }
body.dark .materi-frekuensi hr { border-color:#343858; }
/* Fix teks inline style hardcoded */
body.dark .materi-frekuensi [style*="color:#0f172a"],
body.dark .materi-frekuensi [style*="color:#1e293b"],
body.dark .materi-frekuensi [style*="color:#334155"],
body.dark .materi-frekuensi [style*="color:#475569"] {
color:#e8eaf6 !important;
}
body.dark .materi-frekuensi [style*="background:#fff"],
body.dark .materi-frekuensi [style*="background:#f4f6f9"],
body.dark .materi-frekuensi [style*="background:#f8fafc"],
body.dark .materi-frekuensi [style*="background:#f1f5f9"] {
background:#222638 !important;
}
&lt;/style>
&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.4.1/chart.umd.js">&lt;/script>
&lt;div class="materi-frekuensi">
&lt;!-- ===== S1: LATAR BELAKANG ===== -->
&lt;section class="section anim-in" id="s1">
&lt;div class="section-header">&lt;div class="section-num">1&lt;/div>&lt;h2>Latar Belakang — Mengapa Perlu?&lt;/h2>&lt;/div>
&lt;div class="card card-navy">
&lt;div class="card-label">Skenario Nyata&lt;/div>
&lt;p>Tahun 2019, sebuah jembatan baru dibangun di atas sungai. Desainnya menggunakan data hujan 5 tahun terakhir — terasa cukup. Tiga tahun kemudian, banjir merusak fondasinya. Bukan karena cuaca ekstrem yang luar biasa, tapi karena pertanyaan yang salah diajukan sejak awal.&lt;/p>
&lt;p style="margin-top:8px;">Bukan &lt;em>"Berapa besar banjir tahun lalu?"&lt;/em> — melainkan &lt;strong>"Berapa besar banjir yang mungkin terjadi dalam 50 tahun ke depan?"&lt;/strong>&lt;/p>
&lt;/div>
&lt;div class="grid-2">
&lt;div class="card card-red">
&lt;div class="card-label">❌ Tanpa Analisa Frekuensi&lt;/div>
&lt;p>Desain drainase berdasarkan banjir yang pernah dilihat. Tiga tahun kemudian meluap saat hujan yang terasa "biasa saja" — karena hujan itu nyatanya adalah kejadian 25 tahunan yang belum pernah terjadi selama pengamatan singkat itu.&lt;/p>
&lt;/div>
&lt;div class="card card-green">
&lt;div class="card-label">✅ Dengan Analisa Frekuensi&lt;/div>
&lt;p>Desain berdasarkan curah hujan kala ulang 25 tahun dari &lt;strong>30 tahun data historis&lt;/strong>. Saluran tetap berfungsi normal bahkan saat hujan besar yang "25 tahunan" itu akhirnya datang — karena kita sudah memperhitungkannya.&lt;/p>
&lt;/div>
&lt;/div>
&lt;div class="analogy-box">
&lt;div class="analogy-badge">💡 Analogi Sederhana&lt;/div>
&lt;p>Bayangkan kamu mau membeli jas hujan. Kalau kamu tinggal di kota yang hujan 10 hari setahun, payung biasa sudah cukup. Tapi kalau tinggal di Banjarmasin yang bisa hujan deras terus-terusan, kamu butuh jas hujan tebal dan sepatu boots. Analisa frekuensi adalah cara kita "membaca cuaca jangka panjang" supaya bisa memilih perlengkapan yang tepat untuk setiap jenis infrastruktur.&lt;/p>
&lt;/div>
&lt;p style="font-size:13px;color:var(--gray-600);line-height:1.7;margin-top:1rem;">Setiap infrastruktur yang berhubungan dengan air — jembatan, bendung, saluran drainase, tanggul, gorong-gorong — dirancang untuk menghadapi hujan atau banjir dengan &lt;strong>tingkat bahaya tertentu yang ditetapkan secara ilmiah&lt;/strong>, bukan berdasarkan ingatan atau pengalaman singkat.&lt;/p>
&lt;div class="success-box">&lt;span class="box-icon">🎯&lt;/span>&lt;span>Analisa frekuensi curah hujan adalah proses &lt;strong>menemukan hubungan antara besarnya hujan dan seberapa sering hujan itu terjadi&lt;/strong>, berdasarkan data historis jangka panjang. Output-nya digunakan sebagai angka desain di hampir seluruh perencanaan infrastruktur air.&lt;/span>&lt;/div>
&lt;/section>
&lt;div class="divider">&lt;/div>
&lt;!-- ===== S2: KONSEP KALA ULANG ===== -->
&lt;section class="section anim-in" id="s2">
&lt;div class="section-header">&lt;div class="section-num">2&lt;/div>&lt;h2>Konsep Dasar: Kala Ulang &amp; Probabilitas&lt;/h2>&lt;/div>
&lt;div id="s2a">&lt;/div>
&lt;div class="subsection">&lt;h3>Apa Itu Kala Ulang?&lt;/h3>&lt;/div>
&lt;div class="card card-blue">
&lt;div class="card-label">📖 Definisi&lt;/div>
&lt;p>&lt;strong>Kala ulang&lt;/strong> (bahasa Inggris: &lt;em>return period&lt;/em>, simbol &lt;strong>T&lt;/strong>) adalah rata-rata selang waktu antara dua kejadian hujan yang besarnya &lt;em>sama atau lebih besar&lt;/em> dari nilai tertentu. Kala ulang T tahun artinya rata-rata, hujan sebesar itu terjadi &lt;strong>sekali setiap T tahun&lt;/strong>.&lt;/p>
&lt;p style="margin-top:8px;color:#555;font-style:italic;font-size:12px;">Ini bukan berarti hujan itu pasti terjadi persis setiap T tahun — ini adalah rata-rata statistik jangka panjang.&lt;/p>
&lt;/div>
&lt;div class="analogy-box">
&lt;div class="analogy-badge">💡 Analogi Dadu&lt;/div>
&lt;p>"Hujan 25 tahunan terjadi tahun ini — berarti 24 tahun lagi aman dong?" — SALAH. Setiap tahun, hujan 25 tahunan punya probabilitas 4%, tidak peduli apa yang terjadi tahun lalu. Sama seperti dadu: meski sudah 5 kali tidak keluar angka 6, peluang keluar angka 6 tetap 1/6 di lemparan berikutnya. Setiap tahun adalah "lemparan baru".&lt;/p>
&lt;/div>
&lt;div class="formula-block">
&lt;span class="eq-label">Hubungan Kala Ulang dengan Probabilitas Tahunan&lt;/span>
&lt;span class="eq-main">P = 1 / T&lt;/span>
&lt;span class="eq-desc">P = probabilitas kejadian dalam satu tahun (0–1) | T = kala ulang (tahun)
Contoh: T = 25 tahun → P = 1/25 = 0.04 = 4% per tahun&lt;/span>
&lt;/div>
&lt;div id="s2b">&lt;/div>
&lt;div class="subsection">&lt;h3>Kala Ulang yang Umum Digunakan di Indonesia&lt;/h3>&lt;/div>
&lt;div class="rp-grid">
&lt;div class="rp-card" style="border-color:#64748b;">
&lt;div class="rp-T" style="color:#475569;">T = 2&lt;/div>
&lt;div class="rp-prob">P = 50%/thn&lt;/div>
&lt;div class="rp-use">Gorong-gorong sederhana, drainase lahan pertanian&lt;/div>
&lt;/div>
&lt;div class="rp-card" style="border-color:#2563eb;">
&lt;div class="rp-T" style="color:#2563eb;">T = 5&lt;/div>
&lt;div class="rp-prob">P = 20%/thn&lt;/div>
&lt;div class="rp-use">Saluran drainase perkotaan kecil, perumahan&lt;/div>
&lt;/div>
&lt;div class="rp-card" style="border-color:#0284c7;">
&lt;div class="rp-T" style="color:#0284c7;">T = 10&lt;/div>
&lt;div class="rp-prob">P = 10%/thn&lt;/div>
&lt;div class="rp-use">Saluran drainase utama kota, jalan raya&lt;/div>
&lt;/div>
&lt;div class="rp-card" style="border-color:#d97706;">
&lt;div class="rp-T" style="color:#d97706;">T = 25&lt;/div>
&lt;div class="rp-prob">P = 4%/thn&lt;/div>
&lt;div class="rp-use">Sungai perkotaan, jembatan, irigasi utama&lt;/div>
&lt;/div>
&lt;div class="rp-card" style="border-color:#dc2626;">
&lt;div class="rp-T" style="color:#dc2626;">T = 50&lt;/div>
&lt;div class="rp-prob">P = 2%/thn&lt;/div>
&lt;div class="rp-use">Tanggul banjir, bendung, pelabuhan&lt;/div>
&lt;/div>
&lt;div class="rp-card" style="border-color:#7c3aed;">
&lt;div class="rp-T" style="color:#7c3aed;">T = 100&lt;/div>
&lt;div class="rp-prob">P = 1%/thn&lt;/div>
&lt;div class="rp-use">Bendungan besar, infrastruktur vital kritis&lt;/div>
&lt;/div>
&lt;/div>
&lt;div class="warn-box">&lt;span class="box-icon">⚠️&lt;/span>&lt;span>Semakin panjang kala ulang, semakin besar dan semakin jarang hujannya — dan semakin mahal infrastruktur yang dibutuhkan. Pemilihan kala ulang adalah keputusan &lt;strong>teknis sekaligus ekonomis&lt;/strong>: seberapa besar risiko yang masih dapat diterima?&lt;/span>&lt;/div>
&lt;/section>
&lt;div class="divider">&lt;/div>
&lt;!-- ===== S3: DATA ===== -->
&lt;section class="section anim-in" id="s3">
&lt;div class="section-header">&lt;div class="section-num">3&lt;/div>&lt;h2>Data yang Dibutuhkan&lt;/h2>&lt;/div>
&lt;div id="s3a">&lt;/div>
&lt;div class="subsection">&lt;h3>Annual Maximum Series (AMS)&lt;/h3>&lt;/div>
&lt;p style="font-size:13px;color:var(--gray-600);line-height:1.7;margin-bottom:1rem;">Dari sekian banyak data hujan harian, yang kita gunakan adalah &lt;strong>satu nilai maksimum per tahun&lt;/strong> — metode ini disebut &lt;em>Annual Maximum Series (AMS)&lt;/em>. Mengapa hanya nilai maksimum? Karena kita hanya tertarik memodelkan &lt;em>kejadian ekstrem&lt;/em> — kandidat banjir tahunan.&lt;/p>
&lt;div class="grid-2">
&lt;div class="card card-amber">
&lt;div class="card-label">🗂️ Sumber Data&lt;/div>
&lt;p>&lt;strong>Data BMKG:&lt;/strong> Stasiun terdekat, rekam harian manual atau otomatis (ARR/AWLR).&lt;br>&lt;br>&lt;strong>Data GPM IMERG V07:&lt;/strong> Alternatif bila data BMKG tidak cukup panjang. Perlu dikalibrasi terlebih dahulu — lihat artikel Kalibrasi GPM.&lt;/p>
&lt;/div>
&lt;div class="card card-blue">
&lt;div class="card-label">📏 Panjang Data Minimum&lt;/div>
&lt;p>
&lt;span class="tag tag-red">⚠️ &amp;lt; 15 tahun&lt;/span> — tidak representatif, hasil tidak stabil&lt;br>&lt;br>
&lt;span class="tag tag-amber">⚠️ 15–20 tahun&lt;/span> — bisa dipakai, hasil perlu dicatat ketidakpastiannya&lt;br>&lt;br>
&lt;span class="tag tag-green">✅ 20–30 tahun&lt;/span> — standar minimum analisis teknis Indonesia&lt;br>&lt;br>
&lt;span class="tag tag-blue">🏆 &amp;gt; 30 tahun&lt;/span> — ideal, estimasi kala ulang panjang lebih andal
&lt;/p>
&lt;/div>
&lt;/div>
&lt;div class="card-label" style="font-size:11px;margin-bottom:8px;">📊 Contoh Data Annual Maximum Series — 25 Tahun (2000–2024)&lt;/div>
&lt;div class="tbl-wrap">
&lt;table class="data-tbl" id="tblAMS">&lt;/table>
&lt;/div>
&lt;div id="s3b">&lt;/div>
&lt;div class="subsection">&lt;h3>Statistik Dasar — Fondasi Semua Distribusi&lt;/h3>&lt;/div>
&lt;p style="font-size:13px;color:var(--gray-600);line-height:1.7;margin-bottom:1rem;">Sebelum memilih distribusi, kita wajib menghitung &lt;strong>4 parameter statistik&lt;/strong> dari data AMS. Parameter ini menggambarkan "karakter" data hujan kita.&lt;/p>
&lt;div class="grid-4" id="statCards">&lt;/div>
&lt;div class="formula-block">
&lt;span class="eq-label">Rumus 4 Parameter Statistik Dasar&lt;/span>
&lt;span class="eq-main">x̄ = (1/n)·Σxᵢ &amp;nbsp;|&amp;nbsp; S = √[(1/(n-1))·Σ(xᵢ−x̄)²]&lt;/span>
&lt;span class="eq-main">Cs = [n·Σ(xᵢ−x̄)³] / [(n-1)(n-2)·S³] &amp;nbsp;|&amp;nbsp; CV = S / x̄&lt;/span>
&lt;span class="eq-desc">x̄ = rata-rata | S = standar deviasi | Cs = koefisien kemencengan (skewness) | CV = koefisien variasi&lt;/span>
&lt;/div>
&lt;div class="info-box">&lt;span class="box-icon">ℹ️&lt;/span>&lt;span>Nilai &lt;strong>Cs (koefisien kemencengan)&lt;/strong> adalah panduan awal pemilihan distribusi. Cs ≈ 0 → Normal; Cs ≈ 1.14 → Gumbel; Cs bebas → Log-Pearson III dapat menyesuaikan. Data hujan tropis umumnya memiliki Cs positif (ekor distribusi condong ke kanan — ada nilai ekstrem yang jarang tapi besar).&lt;/span>&lt;/div>
&lt;/section>
&lt;div class="divider">&lt;/div>
&lt;!-- ===== S4: DISTRIBUSI ===== -->
&lt;section class="section anim-in" id="s4">
&lt;div class="section-header">&lt;div class="section-num">4&lt;/div>&lt;h2>Empat Distribusi Teoritis&lt;/h2>&lt;/div>
&lt;p style="font-size:13px;color:var(--gray-600);line-height:1.7;margin-bottom:1rem;">Distribusi teoritis adalah "model matematika" yang mencoba merepresentasikan pola data hujan kita. Bayangkan seperti sketsa wajah dari foto — kita mencoba 4 seniman berbeda, lalu pilih yang paling mirip dengan aslinya.&lt;/p>
&lt;div class="dist-grid">
&lt;div class="card card-navy">
&lt;div class="card-label">① Distribusi Normal&lt;/div>
&lt;p>Bentuk "lonceng simetris" yang paling dikenal. Nilai besar dan kecil sama-sama jarang; nilai tengah paling sering muncul. Jarang cocok untuk data hujan tropis yang biasanya miring ke kanan.&lt;/p>
&lt;div class="formula-block" style="margin-top:10px;padding:0.7rem 1rem;">
&lt;span class="eq-label">Curah Hujan Rencana&lt;/span>
&lt;span class="eq-main" style="font-size:13px;">x_T = x̄ + K_T · S&lt;/span>
&lt;span class="eq-desc">K_T dari tabel distribusi Normal standar (z-score)&lt;/span>
&lt;/div>
&lt;p style="margin-top:6px;">&lt;span class="tag tag-blue">Syarat: Cs ≈ 0&lt;/span> &lt;span class="tag tag-blue">Ck ≈ 3&lt;/span>&lt;/p>
&lt;/div>
&lt;div class="card card-blue">
&lt;div class="card-label">② Log-Normal 2 Parameter&lt;/div>
&lt;p>Transformasi logaritmik diterapkan ke data, lalu data log-nya dianggap berdistribusi Normal. Bagus untuk data positif yang miring ke kanan — tipikal curah hujan. Sangat umum dalam hidrologi.&lt;/p>
&lt;div class="formula-block" style="margin-top:10px;padding:0.7rem 1rem;">
&lt;span class="eq-label">Curah Hujan Rencana&lt;/span>
&lt;span class="eq-main" style="font-size:13px;">ln(x_T) = ȳ + K_T · Sy&lt;/span>
&lt;span class="eq-desc">ȳ = mean(ln x) | Sy = std.dev(ln x)&lt;/span>
&lt;/div>
&lt;p style="margin-top:6px;">&lt;span class="tag tag-blue">Cs ≈ 3·CV + CV³&lt;/span>&lt;/p>
&lt;/div>
&lt;div class="card card-amber">
&lt;div class="card-label">③ Distribusi Gumbel (EV Type I)&lt;/div>
&lt;p>Dirancang khusus secara teori untuk memodelkan nilai-nilai &lt;em>maksimum&lt;/em>. Sangat populer untuk analisis banjir dan hujan ekstrem. Secara teori adalah pilihan yang tepat untuk data Annual Maximum Series.&lt;/p>
&lt;div class="formula-block" style="margin-top:10px;padding:0.7rem 1rem;border-left-color:var(--amber);">
&lt;span class="eq-label">Parameter &amp; Curah Hujan Rencana&lt;/span>
&lt;span class="eq-main" style="font-size:12px;">α = S·π/√6 &amp;nbsp;|&amp;nbsp; μ = x̄ − 0.5772·α&lt;/span>
&lt;span class="eq-main" style="font-size:12px;">K_T = −(√6/π)·[0.5772 + ln(ln(T/(T-1)))]&lt;/span>
&lt;span class="eq-desc">Rumus K_T ini khusus untuk distribusi Gumbel&lt;/span>
&lt;/div>
&lt;p style="margin-top:6px;">&lt;span class="tag tag-amber">Syarat: Cs ≈ 1.14&lt;/span> &lt;span class="tag tag-amber">Ck ≈ 5.40&lt;/span>&lt;/p>
&lt;/div>
&lt;div class="card card-green">
&lt;div class="card-label">④ Log-Pearson III (LP3)&lt;/div>
&lt;p>Yang paling fleksibel dari keempatnya. Menggunakan tiga parameter dari data log (mean, std dev, skewness) — bisa mengikuti hampir semua bentuk distribusi data hidrologi. Standar wajib di banyak negara.&lt;/p>
&lt;div class="formula-block" style="margin-top:10px;padding:0.7rem 1rem;border-left-color:var(--green);">
&lt;span class="eq-label">Curah Hujan Rencana&lt;/span>
&lt;span class="eq-main" style="font-size:13px;">ln(x_T) = ȳ + K_T · Sy&lt;/span>
&lt;span class="eq-desc">K_T = f(T, Cs_y) dari tabel Pearson III | Cs_y dihitung dari data y = ln(x)&lt;/span>
&lt;/div>
&lt;p style="margin-top:6px;">&lt;span class="tag tag-green">Cs bebas — paling adaptif&lt;/span>&lt;/p>
&lt;/div>
&lt;/div>
&lt;div class="chart-card">
&lt;div class="chart-title">Perbandingan CDF: Empiris vs 4 Distribusi Teoritis&lt;/div>
&lt;div class="chart-sub">Titik = plotting position empiris (P = i/(n+1)) · Garis = CDF teoritis masing-masing distribusi&lt;/div>
&lt;div class="chart-wrap" style="height:320px;">&lt;canvas id="chartCDF">&lt;/canvas>&lt;/div>
&lt;div class="legend-row">
&lt;div class="legend-item">&lt;div class="legend-sq" style="background:#64748b;">&lt;/div> Data Empiris&lt;/div>
&lt;div class="legend-item">&lt;div class="legend-sq" style="background:#2563eb;">&lt;/div> Normal&lt;/div>
&lt;div class="legend-item">&lt;div class="legend-sq" style="background:#0891b2;">&lt;/div> Log-Normal&lt;/div>
&lt;div class="legend-item">&lt;div class="legend-sq" style="background:#d97706;">&lt;/div> Gumbel&lt;/div>
&lt;div class="legend-item">&lt;div class="legend-sq" style="background:#16a34a;">&lt;/div> Log-Pearson III&lt;/div>
&lt;/div>
&lt;/div>
&lt;/section>
&lt;div class="divider">&lt;/div>
&lt;!-- ===== S5: UJI KECOCOKAN ===== -->
&lt;section class="section anim-in" id="s5">
&lt;div class="section-header">&lt;div class="section-num">5&lt;/div>&lt;h2>Uji Kecocokan (Goodness of Fit Test)&lt;/h2>&lt;/div>
&lt;p style="font-size:13px;color:var(--gray-600);line-height:1.7;margin-bottom:1rem;">Setelah mencoba keempat distribusi, kita perlu menjawab secara objektif: &lt;strong>distribusi mana yang paling baik merepresentasikan data?&lt;/strong> Jawabannya dari dua uji statistik.&lt;/p>
&lt;div id="s5a">&lt;/div>
&lt;div class="subsection">&lt;h3>Uji Kolmogorov-Smirnov (KS Test)&lt;/h3>&lt;/div>
&lt;div class="card card-purple">
&lt;div class="card-label">Prinsip Uji KS&lt;/div>
&lt;p>Uji KS mengukur &lt;strong>selisih terbesar (D)&lt;/strong> antara CDF empiris dari data kita dengan CDF teoritis dari distribusi yang diuji. Semakin kecil D, semakin cocok distribusinya. Distribusi diterima jika D-hitung &amp;lt; D-kritis (dari tabel, tergantung n dan α).&lt;/p>
&lt;/div>
&lt;div class="step-flow">
&lt;div class="step-item">
&lt;div class="step-line">&lt;div class="step-dot navy">1&lt;/div>&lt;div class="step-connector">&lt;/div>&lt;/div>
&lt;div class="step-body">
&lt;div class="step-title">Urutkan data dari kecil ke besar&lt;/div>
&lt;div class="step-desc">x₁ ≤ x₂ ≤ ... ≤ xₙ. Beri ranking i = 1, 2, ..., n.&lt;/div>
&lt;/div>
&lt;/div>
&lt;div class="step-item">
&lt;div class="step-line">&lt;div class="step-dot navy">2&lt;/div>&lt;div class="step-connector">&lt;/div>&lt;/div>
&lt;div class="step-body">
&lt;div class="step-title">Hitung probabilitas empiris (plotting position)&lt;/div>
&lt;div class="step-desc">P_emp(xᵢ) = i / (n+1) — rumus Weibull. Ini adalah "probabilitas seharusnya" berdasarkan posisi data dalam ranking.&lt;/div>
&lt;/div>
&lt;/div>
&lt;div class="step-item">
&lt;div class="step-line">&lt;div class="step-dot navy">3&lt;/div>&lt;div class="step-connector">&lt;/div>&lt;/div>
&lt;div class="step-body">
&lt;div class="step-title">Hitung CDF teoritis untuk setiap data&lt;/div>
&lt;div class="step-desc">P_teo(xᵢ) dari fungsi distribusi yang diuji (Normal, Log-Normal, Gumbel, atau LP3).&lt;/div>
&lt;/div>
&lt;/div>
&lt;div class="step-item">
&lt;div class="step-line">&lt;div class="step-dot navy">4&lt;/div>&lt;div class="step-connector">&lt;/div>&lt;/div>
&lt;div class="step-body">
&lt;div class="step-title">Hitung D = selisih maksimum&lt;/div>
&lt;div class="step-desc">D = max |P_emp(xᵢ) − P_teo(xᵢ)| untuk semua i.&lt;/div>
&lt;/div>
&lt;/div>
&lt;div class="step-item">
&lt;div class="step-line">&lt;div class="step-dot green">5&lt;/div>&lt;div class="step-connector">&lt;/div>&lt;/div>
&lt;div class="step-body">
&lt;div class="step-title">Bandingkan dengan D-kritis&lt;/div>
&lt;div class="step-desc">Untuk n=25, α=5%: D-kritis = 0.264. Jika D-hitung &amp;lt; 0.264 → &lt;strong style="color:var(--green);">distribusi DITERIMA ✅&lt;/strong>&lt;/div>
&lt;/div>
&lt;/div>
&lt;/div>
&lt;div id="s5b">&lt;/div>
&lt;div class="subsection">&lt;h3>Uji Chi-Kuadrat (χ²)&lt;/h3>&lt;/div>
&lt;div class="card card-blue">
&lt;div class="card-label">Prinsip Uji Chi-Kuadrat&lt;/div>
&lt;p>Data dibagi ke dalam beberapa kelas (bin), lalu dibandingkan berapa banyak data yang &lt;em>sebenarnya&lt;/em> jatuh di setiap kelas (Oᵢ) versus berapa banyak yang &lt;em>diharapkan&lt;/em> oleh distribusi teoritis (Eᵢ).&lt;/p>
&lt;/div>
&lt;div class="formula-block">
&lt;span class="eq-label">Statistik Uji Chi-Kuadrat&lt;/span>
&lt;span class="eq-main">χ² = Σ [ (Oᵢ − Eᵢ)² / Eᵢ ]&lt;/span>
&lt;span class="eq-desc">Oᵢ = frekuensi observasi kelas ke-i | Eᵢ = frekuensi yang diharapkan dari distribusi teoritis
Derajat kebebasan: dk = k − m − 1 (k = jumlah kelas, m = jumlah parameter distribusi)
Jika χ²-hitung &amp;lt; χ²-kritis(α, dk) → distribusi DITERIMA&lt;/span>
&lt;/div>
&lt;div id="s5c">&lt;/div>
&lt;div class="subsection">&lt;h3>Hasil Uji dan Pemilihan Distribusi Terbaik&lt;/h3>&lt;/div>
&lt;div class="tbl-wrap">
&lt;table class="data-tbl">
&lt;thead>
&lt;tr>
&lt;th>Distribusi&lt;/th>
&lt;th>D-hitung (KS)&lt;/th>
&lt;th>D-kritis (5%)&lt;/th>
&lt;th>Status KS&lt;/th>
&lt;th>χ²-hitung&lt;/th>
&lt;th>χ²-kritis (5%)&lt;/th>
&lt;th>Status χ²&lt;/th>
&lt;th>Keputusan&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td class="td-label">Normal&lt;/td>
&lt;td>0.091&lt;/td>&lt;td>0.264&lt;/td>
&lt;td class="pass">✅ Diterima&lt;/td>
&lt;td>3.12&lt;/td>&lt;td>5.991&lt;/td>
&lt;td class="pass">✅ Diterima&lt;/td>
&lt;td>&lt;span class="tag tag-blue">Layak&lt;/span>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td class="td-label">Log-Normal&lt;/td>
&lt;td>0.074&lt;/td>&lt;td>0.264&lt;/td>
&lt;td class="pass">✅ Diterima&lt;/td>
&lt;td>2.47&lt;/td>&lt;td>5.991&lt;/td>
&lt;td class="pass">✅ Diterima&lt;/td>
&lt;td>&lt;span class="tag tag-blue">Layak&lt;/span>&lt;/td>
&lt;/tr>
&lt;tr class="highlight">
&lt;td class="td-label" style="color:var(--amber);font-weight:700;">Gumbel 🏆&lt;/td>
&lt;td class="best">0.058&lt;/td>&lt;td>0.264&lt;/td>
&lt;td class="pass">✅ Diterima&lt;/td>
&lt;td class="best">1.83&lt;/td>&lt;td>5.991&lt;/td>
&lt;td class="pass">✅ Diterima&lt;/td>
&lt;td>&lt;span class="tag tag-green">🏆 Terbaik&lt;/span>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td class="td-label">Log-Pearson III&lt;/td>
&lt;td>0.063&lt;/td>&lt;td>0.264&lt;/td>
&lt;td class="pass">✅ Diterima&lt;/td>
&lt;td>2.15&lt;/td>&lt;td>5.991&lt;/td>
&lt;td class="pass">✅ Diterima&lt;/td>
&lt;td>&lt;span class="tag tag-blue">Layak&lt;/span>&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;/div>
&lt;p style="font-size:11px;color:var(--gray-500);margin-top:-0.5rem;margin-bottom:1rem;">*Contoh hasil analisis. Distribusi terbaik = nilai D dan χ² terkecil yang tetap lulus kedua uji. n=25, α=5%.&lt;/p>
&lt;div class="chart-card">
&lt;div class="chart-title">Perbandingan Nilai D (KS Test) — Semua Distribusi&lt;/div>
&lt;div class="chart-sub">Semakin rendah D-hitung, semakin cocok distribusinya. Semua distribusi harus di bawah garis D-kritis.&lt;/div>
&lt;div class="chart-wrap" style="height:240px;">&lt;canvas id="chartKS">&lt;/canvas>&lt;/div>
&lt;/div>
&lt;div class="success-box">&lt;span class="box-icon">🎯&lt;/span>&lt;span>Distribusi &lt;strong>Gumbel&lt;/strong> terpilih sebagai distribusi terbaik untuk data contoh ini (D = 0.058, χ² = 1.83 — keduanya terkecil di antara semua distribusi). Seluruh perhitungan curah hujan rencana dan IDF selanjutnya menggunakan distribusi Gumbel.&lt;/span>&lt;/div>
&lt;/section>
&lt;div class="divider">&lt;/div>
&lt;!-- ===== S6: CURAH HUJAN RENCANA ===== -->
&lt;section class="section anim-in" id="s6">
&lt;div class="section-header">&lt;div class="section-num">6&lt;/div>&lt;h2>Curah Hujan Rencana&lt;/h2>&lt;/div>
&lt;div class="card card-amber">
&lt;div class="card-label">📌 Apa Itu Curah Hujan Rencana?&lt;/div>
&lt;p>Curah hujan rencana (R_T) adalah estimasi besarnya curah hujan harian maksimum yang diharapkan terjadi rata-rata sekali dalam T tahun. Ini adalah &lt;strong>angka desain utama&lt;/strong> yang menjadi input untuk semua analisis hidrologi selanjutnya: debit banjir, drainase, bendung, dan seterusnya.&lt;/p>
&lt;/div>
&lt;div class="formula-block">
&lt;span class="eq-label">Curah Hujan Rencana — Distribusi Gumbel&lt;/span>
&lt;span class="eq-main">R_T = x̄ + K_T · S&lt;/span>
&lt;span class="eq-main">K_T = −(√6/π) · [0.5772 + ln(ln(T/(T−1)))]&lt;/span>
&lt;span class="eq-desc">x̄ = 104.58 mm | S = 22.67 mm | α = S·π/√6 = 29.09 | μ = x̄ − 0.5772·α = 87.77&lt;/span>
&lt;/div>
&lt;div class="tbl-wrap">
&lt;table class="data-tbl" id="tblRencana">&lt;/table>
&lt;/div>
&lt;div class="chart-card">
&lt;div class="chart-title">Curah Hujan Rencana per Kala Ulang — Perbandingan 4 Distribusi&lt;/div>
&lt;div class="chart-sub">Semua distribusi menghasilkan nilai yang berdekatan — semakin panjang kala ulang, selisihnya semakin terlihat&lt;/div>
&lt;div class="chart-wrap" style="height:300px;">&lt;canvas id="chartRencana">&lt;/canvas>&lt;/div>
&lt;div class="legend-row">
&lt;div class="legend-item">&lt;div class="legend-sq" style="background:#2563eb;">&lt;/div> Normal&lt;/div>
&lt;div class="legend-item">&lt;div class="legend-sq" style="background:#0891b2;">&lt;/div> Log-Normal&lt;/div>
&lt;div class="legend-item">&lt;div class="legend-sq" style="background:#d97706;border:2px solid #92400e;">&lt;/div> Gumbel (terpilih)&lt;/div>
&lt;div class="legend-item">&lt;div class="legend-sq" style="background:#16a34a;">&lt;/div> Log-Pearson III&lt;/div>
&lt;/div>
&lt;/div>
&lt;div class="info-box">&lt;span class="box-icon">ℹ️&lt;/span>&lt;span>Perbedaan hasil antar distribusi pada kala ulang pendek (T=2, T=5) relatif kecil. Perbedaan yang signifikan baru terlihat pada kala ulang panjang (T=50, T=100). Inilah mengapa pemilihan distribusi yang tepat sangat penting untuk desain infrastruktur besar.&lt;/span>&lt;/div>
&lt;/section>
&lt;div class="divider">&lt;/div>
&lt;!-- ===== S7: KURVA IDF ===== -->
&lt;section class="section anim-in" id="s7">
&lt;div class="section-header">&lt;div class="section-num">7&lt;/div>&lt;h2>Kurva IDF (Intensitas–Durasi–Frekuensi)&lt;/h2>&lt;/div>
&lt;p style="font-size:13px;color:var(--gray-600);line-height:1.7;margin-bottom:1rem;">Curah hujan rencana R_T (mm/hari) belum bisa langsung dipakai untuk desain drainase dan saluran. Yang dibutuhkan adalah &lt;strong>intensitas hujan I (mm/jam)&lt;/strong> untuk berbagai durasi. Inilah peran Kurva IDF.&lt;/p>
&lt;div class="analogy-box">
&lt;div class="analogy-badge">💡 Mengapa Perlu IDF?&lt;/div>
&lt;p>Hujan 165 mm dalam sehari terasa besar, tapi mungkin bisa ditampung drainase yang baik. Tapi bayangkan 165 mm turun dalam 1 jam — bencana. Kurva IDF mengubah "hujan harian" menjadi "intensitas per jam" untuk berbagai durasi, supaya kita bisa merancang drainase yang tepat untuk durasi hujan yang paling kritis.&lt;/p>
&lt;/div>
&lt;div class="card card-purple">
&lt;div class="card-label">Rumus Mononobe — Metode Standar Indonesia&lt;/div>
&lt;/div>
&lt;div class="formula-block">
&lt;span class="eq-label">Intensitas Hujan Rencana (Rumus Mononobe)&lt;/span>
&lt;span class="eq-main">I = (R₂₄ / 24) · (24 / t)^(2/3)&lt;/span>
&lt;span class="eq-desc">I = intensitas hujan (mm/jam) | R₂₄ = curah hujan harian rencana (mm) | t = durasi hujan (jam)
Sumber: Mononobe (1932). Digunakan luas di Indonesia untuk durasi 5 menit hingga 24 jam.&lt;/span>
&lt;/div>
&lt;div class="card-label" style="font-size:11px;margin-bottom:8px;">📊 Tabel Intensitas Hujan I (mm/jam) — Distribusi Gumbel, Rumus Mononobe&lt;/div>
&lt;div class="tbl-wrap">
&lt;table class="data-tbl" id="tblIDF">&lt;/table>
&lt;/div>
&lt;p style="font-size:11px;color:var(--gray-500);margin-top:-0.5rem;margin-bottom:1rem;">*Baris yang disorot (t = 60 mnt) paling sering digunakan dalam desain drainase perkotaan dengan metode rasional.&lt;/p>
&lt;div class="chart-card">
&lt;div class="chart-title">Kurva IDF — Intensitas vs Durasi per Kala Ulang&lt;/div>
&lt;div class="chart-sub">Semakin pendek durasi → intensitas makin tinggi. Semakin panjang kala ulang → kurva makin atas.&lt;/div>
&lt;div class="chart-wrap" style="height:320px;">&lt;canvas id="chartIDF">&lt;/canvas>&lt;/div>
&lt;div class="legend-row">
&lt;div class="legend-item">&lt;div class="legend-sq" style="background:#7c3aed;">&lt;/div> T = 100 thn&lt;/div>
&lt;div class="legend-item">&lt;div class="legend-sq" style="background:#dc2626;">&lt;/div> T = 50 thn&lt;/div>
&lt;div class="legend-item">&lt;div class="legend-sq" style="background:#d97706;">&lt;/div> T = 25 thn&lt;/div>
&lt;div class="legend-item">&lt;div class="legend-sq" style="background:#0284c7;">&lt;/div> T = 10 thn&lt;/div>
&lt;div class="legend-item">&lt;div class="legend-sq" style="background:#2563eb;">&lt;/div> T = 5 thn&lt;/div>
&lt;div class="legend-item">&lt;div class="legend-sq" style="background:#64748b;">&lt;/div> T = 2 thn&lt;/div>
&lt;/div>
&lt;/div>
&lt;div class="success-box">&lt;span class="box-icon">🎯&lt;/span>&lt;span>Tabel IDF dan kurva IDF di atas adalah &lt;strong>output final yang siap pakai&lt;/strong> untuk desain infrastruktur. Nilai I pada t = 60 menit digunakan langsung dalam metode rasional Q = 0.278·C·I·A untuk menghitung debit rencana.&lt;/span>&lt;/div>
&lt;/section>
&lt;div class="divider">&lt;/div>
&lt;!-- ===== S8: KODE R ===== -->
&lt;section class="section anim-in" id="s8">
&lt;div class="section-header">&lt;div class="section-num">8&lt;/div>&lt;h2>Kode R — Implementasi Lengkap&lt;/h2>&lt;/div>
&lt;div class="code-wrap">
&lt;div class="code-header">
&lt;span class="code-lang">&lt;span class="dot" style="background:#4fc3f7;">&lt;/span>R · Baca Data &amp; Hitung Statistik Dasar&lt;/span>
&lt;button class="copy-btn" onclick="copyCode(this)">Salin&lt;/button>
&lt;/div>
&lt;pre>&lt;span class="kw">library&lt;/span>(&lt;span class="pkg">readxl&lt;/span>); &lt;span class="kw">library&lt;/span>(&lt;span class="pkg">dplyr&lt;/span>); &lt;span class="kw">library&lt;/span>(&lt;span class="pkg">e1071&lt;/span>)
&lt;span class="fn">options&lt;/span>(OutDec = &lt;span class="str">"."&lt;/span>) &lt;span class="cm"># pastikan desimal pakai titik&lt;/span>
&lt;span class="cm"># ── Baca data dari Excel ──────────────────────────────────────&lt;/span>
df &lt;span class="op">&amp;lt;-&lt;/span> &lt;span class="fn">read_excel&lt;/span>(&lt;span class="str">"Data_Input_Frekuensi.xlsx"&lt;/span>, sheet = &lt;span class="str">"Data_Hujan"&lt;/span>)
x &lt;span class="op">&amp;lt;-&lt;/span> df&lt;span class="op">$&lt;/span>hujan_maks &lt;span class="cm"># vektor data hujan maks tahunan (mm)&lt;/span>
n &lt;span class="op">&amp;lt;-&lt;/span> &lt;span class="fn">length&lt;/span>(x)
&lt;span class="cm"># ── Statistik dasar ───────────────────────────────────────────&lt;/span>
x_bar &lt;span class="op">&amp;lt;-&lt;/span> &lt;span class="fn">mean&lt;/span>(x)
S &lt;span class="op">&amp;lt;-&lt;/span> &lt;span class="fn">sd&lt;/span>(x)
CV &lt;span class="op">&amp;lt;-&lt;/span> S / x_bar
Cs &lt;span class="op">&amp;lt;-&lt;/span> &lt;span class="fn">skewness&lt;/span>(x) &lt;span class="cm"># dari paket e1071&lt;/span>
Ck &lt;span class="op">&amp;lt;-&lt;/span> &lt;span class="fn">kurtosis&lt;/span>(x)
&lt;span class="fn">cat&lt;/span>(&lt;span class="str">"n ="&lt;/span>, n, &lt;span class="str">"\n"&lt;/span>)
&lt;span class="fn">cat&lt;/span>(&lt;span class="str">"x_bar ="&lt;/span>, &lt;span class="fn">round&lt;/span>(x_bar, &lt;span class="num">2&lt;/span>), &lt;span class="str">"mm\n"&lt;/span>)
&lt;span class="fn">cat&lt;/span>(&lt;span class="str">"S ="&lt;/span>, &lt;span class="fn">round&lt;/span>(S, &lt;span class="num">2&lt;/span>), &lt;span class="str">"mm\n"&lt;/span>)
&lt;span class="fn">cat&lt;/span>(&lt;span class="str">"CV ="&lt;/span>, &lt;span class="fn">round&lt;/span>(CV, &lt;span class="num">3&lt;/span>), &lt;span class="str">"\n"&lt;/span>)
&lt;span class="fn">cat&lt;/span>(&lt;span class="str">"Cs ="&lt;/span>, &lt;span class="fn">round&lt;/span>(Cs, &lt;span class="num">3&lt;/span>), &lt;span class="str">"\n"&lt;/span>)&lt;/pre>
&lt;/div>
&lt;div class="code-wrap">
&lt;div class="code-header">
&lt;span class="code-lang">&lt;span class="dot" style="background:#4fc3f7;">&lt;/span>R · Fit Distribusi Gumbel &amp; Curah Hujan Rencana&lt;/span>
&lt;button class="copy-btn" onclick="copyCode(this)">Salin&lt;/button>
&lt;/div>
&lt;pre>&lt;span class="cm"># ── Parameter distribusi Gumbel ───────────────────────────────&lt;/span>
alpha_g &lt;span class="op">&amp;lt;-&lt;/span> S &lt;span class="op">*&lt;/span> pi / &lt;span class="fn">sqrt&lt;/span>(&lt;span class="num">6&lt;/span>)
mu_g &lt;span class="op">&amp;lt;-&lt;/span> x_bar &lt;span class="op">-&lt;/span> &lt;span class="num">0.5772&lt;/span> &lt;span class="op">*&lt;/span> alpha_g
&lt;span class="cm"># ── Fungsi faktor frekuensi Gumbel ───────────────────────────&lt;/span>
KT_gumbel &lt;span class="op">&amp;lt;-&lt;/span> &lt;span class="kw">function&lt;/span>(T) {
&lt;span class="op">-&lt;/span>(&lt;span class="fn">sqrt&lt;/span>(&lt;span class="num">6&lt;/span>) / pi) &lt;span class="op">*&lt;/span> (&lt;span class="num">0.5772&lt;/span> &lt;span class="op">+&lt;/span> &lt;span class="fn">log&lt;/span>(&lt;span class="fn">log&lt;/span>(T / (T &lt;span class="op">-&lt;/span> &lt;span class="num">1&lt;/span>))))
}
&lt;span class="cm"># ── Hitung curah hujan rencana ────────────────────────────────&lt;/span>
T_values &lt;span class="op">&amp;lt;-&lt;/span> &lt;span class="fn">c&lt;/span>(&lt;span class="num">2&lt;/span>, &lt;span class="num">5&lt;/span>, &lt;span class="num">10&lt;/span>, &lt;span class="num">25&lt;/span>, &lt;span class="num">50&lt;/span>, &lt;span class="num">100&lt;/span>)
hasil_gumbel &lt;span class="op">&amp;lt;-&lt;/span> &lt;span class="fn">data.frame&lt;/span>(
T = T_values,
KT = &lt;span class="fn">round&lt;/span>(&lt;span class="fn">sapply&lt;/span>(T_values, KT_gumbel), &lt;span class="num">3&lt;/span>),
R_T_mm = &lt;span class="fn">round&lt;/span>(x_bar &lt;span class="op">+&lt;/span> &lt;span class="fn">sapply&lt;/span>(T_values, KT_gumbel) &lt;span class="op">*&lt;/span> S, &lt;span class="num">1&lt;/span>)
)
&lt;span class="fn">print&lt;/span>(hasil_gumbel)&lt;/pre>
&lt;/div>
&lt;div class="code-wrap">
&lt;div class="code-header">
&lt;span class="code-lang">&lt;span class="dot" style="background:#4fc3f7;">&lt;/span>R · Uji Kolmogorov-Smirnov&lt;/span>
&lt;button class="copy-btn" onclick="copyCode(this)">Salin&lt;/button>
&lt;/div>
&lt;pre>&lt;span class="cm"># ── Uji KS untuk Distribusi Gumbel ───────────────────────────&lt;/span>
x_sorted &lt;span class="op">&amp;lt;-&lt;/span> &lt;span class="fn">sort&lt;/span>(x)
P_emp &lt;span class="op">&amp;lt;-&lt;/span> (&lt;span class="num">1&lt;/span>&lt;span class="op">:&lt;/span>n) / (n &lt;span class="op">+&lt;/span> &lt;span class="num">1&lt;/span>) &lt;span class="cm"># plotting position Weibull&lt;/span>
&lt;span class="cm"># CDF Gumbel teoritis: F(x) = exp(-exp(-(x - mu)/alpha))&lt;/span>
P_teo_gumbel &lt;span class="op">&amp;lt;-&lt;/span> &lt;span class="fn">exp&lt;/span>(&lt;span class="op">-&lt;/span>&lt;span class="fn">exp&lt;/span>(&lt;span class="op">-&lt;/span>(x_sorted &lt;span class="op">-&lt;/span> mu_g) &lt;span class="op">/&lt;/span> alpha_g))
D_hitung &lt;span class="op">&amp;lt;-&lt;/span> &lt;span class="fn">max&lt;/span>(&lt;span class="fn">abs&lt;/span>(P_emp &lt;span class="op">-&lt;/span> P_teo_gumbel))
&lt;span class="cm"># D kritis untuk n=25, alpha=5%: D_kritis = 1.36/sqrt(n)&lt;/span>
D_kritis &lt;span class="op">&amp;lt;-&lt;/span> &lt;span class="num">1.36&lt;/span> / &lt;span class="fn">sqrt&lt;/span>(n)
&lt;span class="fn">cat&lt;/span>(&lt;span class="str">"D-hitung:"&lt;/span>, &lt;span class="fn">round&lt;/span>(D_hitung, &lt;span class="num">4&lt;/span>), &lt;span class="str">"\n"&lt;/span>)
&lt;span class="fn">cat&lt;/span>(&lt;span class="str">"D-kritis:"&lt;/span>, &lt;span class="fn">round&lt;/span>(D_kritis, &lt;span class="num">4&lt;/span>), &lt;span class="str">"\n"&lt;/span>)
&lt;span class="fn">cat&lt;/span>(&lt;span class="str">"Status :"&lt;/span>, &lt;span class="fn">ifelse&lt;/span>(D_hitung &lt;span class="op">&amp;lt;&lt;/span> D_kritis, &lt;span class="str">"✅ DITERIMA"&lt;/span>, &lt;span class="str">"❌ DITOLAK"&lt;/span>), &lt;span class="str">"\n"&lt;/span>)&lt;/pre>
&lt;/div>
&lt;div class="code-wrap">
&lt;div class="code-header">
&lt;span class="code-lang">&lt;span class="dot" style="background:#4fc3f7;">&lt;/span>R · Hitung Kurva IDF (Rumus Mononobe)&lt;/span>
&lt;button class="copy-btn" onclick="copyCode(this)">Salin&lt;/button>
&lt;/div>
&lt;pre>&lt;span class="cm"># ── Hitung tabel IDF dengan rumus Mononobe ────────────────────&lt;/span>
&lt;span class="kw">library&lt;/span>(&lt;span class="pkg">tidyr&lt;/span>); &lt;span class="kw">library&lt;/span>(&lt;span class="pkg">ggplot2&lt;/span>)
durasi_jam &lt;span class="op">&amp;lt;-&lt;/span> &lt;span class="fn">c&lt;/span>(&lt;span class="num">5&lt;/span>&lt;span class="op">/&lt;/span>&lt;span class="num">60&lt;/span>, &lt;span class="num">10&lt;/span>&lt;span class="op">/&lt;/span>&lt;span class="num">60&lt;/span>, &lt;span class="num">15&lt;/span>&lt;span class="op">/&lt;/span>&lt;span class="num">60&lt;/span>, &lt;span class="num">0.5&lt;/span>, &lt;span class="num">1&lt;/span>, &lt;span class="num">2&lt;/span>, &lt;span class="num">3&lt;/span>, &lt;span class="num">6&lt;/span>, &lt;span class="num">12&lt;/span>, &lt;span class="num">24&lt;/span>)
&lt;span class="cm"># Fungsi Mononobe: I = (R24/24) * (24/t)^(2/3)&lt;/span>
mononobe &lt;span class="op">&amp;lt;-&lt;/span> &lt;span class="kw">function&lt;/span>(R24, t) (R24 / &lt;span class="num">24&lt;/span>) &lt;span class="op">*&lt;/span> (&lt;span class="num">24&lt;/span> / t)^(&lt;span class="num">2&lt;/span>&lt;span class="op">/&lt;/span>&lt;span class="num">3&lt;/span>)
&lt;span class="cm"># Buat tabel IDF untuk semua kala ulang&lt;/span>
tbl_idf &lt;span class="op">&amp;lt;-&lt;/span> &lt;span class="fn">expand.grid&lt;/span>(t = durasi_jam, T = T_values) &lt;span class="op">|&amp;gt;&lt;/span>
&lt;span class="fn">left_join&lt;/span>(hasil_gumbel &lt;span class="op">|&amp;gt;&lt;/span> &lt;span class="fn">select&lt;/span>(T, R_T_mm), by = &lt;span class="str">"T"&lt;/span>) &lt;span class="op">|&amp;gt;&lt;/span>
&lt;span class="fn">mutate&lt;/span>(
I_mmjam = &lt;span class="fn">round&lt;/span>(&lt;span class="fn">mononobe&lt;/span>(R_T_mm, t), &lt;span class="num">1&lt;/span>),
T_label = &lt;span class="fn">paste0&lt;/span>(&lt;span class="str">"T"&lt;/span>, T, &lt;span class="str">"thn"&lt;/span>)
)
&lt;span class="cm"># ── Plot Kurva IDF ─────────────────────────────────────────────&lt;/span>
ggplot(tbl_idf, &lt;span class="fn">aes&lt;/span>(x = t, y = I_mmjam, color = &lt;span class="fn">factor&lt;/span>(T), group = T)) &lt;span class="op">+&lt;/span>
&lt;span class="fn">geom_line&lt;/span>(linewidth = &lt;span class="num">0.9&lt;/span>) &lt;span class="op">+&lt;/span>
&lt;span class="fn">geom_point&lt;/span>(size = &lt;span class="num">1.5&lt;/span>) &lt;span class="op">+&lt;/span>
&lt;span class="fn">scale_x_log10&lt;/span>(breaks = durasi_jam,
labels = &lt;span class="fn">c&lt;/span>(&lt;span class="str">"5'"&lt;/span>,&lt;span class="str">"10'"&lt;/span>,&lt;span class="str">"15'"&lt;/span>,&lt;span class="str">"30'"&lt;/span>,&lt;span class="str">"1j"&lt;/span>,&lt;span class="str">"2j"&lt;/span>,&lt;span class="str">"3j"&lt;/span>,&lt;span class="str">"6j"&lt;/span>,&lt;span class="str">"12j"&lt;/span>,&lt;span class="str">"24j"&lt;/span>)) &lt;span class="op">+&lt;/span>
&lt;span class="fn">scale_y_log10&lt;/span>() &lt;span class="op">+&lt;/span>
&lt;span class="fn">labs&lt;/span>(
title = &lt;span class="str">"Kurva IDF — Distribusi Gumbel, Rumus Mononobe"&lt;/span>,
subtitle = &lt;span class="fn">paste0&lt;/span>(&lt;span class="str">"Stasiun: ... | n = "&lt;/span>, n, &lt;span class="str">" tahun"&lt;/span>),
x = &lt;span class="str">"Durasi (jam, log scale)"&lt;/span>,
y = &lt;span class="str">"Intensitas (mm/jam, log scale)"&lt;/span>,
color = &lt;span class="str">"Kala Ulang"&lt;/span>,
caption = &lt;span class="str">"Metode: Mononobe (1932) | Distribusi: Gumbel EV-I"&lt;/span>
) &lt;span class="op">+&lt;/span>
&lt;span class="fn">theme_minimal&lt;/span>(base_size = &lt;span class="num">11&lt;/span>) &lt;span class="op">+&lt;/span>
&lt;span class="fn">theme&lt;/span>(plot.title = &lt;span class="fn">element_text&lt;/span>(face = &lt;span class="str">"bold"&lt;/span>))&lt;/pre>
&lt;/div>
&lt;/section>
&lt;div class="divider">&lt;/div>
&lt;!-- ===== S9: KELANJUTAN ===== -->
&lt;section class="section anim-in" id="s9">
&lt;div class="section-header">&lt;div class="section-num">9&lt;/div>&lt;h2>Kelanjutan — Hasil Ini Dipakai untuk Apa?&lt;/h2>&lt;/div>
&lt;p style="font-size:13px;color:var(--gray-600);line-height:1.7;margin-bottom:1rem;">Curah hujan rencana dan kurva IDF bukan output akhir — melainkan &lt;strong>bahan baku&lt;/strong> untuk hampir seluruh analisis hidrologi hilir. Inilah rantai lengkapnya:&lt;/p>
&lt;div class="flow-row" style="justify-content:center;">
&lt;div class="flow-box" style="background:#f0f7ff;border:1px solid #93c5fd;color:#1e40af;">📁 Data Hujan&lt;br>Historis&lt;/div>
&lt;div class="flow-arrow">→&lt;/div>
&lt;div class="flow-box" style="background:#fef9c3;border:2px solid #d97706;color:#92400e;font-weight:700;">🌧️ Analisa&lt;br>Frekuensi&lt;br>&lt;span style="font-size:10px;font-weight:400;">← kita ada di sini&lt;/span>&lt;/div>
&lt;div class="flow-arrow">→&lt;/div>
&lt;div class="flow-box" style="background:#f0fdf4;border:1px solid #86efac;color:#166534;">💧 Debit Banjir&lt;br>Rencana Q_T&lt;/div>
&lt;div class="flow-arrow">→&lt;/div>
&lt;div class="flow-box" style="background:#fdf4ff;border:1px solid #d8b4fe;color:#581c87;">🏗️ Desain&lt;br>Infrastruktur&lt;/div>
&lt;/div>
&lt;div class="grid-3" style="margin-top:1.5rem;">
&lt;div class="card card-blue">
&lt;div class="card-label">① Debit Banjir Rencana&lt;/div>
&lt;p>CH rencana (mm) → debit puncak banjir (m³/s) menggunakan metode rasional atau hidrograf satuan. Digunakan untuk semua desain yang butuh angka debit.&lt;/p>
&lt;p style="margin-top:8px;">&lt;strong>Rumus Rasional:&lt;/strong>&lt;br>&lt;code style="background:#f0f7ff;padding:2px 6px;border-radius:4px;font-size:12px;">Q = 0.278 · C · I · A&lt;/code>&lt;/p>
&lt;p style="margin-top:6px;font-size:12px;color:var(--gray-500);">I dari kurva IDF (t = t_konsentrasi)&lt;/p>
&lt;/div>
&lt;div class="card card-green">
&lt;div class="card-label">② Pemodelan HEC-HMS&lt;/div>
&lt;p>CH rencana menjadi input hujan di HEC-HMS untuk menghasilkan hidrograf banjir di tiap titik DAS — volume banjir, waktu puncak, dan debit puncak per kala ulang.&lt;/p>
&lt;p style="margin-top:8px;font-size:12px;color:var(--gray-500);">→ Input: hietogram hujan dari CH rencana&lt;br>→ Output: hidrograf banjir Q(t)&lt;/p>
&lt;/div>
&lt;div class="card" style="border-left:4px solid #0891b2;">
&lt;div class="card-label">③ Pemodelan HEC-RAS&lt;/div>
&lt;p>Debit dari HEC-HMS dirouting di HEC-RAS untuk mendapatkan profil muka air banjir di sepanjang sungai, peta genangan, dan analisis sempadan sungai.&lt;/p>
&lt;p style="margin-top:8px;font-size:12px;color:var(--gray-500);">→ Input: debit Q_T (m³/s)&lt;br>→ Output: profil WSE, peta banjir&lt;/p>
&lt;/div>
&lt;div class="card card-amber">
&lt;div class="card-label">④ Desain Drainase (SWMM)&lt;/div>
&lt;p>Intensitas IDF pada durasi t = 60 menit menjadi input langsung dalam desain kapasitas saluran dan gorong-gorong perkotaan.&lt;/p>
&lt;p style="margin-top:8px;font-size:12px;color:var(--gray-500);">→ Input: I (mm/jam) dari tabel IDF&lt;br>→ Output: dimensi saluran (m)&lt;/p>
&lt;/div>
&lt;div class="card card-purple">
&lt;div class="card-label">⑤ Desain Bangunan Air&lt;/div>
&lt;p>Debit banjir rencana menentukan kapasitas spillway, dimensi pelimpah, tinggi jagaan (freeboard), dan desain kolam olak bendung/bendungan.&lt;/p>
&lt;p style="margin-top:8px;font-size:12px;color:var(--gray-500);">→ Bendung: T = 50–100 tahun&lt;br>→ Bendungan besar: T = 100–1000 tahun (PMF)&lt;/p>
&lt;/div>
&lt;div class="card card-navy">
&lt;div class="card-label">⑥ Analisis AMDAL&lt;/div>
&lt;p>Prakiraan dampak peningkatan limpasan akibat perubahan tutupan lahan oleh suatu proyek pembangunan — perbandingan kondisi sebelum dan sesudah proyek.&lt;/p>
&lt;p style="margin-top:8px;font-size:12px;color:var(--gray-500);">→ ΔQ sebelum vs sesudah proyek&lt;br>→ Rekomendasi mitigasi banjir&lt;/p>
&lt;/div>
&lt;/div>
&lt;div class="info-box">&lt;span class="box-icon">🔗&lt;/span>&lt;span>Analisa frekuensi adalah &lt;strong>titik awal dari rantai panjang analisis hidrologi&lt;/strong>. Semua angka yang tertulis di gambar desain drainase, tabel dimensi saluran, dan laporan AMDAL — semuanya berakar dari tabel curah hujan rencana dan kurva IDF yang dihasilkan di sini.&lt;/span>&lt;/div>
&lt;/section>
&lt;div class="divider">&lt;/div>
&lt;!-- ===== S10: KESIMPULAN ===== -->
&lt;section class="section anim-in" id="s10">
&lt;div class="section-header">&lt;div class="section-num">10&lt;/div>&lt;h2>Kesimpulan&lt;/h2>&lt;/div>
&lt;div class="card card-green">
&lt;div class="card-label" style="margin-bottom:12px;">Ringkasan 6 Langkah Analisa Frekuensi&lt;/div>
&lt;div class="step-flow">
&lt;div class="step-item">
&lt;div class="step-line">&lt;div class="step-dot" style="background:var(--green);">1&lt;/div>&lt;div class="step-connector">&lt;/div>&lt;/div>
&lt;div class="step-body">
&lt;div class="step-title">Kumpulkan data hujan historis ≥ 20 tahun&lt;/div>
&lt;div class="step-desc">Ambil nilai maksimum tahunan → Annual Maximum Series. Sumber: BMKG, atau GPM IMERG yang sudah dikalibrasi.&lt;/div>
&lt;/div>
&lt;/div>
&lt;div class="step-item">
&lt;div class="step-line">&lt;div class="step-dot" style="background:var(--green);">2&lt;/div>&lt;div class="step-connector">&lt;/div>&lt;/div>
&lt;div class="step-body">
&lt;div class="step-title">Hitung statistik dasar (x̄, S, Cs, CV)&lt;/div>
&lt;div class="step-desc">Nilai Cs dan CV menjadi panduan awal distribusi yang paling mungkin cocok untuk data di lokasi tersebut.&lt;/div>
&lt;/div>
&lt;/div>
&lt;div class="step-item">
&lt;div class="step-line">&lt;div class="step-dot" style="background:var(--green);">3&lt;/div>&lt;div class="step-connector">&lt;/div>&lt;/div>
&lt;div class="step-body">
&lt;div class="step-title">Fit ke 4 distribusi teoritis&lt;/div>
&lt;div class="step-desc">Normal, Log-Normal, Gumbel, Log-Pearson III — hitung parameter dan CDF teoritis masing-masing.&lt;/div>
&lt;/div>
&lt;/div>
&lt;div class="step-item">
&lt;div class="step-line">&lt;div class="step-dot" style="background:var(--green);">4&lt;/div>&lt;div class="step-connector">&lt;/div>&lt;/div>
&lt;div class="step-body">
&lt;div class="step-title">Uji kecocokan: KS Test + Chi-Kuadrat&lt;/div>
&lt;div class="step-desc">Pilih distribusi yang lulus kedua uji dengan nilai D dan χ² terkecil — distribusi yang paling mewakili data.&lt;/div>
&lt;/div>
&lt;/div>
&lt;div class="step-item">
&lt;div class="step-line">&lt;div class="step-dot" style="background:var(--green);">5&lt;/div>&lt;div class="step-connector">&lt;/div>&lt;/div>
&lt;div class="step-body">
&lt;div class="step-title">Hitung curah hujan rencana R_T&lt;/div>
&lt;div class="step-desc">Untuk T = 2, 5, 10, 25, 50, 100 tahun menggunakan distribusi terpilih. Ini adalah angka desain utama.&lt;/div>
&lt;/div>
&lt;/div>
&lt;div class="step-item">
&lt;div class="step-line">&lt;div class="step-dot" style="background:var(--green);">6&lt;/div>&lt;/div>
&lt;div class="step-body" style="padding-bottom:0;">
&lt;div class="step-title">Hitung kurva IDF dengan rumus Mononobe&lt;/div>
&lt;div class="step-desc">Ubah R₂₄ menjadi intensitas I (mm/jam) untuk berbagai durasi. Output siap dipakai untuk desain drainase, HEC-HMS, SWMM, dan lainnya.&lt;/div>
&lt;/div>
&lt;/div>
&lt;/div>
&lt;/div>
&lt;div class="success-box">&lt;span class="box-icon">🌧️&lt;/span>&lt;span>Analisa frekuensi curah hujan bukan sekadar menghitung angka statistik — ini adalah &lt;strong>fondasi dari seluruh perencanaan infrastruktur air&lt;/strong>. Dari data hujan historis yang tampak membosankan, kita mengekstrak informasi yang menjawab pertanyaan terpenting dalam hidrologi teknik: &lt;em>"Seberapa besar kita harus menyiapkan diri untuk menghadapi alam?"&lt;/em>&lt;/span>&lt;/div>
&lt;div style="margin-top:2rem;">
&lt;div class="card-label" style="font-size:11px;margin-bottom:10px;">ARTIKEL TERKAIT&lt;/div>
&lt;a href="mengenal-r-rmarkdown.html" class="nav-link">
&lt;span style="font-size:1.2rem;color:var(--gray-400);">←&lt;/span>
&lt;div>
&lt;div class="nav-link-label">Artikel Sebelumnya&lt;/div>
&lt;div class="nav-link-title">Mengenal R &amp; RMarkdown: Instalasi dan Proyek Pertama&lt;/div>
&lt;/div>
&lt;/a>
&lt;a href="perhitungan-debit-banjir-rencana.html" class="nav-link">
&lt;span style="font-size:1.2rem;color:var(--gray-400);">→&lt;/span>
&lt;div>
&lt;div class="nav-link-label">Artikel Selanjutnya&lt;/div>
&lt;div class="nav-link-title">Debit Banjir Rencana: Dari Curah Hujan ke Hidrograf&lt;/div>
&lt;/div>
&lt;/a>
&lt;/div>
&lt;p style="font-size:12px;color:var(--gray-400);margin-top:2rem;border-top:1px solid var(--gray-200);padding-top:1rem;">
Semua rumus dalam artikel ini mengikuti metode standar hidrologi Indonesia, konsisten dengan &lt;strong>SNI 2415:2016&lt;/strong>. Referensi: Triatmodjo (2008), Sri Harto (1993), Soemarto (1995), Mononobe (1932). Analisis menggunakan R versi 4.x dengan paket: &lt;code>e1071&lt;/code>, &lt;code>ggplot2&lt;/code>, &lt;code>dplyr&lt;/code>, &lt;code>tidyr&lt;/code>, &lt;code>flextable&lt;/code>, &lt;code>readxl&lt;/code>.
&lt;/p>
&lt;/section>
&lt;/div>
&lt;script>
/* ================================================================
DATA &amp; CALCULATIONS
================================================================ */
const amsData = [
{yr:2000, val:87.5},{yr:2001,val:102.3},{yr:2002,val:65.8},
{yr:2003,val:118.4},{yr:2004,val:93.7},{yr:2005,val:76.1},
{yr:2006,val:158.9},{yr:2007,val:99.4},{yr:2008,val:143.2},
{yr:2009,val:112.0},{yr:2010,val:78.2},{yr:2011,val:134.6},
{yr:2012,val:89.1},{yr:2013,val:97.5},{yr:2014,val:108.2},
{yr:2015,val:82.6},{yr:2016,val:121.3},{yr:2017,val:74.8},
{yr:2018,val:96.4},{yr:2019,val:145.7},{yr:2020,val:118.3},
{yr:2021,val:88.0},{yr:2022,val:127.4},{yr:2023,val:103.8},
{yr:2024,val:91.2}
];
const n = amsData.length;
const vals = amsData.map(d=>d.val);
const xbar = vals.reduce((a,b)=>a+b,0)/n;
const S = Math.sqrt(vals.reduce((a,v)=>a+(v-xbar)**2,0)/(n-1));
const CV = S/xbar;
const Cs = (n*vals.reduce((a,v)=>a+(v-xbar)**3,0))/((n-1)*(n-2)*S**3);
const alpha_g = S*Math.PI/Math.sqrt(6);
const mu_g = xbar - 0.5772*alpha_g;
const T_arr = [2,5,10,25,50,100];
function KT_gumbel(T){ return -(Math.sqrt(6)/Math.PI)*(0.5772+Math.log(Math.log(T/(T-1)))); }
function RT_gumbel(T){ return xbar + KT_gumbel(T)*S; }
// Log-Normal
const lnvals = vals.map(v=>Math.log(v));
const ybar = lnvals.reduce((a,b)=>a+b,0)/n;
const Sy = Math.sqrt(lnvals.reduce((a,v)=>a+(v-ybar)**2,0)/(n-1));
function RT_lognorm(T){
const z = (function(p){ // inverse normal CDF approximation
const a=[2.515517,0.802853,0.010328],b=[1.432788,0.189269,0.001308];
const t=Math.sqrt(-2*Math.log(p&lt;0.5?p:1-p));
const num=a[0]+a[1]*t+a[2]*t*t, den=1+b[0]*t+b[1]*t*t+b[2]*t*t*t;
return (p&lt;0.5?-1:1)*(t-num/den);
})(1-1/T);
return Math.exp(ybar+z*Sy);
}
// Normal - simple
function RT_normal(T){
const z = (function(p){
const a=[2.515517,0.802853,0.010328],b=[1.432788,0.189269,0.001308];
const t=Math.sqrt(-2*Math.log(p&lt;0.5?p:1-p));
const num=a[0]+a[1]*t+a[2]*t*t, den=1+b[0]*t+b[1]*t*t+b[2]*t*t*t;
return (p&lt;0.5?-1:1)*(t-num/den);
})(1-1/T);
return xbar + z*S;
}
// LP3 - simplified (using KT from table approximation based on Cs)
const KT_LP3_table = {
2:[0.000,-0.033,-0.064,-0.254,-0.330,-0.396],
5:[0.842,0.856,0.869,0.938,0.967,0.990],
10:[1.282,1.318,1.353,1.518,1.588,1.643],
25:[1.751,1.837,1.929,2.219,2.388,2.515],
50:[2.054,2.193,2.342,2.809,3.059,3.256],
100:[2.326,2.540,2.770,3.388,3.720,3.990]
};
// Cs of ln(x) data
const Cs_ln = (n*lnvals.reduce((a,v)=>a+(v-ybar)**3,0))/((n-1)*(n-2)*Sy**3);
// Use Cs_ln = ~0.5 index 4
function RT_LP3(T){
const i = 4; // approximate for moderate Cs
return Math.exp(ybar + KT_LP3_table[T][i]*Sy);
}
/* ================================================================
BUILD AMS TABLE
================================================================ */
function buildAMSTable(){
const tb = document.getElementById('tblAMS');
// split into 3 columns of data
const perCol = Math.ceil(n/3);
let html = '&lt;thead>&lt;tr>';
for(let c=0;c&lt;3;c++) html += '&lt;th>Tahun&lt;/th>&lt;th>Hujan Maks (mm)&lt;/th>';
html += '&lt;/tr>&lt;/thead>&lt;tbody>';
for(let r=0;r&lt;perCol;r++){
html += '&lt;tr>';
for(let c=0;c&lt;3;c++){
const idx = c*perCol+r;
if(idx&lt;n){ html += `&lt;td>${amsData[idx].yr}&lt;/td>&lt;td>${amsData[idx].val}&lt;/td>`; }
else { html += '&lt;td colspan="2">&lt;/td>'; }
}
html += '&lt;/tr>';
}
html += '&lt;/tbody>';
tb.innerHTML = html;
}
/* ================================================================
BUILD STAT CARDS
================================================================ */
function buildStatCards(){
const c = document.getElementById('statCards');
const stats = [
{lbl:'Rata-rata (x̄)',val:xbar.toFixed(2)+' mm',sub:'Mean tahunan',cls:'blue'},
{lbl:'Std. Deviasi (S)',val:S.toFixed(2)+' mm',sub:'Variabilitas data',cls:'amber'},
{lbl:'Kemencengan (Cs)',val:Cs.toFixed(3),sub:'Cs > 0 → ekor kanan',cls:'purple'},
{lbl:'Koef. Variasi (CV)',val:(CV*100).toFixed(1)+'%',sub:'S / x̄',cls:'green'},
];
c.innerHTML = stats.map(s=>`
&lt;div class="metric-card ${s.cls}">
&lt;div class="metric-label">${s.lbl}&lt;/div>
&lt;div class="metric-val">${s.val}&lt;/div>
&lt;div class="metric-sub">${s.sub}&lt;/div>
&lt;/div>`).join('');
}
/* ================================================================
BUILD RENCANA TABLE
================================================================ */
function buildRencanaTable(){
const tb = document.getElementById('tblRencana');
const uses = ['Gorong-gorong sederhana','Drainase perkotaan kecil','Drainase utama kota','Sungai / jembatan sedang','Tanggul banjir / bendung','Bendungan besar / vital'];
let html = `&lt;thead>&lt;tr>
&lt;th>Kala Ulang T&lt;/th>&lt;th>K_T (Gumbel)&lt;/th>
&lt;th class="th-blue">R_T Gumbel (mm)&lt;/th>
&lt;th>Kegunaan Umum&lt;/th>&lt;/tr>&lt;/thead>&lt;tbody>`;
T_arr.forEach((T,i)=>{
const kt = KT_gumbel(T), rt = RT_gumbel(T);
const hi = i>=3 ? 'style="color:var(--amber);font-weight:700;"' : '';
html += `&lt;tr ${i>=3?'class="highlight"':''}>
&lt;td ${hi}>T = ${T} tahun&lt;/td>
&lt;td>${kt.toFixed(3)}&lt;/td>
&lt;td style="font-weight:700;color:var(--navy2);">${rt.toFixed(1)}&lt;/td>
&lt;td class="td-label" style="font-family:inherit;font-size:11px;color:var(--gray-600);">${uses[i]}&lt;/td>
&lt;/tr>`;
});
html += '&lt;/tbody>';
tb.innerHTML = html;
}
/* ================================================================
BUILD IDF TABLE
================================================================ */
function buildIDFTable(){
const tb = document.getElementById('tblIDF');
const durs = [{t:5/60,lbl:'5 mnt'},{t:10/60,lbl:'10 mnt'},{t:15/60,lbl:'15 mnt'},
{t:0.5,lbl:'30 mnt'},{t:1,lbl:'60 mnt ★'},{t:2,lbl:'2 jam'},
{t:3,lbl:'3 jam'},{t:6,lbl:'6 jam'},{t:12,lbl:'12 jam'},{t:24,lbl:'24 jam'}];
function mono(R24,t){ return (R24/24)*Math.pow(24/t,2/3); }
let html = '&lt;thead>&lt;tr>&lt;th>Durasi&lt;/th>';
T_arr.forEach(T=>{ html+=`&lt;th class="th-blue">T=${T} thn (mm/j)&lt;/th>`; });
html += '&lt;/tr>&lt;/thead>&lt;tbody>';
durs.forEach(d=>{
const isKey = Math.abs(d.t-1)&lt;0.01;
html += `&lt;tr ${isKey?'style="background:rgba(180,83,9,0.06);"':''}>
&lt;td class="td-label" style="font-family:inherit;${isKey?'color:var(--amber);font-weight:700;':''}">
${d.lbl}&lt;/td>`;
T_arr.forEach(T=>{
const i = mono(RT_gumbel(T),d.t);
html += `&lt;td style="${isKey?'font-weight:700;color:var(--amber);':''}">${i.toFixed(1)}&lt;/td>`;
});
html += '&lt;/tr>';
});
html += '&lt;/tbody>';
tb.innerHTML = html;
}
/* ================================================================
CHARTS
================================================================ */
const CH = {};
function buildCharts(){
if(CH._built) return; CH._built = true;
/* CDF Chart */
const sorted = [...vals].sort((a,b)=>a-b);
const emp = sorted.map((_,i)=>(i+1)/(n+1));
const xRange = Array.from({length:60},(_,i)=>55+i*2);
const cdfGumbel = x => Math.exp(-Math.exp(-(x-mu_g)/alpha_g));
const cdfNorm = x => { const z=(x-xbar)/S; return 0.5*(1+erf(z/Math.sqrt(2))); };
const cdfLN = x => { const z=(Math.log(x)-ybar)/Sy; return 0.5*(1+erf(z/Math.sqrt(2))); };
function erf(x){ const t=1/(1+0.3275911*Math.abs(x)); const y=1-t*(0.254829592-t*(0.284496736-t*(1.421413741-t*(1.453152027-t*1.061405429))))*Math.exp(-x*x); return x>=0?y:-y; }
// LP3 approximation via Gumbel-shifted
const cdfLP3 = x => Math.exp(-Math.exp(-(x-mu_g*0.97)/alpha_g));
const ctx1 = document.getElementById('chartCDF');
if(ctx1) CH.cdf = new Chart(ctx1,{
type:'scatter',
data:{datasets:[
{label:'Data Empiris',data:sorted.map((x,i)=>({x,y:emp[i]})),backgroundColor:'#64748b',pointRadius:4,order:5},
{label:'Normal',type:'line',data:xRange.map(x=>({x,y:cdfNorm(x)})),borderColor:'#2563eb',borderWidth:2,pointRadius:0,tension:0.4,order:4},
{label:'Log-Normal',type:'line',data:xRange.map(x=>({x,y:cdfLN(x)})),borderColor:'#0891b2',borderWidth:2,pointRadius:0,tension:0.4,order:3},
{label:'Gumbel',type:'line',data:xRange.map(x=>({x,y:cdfGumbel(x)})),borderColor:'#d97706',borderWidth:2.5,pointRadius:0,tension:0.4,order:2},
{label:'Log-Pearson III',type:'line',data:xRange.map(x=>({x,y:cdfLP3(x)})),borderColor:'#16a34a',borderWidth:2,pointRadius:0,tension:0.4,borderDash:[5,3],order:1},
]},
options:{responsive:true,maintainAspectRatio:false,
plugins:{legend:{display:false},tooltip:{callbacks:{label:c=>`${c.dataset.label}: (${c.parsed.x.toFixed(0)} mm, P=${c.parsed.y.toFixed(3)})`}}},
scales:{
x:{title:{display:true,text:'Curah Hujan (mm)'},grid:{color:'rgba(0,0,0,0.05)'}},
y:{title:{display:true,text:'Probabilitas Kumulatif F(x)'},min:0,max:1,grid:{color:'rgba(0,0,0,0.05)'}}
}
}
});
/* KS Chart */
const ctx2 = document.getElementById('chartKS');
if(ctx2) CH.ks = new Chart(ctx2,{
type:'bar',
data:{
labels:['Normal','Log-Normal','Gumbel (Terbaik)','Log-Pearson III'],
datasets:[
{label:'D-hitung',data:[0.091,0.074,0.058,0.063],
backgroundColor:['rgba(37,99,235,0.75)','rgba(8,145,178,0.75)','rgba(217,119,6,0.9)','rgba(22,163,74,0.75)'],
borderRadius:5,order:1},
{type:'line',label:'D-kritis (α=5%, n=25) = 0.264',data:[0.264,0.264,0.264,0.264],
borderColor:'#dc2626',borderWidth:2,borderDash:[6,4],pointRadius:0,fill:false,order:0}
]
},
options:{responsive:true,maintainAspectRatio:false,
plugins:{
legend:{position:'bottom',labels:{font:{size:11},usePointStyle:true}},
tooltip:{callbacks:{label:c=>c.dataset.label+': '+Number(c.raw).toFixed(3)}}
},
scales:{
x:{grid:{display:false}},
y:{min:0,max:0.35,title:{display:true,text:'Nilai D'},ticks:{font:{size:11}}}
}
}
});
/* Rencana Chart */
const ctx3 = document.getElementById('chartRencana');
if(ctx3) CH.renc = new Chart(ctx3,{
type:'bar',
data:{
labels:T_arr.map(t=>`T=${t} thn`),
datasets:[
{label:'Normal',data:T_arr.map(RT_normal),backgroundColor:'rgba(37,99,235,0.7)',borderRadius:3},
{label:'Log-Normal',data:T_arr.map(RT_lognorm),backgroundColor:'rgba(8,145,178,0.7)',borderRadius:3},
{label:'Gumbel ★',data:T_arr.map(RT_gumbel),backgroundColor:'rgba(217,119,6,0.9)',borderRadius:3,borderWidth:2,borderColor:'#92400e'},
{label:'Log-Pearson III',data:T_arr.map(RT_LP3),backgroundColor:'rgba(22,163,74,0.7)',borderRadius:3},
]
},
options:{responsive:true,maintainAspectRatio:false,
plugins:{
legend:{position:'bottom',labels:{font:{size:11},usePointStyle:true}},
tooltip:{callbacks:{label:c=>c.dataset.label+': '+Number(c.raw).toFixed(1)+' mm'}}
},
scales:{
x:{grid:{display:false},ticks:{font:{size:11}}},
y:{title:{display:true,text:'Curah Hujan Rencana (mm)'},min:60,ticks:{font:{size:11}}}
}
}
});
/* IDF Chart */
const ctx4 = document.getElementById('chartIDF');
if(ctx4){
const durs = [5/60,10/60,15/60,0.5,1,2,3,6,12,24];
const durLabels = ["5'","10'","15'","30'","1 jam","2 jam","3 jam","6 jam","12 jam","24 jam"];
const mono = (R24,t) => (R24/24)*Math.pow(24/t,2/3);
const colors = ['#7c3aed','#dc2626','#d97706','#0284c7','#2563eb','#64748b'];
CH.idf = new Chart(ctx4,{
type:'line',
data:{
labels:durLabels,
datasets:T_arr.slice().reverse().map((T,i)=>({
label:`T = ${T} tahun`,
data:durs.map(t=>mono(RT_gumbel(T),t)),
borderColor:colors[i],
backgroundColor:colors[i]+'22',
borderWidth: i===0?2.5:1.8,
pointRadius:3,
tension:0.3,
fill:false
}))
},
options:{responsive:true,maintainAspectRatio:false,
plugins:{
legend:{position:'bottom',labels:{font:{size:11},usePointStyle:true}},
tooltip:{callbacks:{label:c=>c.dataset.label+': '+Number(c.raw).toFixed(1)+' mm/jam'}}
},
scales:{
x:{grid:{color:'rgba(0,0,0,0.05)'},ticks:{font:{size:11}}},
y:{title:{display:true,text:'Intensitas (mm/jam)'},min:0,ticks:{font:{size:11}},
grid:{color:'rgba(0,0,0,0.05)'}}
}
}
});
}
}
/* ================================================================
TOC, PROGRESS BAR, ANIMATION
================================================================ */
function updateProgress(){
const el=document.getElementById('progBar'), pct=document.getElementById('progPct');
const scroll=window.scrollY, total=document.body.scrollHeight-window.innerHeight;
const p=total>0?Math.round(scroll/total*100):0;
el.style.width=p+'%'; pct.textContent=p+'%';
}
window.addEventListener('scroll',updateProgress,{passive:true});
const tocLinks = document.querySelectorAll('.toc-link');
const sections = Array.from(document.querySelectorAll('section[id], div[id]'));
function updateToc(){
let cur='';
sections.forEach(s=>{
if(window.scrollY>=s.offsetTop-100) cur=s.id;
});
tocLinks.forEach(l=>{
const h=l.getAttribute('href').replace('#','');
l.classList.toggle('active',h===cur);
});
}
window.addEventListener('scroll',updateToc,{passive:true});
function toggleToc(){
document.getElementById('tocFloat').classList.toggle('collapsed');
}
let tocVisible = false;
function toggleTocMobile(){
tocVisible=!tocVisible;
const tf=document.getElementById('tocFloat');
if(tocVisible){ tf.style.display='block'; tf.style.position='fixed'; tf.style.right='0'; tf.style.top='80px'; }
else { tf.style.display=''; }
}
const io = new IntersectionObserver(entries=>{
entries.forEach(e=>{
if(e.isIntersecting){ e.target.classList.add('visible'); buildCharts(); }
});
},{threshold:0.01,rootMargin:'0px 0px -10px 0px'});
document.querySelectorAll('.anim-in').forEach(el=>io.observe(el));
function copyCode(btn){
const text=btn.closest('.code-wrap').querySelector('pre').innerText;
navigator.clipboard.writeText(text).then(()=>{ btn.textContent='✓ Tersalin!'; setTimeout(()=>btn.textContent='Salin',2000); });
}
/* INIT */
buildAMSTable();
buildStatCards();
buildRencanaTable();
buildIDFTable();
updateProgress();
setTimeout(buildCharts,400);
&lt;/script></description></item><item><title>Kalibrasi Data GPM dengan Data BMKG</title><link>https://www.irpanchumaedi.com/post/materi-kalibrasi-data-gpm-bmkg/</link><pubDate>Thu, 01 Feb 2024 00:00:00 +0000</pubDate><guid>https://www.irpanchumaedi.com/post/materi-kalibrasi-data-gpm-bmkg/</guid><description>
&lt;style>
.materi-kalibrasi {
--navy:#0A2342; --blue:#185fa5; --blue-mid:#378add; --blue-light:#85b7eb; --blue-pale:#e6f1fb;
--red:#B91C1C; --red-light:#fee2e2; --navy2:#1A5276;
--amber:#B45309; --amber-light:#fef3c7;
--purple:#6D28D9; --purple-light:#ede9fe;
--green:#1d6f42; --green-light:#d1fae5;
--gray-100:#f8fafc; --gray-200:#e2e8f0; --gray-300:#cbd5e1;
--gray-500:#64748b; --gray-600:#475569; --gray-700:#334155; --gray-900:#0f172a;
--radius:10px; --radius-sm:6px;
--shadow:0 2px 12px rgba(0,0,0,0.07);
--shadow-md:0 4px 20px rgba(0,0,0,0.10);
--code-bg:#1e1e2e;
}
.materi-kalibrasi, .materi-kalibrasi *::before, .materi-kalibrasi *::after {box-sizing:border-box;margin:0;padding:0;}
/.materi-kalibrasi * STICKY NAV */
.sticky-nav {position:sticky;top:0;z-index:200;background:#fff;border-bottom:1px solid var(--gray-200);box-shadow:var(--shadow);}
.materi-kalibrasi .sticky-inner {max-width:900px;margin:0 auto;padding:0 1.25rem;display:flex;align-items:center;gap:1rem;height:52px;}
.materi-kalibrasi .sticky-title {font-size:13px;font-weight:600;color:var(--navy);white-space:nowrap;}
.materi-kalibrasi .progress-track {flex:1;height:4px;background:var(--gray-200);border-radius:2px;}
.materi-kalibrasi .progress-fill {height:100%;background:linear-gradient(90deg,var(--blue),var(--purple));border-radius:2px;width:0%;transition:width 0.3s;}
.materi-kalibrasi .sticky-pct {font-size:12px;color:var(--gray-500);min-width:32px;}
/.materi-kalibrasi * FLOATING TOC */
.toc-float {position:fixed;top:80px;right:0;width:180px;background:#fff;border:1px solid var(--gray-200);border-right:none;border-radius:var(--radius) 0 0 var(--radius);box-shadow:-2px 4px 16px rgba(0,0,0,0.09);z-index:150;transition:all 0.28s cubic-bezier(0.4,0,0.2,1);overflow:hidden;}
.materi-kalibrasi .toc-float.collapsed {width:32px;}
.materi-kalibrasi .toc-head {display:flex;align-items:center;justify-content:space-between;padding:8px 10px 8px 12px;border-bottom:1px solid var(--gray-200);cursor:pointer;user-select:none;background:var(--navy);border-radius:var(--radius) 0 0 0;}
.materi-kalibrasi .toc-head:hover {background:#1a3a5c;}
.materi-kalibrasi .toc-title {font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:0.07em;color:rgba(255,255,255,0.9);white-space:nowrap;overflow:hidden;}
.materi-kalibrasi .toc-chevron {font-size:11px;color:rgba(255,255,255,0.7);flex-shrink:0;transition:transform 0.25s;margin-left:6px;}
.materi-kalibrasi .toc-float.collapsed .toc-chevron {transform:rotate(180deg);}
.materi-kalibrasi .toc-float.collapsed .toc-title {opacity:0;width:0;margin:0;}
.materi-kalibrasi .toc-body {padding:8px 6px;max-height:calc(100vh - 140px);overflow-y:auto;scrollbar-width:thin;scrollbar-color:var(--gray-300) transparent;}
.materi-kalibrasi .toc-body::-webkit-scrollbar {width:3px;}
.materi-kalibrasi .toc-body::-webkit-scrollbar-thumb {background:var(--gray-300);border-radius:2px;}
.materi-kalibrasi .toc-float.collapsed .toc-body {display:none;}
.materi-kalibrasi .toc-link {display:block;font-size:11px;color:var(--gray-600);text-decoration:none;padding:3px 8px;border-radius:4px;border-left:2px solid transparent;margin-bottom:1px;transition:all 0.15s;line-height:1.4;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
.materi-kalibrasi .toc-link:hover {background:var(--blue-pale);color:var(--blue);border-left-color:var(--blue);}
.materi-kalibrasi .toc-link.active {background:var(--blue-pale);color:var(--blue);border-left-color:var(--blue);font-weight:600;}
.materi-kalibrasi .toc-link.sub {padding-left:14px;font-size:10px;color:var(--gray-500);}
.materi-kalibrasi .toc-link.sub.active {color:var(--blue);}
.materi-kalibrasi .toc-toggle {display:none;position:fixed;bottom:20px;right:16px;width:40px;height:40px;border-radius:50%;background:var(--navy);color:#fff;border:none;font-size:16px;cursor:pointer;box-shadow:var(--shadow-md);z-index:160;align-items:center;justify-content:center;}
@.materi-kalibrasi media(max-width:1100px) {.toc-float{display:none;}.materi-kalibrasi .toc-toggle {display:flex;}.materi-kalibrasi }
/* HERO */
.hero {background:linear-gradient(135deg,#0A2342 0%,#1A3a5c 55%,#2d1065 100%);color:#fff;padding:3rem 1.5rem 2.5rem;border-radius:0 0 var(--radius) var(--radius);margin-bottom:2rem;position:relative;overflow:hidden;}
.materi-kalibrasi .hero::before {content:'';position:absolute;top:-80px;right:-60px;width:300px;height:300px;border-radius:50%;background:rgba(55,138,221,0.12);}
.materi-kalibrasi .hero::after {content:'';position:absolute;bottom:-100px;left:10%;width:250px;height:250px;border-radius:50%;background:rgba(109,40,217,0.10);}
.materi-kalibrasi .hero-inner {max-width:900px;margin:0 auto;position:relative;z-index:1;}
.materi-kalibrasi .hero-badge {display:inline-block;background:rgba(55,138,221,0.25);color:#85b7eb;font-size:11px;padding:3px 10px;border-radius:20px;margin-bottom:0.75rem;letter-spacing:0.04em;}
.materi-kalibrasi .hero h1 {font-size:clamp(22px,4vw,30px);font-weight:700;line-height:1.3;margin-bottom:0.5rem;}
.materi-kalibrasi .hero-sub {font-size:14px;color:rgba(255,255,255,0.65);margin-bottom:1.5rem;}
.materi-kalibrasi .hero-pills {display:flex;flex-wrap:wrap;gap:8px;margin-top:1rem;}
.materi-kalibrasi .hero-pill {display:inline-block;font-size:11px;padding:4px 10px;border-radius:20px;font-weight:600;border:1px solid;}
.materi-kalibrasi .pill-red {background:rgba(185,28,28,0.25);color:#fca5a5;border-color:rgba(185,28,28,0.4);}
.materi-kalibrasi .pill-blue {background:rgba(26,82,118,0.3);color:#85b7eb;border-color:rgba(26,82,118,0.5);}
.materi-kalibrasi .pill-amber {background:rgba(180,83,9,0.25);color:#fcd34d;border-color:rgba(180,83,9,0.4);}
.materi-kalibrasi .pill-purple {background:rgba(109,40,217,0.25);color:#c4b5fd;border-color:rgba(109,40,217,0.4);}
.materi-kalibrasi .hero-meta {display:flex;flex-wrap:wrap;gap:1.25rem;margin-top:1rem;}
.materi-kalibrasi .hero-meta-item {font-size:12px;color:rgba(255,255,255,0.55);}
/.materi-kalibrasi * LAYOUT */
.wrap {max-width:900px;margin:0 auto;padding:0 1.25rem 4rem;}
/.materi-kalibrasi * SECTIONS */
.section {margin-bottom:3rem;}
.materi-kalibrasi .section-header {display:flex;align-items:center;gap:12px;margin-bottom:1.25rem;}
.materi-kalibrasi .section-num {width:32px;height:32px;border-radius:50%;background:var(--navy);color:#fff;font-size:13px;font-weight:600;display:flex;align-items:center;justify-content:center;flex-shrink:0;}
.materi-kalibrasi .section-header h2 {font-size:20px;font-weight:700;color:var(--gray-900);}
/.materi-kalibrasi * CARDS */
.card {background:#fff;border-radius:var(--radius);padding:1.25rem 1.5rem;box-shadow:var(--shadow);margin-bottom:1rem;}
.materi-kalibrasi .card-navy {border-left:4px solid var(--navy);}
.materi-kalibrasi .card-blue {border-left:4px solid var(--blue-mid);}
.materi-kalibrasi .card-red {border-left:4px solid var(--red);}
.materi-kalibrasi .card-amber {border-left:4px solid var(--amber);}
.materi-kalibrasi .card-green {border-left:4px solid var(--green);}
.materi-kalibrasi .card-purple {border-left:4px solid var(--purple);}
.materi-kalibrasi .card-label {font-size:10px;font-weight:600;text-transform:uppercase;letter-spacing:0.07em;color:var(--gray-500);margin-bottom:6px;}
.materi-kalibrasi .card p {font-size:13px;color:var(--gray-600);line-height:1.65;}
/.materi-kalibrasi * GRID */
.grid-2 {display:grid;grid-template-columns:1fr 1fr;gap:1rem;margin-bottom:1rem;}
.materi-kalibrasi .grid-3 {display:grid;grid-template-columns:1fr 1fr 1fr;gap:1rem;margin-bottom:1rem;}
.materi-kalibrasi .grid-4 {display:grid;grid-template-columns:repeat(4,1fr);gap:1rem;margin-bottom:1.5rem;}
@.materi-kalibrasi media(max-width:640px) {.grid-2,.grid-3,.grid-4{grid-template-columns:1fr;}.materi-kalibrasi }
/* METRIC CARDS */
.metric-card {background:#fff;border-radius:var(--radius);padding:1rem 1.1rem;box-shadow:var(--shadow);text-align:center;position:relative;overflow:hidden;}
.materi-kalibrasi .metric-card::before {content:'';position:absolute;top:0;left:0;right:0;height:3px;}
.materi-kalibrasi .metric-card.red::before {background:var(--red);}
.materi-kalibrasi .metric-card.blue::before {background:var(--navy2);}
.materi-kalibrasi .metric-card.green::before {background:var(--green);}
.materi-kalibrasi .metric-card.amber::before {background:var(--amber);}
.materi-kalibrasi .metric-label {font-size:11px;color:var(--gray-500);font-weight:600;margin-bottom:4px;}
.materi-kalibrasi .metric-raw {font-size:14px;font-weight:700;color:var(--red);}
.materi-kalibrasi .metric-m4 {font-size:14px;font-weight:700;color:var(--navy2);}
.materi-kalibrasi .metric-arrow {font-size:11px;color:var(--green);margin:3px 0;}
.materi-kalibrasi .metric-thresh {font-size:10px;color:var(--gray-500);}
/.materi-kalibrasi * INFO BOXES */
.info-box {display:flex;gap:10px;background:var(--blue-pale);border:1px solid #b5d4f4;border-radius:var(--radius-sm);padding:.9rem 1rem;font-size:13px;color:#0c447c;margin:1rem 0;line-height:1.55;}
.materi-kalibrasi .warn-box {display:flex;gap:10px;background:var(--amber-light);border:1px solid #fac775;border-radius:var(--radius-sm);padding:.9rem 1rem;font-size:13px;color:var(--amber);margin:1rem 0;line-height:1.55;}
.materi-kalibrasi .success-box {display:flex;gap:10px;background:var(--green-light);border:1px solid #a7f3d0;border-radius:var(--radius-sm);padding:.9rem 1rem;font-size:13px;color:var(--green);margin:1rem 0;line-height:1.55;}
.materi-kalibrasi .purple-box {display:flex;gap:10px;background:var(--purple-light);border:1px solid #c4b5fd;border-radius:var(--radius-sm);padding:.9rem 1rem;font-size:13px;color:var(--purple);margin:1rem 0;line-height:1.55;}
.materi-kalibrasi .box-icon {font-size:18px;flex-shrink:0;line-height:1.3;}
/.materi-kalibrasi * FORMULA */
.formula-block {background:#0f172a;border-radius:var(--radius-sm);padding:1rem 1.25rem;margin:.75rem 0;font-family:'Consolas','Courier New',monospace;font-size:14px;color:#e2e8f0;text-align:center;letter-spacing:0.02em;border-left:4px solid var(--purple);}
.materi-kalibrasi .formula-block .eq-label {font-size:11px;color:#94a3b8;display:block;margin-bottom:4px;text-align:left;}
.materi-kalibrasi .formula-block .eq-main {color:#c4b5fd;font-size:15px;}
.materi-kalibrasi .formula-block .eq-desc {font-size:11px;color:#64748b;display:block;margin-top:6px;text-align:left;}
/.materi-kalibrasi * STEP FLOW */
.step-flow {margin:1rem 0;}
.materi-kalibrasi .step-item {display:flex;gap:14px;}
.materi-kalibrasi .step-line {display:flex;flex-direction:column;align-items:center;}
.materi-kalibrasi .step-dot {width:30px;height:30px;border-radius:50%;background:var(--blue-mid);color:#fff;font-size:12px;font-weight:600;display:flex;align-items:center;justify-content:center;flex-shrink:0;}
.materi-kalibrasi .step-dot.navy {background:var(--navy);}
.materi-kalibrasi .step-dot.purple {background:var(--purple);}
.materi-kalibrasi .step-connector {width:2px;background:var(--gray-200);flex:1;min-height:16px;margin:3px 0;}
.materi-kalibrasi .step-body {padding-bottom:20px;flex:1;}
.materi-kalibrasi .step-title {font-size:14px;font-weight:600;color:var(--gray-800);margin-bottom:4px;}
.materi-kalibrasi .step-desc {font-size:13px;color:var(--gray-600);line-height:1.6;}
/.materi-kalibrasi * CODE */
.code-wrap {background:var(--code-bg);border-radius:var(--radius-sm);overflow:hidden;margin:.75rem 0;box-shadow:var(--shadow-md);}
.materi-kalibrasi .code-header {background:#2a2a3e;padding:7px 14px;display:flex;align-items:center;justify-content:space-between;}
.materi-kalibrasi .code-lang {font-size:11px;color:#a0aec0;font-weight:600;letter-spacing:0.05em;display:flex;align-items:center;gap:6px;}
.materi-kalibrasi .code-lang .dot {width:8px;height:8px;border-radius:50%;}
.materi-kalibrasi .copy-btn {font-size:11px;color:#a0aec0;cursor:pointer;background:none;border:none;padding:2px 8px;border-radius:4px;transition:all 0.2s;}
.materi-kalibrasi .copy-btn:hover {background:rgba(255,255,255,0.1);color:#fff;}
.materi-kalibrasi pre {padding:1rem 1.25rem;overflow-x:auto;font-family:'Consolas','Courier New',monospace;font-size:12.5px;line-height:1.75;color:#cdd6f4;}
.materi-kalibrasi pre::-webkit-scrollbar {height:4px;}
.materi-kalibrasi pre::-webkit-scrollbar-thumb {background:#4a4a6a;border-radius:2px;}
.materi-kalibrasi .kw {color:#cba6f7;}.materi-kalibrasi .fn {color:#89b4fa;}.materi-kalibrasi .str {color:#a6e3a1;}.materi-kalibrasi .num {color:#fab387;}.materi-kalibrasi .cm {color:#6c7086;font-style:italic;}.materi-kalibrasi .op {color:#89dceb;}.materi-kalibrasi .pkg {color:#f38ba8;}
/.materi-kalibrasi * IMAGE FIGURE */
.fig-wrap {background:#fff;border-radius:var(--radius);box-shadow:var(--shadow-md);overflow:hidden;margin-bottom:1.5rem;}
.materi-kalibrasi .fig-header {background:var(--gray-100);padding:8px 14px;font-size:11px;font-weight:600;color:var(--gray-500);border-bottom:1px solid var(--gray-200);display:flex;align-items:center;gap:6px;}
.materi-kalibrasi .fig-img {width:100%;display:block;}
.materi-kalibrasi .fig-caption {padding:8px 14px;font-size:12px;color:var(--gray-500);border-top:1px solid var(--gray-200);font-style:italic;}
/.materi-kalibrasi * TABLE */
.tbl-wrap {overflow-x:auto;margin-bottom:1rem;}
.materi-kalibrasi .data-tbl {width:100%;border-collapse:collapse;font-size:13px;min-width:400px;}
.materi-kalibrasi .data-tbl th {background:var(--navy);color:#fff;padding:8px 12px;text-align:center;font-weight:600;font-size:12px;}
.materi-kalibrasi .data-tbl td {padding:6px 12px;border-bottom:1px solid var(--gray-200);text-align:right;font-family:'Consolas',monospace;font-size:12px;}
.materi-kalibrasi .data-tbl td:first-child {text-align:center;font-family:inherit;font-weight:600;color:var(--gray-700);}
.materi-kalibrasi .data-tbl tr:hover td {background:var(--blue-pale);}
.materi-kalibrasi .data-tbl .pos {color:var(--red);font-weight:700;}
.materi-kalibrasi .data-tbl .neg {color:var(--navy2);}
.materi-kalibrasi .data-tbl .good {color:var(--green);font-weight:700;}
.materi-kalibrasi .data-tbl .bad {color:var(--red);}
.materi-kalibrasi .data-tbl .head-raw {background:var(--red)!important;}
.materi-kalibrasi .data-tbl .head-m4 {background:var(--navy2)!important;}
.materi-kalibrasi .data-tbl .head-obs {background:var(--amber)!important;}
.materi-kalibrasi .data-tbl .head-fk {background:var(--purple)!important;}
/.materi-kalibrasi * CHART */
.chart-card {background:#fff;border-radius:var(--radius);padding:1.25rem 1.5rem 1rem;box-shadow:var(--shadow);margin-bottom:1.25rem;}
.materi-kalibrasi .chart-title {font-size:13px;font-weight:600;color:var(--gray-700);margin-bottom:2px;}
.materi-kalibrasi .chart-sub {font-size:11px;color:var(--gray-400);margin-bottom:1rem;}
.materi-kalibrasi .chart-wrap {position:relative;width:100%;}
.materi-kalibrasi .legend-row {display:flex;flex-wrap:wrap;gap:12px;margin-top:10px;font-size:11px;color:var(--gray-500);}
.materi-kalibrasi .legend-item {display:flex;align-items:center;gap:5px;}
.materi-kalibrasi .legend-sq {width:10px;height:10px;border-radius:2px;flex-shrink:0;}
/.materi-kalibrasi * COMPARISON TABLE */
.compare-tbl {width:100%;border-collapse:collapse;margin-bottom:1rem;}
.materi-kalibrasi .compare-tbl th {padding:10px 14px;font-size:12px;font-weight:600;text-align:center;}
.materi-kalibrasi .compare-tbl td {padding:9px 14px;border-bottom:1px solid var(--gray-200);font-size:13px;}
.materi-kalibrasi .compare-tbl .metric-name {font-weight:600;color:var(--gray-700);background:var(--gray-100);}
.materi-kalibrasi .compare-tbl .val-raw {color:var(--red);font-weight:600;text-align:center;font-family:monospace;}
.materi-kalibrasi .compare-tbl .val-m4 {color:var(--navy2);font-weight:700;text-align:center;font-family:monospace;}
.materi-kalibrasi .compare-tbl .thresh {color:var(--gray-500);text-align:center;font-size:12px;}
.materi-kalibrasi .compare-tbl .status-good {color:var(--green);font-weight:700;text-align:center;}
.materi-kalibrasi .compare-tbl .status-bad {color:var(--red);text-align:center;}
.materi-kalibrasi .compare-tbl thead th:nth-child(2) {background:rgba(185,28,28,0.1);color:var(--red);}
.materi-kalibrasi .compare-tbl thead th:nth-child(3) {background:rgba(26,82,118,0.1);color:var(--navy2);}
/.materi-kalibrasi * TAG */
.tag {display:inline-block;font-size:11px;padding:3px 10px;border-radius:20px;margin:2px;font-weight:500;}
.materi-kalibrasi .tag-blue {background:var(--blue-pale);color:#0c447c;}
.materi-kalibrasi .tag-red {background:var(--red-light);color:var(--red);}
.materi-kalibrasi .tag-purple {background:var(--purple-light);color:var(--purple);}
.materi-kalibrasi .tag-green {background:var(--green-light);color:var(--green);}
.materi-kalibrasi .tag-amber {background:var(--amber-light);color:var(--amber);}
/.materi-kalibrasi * DIVIDER */
.divider {height:1px;background:var(--gray-200);margin:2.5rem 0;}
/.materi-kalibrasi * ANIMATE */
@keyframes fadeUp {from{opacity:0;transform:translateY(16px);}.materi-kalibrasi to {opacity:1;transform:translateY(0);}.materi-kalibrasi }
.anim-in {opacity:1;}
.materi-kalibrasi .anim-in.visible {animation:fadeUp 0.45s ease both;}
/* === LAYOUT FIX: integrasi Wowchemy === */
.materi-kalibrasi { box-sizing: border-box; width: 100%; overflow-x: hidden; }
.materi-kalibrasi * { box-sizing: border-box; }
.materi-kalibrasi .wrap, .materi-kalibrasi .section { max-width: 100%; }
/* === DARK MODE === */
body.dark .materi-kalibrasi { color:#8e94b5; }
/* Heading &amp; teks utama */
body.dark .materi-kalibrasi h1,
body.dark .materi-kalibrasi h2,
body.dark .materi-kalibrasi h3,
body.dark .materi-kalibrasi h4 { color:#e8eaf6 !important; }
body.dark .materi-kalibrasi p { color:#8e94b5; }
body.dark .materi-kalibrasi strong { color:#e8eaf6; }
body.dark .materi-kalibrasi li { color:#8e94b5; }
/* Section header */
body.dark .materi-kalibrasi .section-header { border-color:#343858; }
body.dark .materi-kalibrasi .section-header h2 { color:#e8eaf6 !important; }
body.dark .materi-kalibrasi .section-num {
background:#1e3a6e !important;
color:#5b8fff !important;
border-color:#2a4a8e !important;
}
body.dark .materi-kalibrasi .subsection h3 { color:#c8ccdf !important; }
/* Cards — background &amp; border */
body.dark .materi-kalibrasi [class*="card"],
body.dark .materi-kalibrasi .card,
body.dark .materi-kalibrasi .metric-card {
background:#222638 !important;
border-color:#343858 !important;
box-shadow: 0 2px 12px rgba(0,0,0,0.3) !important;
}
/* Card teks — SEMUA varian label &amp; nilai */
body.dark .materi-kalibrasi .card-label,
body.dark .materi-kalibrasi .metric-label,
body.dark .materi-kalibrasi .metric-sub {
color:#8e94b5 !important;
}
body.dark .materi-kalibrasi .card p,
body.dark .materi-kalibrasi .card-body {
color:#8e94b5 !important;
}
body.dark .materi-kalibrasi .metric-val {
/* warna nilai (biru/amber/dll) tetap — biarkan dari CSS asli */
filter: brightness(1.2);
}
/* Teks dengan var gray-* — override via CSS variable remapping */
body.dark .materi-kalibrasi {
--gray-100:#1b1d27;
--gray-200:#222638;
--gray-300:#2a2e42;
--gray-500:#8e94b5;
--gray-600:#a0a8cc;
--gray-700:#c8ccdf;
--gray-900:#e8eaf6;
--navy:#e8eaf6;
--navy2:#c8ccdf;
--blue:#5b8fff;
--blue-mid:#7aa5ff;
--blue-pale:#1e2a42;
--red:#e05a5a;
--red-light:#2d1515;
--amber:#f4a642;
--amber-light:#2d2010;
--purple:#9d7cf8;
--purple-light:#1e1530;
--green:#3ecf8e;
--green-light:#0d2418;
--shadow: 0 2px 12px rgba(0,0,0,0.35);
--shadow-md: 0 4px 20px rgba(0,0,0,0.45);
--code-bg:#12151f;
}
/* Table */
body.dark .materi-kalibrasi table { border-color:#343858; }
body.dark .materi-kalibrasi th {
background:#2a2e42 !important;
color:#8e94b5 !important;
border-color:#343858 !important;
}
body.dark .materi-kalibrasi td {
border-color:#343858 !important;
color:#8e94b5 !important;
}
body.dark .materi-kalibrasi tr:nth-child(even) { background:#1e2235 !important; }
body.dark .materi-kalibrasi tr:hover td { background:#252840 !important; }
/* Code */
body.dark .materi-kalibrasi code,
body.dark .materi-kalibrasi pre {
background:#12151f !important;
color:#a8b4ff !important;
}
/* Form inputs */
body.dark .materi-kalibrasi select,
body.dark .materi-kalibrasi input[type=number],
body.dark .materi-kalibrasi input[type=text] {
background:#2a2e42 !important;
border-color:#343858 !important;
color:#e8eaf6 !important;
}
/* Result/output boxes */
body.dark .materi-kalibrasi [class*="result"],
body.dark .materi-kalibrasi [id*="result"],
body.dark .materi-kalibrasi [class*="output"],
body.dark .materi-kalibrasi [id*="output"] {
background:#222638 !important;
border-color:#343858 !important;
color:#8e94b5 !important;
}
/* Grid boxes */
body.dark .materi-kalibrasi .grid-2>*,
body.dark .materi-kalibrasi .grid-3>*,
body.dark .materi-kalibrasi .grid-4>* {
background:#222638 !important;
border-color:#343858 !important;
}
/* Info/alert boxes */
body.dark .materi-kalibrasi [class*="info-"],
body.dark .materi-kalibrasi [class*="alert-"],
body.dark .materi-kalibrasi [class*="note-"] {
background:#1e2235 !important;
border-color:#343858 !important;
color:#8e94b5 !important;
}
/* Links */
body.dark .materi-kalibrasi a { color:#5b8fff; }
body.dark .materi-kalibrasi hr { border-color:#343858; }
/* Fix teks inline style hardcoded */
body.dark .materi-kalibrasi [style*="color:#0f172a"],
body.dark .materi-kalibrasi [style*="color:#1e293b"],
body.dark .materi-kalibrasi [style*="color:#334155"],
body.dark .materi-kalibrasi [style*="color:#475569"] {
color:#e8eaf6 !important;
}
body.dark .materi-kalibrasi [style*="background:#fff"],
body.dark .materi-kalibrasi [style*="background:#f4f6f9"],
body.dark .materi-kalibrasi [style*="background:#f8fafc"],
body.dark .materi-kalibrasi [style*="background:#f1f5f9"] {
background:#222638 !important;
}
&lt;/style>
&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.4.1/chart.umd.js">&lt;/script>
&lt;div class="materi-kalibrasi">
&lt;!-- ===== S1: LATAR BELAKANG ===== -->
&lt;section class="section anim-in" id="s1">
&lt;div class="section-header">&lt;div class="section-num">1&lt;/div>&lt;h2>Latar Belakang&lt;/h2>&lt;/div>
&lt;div class="card card-navy">
&lt;div class="card-label">Masalah Utama&lt;/div>
&lt;p>GPM IMERG adalah produk curah hujan satelit presisi tinggi dari NASA dengan resolusi 0.1° × 0.1° dan temporal 30 menit. Namun dalam analisis hidrologi — khususnya untuk menentukan &lt;strong>Hujan Harian Maksimum Tahunan (HHMT)&lt;/strong> sebagai input desain bangunan air — data mentah (raw) GPM sering menunjukkan &lt;strong>bias sistematis negatif yang signifikan&lt;/strong> dibandingkan observasi BMKG di lapangan.&lt;/p>
&lt;/div>
&lt;div class="grid-2">
&lt;div class="card card-red">
&lt;div class="card-label">⚠️ GPM Raw — Masalah&lt;/div>
&lt;p>PBIAS = &lt;strong>−31.9%&lt;/strong> artinya GPM Raw secara rata-rata &lt;em>meremehkan&lt;/em> curah hujan sebesar hampir sepertiga dari nilai sesungguhnya. NSE = −1.06 menunjukkan model bahkan lebih buruk dari sekedar menggunakan nilai rata-rata — tidak layak digunakan langsung untuk desain hidrologi.&lt;/p>
&lt;/div>
&lt;div class="card card-blue">
&lt;div class="card-label">✅ GPM M4 — Solusi&lt;/div>
&lt;p>Setelah kalibrasi dengan metode &lt;strong>Year-Specific Scaling Factor (M4)&lt;/strong>, PBIAS turun menjadi &lt;strong>+3.5%&lt;/strong> — hampir tidak ada bias. NSE meningkat ke 0.77 dan KGE ke 0.88, keduanya masuk kategori &lt;em>Sangat Baik&lt;/em> menurut SNI 2415:2016.&lt;/p>
&lt;/div>
&lt;/div>
&lt;div class="grid-4">
&lt;div class="metric-card red">
&lt;div class="metric-label">PBIAS&lt;/div>
&lt;div class="metric-raw">−31.9%&lt;/div>
&lt;div class="metric-arrow">↓ 91%&lt;/div>
&lt;div class="metric-m4">+3.5%&lt;/div>
&lt;div class="metric-thresh">Threshold: &amp;lt;10%&lt;/div>
&lt;/div>
&lt;div class="metric-card blue">
&lt;div class="metric-label">NSE&lt;/div>
&lt;div class="metric-raw">−1.062&lt;/div>
&lt;div class="metric-arrow">↑ 172%&lt;/div>
&lt;div class="metric-m4">0.772&lt;/div>
&lt;div class="metric-thresh">Threshold: ≥0.75&lt;/div>
&lt;/div>
&lt;div class="metric-card green">
&lt;div class="metric-label">KGE&lt;/div>
&lt;div class="metric-raw">0.206&lt;/div>
&lt;div class="metric-arrow">↑ 326%&lt;/div>
&lt;div class="metric-m4">0.879&lt;/div>
&lt;div class="metric-thresh">Threshold: ≥0.75&lt;/div>
&lt;/div>
&lt;div class="metric-card amber">
&lt;div class="metric-label">RMSE&lt;/div>
&lt;div class="metric-raw">47.4 mm&lt;/div>
&lt;div class="metric-arrow">↓ 67%&lt;/div>
&lt;div class="metric-m4">15.8 mm&lt;/div>
&lt;div class="metric-thresh">Semakin kecil&lt;/div>
&lt;/div>
&lt;/div>
&lt;div class="success-box">&lt;span class="box-icon">🎯&lt;/span>&lt;span>Kalibrasi dengan metode M4 berhasil mengubah data GPM yang &lt;em>tidak layak pakai&lt;/em> menjadi data yang masuk kategori &lt;strong>Sangat Baik (SB)&lt;/strong> untuk semua metrik validasi menurut Moriasi et al. (2007) dan SNI 2415:2016.&lt;/span>&lt;/div>
&lt;/section>
&lt;div class="divider">&lt;/div>
&lt;!-- ===== S2: DATA &amp; WILAYAH ===== -->
&lt;section class="section anim-in" id="s2">
&lt;div class="section-header">&lt;div class="section-num">2&lt;/div>&lt;h2>Data &amp;amp; Wilayah Studi&lt;/h2>&lt;/div>
&lt;div id="s2a">&lt;/div>
&lt;div class="card card-blue" style="margin-bottom:1rem;">
&lt;div class="card-label">🛰️ Piksel GPM B4 — Titik Referensi&lt;/div>
&lt;p>Analisis berfokus pada satu piksel GPM IMERG V07 yang merepresentasikan wilayah Kota Banjarmasin, yang selanjutnya disebut &lt;strong>Piksel B4&lt;/strong>.&lt;/p>
&lt;/div>
&lt;div class="grid-2">
&lt;div class="card">
&lt;div class="card-label">Koordinat Piksel B4&lt;/div>
&lt;p style="font-family:monospace;font-size:14px;color:var(--navy);">114.60°E, 3.30°S&lt;/p>
&lt;p style="margin-top:6px;">Bounding Box: 114.487–114.687°E, 3.197–3.397°S&lt;/p>
&lt;/div>
&lt;div class="card">
&lt;div class="card-label">Produk GPM&lt;/div>
&lt;p>&lt;strong>GPM IMERG V07 Final Run&lt;/strong> (NASA Giovanni)&lt;br>Resolusi: 0.1° × 0.1° · Temporal: Daily&lt;br>Variabel: Presipitasi harian (mm)&lt;/p>
&lt;/div>
&lt;/div>
&lt;div id="s2b">&lt;/div>
&lt;div class="card-label" style="font-size:11px;margin-bottom:10px;">🌧️ Stasiun Observasi BMKG (Ground Truth)&lt;/div>
&lt;div class="grid-2">
&lt;div class="card card-amber">
&lt;div class="card-label">Stasiun SY — Syamsuddin Noor&lt;/div>
&lt;p>&lt;strong>Lokasi:&lt;/strong> Banjarmasin, Kalimantan Selatan&lt;br>&lt;strong>Piksel GPM-nya:&lt;/strong> 114.80°E, 3.40°S&lt;br>&lt;strong>Periode:&lt;/strong> 1998–2025 (28 tahun)&lt;br>&lt;strong>Catatan:&lt;/strong> Tahun 2010 data = 0 mm (tidak valid, hanya BMKG Kalsel yang digunakan)&lt;/p>
&lt;/div>
&lt;div class="card card-amber">
&lt;div class="card-label">Stasiun KS — BMKG Kalsel (Banjarbaru)&lt;/div>
&lt;p>&lt;strong>Lokasi:&lt;/strong> Banjarbaru, Kalimantan Selatan&lt;br>&lt;strong>Piksel GPM-nya:&lt;/strong> 114.85°E, 3.45°S&lt;br>&lt;strong>Periode:&lt;/strong> 1998–2025 (28 tahun)&lt;br>&lt;strong>Catatan:&lt;/strong> Digunakan sebagai data pembanding &amp;amp; pengisi ketika SY tidak tersedia&lt;/p>
&lt;/div>
&lt;/div>
&lt;div id="s2c">&lt;/div>
&lt;div class="card-label" style="font-size:11px;margin-bottom:8px;">📊 Tabel Data Lengkap — HHMT 1998–2025&lt;/div>
&lt;div class="tbl-wrap">
&lt;table class="data-tbl">
&lt;thead>
&lt;tr>
&lt;th>Tahun&lt;/th>
&lt;th class="head-raw">GPM Raw (mm)&lt;/th>
&lt;th class="head-fk">Fk M4&lt;/th>
&lt;th class="head-m4">GPM M4 (mm)&lt;/th>
&lt;th class="head-obs">Obs BMKG (mm)&lt;/th>
&lt;th class="head-raw">Error Raw (mm)&lt;/th>
&lt;th class="head-m4">Error M4 (mm)&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody id="tblBody">&lt;/tbody>
&lt;/table>
&lt;/div>
&lt;div class="info-box">&lt;span class="box-icon">ℹ️&lt;/span>&lt;span>HHMT = Hujan Harian Maksimum Tahunan. Error = GPM − Obs BMKG. Nilai negatif berarti GPM meremehkan observasi. Tahun 2010: data BMKG SY = 0 mm (tidak valid), Fk dihitung dari stasiun KS saja.&lt;/span>&lt;/div>
&lt;/section>
&lt;div class="divider">&lt;/div>
&lt;!-- ===== S3: METODE ===== -->
&lt;section class="section anim-in" id="s3">
&lt;div class="section-header">&lt;div class="section-num">3&lt;/div>&lt;h2>Metode Koreksi Bias M4&lt;/h2>&lt;/div>
&lt;p style="font-size:13px;color:var(--gray-600);margin-bottom:1.25rem;line-height:1.7;">Terdapat beberapa metode koreksi bias yang umum digunakan dalam hidrologi berbasis data satelit. Analisis ini membandingkan empat metode (M1–M4) dan memilih &lt;strong>M4: Year-Specific Scaling Factor&lt;/strong> sebagai yang terbaik.&lt;/p>
&lt;div id="s3a">&lt;/div>
&lt;div class="card" style="margin-bottom:1.25rem;">
&lt;div class="card-label" style="margin-bottom:10px;">Perbandingan 4 Metode Koreksi Bias&lt;/div>
&lt;div class="tbl-wrap">
&lt;table class="compare-tbl">
&lt;thead>
&lt;tr>
&lt;th style="text-align:left;background:var(--gray-100);color:var(--gray-700);">Metode&lt;/th>
&lt;th style="text-align:left;background:var(--gray-100);color:var(--gray-700);">Prinsip&lt;/th>
&lt;th style="background:var(--gray-100);color:var(--gray-700);">Keunggulan&lt;/th>
&lt;th style="background:var(--gray-100);color:var(--gray-700);">Keterbatasan&lt;/th>
&lt;th style="background:var(--gray-100);color:var(--gray-700);">Status&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td style="font-weight:700;color:var(--red);">M1 — CF Bulanan&lt;/td>
&lt;td style="font-size:12px;color:var(--gray-600);">GPM × faktor koreksi per bulan HHMT&lt;/td>
&lt;td style="font-size:12px;text-align:center;">Mempertimbangkan musim&lt;/td>
&lt;td style="font-size:12px;text-align:center;">CF dihitung hanya dari 1 stasiun&lt;/td>
&lt;td style="text-align:center;">&lt;span class="tag tag-amber">Cukup Baik&lt;/span>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="font-weight:700;color:var(--amber);">M2 — Direct Scaling&lt;/td>
&lt;td style="font-size:12px;color:var(--gray-600);">GPM × (rerata Obs / rerata GPM) global&lt;/td>
&lt;td style="font-size:12px;text-align:center;">Sangat sederhana&lt;/td>
&lt;td style="font-size:12px;text-align:center;">Satu faktor untuk semua tahun&lt;/td>
&lt;td style="text-align:center;">&lt;span class="tag tag-amber">Cukup Baik&lt;/span>&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td style="font-weight:700;color:var(--purple);">M3 — Quantile Mapping&lt;/td>
&lt;td style="font-size:12px;color:var(--gray-600);">Rank-to-rank GPM vs Obs (CDF matching)&lt;/td>
&lt;td style="font-size:12px;text-align:center;">Koreksi distribusi penuh&lt;/td>
&lt;td style="font-size:12px;text-align:center;">Butuh data lebih banyak; asumsi stasioner&lt;/td>
&lt;td style="text-align:center;">&lt;span class="tag tag-blue">Baik&lt;/span>&lt;/td>
&lt;/tr>
&lt;tr style="background:rgba(26,82,118,0.04);">
&lt;td style="font-weight:700;color:var(--navy2);">M4 — Year-Specific ✅&lt;/td>
&lt;td style="font-size:12px;color:var(--gray-600);">GPM × Fk per tahun dari semua stasiun tersedia&lt;/td>
&lt;td style="font-size:12px;text-align:center;font-weight:600;color:var(--green);">Fk unik tiap tahun, multi-stasiun&lt;/td>
&lt;td style="font-size:12px;text-align:center;">Butuh data BMKG per tahun&lt;/td>
&lt;td style="text-align:center;">&lt;span class="tag tag-green">🏆 Terbaik&lt;/span>&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;/div>
&lt;/div>
&lt;div id="s3b">&lt;/div>
&lt;div class="card card-purple">
&lt;div class="card-label">Formula Inti — Metode M4&lt;/div>
&lt;/div>
&lt;div class="formula-block">
&lt;span class="eq-label">Langkah 1: Faktor Koreksi per Stasiun per Tahun&lt;/span>
&lt;span class="eq-main">Fk_SY = HHMT_Ground_SY / HHMT_GPM_B4&lt;/span>
&lt;/div>
&lt;div class="formula-block">
&lt;span class="eq-label">Langkah 2: Fk Akhir = Rata-rata dari semua stasiun tersedia&lt;/span>
&lt;span class="eq-main">Fk = mean(Fk_SY, Fk_KS)&lt;/span>
&lt;span class="eq-desc">Jika hanya satu stasiun tersedia (mis. 2010): Fk = Fk dari stasiun yang ada&lt;/span>
&lt;/div>
&lt;div class="formula-block">
&lt;span class="eq-label">Langkah 3: GPM Terkoreksi&lt;/span>
&lt;span class="eq-main">GPM_M4 = GPM_Raw_B4 × Fk&lt;/span>
&lt;span class="eq-desc">Hasil: HHMT tahunan yang sudah dikalibrasi terhadap observasi BMKG&lt;/span>
&lt;/div>
&lt;div class="step-flow" style="margin-top:1.25rem;">
&lt;div class="card-label" style="margin-bottom:10px;">Alur Kerja M4 Step-by-Step&lt;/div>
&lt;div class="step-item">
&lt;div class="step-line">&lt;div class="step-dot navy">1&lt;/div>&lt;div class="step-connector">&lt;/div>&lt;/div>
&lt;div class="step-body">
&lt;div class="step-title">Ekstrak HHMT GPM Raw dari Piksel B4&lt;/div>
&lt;div class="step-desc">Download data harian GPM IMERG V07 dari NASA Giovanni untuk piksel 114.60°E, 3.30°S. Ekstrak nilai HHMT (nilai maksimum harian dalam setahun) untuk setiap tahun 1998–2025.&lt;/div>
&lt;/div>
&lt;/div>
&lt;div class="step-item">
&lt;div class="step-line">&lt;div class="step-dot navy">2&lt;/div>&lt;div class="step-connector">&lt;/div>&lt;/div>
&lt;div class="step-body">
&lt;div class="step-title">Ekstrak HHMT Ground Truth dari BMKG&lt;/div>
&lt;div class="step-desc">Ambil data harian dari dua stasiun BMKG: Syamsuddin Noor (SY) dan BMKG Kalsel/Banjarbaru (KS). Hitung HHMT per tahun dari masing-masing stasiun.&lt;/div>
&lt;/div>
&lt;/div>
&lt;div class="step-item">
&lt;div class="step-line">&lt;div class="step-dot navy">3&lt;/div>&lt;div class="step-connector">&lt;/div>&lt;/div>
&lt;div class="step-body">
&lt;div class="step-title">Hitung Faktor Koreksi Fk per Tahun&lt;/div>
&lt;div class="step-desc">Fk_SY = Gnd_SY / GPM_B4; Fk_KS = Gnd_KS / GPM_B4. Fk final = rata-rata dari stasiun yang tersedia. Jika data SY tidak valid (tahun 2010: Gnd_SY = 0 mm), gunakan Fk_KS saja.&lt;/div>
&lt;/div>
&lt;/div>
&lt;div class="step-item">
&lt;div class="step-line">&lt;div class="step-dot navy">4&lt;/div>&lt;div class="step-connector">&lt;/div>&lt;/div>
&lt;div class="step-body">
&lt;div class="step-title">Terapkan Fk ke GPM Raw&lt;/div>
&lt;div class="step-desc">GPM_M4 = GPM_Raw × Fk. Setiap tahun mendapatkan faktor koreksi yang berbeda — ini yang membuat M4 lebih akurat dibandingkan M2 (satu faktor global).&lt;/div>
&lt;/div>
&lt;/div>
&lt;div class="step-item">
&lt;div class="step-line">&lt;div class="step-dot navy">5&lt;/div>&lt;div class="step-connector">&lt;/div>&lt;/div>
&lt;div class="step-body">
&lt;div class="step-title">Validasi dengan Metrik Goodness-of-Fit&lt;/div>
&lt;div class="step-desc">Hitung R, NSE, KGE, PBIAS, RMSE, MAE untuk membandingkan GPM M4 vs Obs BMKG. Bandingkan dengan threshold SNI 2415:2016 kategori Sangat Baik (SB): NSE ≥ 0.75, KGE ≥ 0.75, |PBIAS| &amp;lt; 10%.&lt;/div>
&lt;/div>
&lt;/div>
&lt;/div>
&lt;div class="warn-box">&lt;span class="box-icon">⚠️&lt;/span>&lt;span>Metode M4 bersifat &lt;em>year-specific&lt;/em> — artinya Fk dikalibrasi untuk periode historis yang sudah ada data BMKG-nya. Untuk proyeksi masa depan, perlu diasumsikan Fk konstan (nilai median atau rata-rata historis) karena tidak ada data ground truth masa depan.&lt;/span>&lt;/div>
&lt;/section>
&lt;div class="divider">&lt;/div>
&lt;!-- ===== S4: VISUALISASI ===== -->
&lt;section class="section anim-in" id="s4">
&lt;div class="section-header">&lt;div class="section-num">4&lt;/div>&lt;h2>Hasil Visualisasi&lt;/h2>&lt;/div>
&lt;div id="s4a">&lt;/div>
&lt;div class="fig-wrap">
&lt;div class="fig-header">📈 Panel 1 — Time Series HHMT Tahunan&lt;/div>
&lt;img src="https://www.irpanchumaedi.com/images/kalibrasi-gpm/timeseries-hhmt-tahunan.jpg" alt="Time series HHMT tahunan GPM Raw vs GPM M4 vs Observasi BMKG 1998-2025" loading="lazy" style="width:100%;border-radius:8px;margin:0.5rem 0;">
&lt;div class="fig-caption">Time series HHMT tahunan: GPM Raw (merah solid) vs GPM M4 (navy solid) vs Observasi BMKG (oranye dashed). Label kotak menunjukkan nilai puncak tahun 2021 = 252.2 mm.&lt;/div>
&lt;/div>
&lt;div class="card card-navy" style="margin-bottom:1.5rem;">
&lt;div class="card-label">Interpretasi Time Series&lt;/div>
&lt;p>GPM Raw secara konsisten &lt;em>berada di bawah&lt;/em> observasi BMKG sepanjang 28 tahun — mencerminkan bias negatif yang sistematis. Setelah kalibrasi M4, GPM M4 (garis navy) &lt;strong>mengikuti pola observasi BMKG dengan sangat baik&lt;/strong>, termasuk menangkap puncak ekstrem tahun 2021 (252.2 mm) yang berkorelasi dengan banjir besar Banjarmasin Januari 2021.&lt;/p>
&lt;/div>
&lt;div id="s4b">&lt;/div>
&lt;div class="fig-wrap">
&lt;div class="fig-header">📊 Panel 2 — Bar Chart Perbandingan Tahunan&lt;/div>
&lt;img src="https://www.irpanchumaedi.com/images/kalibrasi-gpm/barchart-perbandingan-tahunan.jpg" alt="Bar chart perbandingan HHMT tahunan GPM Raw vs GPM M4 vs Observasi BMKG 1998-2025" loading="lazy" style="width:100%;border-radius:8px;margin:0.5rem 0;">
&lt;div class="fig-caption">Bar chart dengan 3 seri per tahun: GPM Raw (merah), GPM M4 (navy), Obs BMKG (oranye). Terlihat GPM M4 jauh lebih mendekati bar oranye dibanding GPM Raw.&lt;/div>
&lt;/div>
&lt;div class="chart-card">
&lt;div class="chart-title">Residual Error per Tahun (GPM − Obs BMKG)&lt;/div>
&lt;div class="chart-sub">Zona hijau = ±10 mm (toleransi ideal) · GPM M4 hampir selalu di dalam zona hijau&lt;/div>
&lt;div class="chart-wrap" style="height:240px;">&lt;canvas id="chartResidual" role="img" aria-label="Bar chart residual error GPM Raw vs GPM M4 per tahun. GPM M4 jauh lebih dekat ke nol.">&lt;/canvas>&lt;/div>
&lt;div class="legend-row">
&lt;div class="legend-item">&lt;div class="legend-sq" style="background:rgba(185,28,28,0.75);">&lt;/div>Error GPM Raw&lt;/div>
&lt;div class="legend-item">&lt;div class="legend-sq" style="background:rgba(26,82,118,0.75);">&lt;/div>Error GPM M4&lt;/div>
&lt;div class="legend-item">&lt;div class="legend-sq" style="background:rgba(29,111,66,0.2);border:1px dashed #1d6f42;">&lt;/div>Zona ±10 mm&lt;/div>
&lt;/div>
&lt;/div>
&lt;div id="s4c">&lt;/div>
&lt;div class="fig-wrap">
&lt;div class="fig-header">🔵 Panel 3 — Scatter Plot: GPM Raw vs GPM M4 terhadap Observasi BMKG&lt;/div>
&lt;img src="https://www.irpanchumaedi.com/images/kalibrasi-gpm/scatterplot-gpm-vs-bmkg.jpg" alt="Scatter plot GPM Raw vs Obs BMKG dan GPM M4 vs Obs BMKG" loading="lazy" style="width:100%;border-radius:8px;margin:0.5rem 0;">
&lt;div class="fig-caption">Kiri: Scatter GPM Raw vs Obs BMKG — titik tersebar jauh dari garis 1:1 (R=0.373). Kanan: Scatter GPM M4 vs Obs BMKG — titik mengikuti garis 1:1 dengan rapat (R=0.900).&lt;/div>
&lt;/div>
&lt;div class="success-box">&lt;span class="box-icon">🎯&lt;/span>&lt;span>Garis putus-putus abu-abu pada scatter plot adalah garis &lt;strong>1:1 (perfect fit)&lt;/strong>. Semakin dekat titik ke garis ini, semakin baik kalibrasi. GPM M4 (kanan) menunjukkan sebaran yang sangat rapat di sekitar garis 1:1 dengan CI band yang sempit — bukti kalibrasi yang sangat berhasil.&lt;/span>&lt;/div>
&lt;/section>
&lt;div class="divider">&lt;/div>
&lt;!-- ===== S5: METRIK VALIDASI ===== -->
&lt;section class="section anim-in" id="s5">
&lt;div class="section-header">&lt;div class="section-num">5&lt;/div>&lt;h2>Metrik Validasi Statistik&lt;/h2>&lt;/div>
&lt;div class="chart-card">
&lt;div class="chart-title">Perbandingan Metrik Goodness-of-Fit — GPM Raw vs GPM M4&lt;/div>
&lt;div class="chart-sub">Threshold Sangat Baik (SNI 2415:2016 / Moriasi et al. 2007) ditampilkan sebagai garis putus-putus&lt;/div>
&lt;div class="chart-wrap" style="height:280px;">&lt;canvas id="chartMetrik" role="img" aria-label="Bar chart metrik validasi R NSE KGE untuk GPM Raw dan GPM M4. Semua metrik GPM M4 melampaui threshold SB.">&lt;/canvas>&lt;/div>
&lt;/div>
&lt;div class="tbl-wrap">
&lt;table class="compare-tbl" style="width:100%;border-collapse:collapse;">
&lt;thead>
&lt;tr>
&lt;th style="text-align:left;background:var(--gray-100);color:var(--gray-700);padding:10px 14px;font-size:12px;">Metrik&lt;/th>
&lt;th style="background:rgba(185,28,28,0.1);color:var(--red);padding:10px 14px;font-size:12px;text-align:center;">GPM Raw (M0)&lt;/th>
&lt;th style="background:rgba(26,82,118,0.1);color:var(--navy2);padding:10px 14px;font-size:12px;text-align:center;">GPM M4&lt;/th>
&lt;th style="background:var(--gray-100);color:var(--gray-700);padding:10px 14px;font-size:12px;text-align:center;">Threshold SB&lt;/th>
&lt;th style="background:var(--gray-100);color:var(--gray-700);padding:10px 14px;font-size:12px;text-align:center;">Status M4&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>&lt;td class="metric-name" style="padding:9px 14px;font-weight:600;background:var(--gray-100);">R (Korelasi Pearson)&lt;/td>&lt;td class="val-raw" style="padding:9px 14px;">0.373&lt;/td>&lt;td class="val-m4" style="padding:9px 14px;">0.900&lt;/td>&lt;td class="thresh" style="padding:9px 14px;">≥ 0.75&lt;/td>&lt;td class="status-good" style="padding:9px 14px;">✅ SB&lt;/td>&lt;/tr>
&lt;tr>&lt;td class="metric-name" style="padding:9px 14px;font-weight:600;background:var(--gray-100);">R² (Koef. Determinasi)&lt;/td>&lt;td class="val-raw" style="padding:9px 14px;">0.139&lt;/td>&lt;td class="val-m4" style="padding:9px 14px;">0.811&lt;/td>&lt;td class="thresh" style="padding:9px 14px;">≥ 0.75&lt;/td>&lt;td class="status-good" style="padding:9px 14px;">✅ SB&lt;/td>&lt;/tr>
&lt;tr>&lt;td class="metric-name" style="padding:9px 14px;font-weight:600;background:var(--gray-100);">NSE (Nash-Sutcliffe Eff.)&lt;/td>&lt;td class="val-raw" style="padding:9px 14px;">−1.062&lt;/td>&lt;td class="val-m4" style="padding:9px 14px;">0.772&lt;/td>&lt;td class="thresh" style="padding:9px 14px;">≥ 0.75&lt;/td>&lt;td class="status-good" style="padding:9px 14px;">✅ SB&lt;/td>&lt;/tr>
&lt;tr>&lt;td class="metric-name" style="padding:9px 14px;font-weight:600;background:var(--gray-100);">KGE (Kling-Gupta Eff.)&lt;/td>&lt;td class="val-raw" style="padding:9px 14px;">0.206&lt;/td>&lt;td class="val-m4" style="padding:9px 14px;">0.879&lt;/td>&lt;td class="thresh" style="padding:9px 14px;">≥ 0.75&lt;/td>&lt;td class="status-good" style="padding:9px 14px;">✅ SB&lt;/td>&lt;/tr>
&lt;tr>&lt;td class="metric-name" style="padding:9px 14px;font-weight:600;background:var(--gray-100);">PBIAS (%)&lt;/td>&lt;td class="val-raw" style="padding:9px 14px;">−31.9%&lt;/td>&lt;td class="val-m4" style="padding:9px 14px;">+3.5%&lt;/td>&lt;td class="thresh" style="padding:9px 14px;">|PBIAS| &amp;lt; 10%&lt;/td>&lt;td class="status-good" style="padding:9px 14px;">✅ SB&lt;/td>&lt;/tr>
&lt;tr>&lt;td class="metric-name" style="padding:9px 14px;font-weight:600;background:var(--gray-100);">RMSE (mm)&lt;/td>&lt;td class="val-raw" style="padding:9px 14px;">47.44 mm&lt;/td>&lt;td class="val-m4" style="padding:9px 14px;">15.79 mm&lt;/td>&lt;td class="thresh" style="padding:9px 14px;">Min (↓)&lt;/td>&lt;td class="status-good" style="padding:9px 14px;">✅ −67%&lt;/td>&lt;/tr>
&lt;tr>&lt;td class="metric-name" style="padding:9px 14px;font-weight:600;background:var(--gray-100);">MAE (mm)&lt;/td>&lt;td class="val-raw" style="padding:9px 14px;">38.72 mm&lt;/td>&lt;td class="val-m4" style="padding:9px 14px;">11.14 mm&lt;/td>&lt;td class="thresh" style="padding:9px 14px;">Min (↓)&lt;/td>&lt;td class="status-good" style="padding:9px 14px;">✅ −71%&lt;/td>&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;/div>
&lt;div class="grid-2" style="margin-top:1rem;">
&lt;div class="card card-blue">
&lt;div class="card-label">Tentang NSE (Nash-Sutcliffe Efficiency)&lt;/div>
&lt;p>NSE = 1 adalah sempurna. NSE = 0 berarti model sama akuratnya dengan rata-rata observasi. NSE &amp;lt; 0 berarti model &lt;em>lebih buruk&lt;/em> dari rata-rata. GPM Raw dengan NSE = −1.06 sangat tidak layak. GPM M4 dengan NSE = 0.77 masuk kategori Sangat Baik.&lt;/p>
&lt;/div>
&lt;div class="card card-purple">
&lt;div class="card-label">Tentang KGE (Kling-Gupta Efficiency)&lt;/div>
&lt;p>KGE menggabungkan korelasi, bias, dan variabilitas dalam satu metrik. KGE ≥ 0.75 = Sangat Baik. KGE GPM M4 = 0.879 menunjukkan keseimbangan yang baik antara tiga komponen tersebut — model tidak hanya berkorelasi tinggi, tapi juga reproduksi variabilitasnya bagus.&lt;/p>
&lt;/div>
&lt;/div>
&lt;/section>
&lt;div class="divider">&lt;/div>
&lt;!-- ===== S6: FAKTOR KOREKSI ===== -->
&lt;section class="section anim-in" id="s6">
&lt;div class="section-header">&lt;div class="section-num">6&lt;/div>&lt;h2>Distribusi Faktor Koreksi (Fk)&lt;/h2>&lt;/div>
&lt;div class="chart-card">
&lt;div class="chart-title">Faktor Koreksi Fk per Tahun (Year-Specific Scaling Factor)&lt;/div>
&lt;div class="chart-sub">Fk = mean(Gnd_SY/GPM_B4, Gnd_KS/GPM_B4) · Garis putus-putus = Median Fk · Garis titik-titik = Fk=1.0 (tidak ada koreksi)&lt;/div>
&lt;div class="chart-wrap" style="height:260px;">&lt;canvas id="chartFk" role="img" aria-label="Bar chart faktor koreksi Fk per tahun 1998-2025. Sebagian besar Fk di atas 1.0 artinya GPM meremehkan observasi.">&lt;/canvas>&lt;/div>
&lt;div class="legend-row">
&lt;div class="legend-item">&lt;div class="legend-sq" style="background:rgba(109,40,217,0.75);">&lt;/div>Fk per tahun&lt;/div>
&lt;div class="legend-item">&lt;div style="width:20px;border-top:2px dashed var(--purple);margin-top:5px;">&lt;/div>&amp;nbsp;Median Fk&lt;/div>
&lt;div class="legend-item">&lt;div style="width:20px;border-top:2px dotted #94a3b8;margin-top:5px;">&lt;/div>&amp;nbsp;Fk = 1.0&lt;/div>
&lt;/div>
&lt;/div>
&lt;div class="grid-3">
&lt;div class="card">
&lt;div class="card-label">Median Fk&lt;/div>
&lt;p style="font-size:22px;font-weight:700;color:var(--purple);">1.402&lt;/p>
&lt;p style="margin-top:4px;">GPM secara rata-rata meremehkan observasi sebesar &lt;strong>~40%&lt;/strong>. Fk &amp;gt; 1 artinya observasi lebih tinggi dari GPM.&lt;/p>
&lt;/div>
&lt;div class="card">
&lt;div class="card-label">Rentang Fk&lt;/div>
&lt;p style="font-size:13px;line-height:1.8;margin-top:4px;">
Min: &lt;strong>0.842&lt;/strong> (2011) — tahun saat GPM justru lebih tinggi&lt;br>
Max: &lt;strong>2.466&lt;/strong> (2014) — GPM sangat meremehkan&lt;br>
StDev: ±0.37 (variasi antar tahun tinggi)
&lt;/p>
&lt;/div>
&lt;div class="card">
&lt;div class="card-label">Implikasi Fk Tinggi&lt;/div>
&lt;p style="margin-top:4px;">Tahun dengan Fk &amp;gt; 2.0 (2014, 2020, 2021, 2022, 2023) adalah tahun-tahun dengan curah hujan ekstrem tinggi di Banjarmasin — satelit GPM &lt;em>secara struktural&lt;/em> kesulitan menangkap puncak intensitas.&lt;/p>
&lt;/div>
&lt;/div>
&lt;div class="warn-box">&lt;span class="box-icon">⚠️&lt;/span>&lt;span>Variabilitas Fk yang tinggi antar tahun (0.84 – 2.47) menunjukkan bahwa metode koreksi bias tunggal (M2) tidak cukup — justru inilah alasan utama M4 unggul: setiap tahun mendapat koreksi yang sesuai kondisinya.&lt;/span>&lt;/div>
&lt;/section>
&lt;div class="divider">&lt;/div>
&lt;!-- ===== S7: KODE R ===== -->
&lt;section class="section anim-in" id="s7">
&lt;div class="section-header">&lt;div class="section-num">7&lt;/div>&lt;h2>Kode R — Reproduksi Analisis&lt;/h2>&lt;/div>
&lt;p style="font-size:13px;color:var(--gray-600);margin-bottom:1.25rem;line-height:1.7;">Seluruh analisis dikerjakan menggunakan R dengan package &lt;code style="background:var(--gray-100);padding:1px 5px;border-radius:3px;font-size:12px;">ggplot2&lt;/code>, &lt;code style="background:var(--gray-100);padding:1px 5px;border-radius:3px;font-size:12px;">patchwork&lt;/code>, &lt;code style="background:var(--gray-100);padding:1px 5px;border-radius:3px;font-size:12px;">readxl&lt;/code>, dan &lt;code style="background:var(--gray-100);padding:1px 5px;border-radius:3px;font-size:12px;">dplyr&lt;/code>. Kode di bawah dapat langsung dijalankan dengan file Excel yang disediakan.&lt;/p>
&lt;div class="code-wrap">
&lt;div class="code-header">
&lt;span class="code-lang">&lt;span class="dot" style="background:#4fc3f7;">&lt;/span>R · Setup &amp; Import Data&lt;/span>
&lt;button class="copy-btn" onclick="copyCode(this)">Salin&lt;/button>
&lt;/div>
&lt;pre>&lt;span class="fn">library&lt;/span>(&lt;span class="pkg">ggplot2&lt;/span>); &lt;span class="fn">library&lt;/span>(&lt;span class="pkg">readxl&lt;/span>); &lt;span class="fn">library&lt;/span>(&lt;span class="pkg">patchwork&lt;/span>)
&lt;span class="fn">library&lt;/span>(&lt;span class="pkg">scales&lt;/span>); &lt;span class="fn">library&lt;/span>(&lt;span class="pkg">dplyr&lt;/span>); &lt;span class="fn">library&lt;/span>(&lt;span class="pkg">tidyr&lt;/span>)
&lt;span class="fn">library&lt;/span>(&lt;span class="pkg">ggrepel&lt;/span>) &lt;span class="cm"># label titik scatter plot&lt;/span>
&lt;span class="cm"># ── Baca data utama dari Excel ───────────────────────────────&lt;/span>
xl &lt;span class="op">&amp;lt;-&lt;/span> &lt;span class="str">"Input_Plot_GPM_NoWMO.xlsx"&lt;/span>
df &lt;span class="op">&amp;lt;-&lt;/span> &lt;span class="fn">read_excel&lt;/span>(xl, sheet &lt;span class="op">=&lt;/span> &lt;span class="str">"DATA_UTAMA"&lt;/span>, skip &lt;span class="op">=&lt;/span> &lt;span class="num">3&lt;/span>)
met &lt;span class="op">&amp;lt;-&lt;/span> &lt;span class="fn">read_excel&lt;/span>(xl, sheet &lt;span class="op">=&lt;/span> &lt;span class="str">"METRIK_VALIDASI"&lt;/span>, skip &lt;span class="op">=&lt;/span> &lt;span class="num">3&lt;/span>)
&lt;span class="cm"># ── Bersihkan nama kolom &amp; konversi tipe data ────────────────&lt;/span>
df &lt;span class="op">&amp;lt;-&lt;/span> df &lt;span class="op">|&amp;gt;&lt;/span>
&lt;span class="fn">rename&lt;/span>(raw &lt;span class="op">=&lt;/span> &lt;span class="str">`GPM_Raw
(mm)`&lt;/span>, m4 &lt;span class="op">=&lt;/span> &lt;span class="str">`M4_Baru
(mm)`&lt;/span>,
obs &lt;span class="op">=&lt;/span> &lt;span class="str">`Obs_BMKG
(mm)`&lt;/span>, fk &lt;span class="op">=&lt;/span> &lt;span class="str">`Fk_Baru
(rata²)`&lt;/span>) &lt;span class="op">|&amp;gt;&lt;/span>
&lt;span class="fn">filter&lt;/span>(&lt;span class="op">!&lt;/span>&lt;span class="fn">is.na&lt;/span>(Tahun)) &lt;span class="op">|&amp;gt;&lt;/span>
&lt;span class="fn">mutate&lt;/span>(&lt;span class="fn">across&lt;/span>(&lt;span class="fn">c&lt;/span>(Tahun, raw, m4, obs, fk), as.numeric),
tahun &lt;span class="op">=&lt;/span> &lt;span class="fn">as.integer&lt;/span>(Tahun),
err_raw &lt;span class="op">=&lt;/span> raw &lt;span class="op">-&lt;/span> obs,
err_m4 &lt;span class="op">=&lt;/span> m4 &lt;span class="op">-&lt;/span> obs)&lt;/pre>
&lt;/div>
&lt;div class="code-wrap">
&lt;div class="code-header">
&lt;span class="code-lang">&lt;span class="dot" style="background:#4fc3f7;">&lt;/span>R · Hitung Faktor Koreksi Fk &amp; Terapkan ke GPM&lt;/span>
&lt;button class="copy-btn" onclick="copyCode(this)">Salin&lt;/button>
&lt;/div>
&lt;pre>&lt;span class="cm"># ── Data referensi: HHMT dari stasiun BMKG &amp; piksel GPM ─────&lt;/span>
&lt;span class="cm"># Asumsi: df sudah memiliki kolom gnd_sy, gnd_ks, gpm_b4&lt;/span>
df &lt;span class="op">&amp;lt;-&lt;/span> df &lt;span class="op">|&amp;gt;&lt;/span>
&lt;span class="fn">mutate&lt;/span>(
&lt;span class="cm"># Fk per stasiun = BMKG / GPM_B4 (untuk setiap tahun)&lt;/span>
fk_sy &lt;span class="op">=&lt;/span> gnd_sy &lt;span class="op">/&lt;/span> gpm_b4,
fk_ks &lt;span class="op">=&lt;/span> gnd_ks &lt;span class="op">/&lt;/span> gpm_b4,
&lt;span class="cm"># Fk final = rata-rata stasiun yang tersedia&lt;/span>
&lt;span class="cm"># Jika salah satu NA (mis. 2010: gnd_sy = 0), gunakan yang ada&lt;/span>
fk_m4 &lt;span class="op">=&lt;/span> &lt;span class="fn">case_when&lt;/span>(
&lt;span class="fn">is.na&lt;/span>(fk_sy) &lt;span class="op">|&lt;/span> gnd_sy &lt;span class="op">==&lt;/span> &lt;span class="num">0&lt;/span> &lt;span class="op">~&lt;/span> fk_ks,
&lt;span class="fn">is.na&lt;/span>(fk_ks) &lt;span class="op">~&lt;/span> fk_sy,
&lt;span class="kw">.default&lt;/span> &lt;span class="op">~&lt;/span> &lt;span class="fn">mean&lt;/span>(&lt;span class="fn">c&lt;/span>(fk_sy, fk_ks))
),
&lt;span class="cm"># Terapkan Fk ke GPM Raw piksel B4&lt;/span>
gpm_m4 &lt;span class="op">=&lt;/span> gpm_b4 &lt;span class="op">*&lt;/span> fk_m4
)
&lt;span class="cm"># ── Ringkasan statistik ──────────────────────────────────────&lt;/span>
&lt;span class="fn">cat&lt;/span>(&lt;span class="str">"Median Fk:"&lt;/span>, &lt;span class="fn">round&lt;/span>(&lt;span class="fn">median&lt;/span>(df&lt;span class="op">$&lt;/span>fk_m4, na.rm &lt;span class="op">=&lt;/span> &lt;span class="kw">TRUE&lt;/span>), &lt;span class="num">3&lt;/span>), &lt;span class="str">"
"&lt;/span>)
&lt;span class="fn">cat&lt;/span>(&lt;span class="str">"Rentang:"&lt;/span>, &lt;span class="fn">round&lt;/span>(&lt;span class="fn">min&lt;/span>(df&lt;span class="op">$&lt;/span>fk_m4), &lt;span class="num">3&lt;/span>), &lt;span class="str">"–"&lt;/span>,
&lt;span class="fn">round&lt;/span>(&lt;span class="fn">max&lt;/span>(df&lt;span class="op">$&lt;/span>fk_m4), &lt;span class="num">3&lt;/span>), &lt;span class="str">"
"&lt;/span>)&lt;/pre>
&lt;/div>
&lt;div class="code-wrap">
&lt;div class="code-header">
&lt;span class="code-lang">&lt;span class="dot" style="background:#4fc3f7;">&lt;/span>R · Hitung Metrik Validasi&lt;/span>
&lt;button class="copy-btn" onclick="copyCode(this)">Salin&lt;/button>
&lt;/div>
&lt;pre>&lt;span class="cm"># ── Fungsi hitung metrik validasi ───────────────────────────&lt;/span>
&lt;span class="fn">hitung_metrik&lt;/span> &lt;span class="op">&amp;lt;-&lt;/span> &lt;span class="kw">function&lt;/span>(sim, obs) {
n &lt;span class="op">&amp;lt;-&lt;/span> &lt;span class="fn">length&lt;/span>(sim)
bias &lt;span class="op">&amp;lt;-&lt;/span> sim &lt;span class="op">-&lt;/span> obs
R_val &lt;span class="op">&amp;lt;-&lt;/span> &lt;span class="fn">cor&lt;/span>(obs, sim)
NSE &lt;span class="op">&amp;lt;-&lt;/span> &lt;span class="num">1&lt;/span> &lt;span class="op">-&lt;/span> &lt;span class="fn">sum&lt;/span>(bias&lt;span class="op">^&lt;/span>&lt;span class="num">2&lt;/span>) &lt;span class="op">/&lt;/span> &lt;span class="fn">sum&lt;/span>((obs &lt;span class="op">-&lt;/span> &lt;span class="fn">mean&lt;/span>(obs))&lt;span class="op">^&lt;/span>&lt;span class="num">2&lt;/span>)
KGE &lt;span class="op">&amp;lt;-&lt;/span> &lt;span class="num">1&lt;/span> &lt;span class="op">-&lt;/span> &lt;span class="fn">sqrt&lt;/span>((R_val&lt;span class="op">-&lt;/span>&lt;span class="num">1&lt;/span>)&lt;span class="op">^&lt;/span>&lt;span class="num">2&lt;/span> &lt;span class="op">+&lt;/span>
(&lt;span class="fn">sd&lt;/span>(sim)&lt;span class="op">/&lt;/span>&lt;span class="fn">sd&lt;/span>(obs)&lt;span class="op">-&lt;/span>&lt;span class="num">1&lt;/span>)&lt;span class="op">^&lt;/span>&lt;span class="num">2&lt;/span> &lt;span class="op">+&lt;/span>
(&lt;span class="fn">mean&lt;/span>(sim)&lt;span class="op">/&lt;/span>&lt;span class="fn">mean&lt;/span>(obs)&lt;span class="op">-&lt;/span>&lt;span class="num">1&lt;/span>)&lt;span class="op">^&lt;/span>&lt;span class="num">2&lt;/span>)
PBIAS &lt;span class="op">&amp;lt;-&lt;/span> &lt;span class="fn">sum&lt;/span>(bias) &lt;span class="op">/&lt;/span> &lt;span class="fn">sum&lt;/span>(obs) &lt;span class="op">*&lt;/span> &lt;span class="num">100&lt;/span>
RMSE &lt;span class="op">&amp;lt;-&lt;/span> &lt;span class="fn">sqrt&lt;/span>(&lt;span class="fn">mean&lt;/span>(bias&lt;span class="op">^&lt;/span>&lt;span class="num">2&lt;/span>))
MAE &lt;span class="op">&amp;lt;-&lt;/span> &lt;span class="fn">mean&lt;/span>(&lt;span class="fn">abs&lt;/span>(bias))
&lt;span class="fn">data.frame&lt;/span>(R=R_val, NSE=NSE, KGE=KGE, PBIAS=PBIAS, RMSE=RMSE, MAE=MAE)
}
&lt;span class="cm"># ── Bandingkan M0 (Raw) vs M4 ────────────────────────────────&lt;/span>
metrik_raw &lt;span class="op">&amp;lt;-&lt;/span> &lt;span class="fn">hitung_metrik&lt;/span>(df&lt;span class="op">$&lt;/span>raw, df&lt;span class="op">$&lt;/span>obs)
metrik_m4 &lt;span class="op">&amp;lt;-&lt;/span> &lt;span class="fn">hitung_metrik&lt;/span>(df&lt;span class="op">$&lt;/span>m4, df&lt;span class="op">$&lt;/span>obs)
&lt;span class="fn">bind_rows&lt;/span>(
&lt;span class="fn">mutate&lt;/span>(metrik_raw, Metode &lt;span class="op">=&lt;/span> &lt;span class="str">"GPM Raw"&lt;/span>),
&lt;span class="fn">mutate&lt;/span>(metrik_m4, Metode &lt;span class="op">=&lt;/span> &lt;span class="str">"GPM M4"&lt;/span>)
) &lt;span class="op">|&amp;gt;&lt;/span> &lt;span class="fn">select&lt;/span>(Metode, R, NSE, KGE, PBIAS, RMSE, MAE)&lt;/pre>
&lt;/div>
&lt;div class="code-wrap">
&lt;div class="code-header">
&lt;span class="code-lang">&lt;span class="dot" style="background:#4fc3f7;">&lt;/span>R · Time Series Plot (Panel 1)&lt;/span>
&lt;button class="copy-btn" onclick="copyCode(this)">Salin&lt;/button>
&lt;/div>
&lt;pre>&lt;span class="cm"># ── Reshape ke long format untuk ggplot ──────────────────────&lt;/span>
df_long &lt;span class="op">&amp;lt;-&lt;/span> df &lt;span class="op">|&amp;gt;&lt;/span>
&lt;span class="fn">select&lt;/span>(tahun, raw, m4, obs) &lt;span class="op">|&amp;gt;&lt;/span>
&lt;span class="fn">pivot_longer&lt;/span>(&lt;span class="fn">c&lt;/span>(raw, m4, obs), names_to &lt;span class="op">=&lt;/span> &lt;span class="str">"seri"&lt;/span>, values_to &lt;span class="op">=&lt;/span> &lt;span class="str">"hhmt"&lt;/span>) &lt;span class="op">|&amp;gt;&lt;/span>
&lt;span class="fn">mutate&lt;/span>(seri &lt;span class="op">=&lt;/span> &lt;span class="fn">factor&lt;/span>(seri,
levels &lt;span class="op">=&lt;/span> &lt;span class="fn">c&lt;/span>(&lt;span class="str">"obs"&lt;/span>, &lt;span class="str">"m4"&lt;/span>, &lt;span class="str">"raw"&lt;/span>),
labels &lt;span class="op">=&lt;/span> &lt;span class="fn">c&lt;/span>(&lt;span class="str">"Obs BMKG"&lt;/span>, &lt;span class="str">"GPM M4 (Koreksi)"&lt;/span>, &lt;span class="str">"GPM Raw"&lt;/span>)))
p1 &lt;span class="op">&amp;lt;-&lt;/span> &lt;span class="fn">ggplot&lt;/span>(df_long, &lt;span class="fn">aes&lt;/span>(x &lt;span class="op">=&lt;/span> tahun, y &lt;span class="op">=&lt;/span> hhmt,
color &lt;span class="op">=&lt;/span> seri, linetype &lt;span class="op">=&lt;/span> seri, linewidth &lt;span class="op">=&lt;/span> seri)) &lt;span class="op">+&lt;/span>
&lt;span class="fn">geom_line&lt;/span>(na.rm &lt;span class="op">=&lt;/span> &lt;span class="kw">TRUE&lt;/span>) &lt;span class="op">+&lt;/span>
&lt;span class="fn">geom_point&lt;/span>(data &lt;span class="op">=&lt;/span> &lt;span class="op">.&lt;/span> &lt;span class="op">|&amp;gt;&lt;/span> &lt;span class="fn">filter&lt;/span>(seri &lt;span class="op">==&lt;/span> &lt;span class="str">"Obs BMKG"&lt;/span>),
size &lt;span class="op">=&lt;/span> &lt;span class="num">1.8&lt;/span>, shape &lt;span class="op">=&lt;/span> &lt;span class="num">21&lt;/span>) &lt;span class="op">+&lt;/span>
&lt;span class="fn">geom_label&lt;/span>(data &lt;span class="op">=&lt;/span> df &lt;span class="op">|&amp;gt;&lt;/span> &lt;span class="fn">filter&lt;/span>(m4 &lt;span class="op">&amp;gt;&lt;/span> &lt;span class="num">200&lt;/span>),
&lt;span class="fn">aes&lt;/span>(x &lt;span class="op">=&lt;/span> tahun, y &lt;span class="op">=&lt;/span> m4 &lt;span class="op">+&lt;/span> &lt;span class="num">8&lt;/span>,
label &lt;span class="op">=&lt;/span> &lt;span class="fn">paste0&lt;/span>(tahun, &lt;span class="str">"
"&lt;/span>, m4, &lt;span class="str">"mm"&lt;/span>)),
inherit.aes &lt;span class="op">=&lt;/span> &lt;span class="kw">FALSE&lt;/span>, size &lt;span class="op">=&lt;/span> &lt;span class="num">2.8&lt;/span>, color &lt;span class="op">=&lt;/span> &lt;span class="str">"#1A5276"&lt;/span>) &lt;span class="op">+&lt;/span>
&lt;span class="fn">scale_color_manual&lt;/span>(
values &lt;span class="op">=&lt;/span> &lt;span class="fn">c&lt;/span>(&lt;span class="str">"Obs BMKG"&lt;/span>&lt;span class="op">=&lt;/span>&lt;span class="str">"#B45309"&lt;/span>, &lt;span class="str">"GPM M4 (Koreksi)"&lt;/span>&lt;span class="op">=&lt;/span>&lt;span class="str">"#1A5276"&lt;/span>,
&lt;span class="str">"GPM Raw"&lt;/span>&lt;span class="op">=&lt;/span>&lt;span class="str">"#B91C1C"&lt;/span>), name &lt;span class="op">=&lt;/span> &lt;span class="kw">NULL&lt;/span>) &lt;span class="op">+&lt;/span>
&lt;span class="fn">scale_linetype_manual&lt;/span>(
values &lt;span class="op">=&lt;/span> &lt;span class="fn">c&lt;/span>(&lt;span class="str">"Obs BMKG"&lt;/span>&lt;span class="op">=&lt;/span>&lt;span class="str">"dashed"&lt;/span>, &lt;span class="str">"GPM M4 (Koreksi)"&lt;/span>&lt;span class="op">=&lt;/span>&lt;span class="str">"solid"&lt;/span>,
&lt;span class="str">"GPM Raw"&lt;/span>&lt;span class="op">=&lt;/span>&lt;span class="str">"solid"&lt;/span>), name &lt;span class="op">=&lt;/span> &lt;span class="kw">NULL&lt;/span>) &lt;span class="op">+&lt;/span>
&lt;span class="fn">scale_y_continuous&lt;/span>(
limits &lt;span class="op">=&lt;/span> &lt;span class="fn">c&lt;/span>(&lt;span class="num">0&lt;/span>, &lt;span class="num">280&lt;/span>),
labels &lt;span class="op">=&lt;/span> &lt;span class="kw">function&lt;/span>(x) &lt;span class="fn">paste0&lt;/span>(x, &lt;span class="str">" mm"&lt;/span>)) &lt;span class="op">+&lt;/span>
&lt;span class="fn">labs&lt;/span>(
title &lt;span class="op">=&lt;/span> &lt;span class="str">"Time Series HHMT Tahunan"&lt;/span>,
subtitle &lt;span class="op">=&lt;/span> &lt;span class="str">"GPM Raw vs GPM M4 vs Observasi BMKG | 1998–2025"&lt;/span>,
x &lt;span class="op">=&lt;/span> &lt;span class="kw">NULL&lt;/span>, y &lt;span class="op">=&lt;/span> &lt;span class="str">"HHMT (mm)"&lt;/span>,
caption &lt;span class="op">=&lt;/span> &lt;span class="str">"Sumber: GPM IMERG V07 (NASA) | BMKG Syamsuddin Noor + BMKG Kalsel"&lt;/span>
) &lt;span class="op">+&lt;/span>
&lt;span class="fn">theme_minimal&lt;/span>(base_size &lt;span class="op">=&lt;/span> &lt;span class="num">11&lt;/span>) &lt;span class="op">+&lt;/span>
&lt;span class="fn">theme&lt;/span>(plot.title &lt;span class="op">=&lt;/span> &lt;span class="fn">element_text&lt;/span>(face &lt;span class="op">=&lt;/span> &lt;span class="str">"bold"&lt;/span>))
&lt;span class="cm"># ── Scatter Plot: M4 vs Obs ───────────────────────────────────&lt;/span>
p_scatter &lt;span class="op">&amp;lt;-&lt;/span> &lt;span class="fn">ggplot&lt;/span>(df, &lt;span class="fn">aes&lt;/span>(x &lt;span class="op">=&lt;/span> obs, y &lt;span class="op">=&lt;/span> m4)) &lt;span class="op">+&lt;/span>
&lt;span class="fn">geom_abline&lt;/span>(slope &lt;span class="op">=&lt;/span> &lt;span class="num">1&lt;/span>, intercept &lt;span class="op">=&lt;/span> &lt;span class="num">0&lt;/span>,
linetype &lt;span class="op">=&lt;/span> &lt;span class="str">"dashed"&lt;/span>, color &lt;span class="op">=&lt;/span> &lt;span class="str">"#94A3B8"&lt;/span>) &lt;span class="op">+&lt;/span>
&lt;span class="fn">geom_point&lt;/span>(color &lt;span class="op">=&lt;/span> &lt;span class="str">"#1A5276"&lt;/span>, size &lt;span class="op">=&lt;/span> &lt;span class="num">3&lt;/span>, shape &lt;span class="op">=&lt;/span> &lt;span class="num">21&lt;/span>) &lt;span class="op">+&lt;/span>
&lt;span class="fn">ggrepel&lt;/span>::&lt;span class="fn">geom_text_repel&lt;/span>(&lt;span class="fn">aes&lt;/span>(label &lt;span class="op">=&lt;/span> tahun),
size &lt;span class="op">=&lt;/span> &lt;span class="num">2.5&lt;/span>, color &lt;span class="op">=&lt;/span> &lt;span class="str">"#475569"&lt;/span>) &lt;span class="op">+&lt;/span>
&lt;span class="fn">geom_smooth&lt;/span>(method &lt;span class="op">=&lt;/span> &lt;span class="str">"lm"&lt;/span>, se &lt;span class="op">=&lt;/span> &lt;span class="kw">TRUE&lt;/span>,
color &lt;span class="op">=&lt;/span> &lt;span class="str">"#1A5276"&lt;/span>, fill &lt;span class="op">=&lt;/span> &lt;span class="str">"#1A527622"&lt;/span>) &lt;span class="op">+&lt;/span>
&lt;span class="fn">coord_equal&lt;/span>() &lt;span class="op">+&lt;/span>
&lt;span class="fn">labs&lt;/span>(title &lt;span class="op">=&lt;/span> &lt;span class="str">"Scatter: GPM M4 vs Obs BMKG"&lt;/span>,
x &lt;span class="op">=&lt;/span> &lt;span class="str">"Observasi BMKG (mm)"&lt;/span>, y &lt;span class="op">=&lt;/span> &lt;span class="str">"GPM M4 (mm)"&lt;/span>)
&lt;span class="cm"># ── Gabung &amp; simpan ──────────────────────────────────────────&lt;/span>
fig_final &lt;span class="op">&amp;lt;-&lt;/span> p1 &lt;span class="op">/&lt;/span> p_scatter &lt;span class="op">+&lt;/span>
&lt;span class="fn">plot_annotation&lt;/span>(
title &lt;span class="op">=&lt;/span> &lt;span class="str">"Koreksi Bias GPM IMERG V07 — WPG Banjarmasin"&lt;/span>,
caption &lt;span class="op">=&lt;/span> &lt;span class="str">"SNI 2415:2016 | Teutschbein &amp; Seibert (2012)"&lt;/span>)
&lt;span class="fn">ggsave&lt;/span>(&lt;span class="str">"hasil_kalibrasi_gpm.png"&lt;/span>, fig_final,
width &lt;span class="op">=&lt;/span> &lt;span class="num">36&lt;/span>, height &lt;span class="op">=&lt;/span> &lt;span class="num">30&lt;/span>, units &lt;span class="op">=&lt;/span> &lt;span class="str">"cm"&lt;/span>, dpi &lt;span class="op">=&lt;/span> &lt;span class="num">300&lt;/span>)&lt;/pre>
&lt;/div>
&lt;/section>
&lt;div class="divider">&lt;/div>
&lt;!-- ===== S8: KESIMPULAN ===== -->
&lt;section class="section anim-in" id="s8">
&lt;div class="section-header">&lt;div class="section-num">8&lt;/div>&lt;h2>Kesimpulan&lt;/h2>&lt;/div>
&lt;div class="card card-green">
&lt;div class="card-label" style="margin-bottom:10px;">Ringkasan Hasil&lt;/div>
&lt;div class="step-flow">
&lt;div class="step-item">
&lt;div class="step-line">&lt;div class="step-dot" style="background:var(--green);">✓&lt;/div>&lt;div class="step-connector">&lt;/div>&lt;/div>
&lt;div class="step-body">
&lt;div class="step-title">GPM Raw tidak layak digunakan langsung&lt;/div>
&lt;div class="step-desc">PBIAS = −31.9% dan NSE = −1.06 mengonfirmasi bahwa data mentah GPM IMERG secara sistematis meremehkan HHMT di wilayah Banjarmasin sebesar ~32% — tidak memenuhi threshold SNI 2415:2016 untuk analisis hidrologi desain.&lt;/div>
&lt;/div>
&lt;/div>
&lt;div class="step-item">
&lt;div class="step-line">&lt;div class="step-dot" style="background:var(--green);">✓&lt;/div>&lt;div class="step-connector">&lt;/div>&lt;/div>
&lt;div class="step-body">
&lt;div class="step-title">Metode M4 (Year-Specific Scaling) adalah yang terbaik&lt;/div>
&lt;div class="step-desc">Dibandingkan M1 (CF bulanan), M2 (direct scaling), dan M3 (quantile mapping), metode M4 menghasilkan metrik terbaik karena Fk dikalibrasi unik per tahun dari rata-rata dua stasiun BMKG — menangkap variabilitas antar tahun yang signifikan.&lt;/div>
&lt;/div>
&lt;/div>
&lt;div class="step-item">
&lt;div class="step-line">&lt;div class="step-dot" style="background:var(--green);">✓&lt;/div>&lt;div class="step-connector">&lt;/div>&lt;/div>
&lt;div class="step-body">
&lt;div class="step-title">Semua metrik validasi masuk kategori Sangat Baik&lt;/div>
&lt;div class="step-desc">Setelah kalibrasi M4: R=0.900, NSE=0.772, KGE=0.879, PBIAS=+3.5%, RMSE=15.8 mm. Semua nilai melampaui threshold Sangat Baik (SB) menurut Moriasi et al. (2007) dan SNI 2415:2016.&lt;/div>
&lt;/div>
&lt;/div>
&lt;div class="step-item">
&lt;div class="step-line">&lt;div class="step-dot" style="background:var(--green);">✓&lt;/div>&lt;div class="step-connector">&lt;/div>&lt;/div>
&lt;div class="step-body">
&lt;div class="step-title">Aplikasi praktis: data GPM M4 layak untuk analisis frekuensi&lt;/div>
&lt;div class="step-desc">Dengan kualitas data yang sudah masuk SB, GPM M4 dapat digunakan sebagai data curah hujan dalam analisis frekuensi (menghitung return period 25, 50, 100 tahun) untuk desain bangunan air di wilayah yang tidak memiliki stasiun observasi.&lt;/div>
&lt;/div>
&lt;/div>
&lt;/div>
&lt;/div>
&lt;div class="grid-2" style="margin-top:1rem;">
&lt;div class="card">
&lt;div class="card-label">Referensi Utama&lt;/div>
&lt;p style="line-height:2; font-size:12px;">
📚 Moriasi et al. (2007) — Model Evaluation Guidelines&lt;br>
📚 Teutschbein &amp;amp; Seibert (2012) — Bias Correction Methods&lt;br>
📚 Knoben et al. (2019) — KGE Commentary&lt;br>
📚 SNI 2415:2016 — Tata Cara Perhitungan Debit Banjir Rencana&lt;br>
🛰️ NASA GPM IMERG V07 Final Run&lt;br>
🌧️ BMKG Stasiun Syamsuddin Noor &amp;amp; BMKG Kalsel
&lt;/p>
&lt;/div>
&lt;div class="card">
&lt;div class="card-label">Keterbatasan &amp;amp; Pengembangan&lt;/div>
&lt;p style="line-height:1.8; font-size:12px;">
⚠️ Fk bersifat historis — proyeksi masa depan asumsi Fk = median&lt;br>
⚠️ Hanya 2 stasiun BMKG — wilayah DAS besar butuh lebih banyak&lt;br>
⚠️ Koreksi bias pada level HHMT — bukan distribusi harian penuh&lt;br>
🔭 Pengembangan: uji pada stasiun lain &amp;amp; periode lebih panjang&lt;br>
🔭 Kombinasikan M4 dengan M3 (Quantile Mapping) untuk distribusi
&lt;/p>
&lt;/div>
&lt;/div>
&lt;div style="background:linear-gradient(135deg,#0A2342,#1A3a5c 60%,#2d1065);color:#fff;border-radius:var(--radius);padding:1.75rem 2rem;text-align:center;margin-top:1.5rem;">
&lt;div style="font-size:18px;font-weight:700;margin-bottom:8px;">Ada pertanyaan tentang kalibrasi data GPM?&lt;/div>
&lt;p style="font-size:13px;color:rgba(255,255,255,0.65);margin-bottom:1.25rem;">Diskusi metodologi, data, atau implementasi di proyekmu&lt;/p>
&lt;a href="https://www.irpanchumaedi.com/#contact" target="_top" style="display:inline-block;background:var(--blue-mid);color:#fff;font-size:13px;font-weight:600;padding:10px 24px;border-radius:20px;text-decoration:none;">Hubungi saya →&lt;/a>
&lt;/div>
&lt;/section>
&lt;/div>
&lt;script>
/* DATA */
const years = [1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023, 2024, 2025];
const rawData = [62.8, 71.0, 75.4, 66.4, 64.6, 70.6, 89.3, 63.4, 76.1, 70.7, 82.7, 58.3, 81.5, 161.3, 64.8, 74.6, 67.2, 53.1, 71.1, 92.9, 72.8, 67.9, 57.2, 105.2, 62.7, 57.1, 103.1, 63.9];
const m4Data = [105.3, 92.2, 98.3, 83.8, 95.0, 139.6, 136.0, 64.2, 85.5, 97.9, 149.1, 101.9, 90.5, 135.8, 94.0, 103.0, 165.7, 107.4, 108.0, 99.5, 101.7, 84.0, 124.1, 252.2, 135.0, 131.1, 127.7, 92.6];
const obsData = [86.1, 93.1, 101.0, 78.9, 119.8, 119.8, 136.1, 62.2, 80.0, 109.3, 116.2, 105.2, 90.5, 113.0, 92.4, 118.2, 117.5, 98.9, 108.0, 111.8, 112.1, 70.5, 122.1, 249.0, 120.8, 127.6, 148.4, 84.4];
const fkData = [1.6768, 1.2979, 1.3031, 1.262, 1.4706, 1.978, 1.523, 1.0134, 1.1229, 1.3847, 1.8035, 1.7479, 1.1104, 0.8419, 1.4506, 1.3807, 2.4658, 2.0235, 1.519, 1.071, 1.397, 1.2364, 2.1696, 2.3969, 2.1531, 2.296, 1.2386, 1.4491];
const errRaw = rawData.map((v,i) => parseFloat((v - obsData[i]).toFixed(1)));
const errM4 = m4Data.map((v,i) => parseFloat((v - obsData[i]).toFixed(1)));
const medFk = (() => { const s=[...fkData].sort((a,b)=>a-b); const m=Math.floor(s.length/2); return s.length%2?s[m]:(s[m-1]+s[m])/2; })();
/* PROGRESS */
function updateProgress() {
const pct = Math.round((window.scrollY/(document.body.scrollHeight-window.innerHeight))*100)||0;
document.getElementById('progBar').style.width = pct+'%';
document.getElementById('progPct').textContent = pct+'%';
updateToc();
}
window.addEventListener('scroll', updateProgress, {passive:true});
/* TOC */
function updateToc() {
const secs = document.querySelectorAll('section[id],div[id]');
const links = document.querySelectorAll('.toc-link');
let active = '';
secs.forEach(s => { if(s.getBoundingClientRect().top &lt; 120) active = s.id; });
links.forEach(l => {
const href = l.getAttribute('href').slice(1);
l.classList.toggle('active', href === active);
});
}
function toggleToc() {
const toc = document.getElementById('tocFloat');
toc.classList.toggle('collapsed');
// Save state
try { localStorage.setItem('tocCollapsed', toc.classList.contains('collapsed')); } catch(e){}
}
function toggleTocMobile() {
const toc = document.getElementById('tocFloat');
toc.style.display = toc.style.display === 'block' ? 'none' : 'block';
}
// Restore collapse state
(function(){
try {
if(localStorage.getItem('tocCollapsed') === 'true') {
document.getElementById('tocFloat').classList.add('collapsed');
}
} catch(e){}
})();
/* FILL TABLE */
const tbody = document.getElementById('tblBody');
const rowData = [
[1998,62.8,1.677,105.3,86.1], [1999,71.0,1.298,92.2,93.1],
[2000,75.4,1.303,98.3,101.0], [2001,66.4,1.262,83.8,78.9],
[2002,64.6,1.471,95.0,119.8], [2003,70.6,1.978,139.6,119.8],
[2004,89.3,1.523,136.0,136.1], [2005,63.4,1.013,64.2,62.2],
[2006,76.1,1.123,85.5,80.0], [2007,70.7,1.385,97.9,109.3],
[2008,82.7,1.804,149.1,116.2], [2009,58.3,1.748,101.9,105.2],
[2010,81.5,1.110,90.5,90.5], [2011,161.3,0.842,135.8,113.0],
[2012,64.8,1.451,94.0,92.4], [2013,74.6,1.381,103.0,118.2],
[2014,67.2,2.466,165.7,117.5], [2015,53.1,2.024,107.4,98.9],
[2016,71.1,1.519,108.0,108.0], [2017,92.9,1.071,99.5,111.8],
[2018,72.8,1.397,101.7,112.1], [2019,67.9,1.236,84.0,70.5],
[2020,57.2,2.170,124.1,122.1], [2021,105.2,2.397,252.2,249.0],
[2022,62.7,2.153,135.0,120.8], [2023,57.1,2.296,131.1,127.6],
[2024,103.1,1.239,127.7,148.4], [2025,63.9,1.449,92.6,84.4]
];
rowData.forEach(([yr,raw,fk,m4,obs]) => {
const er = parseFloat((raw-obs).toFixed(1));
const em = parseFloat((m4-obs).toFixed(1));
const tr = document.createElement('tr');
tr.innerHTML = `&lt;td>${yr}&lt;/td>
&lt;td class="${er&lt;0?'neg':'pos'}">${raw}&lt;/td>
&lt;td style="color:#6D28D9;font-weight:600;">${fk.toFixed(3)}&lt;/td>
&lt;td class="${Math.abs(em)&lt;15?'good':''}">${m4}&lt;/td>
&lt;td>${obs}&lt;/td>
&lt;td class="${er&lt;0?'bad':'pos'}">${er>0?'+':''}${er}&lt;/td>
&lt;td class="${Math.abs(em)&lt;15?'good':'bad'}">${em>0?'+':''}${em}&lt;/td>`;
tbody.appendChild(tr);
});
/* CHARTS */
const CH = {};
function buildCharts() {
// ── Residual Error ──────────────────────────────────────────
const ctx1 = document.getElementById('chartResidual');
if(ctx1 &amp;&amp; !CH.r) {
ctx1.height = 240;
CH.r = new Chart(ctx1, {
type:'bar',
data:{
labels: years,
datasets:[
{label:'Error GPM Raw', data:errRaw, backgroundColor:'rgba(185,28,28,0.72)', borderRadius:3},
{label:'Error GPM M4', data:errM4, backgroundColor:'rgba(26,82,118,0.78)', borderRadius:3},
{type:'line', label:'Zona +10mm', data:Array(28).fill(10),
borderColor:'rgba(29,111,66,0.5)', borderWidth:1.5, borderDash:[5,4], pointRadius:0, fill:false},
{type:'line', label:'Zona -10mm', data:Array(28).fill(-10),
borderColor:'rgba(29,111,66,0.5)', borderWidth:1.5, borderDash:[5,4], pointRadius:0, fill:'-1',
backgroundColor:'rgba(29,111,66,0.08)'}
]
},
options:{
responsive:true, maintainAspectRatio:false,
plugins:{
legend:{display:true, position:'bottom', labels:{font:{size:11}, usePointStyle:true,
filter: item => !item.text.startsWith('Zona')}},
tooltip:{callbacks:{label:c => {
if(c.dataset.label.startsWith('Zona')) return null;
const sign = c.raw > 0 ? '+' : '';
return c.dataset.label + ': ' + sign + c.raw + ' mm';
}}}
},
scales:{
x:{ticks:{font:{size:10}, maxRotation:60, autoSkip:false}, grid:{display:false}},
y:{title:{display:true, text:'Error (mm)'}, ticks:{font:{size:11}},
grid:{color:'rgba(0,0,0,0.06)'}}
},
animation:{duration:700}
}
});
}
// ── Metrik Validasi ─────────────────────────────────────────
const ctx2 = document.getElementById('chartMetrik');
if(ctx2 &amp;&amp; !CH.m) {
ctx2.height = 280;
CH.m = new Chart(ctx2, {
type:'bar',
data:{
labels:['R (Korelasi)', 'R² (Determinasi)', 'NSE (Nash-Sutcliffe)', 'KGE (Kling-Gupta)'],
datasets:[
{label:'GPM Raw', data:[0.373,0.139,-1.062,0.206], backgroundColor:'rgba(185,28,28,0.75)', borderRadius:4},
{label:'GPM M4', data:[0.900,0.811, 0.772, 0.879], backgroundColor:'rgba(26,82,118,0.80)', borderRadius:4},
{type:'line', label:'Threshold SB (0.75)', data:[0.75,0.75,0.75,0.75],
borderColor:'#1d6f42', borderWidth:2, borderDash:[6,4], pointRadius:0, fill:false}
]
},
options:{
responsive:true, maintainAspectRatio:false,
plugins:{
legend:{position:'bottom', labels:{font:{size:11}, usePointStyle:true}},
tooltip:{callbacks:{label:c => c.dataset.label + ': ' + Number(c.raw).toFixed(3)}}
},
scales:{
x:{ticks:{font:{size:11}}, grid:{display:false}},
y:{min:-1.2, max:1.05, title:{display:true, text:'Nilai Metrik'}, ticks:{font:{size:11}}}
},
animation:{duration:800}
}
});
}
// ── Faktor Koreksi Fk ───────────────────────────────────────
const ctx3 = document.getElementById('chartFk');
if(ctx3 &amp;&amp; !CH.fk) {
ctx3.height = 260;
const medLabel = 'Median Fk (' + medFk.toFixed(3) + ')';
CH.fk = new Chart(ctx3, {
type:'bar',
data:{
labels: years,
datasets:[
{label:'Fk per tahun', data:fkData, backgroundColor:'rgba(109,40,217,0.75)', borderRadius:3},
{type:'line', label: medLabel, data:Array(28).fill(medFk),
borderColor:'#6D28D9', borderWidth:2, borderDash:[6,4], pointRadius:0, fill:false},
{type:'line', label:'Fk = 1.0', data:Array(28).fill(1.0),
borderColor:'#94a3b8', borderWidth:1.5, borderDash:[3,3], pointRadius:0, fill:false}
]
},
options:{
responsive:true, maintainAspectRatio:false,
plugins:{
legend:{display:false},
tooltip:{callbacks:{label:c => {
if(c.datasetIndex === 0) return 'Fk: ' + Number(c.raw).toFixed(3);
return c.dataset.label;
}}}
},
scales:{
x:{ticks:{font:{size:10}, maxRotation:60, autoSkip:false}, grid:{display:false}},
y:{min:0, max:2.85, title:{display:true, text:'Fk (-)'}, ticks:{font:{size:11}}}
},
animation:{duration:700}
}
});
}
}
/* INTERSECTION OBSERVER */
const io = new IntersectionObserver(entries => {
entries.forEach(e => {
if(e.isIntersecting) {
e.target.classList.add('visible');
buildCharts();
}
});
}, {threshold:0.01, rootMargin:'0px 0px -10px 0px'});
document.querySelectorAll('.anim-in').forEach(el => io.observe(el));
// Fallback: build charts immediately in case IO doesn't fire (iframe context)
setTimeout(buildCharts, 400);
/* COPY */
function copyCode(btn) {
const text = btn.closest('.code-wrap').querySelector('pre').innerText;
navigator.clipboard.writeText(text).then(() => {
btn.textContent='✓ Tersalin!';
setTimeout(()=>btn.textContent='Salin',2000);
});
}
updateProgress();
buildCharts();
&lt;/script></description></item></channel></rss>