/* ==========================================================================
   style.css — Tata rupa OMC-EVAL

   Warna, ukuran huruf, dan proporsi diambil dari laman resmi BMKG yang
   dijadikan acuan: bilah waktu gelap tipis di puncak, kepala putih dengan
   logo di kiri dan navigasi di tengah, badan berlatar biru sangat muda,
   serta kartu putih bersudut tumpul dengan bayangan tipis.

   Seluruh warna disimpan sebagai peubah agar penyesuaian cukup dilakukan
   di satu tempat.
   ========================================================================== */

/* ==========================================================================
   TEMA
   --------------------------------------------------------------------------
   Seluruh warna hidup sebagai peubah bernama menurut warna LITERALnya di
   tema terang (mis. --biru-tua, --putih) — tetapi dipakai di seluruh berkas
   ini menurut PERANNYA (judul, permukaan kartu, dsb). Itu sebabnya tema
   gelap di bawah aman menimpa nilainya dengan warna yang sama sekali
   berbeda: --putih di tema gelap BUKAN putih, melainkan permukaan kartu
   gelap — tapi setiap tempat yang memakai var(--putih) tetap mendapat
   perannya yang benar (warna permukaan) tanpa satu pun aturan lain disentuh.

   Atribut data-theme pada <html> diatur SEBELUM cat pertama oleh skrip kecil
   di <head> index.php, supaya tidak ada kedipan tema terang sekejap saat
   halaman dimuat dengan preferensi gelap.
   ========================================================================== */
:root {
    color-scheme: light;

    /* Identitas BMKG */
    --biru-tua:      #14395e;
    --biru:          #1b5c9c;
    --biru-terang:   #2b7fd4;
    --biru-pucat:    #e8f1fa;
    --biru-pucat-tepi: #cfe1f4;
    --biru-latar:    #f2f7fc;

    --hijau-jam:     #35d07f;   /* angka jam pada bilah waktu */
    --jingga:        #f08a3c;   /* penanda lintasan pesawat */
    --jingga-latar:  #fffaf5;
    --merah:         #d94141;
    --merah-latar:   #fdecec;
    --merah-latar-hover: #fbdcdc;
    --merah-tepi:    #e6b3b3;
    --merah-teks:    #b52d4a;
    --kuning:        #f2c14e;

    --teks:          #16202b;
    --teks-lembut:   #5b6b7c;
    --teks-samar:    #8b9bab;
    --garis:         #dde6ef;
    --putih:         #ffffff;

    /* Permukaan kedua — sedikit lebih redup dari --putih: ujung gradien
       kepala panel/modal, dasar area jatuhan berkas, kaki modal. */
    --permukaan-2:        #fbfdff;
    --permukaan-2-tepi:   #c4d7e8;
    --permukaan-2-terisi: #bcd6ee;

    --panel-latar: rgba(255, 255, 255, .97);
    --modal-latar: rgba(12, 28, 45, .42);
    --peta-latar:  #dfe8f0;
    --switch-latar: #ccd8e4;

    --peringatan-latar: #fff8ec;
    --peringatan-tepi:  #f5dcb0;
    --peringatan-teks:  #7a5a1e;

    --gulir:       #c8d6e4;
    --gulir-hover: #a9bccd;

    --bayang-1: 0 1px 2px rgba(20, 57, 94, .06), 0 2px 8px rgba(20, 57, 94, .05);
    --bayang-2: 0 2px 6px rgba(20, 57, 94, .10), 0 8px 28px rgba(20, 57, 94, .10);
    --bayang-3: 0 12px 40px rgba(20, 57, 94, .18);

    --lengkung:   14px;
    --lengkung-s: 9px;

    --bilah-tinggi:  40px;
    --kepala-tinggi: 68px;
}

:root[data-theme="dark"] {
    color-scheme: dark;

    --biru-tua:      #cfe1f8;
    --biru:          #6fb4f0;
    --biru-terang:   #4aa3ef;
    --biru-pucat:    #16324c;
    --biru-pucat-tepi: #1f3f5c;
    --biru-latar:    #0a121c;

    --hijau-jam:     #46e0a0;
    --jingga:        #f3a35f;
    --jingga-latar:  #2e2013;
    --merah:         #ef6b6b;
    --merah-latar:   #341f22;
    --merah-latar-hover: #442a2e;
    --merah-tepi:    #5c343a;
    --merah-teks:    #f0919c;
    --kuning:        #f2c14e;

    --teks:          #e6edf5;
    --teks-lembut:   #9fb0c2;
    --teks-samar:    #6c7f93;
    --garis:         #24374a;
    --putih:         #141e2a;

    --permukaan-2:        #0e1620;
    --permukaan-2-tepi:   #24374a;
    --permukaan-2-terisi: #2c4258;

    --panel-latar: rgba(20, 30, 42, .94);
    --modal-latar: rgba(0, 0, 0, .6);
    --peta-latar:  #0d141c;
    --switch-latar: #2c3b4a;

    --peringatan-latar: #332711;
    --peringatan-tepi:  #56431c;
    --peringatan-teks:  #f0c878;

    --gulir:       #2c3d4d;
    --gulir-hover: #3d5266;

    --bayang-1: 0 1px 2px rgba(0, 0, 0, .45), 0 2px 10px rgba(0, 0, 0, .35);
    --bayang-2: 0 2px 8px rgba(0, 0, 0, .5), 0 10px 32px rgba(0, 0, 0, .45);
    --bayang-3: 0 16px 48px rgba(0, 0, 0, .6);
}

* { box-sizing: border-box; margin: 0; padding: 0; }

/* [hidden] harus SELALU menang atas "display:" apa pun yang ditetapkan
   lewat kelas elemennya — CSS milik penulis (author, di sini) mengalahkan
   CSS baku peramban (user-agent) pada spesifisitas yang sama, jadi elemen
   seperti .field-pair (display:grid) atau .timeline (display:flex) diam-
   diam TETAP TAMPIL walau atribut hidden terpasang, kecuali baris ini ada.
   Inilah yang membuat kolom "Tanggal mulai/akhir" tetap terlihat padahal
   sakelar "Tetapkan rentang sendiri" belum dinyalakan. Beberapa elemen
   sudah punya tambalan sendiri (mis. .modal-backdrop[hidden]) — tetap
   dibiarkan, tidak saling bertentangan, hanya jadi berlebih. */
[hidden] { display: none !important; }

html, body {
    height: 100%;
    font-family: 'Inter', 'Segoe UI', system-ui, -apple-system, sans-serif;
    font-size: 15px;
    color: var(--teks);
    background: var(--biru-latar);
    -webkit-font-smoothing: antialiased;
}

/* Transisi lembut saat berganti tema, tanpa membuat tiap interaksi biasa
   (hover, fokus) ikut terasa lamban — hanya properti warna yang dipengaruhi
   pergantian tema yang diberi durasi, dan durasinya pendek. */
body, .panel, .modal, .header, .time-bar, input, select, textarea,
button.btn, .settings-tab, .tl-tab, .rain-source button {
    transition: background-color .18s ease, border-color .18s ease, color .18s ease;
}

/* ==========================================================================
   BILAH WAKTU
   ========================================================================== */
.time-bar {
    height: var(--bilah-tinggi);
    background: var(--putih);
    border-bottom: 1px solid var(--garis);
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0 26px;
    font-size: 12.5px;
    letter-spacing: .04em;
    color: var(--teks-lembut);
    font-weight: 600;
}
.time-bar .date { text-transform: uppercase; }
.time-bar .time-right { display: flex; align-items: center; gap: 12px; }
.time-bar .label { text-transform: uppercase; }
.time-bar .clock {
    font-family: 'JetBrains Mono', 'SF Mono', ui-monospace, monospace;
    color: var(--hijau-jam);
    font-size: 13.5px;
    letter-spacing: .12em;
    font-weight: 700;
}
.time-bar .sep { color: var(--teks-samar); }

/* ==========================================================================
   KEPALA
   ========================================================================== */
.header {
    height: var(--kepala-tinggi);
    background: var(--putih);
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0 26px;
    box-shadow: var(--bayang-1);
    position: relative;
    z-index: 400;
}
.brand { display: flex; align-items: center; gap: 13px; }
/* Bukan lagi kotak gradien berisi teks "BMKG" — gambar logo asli (bulat,
   latar transparan) langsung, tanpa bentuk latar apa pun di belakangnya.
   Lihat .logo-img/.logo-img-light/.logo-img-dark di bawah untuk gaya
   gambarnya sendiri (dipakai bersama .login-brand-logo di login.css). */
.brand .logo {
    width: 44px; height: 44px;
    display: grid; place-items: center;
    position: relative;
}

/* Gambar logo — dipakai baik di header aplikasi (.brand .logo) MAUPUN
   laman masuk (.login-brand-logo di login.css), jadi didefinisikan di
   SINI satu kali. Dua salinan <img> ditumpuk (grid place-items: center
   pada wadahnya), yang aktif ditentukan tema lewat data-theme pada
   <html> — bukan JS terpisah, sama seperti pola dark-mode CSS lain di
   berkas ini. border-radius:50% sekadar jaring pengaman (PNG-nya sendiri
   sudah bulat dengan latar transparan); tak ada background/border-radius
   KOTAK apa pun di wadahnya lagi.
   grid-area sama untuk keduanya supaya bertumpuk pas di tempat yang sama
   alih-alih bersebelahan. */
.logo-img {
    grid-area: 1 / 1;
    width: 100%; height: 100%; object-fit: contain; border-radius: 50%;
    animation: logo-denyut 3.6s ease-in-out infinite;
}
.logo-img-dark { display: none; }
:root[data-theme="dark"] .logo-img-light { display: none; }
:root[data-theme="dark"] .logo-img-dark { display: block; }

/* Denyut halus terus-menerus — HANYA bayangan di sekitar logo yang
   mengembang-mengempis, ukuran/posisi gambarnya sendiri tetap diam. Kesan
   "aktif/memantau" tanpa terasa main-main untuk lambang instansi resmi. */
@keyframes logo-denyut {
    0%, 100% { filter: drop-shadow(0 0 0 rgba(43, 127, 212, 0)); }
    50%      { filter: drop-shadow(0 0 7px rgba(43, 127, 212, .55)); }
}
@media (prefers-reduced-motion: reduce) {
    .logo-img { animation: none; }
}

.brand .name {
    font-size: 12.5px; font-weight: 800; line-height: 1.28;
    text-transform: uppercase; letter-spacing: .02em; color: var(--biru-tua);
}
.brand .name span { display: block; }
.brand .name .sub {
    font-weight: 600; color: var(--teks-lembut);
    text-transform: none; letter-spacing: 0; font-size: 11.5px;
}

/* Ikon garis kecil dipakai di mana pun (nav, tab dok, judul kartu) — satu
   aturan untuk seluruhnya, lihat js/icons.js.
   fill/stroke DI SINI, bukan cuma diserahkan ke atribut SVG bawaan
   icons.js: ikon yang ditulis LANGSUNG sebagai <svg class="ic"> di
   index.php (nav kepala, tab dok, dll.) tidak pernah menyertakan
   fill="none" stroke="currentColor" pada tiap svg-nya sendiri — tanpa
   aturan ini keduanya jatuh ke baku SVG (fill hitam pekat, tanpa garis),
   sehingga path TERBUKA (bukan bentuk tertutup) tampil sebagai gumpalan
   hitam yang tidak proporsional, bukan ikon garis bersih seperti yang
   dihasilkan icons.js. display:block menghindari spasi ekstra di bawah
   ikon akibat perataan baseline bawaan elemen inline. */
.ic {
    width: 16px; height: 16px; flex: none; display: block;
    fill: none; stroke: currentColor; stroke-width: 1.7;
    stroke-linecap: round; stroke-linejoin: round;
}

.nav { display: flex; gap: 4px; }
.nav button {
    display: flex; align-items: center; gap: 7px;
    border: 0; background: transparent; cursor: pointer;
    padding: 9px 15px; border-radius: var(--lengkung-s);
    font: inherit; font-size: 14px; font-weight: 600; color: var(--teks-lembut);
    transition: background .14s, color .14s, transform .1s;
}
.nav button:hover { background: var(--biru-pucat); color: var(--biru); }
.nav button.active { background: var(--biru-pucat); color: var(--biru); }
.nav button:active { transform: scale(.96); }

/* Di layar lebar, sidebar Data Masukan dan dok Proses/Hasil/Lapisan/Arsip
   SELALU terlihat sendiri (lihat .sidebar, .dock lebih bawah) — tombol
   navigasi ke sana di kepala cuma menduplikasi tab/laci yang sudah
   tampil, jadi disembunyikan di sini. "Pengaturan" TIDAK ikut disembunyikan
   — satu-satunya tujuan itu yang tak punya rupa lain di layar. Pada layar
   sempit (menu tarik-turun tumpuk, lihat @media max-width:760px) tombol
   ini tetap satu-satunya jalan membuka laci sidebar/dok, jadi dikembalikan
   tampil di sana. */
.nav button[data-sidebar],
.nav button[data-tab] {
    display: none;
}

/* Lencana sambungan */
.conn {
    display: flex; align-items: center; gap: 8px;
    padding: 7px 14px 7px 11px;
    border: 1px solid var(--garis); border-radius: 999px;
    font-size: 12.5px; font-weight: 600; color: var(--teks-lembut);
    background: var(--putih);
}
.conn .led {
    width: 8px; height: 8px; border-radius: 50%;
    background: var(--teks-samar); flex: none;
}
.conn.connected .led { background: var(--hijau-jam); box-shadow: 0 0 0 3px rgba(53,208,127,.18); }
.conn.connecting .led { background: var(--kuning); animation: pulse 1.1s infinite; }
.conn.offline .led { background: var(--merah); }

/* Wadah kanan kepala: lencana sambungan + tombol tema (+ tombol menu pada
   layar sempit). Dipisah dari .header agar space-between-nya tetap membagi
   TIGA kelompok (identitas / navigasi / aksi), bukan berantakan begitu
   tombol baru ditambahkan. */
.header-actions { display: flex; align-items: center; gap: 10px; }

/* Tombol bundar berisi SATU ikon — dipakai tema terang/gelap dan
   Pengaturan, bersisian di header-actions. Sengaja tanpa label teks:
   keduanya sudah cukup jelas maknanya dari ikon + title (tooltip), dan
   header perlu tetap ringkas di layar sempit. */
.icon-btn {
    display: grid; place-items: center;
    width: 34px; height: 34px; flex: none;
    border: 1px solid var(--garis); border-radius: 50%;
    background: var(--putih); color: var(--teks-lembut);
    cursor: pointer;
    transition: background .14s, color .14s, border-color .14s;
}
.icon-btn:hover { background: var(--biru-pucat); color: var(--biru); border-color: var(--biru-pucat-tepi); }
.icon-btn.active { background: var(--biru-pucat); color: var(--biru); border-color: var(--biru-pucat-tepi); }

/* Tombol menu navigasi — hanya tampak pada layar sempit (lihat media query
   di bawah), tempat .nav sendiri disembunyikan menjadi menu tarik-turun. */
.nav-toggle {
    display: none;
    width: 34px; height: 34px; flex: none;
    border: 1px solid var(--garis); border-radius: var(--lengkung-s);
    background: var(--putih); color: var(--biru-tua);
    cursor: pointer; font-size: 16px;
}
@keyframes pulse { 0%,100% { opacity: 1 } 50% { opacity: .3 } }

/* ==========================================================================
   TATA LETAK UTAMA
   --------------------------------------------------------------------------
   Tiga kolom berdampingan, simetris: sidebar Data Masukan tetap di kiri,
   dok Proses/Hasil/Lapisan/Arsip tetap di kanan, peta mengisi apa pun sisa
   ruang di tengah. Keduanya dapat dilipat untuk memberi peta lebar penuh,
   tapi TIDAK PERNAH melayang bebas atau saling menumpuk — beda dari susunan
   sebelumnya di mana Proses/Hasil/Lapisan/Arsip adalah empat jendela lepas
   yang dapat digeser ke atas satu sama lain.
   ========================================================================== */
.body-area {
    position: relative;
    height: calc(100vh - var(--bilah-tinggi) - var(--kepala-tinggi));
    display: flex;
}

/* Sidebar kiri: Data Masukan. */
#panel-data.sidebar {
    position: relative;
    flex: none;
    width: 366px;
    max-width: 46vw;
    height: 100%;
    border: 0;
    border-right: 1px solid var(--garis);
    border-radius: 0;
    box-shadow: var(--bayang-1);
    background: var(--putih);
    z-index: 450;
    transition: width .22s ease;
}
#panel-data.sidebar[hidden] { display: none !important; }

/* Sidebar tidak pernah ditutup, hanya dilipat — tombol tutup sudah tidak
   dituliskan sama sekali di kepalanya (lihat index.php). */
#panel-data.sidebar.collapsed {
    width: 0; overflow: visible; border-right: 0;
}
#panel-data.sidebar.collapsed .panel-body,
#panel-data.sidebar.collapsed .panel-head .panel-title { display: none; }

.map-wrap { position: relative; flex: 1; min-width: 0; height: 100%; }
#map, #map2 { position: absolute; inset: 0; background: var(--peta-latar); }
#map2 { display: none; }

/* ==========================================================================
   BANDINGKAN — GSMaP & Model berdampingan
   --------------------------------------------------------------------------
   Baku (tanpa .compare): #map menutupi seluruh .map-wrap dan #map2 tidak
   pernah ditampilkan. Begitu dinyalakan, .map-wrap berubah jadi baris flex
   dan kedua peta berbagi ruang rata — Leaflet butuh ukuran elemen yang
   pasti (bukan absolute/inset) untuk menghitung ubinnya dengan benar,
   itu sebabnya position/flex-nya ikut ditimpa, bukan sekadar lebarnya.
   ========================================================================== */
.map-wrap.compare { display: flex; }
.map-wrap.compare #map, .map-wrap.compare #map2 {
    position: relative; inset: auto; flex: 1; min-width: 0; display: block;
}
.map-wrap.compare #map { border-right: 2px solid var(--garis); }

.map-split-label {
    display: none;
    position: absolute; top: 12px; z-index: 456;
    background: var(--panel-latar); backdrop-filter: blur(6px);
    border: 1px solid var(--garis); border-radius: 999px;
    padding: 5px 13px; font-size: 11.5px; font-weight: 800;
    letter-spacing: .04em; text-transform: uppercase; color: var(--biru-tua);
    box-shadow: var(--bayang-1); pointer-events: none;
}
.map-split-label-left { left: 12px; }
.map-split-label-right { right: 12px; }
.map-wrap.compare .map-split-label { display: block; }

/* Tombol untuk memunculkan sidebar/dok kembali ketika salah satunya
   dilipat — minimalis (cuma ikon panah, bundar) tapi tetap mudah diklik
   (34×34px). Satu aturan dasar dipakai KEDUANYA, sisi kiri (sidebar) dan
   kanan (dok), simetris — hanya beda posisi dan kapan tampil.
   Tanpa .dock-toggle di sisi kanan, dok yang terlipat di layar LEBAR tak
   dapat dibuka lagi sama sekali — sebelumnya satu-satunya jalan adalah
   tombol navigasi Proses/Hasil/Lapisan/Arsip di kepala, yang justru
   disembunyikan di layar lebar sebab menduplikasi tab dok sendiri (lihat
   .nav button[data-tab] di atas). */
.edge-toggle {
    position: absolute; top: 12px; z-index: 460;
    display: none; align-items: center; justify-content: center;
    width: 34px; height: 34px;
    border: 1px solid var(--garis); background: var(--putih);
    border-radius: 999px; cursor: pointer;
    color: var(--biru); box-shadow: var(--bayang-1);
    transition: background .14s, border-color .14s, transform .12s;
}
.edge-toggle:hover { background: var(--biru-pucat); border-color: var(--biru-pucat-tepi); }
.edge-toggle:active { transform: scale(.94); }
.edge-toggle-left { left: 12px; }
.edge-toggle-right { right: 12px; }
body.sidebar-collapsed .edge-toggle-left { display: flex; }
body.dock-collapsed .edge-toggle-right { display: flex; }

/* ==========================================================================
   DOK — Proses / Hasil / Lapisan / Arsip
   --------------------------------------------------------------------------
   Kolom tetap di kanan, simetris dengan sidebar Data Masukan di kiri. Isi
   berganti lewat tab, bukan lewat membuka jendela baru — satu tempat,
   selalu di sana, tak pernah tumpang tindih dengan apa pun.
   ========================================================================== */
.dock {
    position: relative;
    flex: none;
    width: 384px;
    max-width: 50vw;
    height: 100%;
    display: flex; flex-direction: column;
    background: var(--putih);
    border-left: 1px solid var(--garis);
    box-shadow: var(--bayang-1);
    z-index: 450;
    transition: width .22s ease;
}
.dock.collapsed { width: 0; overflow: visible; border-left: 0; }
.dock.collapsed .dock-tabs, .dock.collapsed .dock-body { display: none; }

.dock-tabs {
    display: flex; align-items: stretch; flex: none;
    border-bottom: 1px solid var(--garis);
    background: linear-gradient(var(--putih), var(--permukaan-2));
    overflow-x: auto;
}
.dock-tabs button {
    position: relative;
    display: flex; flex-direction: column; align-items: center; gap: 4px;
    flex: 1; min-width: 72px;
    border: 0; background: transparent; cursor: pointer;
    padding: 12px 6px 10px;
    font: inherit; font-size: 11px; font-weight: 700; color: var(--teks-samar);
    white-space: nowrap;
    transition: background .14s, color .14s;
}
.dock-tabs button .ic { width: 18px; height: 18px; }
.dock-tabs button:hover { color: var(--biru); background: var(--biru-pucat); }
.dock-tabs button.active { color: var(--biru); }
.dock-tabs button.active::after {
    content: ''; position: absolute; left: 14%; right: 14%; bottom: 0;
    height: 2.5px; border-radius: 2px 2px 0 0;
    background: linear-gradient(90deg, var(--biru-terang), var(--biru));
}
.dock-tab-dot {
    position: absolute; top: 9px; right: 22%;
    width: 7px; height: 7px; border-radius: 50%;
    background: var(--jingga);
    box-shadow: 0 0 0 2px var(--putih);
    animation: pulse 1.4s ease-in-out infinite;
}

.dock-collapse {
    flex: none; width: 32px;
    display: flex; align-items: center; justify-content: center;
    border: 0; border-left: 1px solid var(--garis); background: transparent;
    color: var(--teks-samar); cursor: pointer;
    transition: background .14s, color .14s, transform .22s ease;
}
.dock-collapse:hover { background: var(--biru-pucat); color: var(--biru); }
/* Anak panah menunjuk arah aksi tombolnya: ke kanan (lipat) saat terbuka,
   berputar ke kiri (bentangkan) saat terlipat. Ketika benar-benar terlipat
   tombol ini ikut tersembunyi bersama .dock-tabs — membuka dok kembali
   dilakukan lewat tombol navigasi Proses/Hasil/Lapisan/Arsip di kepala,
   yang selalu terlihat. */
.dock-collapse[aria-expanded="false"] { transform: rotate(180deg); }

.dock-body { flex: 1; overflow: auto; padding: 15px 16px 20px; }
.dock-panel { display: none; animation: rise-fade .22s ease; }
.dock-panel.active { display: block; }

@keyframes rise-fade {
    from { opacity: 0; transform: translateY(6px); }
}

/* ==========================================================================
   PANEL — kini hanya dipakai sidebar Data Masukan
   --------------------------------------------------------------------------
   Sebelumnya juga dasar bagi empat panel yang melayang bebas di atas peta
   (dapat digeser, diubah ukuran, saling menumpuk). Digantikan oleh dok tab
   tetap di kanan (lihat bagian DOK) — kelas ini disederhanakan sesuai
   perannya sekarang: satu kolom tetap, tak lagi perlu digeser atau
   diubah ukuran.
   ========================================================================== */
.panel {
    background: var(--panel-latar);
    border: 1px solid var(--garis);
    border-radius: var(--lengkung);
    box-shadow: var(--bayang-2);
    display: flex; flex-direction: column;
    overflow: hidden;
}
.panel.collapsed .panel-body { display: none; }
.panel[hidden] { display: none !important; }

.panel-head {
    display: flex; align-items: center; gap: 9px;
    padding: 11px 12px 11px 15px;
    border-bottom: 1px solid var(--garis);
    background: linear-gradient(var(--putih), var(--permukaan-2));
    flex: none;
}
.panel-title {
    font-size: 12.5px; font-weight: 800; letter-spacing: .05em;
    text-transform: uppercase; color: var(--biru-tua); flex: 1;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.panel-btn {
    border: 0; background: transparent; cursor: pointer;
    width: 26px; height: 26px; border-radius: 6px;
    display: grid; place-items: center;
    color: var(--teks-samar); font-size: 15px; line-height: 1;
    transition: background .14s, color .14s;
}
.panel-btn:hover { background: var(--biru-pucat); color: var(--biru); }
/* overflow-x:hidden (bukan "auto" polos) — gelembung .info-tip-bubble
   (position:absolute, lihat definisinya di bawah) tetap ikut dihitung
   dalam scrollWidth wadah ini walau visibility:hidden ketika tak
   dihover, karena visibility (beda dari display:none) tak mengeluarkan
   elemen dari perhitungan tata letak/overflow. Tanpa baris ini gelembung
   yang menjorok ke kanan dekat tepi sidebar memicu bilah gulir mendatar
   yang sebenarnya tak perlu — isinya memang tak pernah lebih lebar dari
   panel, cuma gelembung yang sedang tak tampak itu yang menjorok. */
.panel-body { padding: 14px 15px 16px; overflow-y: auto; overflow-x: hidden; }

/* ==========================================================================
   UNSUR ISI PANEL
   ========================================================================== */
.section + .section { margin-top: 18px; padding-top: 16px; border-top: 1px solid var(--garis); }
/* Baris tombol Mulai Pengolahan/Hentikan dulu menempel rapat langsung di
   bawah bagian Masking Wilayah (unggah shapefile) tanpa jarak sama sekali
   — garis pemisah + jarak yang sama seperti antar .section membuatnya
   terasa sebagai aksi TERPISAH, bukan sambungan form di atasnya. */
.section + .btn-row { margin-top: 18px; padding-top: 16px; border-top: 1px solid var(--garis); }
.section-title {
    font-size: 11px; font-weight: 800; letter-spacing: .09em;
    text-transform: uppercase; color: var(--teks-samar); margin-bottom: 10px;
}

/* min-width:0 pada KEDUA anak — baku flexbox membiarkan butir tidak
   menyusut di bawah lebar isinya sendiri ("min-width:auto" bawaan), jadi
   angka/label panjang (mis. volume beberapa juta m³, nama berkas) dulu
   mendorong .row lebih lebar dari dok/sidebar-nya dan memaksa gulir
   mendatar — persis keluhannya. overflow-wrap:anywhere jadi jaring
   pengaman kedua untuk teks yang sama sekali tak punya spasi untuk
   dipenggal (angka beruntun, nama berkas panjang). */
.row { display: flex; justify-content: space-between; gap: 10px; padding: 5px 0; font-size: 13.5px; }
.row .label { color: var(--teks-lembut); min-width: 0; overflow-wrap: anywhere; }
.row .value {
    font-weight: 700; text-align: right; font-variant-numeric: tabular-nums;
    min-width: 0; overflow-wrap: anywhere;
}

/* Angka kunci — satu per panel, seperti pada lembar peta */
.headline {
    background: var(--biru-pucat); border: 1px solid var(--biru-pucat-tepi);
    border-radius: var(--lengkung-s); padding: 13px 15px; margin: 12px 0 4px;
    min-width: 0;
}
.headline .caption { font-size: 11px; font-weight: 700; letter-spacing: .07em;
    text-transform: uppercase; color: var(--biru); margin-bottom: 4px; }
.headline .val {
    font-size: 26px; font-weight: 800; color: var(--biru-tua);
    line-height: 1.1; font-variant-numeric: tabular-nums; overflow-wrap: anywhere;
}
.headline .unit-sm { font-size: 13px; font-weight: 600; color: var(--teks-lembut); }

/* Kendali */
label.field { display: block; margin-bottom: 13px; }
/* inline-flex, BUKAN flex — flex biasa (kotak blok) melebar mengisi
   SELURUH lebar induknya secara baku, sehingga area target hover tooltip
   (lihat blok .info-tip di bawah) ikut selebar itu juga: satu baris penuh
   selebar kolom teks di bawahnya, bukan cuma sepanjang tulisan labelnya
   sendiri. inline-flex menyusut mengikuti isi, persis lebar teks+ikon. */
label.field > .name {
    display: inline-flex; align-items: center; gap: 6px;
    font-size: 12.5px; font-weight: 700; color: var(--teks); margin-bottom: 5px;
}
label.field .unit { font-weight: 600; color: var(--teks-samar); font-size: 11.5px; }
label.field .hint { font-size: 11.5px; color: var(--teks-lembut); line-height: 1.45; margin-top: 4px; }
/* .hint:empty (baku, lihat definisi umum ".hint" di bawah) sudah menutupi
   status pemindaian versi FTP yang kosong sampai tombol "Pindai" ditekan
   — tak perlu diulang di sini lagi. */

/* Tombol keterangan bulat "i" — pengganti paragraf .hint yang dulu SELALU
   tampil di bawah tiap kolom pengaturan, membuat modal penuh teks kecil
   abu-abu. Keterangannya baru muncul saat ikon ini dihover/disentuh/
   difokus (:focus-within lewat keyboard, :hover lewat mouse) — tampilan
   kolomnya sendiri jadi jauh lebih lapang selama tak sedang dibutuhkan. */
.info-tip {
    position: relative; display: inline-flex; flex: none;
    border: 0; background: none; padding: 0; margin: 0; cursor: help;
}
.info-tip-icon {
    width: 15px; height: 15px; border-radius: 50%;
    background: var(--biru-pucat); border: 1px solid var(--biru-pucat-tepi);
    color: var(--biru); font-size: 10px; font-weight: 800; font-style: italic;
    font-family: Georgia, 'Times New Roman', serif;
    display: grid; place-items: center; line-height: 1;
    transition: background .14s, color .14s;
}
/* Target hover DIPERLUAS ke seluruh baris nama (label.field > .name) —
   ikon "i" 15px sendirian terlalu kecil untuk dituju sengaja tanpa
   meleset. .info-tip:hover dipertahankan juga (bukan diganti) untuk
   kolom ya/tidak, yang ikonnya berdiri sendiri di luar .name karena
   label switch-nya sendiri sudah jadi target klik sakelarnya. */
.info-tip:hover .info-tip-icon,
.info-tip:focus-visible .info-tip-icon,
label.field > .name:hover .info-tip-icon {
    background: var(--biru); border-color: var(--biru); color: #fff;
}
/* Dijangkarkan ke KIRI ikon (bukan ditengahkan lewat translateX(-50%))
   supaya gelembungnya SELALU meluas ke kanan secara terprediksi — versi
   ditengahkan sebelumnya terpotong tepi kiri modal tepat pada kolom
   pertama grid dua-kolom, karena ikonnya sendiri sudah dekat tepi kiri
   modal dan separuh gelembung yang harusnya menjorok ke kiri tak lagi
   ada tempat. Sedikit koreksi ke kiri (-6px) sekadar merapikan sejajar
   dengan teks label, bukan lagi demi menengahkan. */
.info-tip-bubble {
    position: absolute; left: -6px; top: calc(100% + 8px);
    transform: translateY(-4px);
    width: max-content; max-width: 240px;
    /* di sidebar (lihat override #panel-data di bawah), lebar 240px ini
       dipersempit — sidebar jauh lebih sempit dari modal pengaturan,
       gelembung selebar itu menjorok keluar tepi kanan panel. */
    background: var(--biru-tua); color: #fff;
    padding: 8px 10px; border-radius: 7px;
    font-size: 11.5px; font-weight: 400; line-height: 1.5; text-align: left;
    box-shadow: var(--bayang-2);
    opacity: 0; visibility: hidden; pointer-events: none; z-index: 30;
    transition: opacity .14s ease, transform .14s ease, visibility .14s;
}
.info-tip-bubble::before {
    content: ''; position: absolute; left: 10px; bottom: 100%;
    border: 5px solid transparent; border-bottom-color: var(--biru-tua);
}
/* Sidebar (366px, jauh lebih sempit dari modal pengaturan) — 240px penuh
   menjorok keluar tepi kanan panel begitu ikonnya tak lagi persis di tepi
   kiri (mis. tombol info yang menyatu di baris "Batas wilayah" atau judul
   bagian yang sudah berjarak dari tepi). 190px teruji pas untuk lebar
   panel ini di kedalaman penjorokan mana pun yang ada saat ini. */
#panel-data .info-tip-bubble { max-width: 190px; }
.info-tip:hover .info-tip-bubble,
.info-tip:focus-visible .info-tip-bubble,
label.field > .name:hover .info-tip-bubble {
    opacity: 1; visibility: visible; transform: translateY(0);
}
/* ...TAPI ditutup paksa begitu kontrolnya SENDIRI (kolom teks/angka,
   dropdown, atau baris dropdown+tombol Pindai pada versi FTP) yang
   dihover — gelembung keterangan dulu sering menutupi persis kolom yang
   justru sedang ingin diisi/dibaca pengguna begitu kursor turun ke
   sana. cursor:help pada .name sekadar penanda visual bahwa baris itu
   bisa dihover untuk keterangan. */
label.field > .name { cursor: help; }
label.field:has(> input:hover, > select:hover, > textarea:hover, > .field-with-btn:hover) .info-tip-bubble {
    opacity: 0 !important; visibility: hidden !important;
}

/* Kolom + satu tombol aksi kecil berdampingan — dipakai pemilih versi FTP
   (kolom, lalu tombol "Pindai" pas di sebelahnya). */
.field-with-btn { display: flex; gap: 6px; }
.field-with-btn select { flex: 1; min-width: 0; }
.field-with-btn .btn.tiny { flex: none; }

/* Baku ".hint" polos (di luar label.field) — TIDAK ADA sebelumnya, cuma
   varian tercakup (label.field .hint, .box-popup .hint, dst.). ".hint"
   sendiri adalah <span>, elemen INLINE, jadi tanpa display:block di sini
   tekscatatan langsung menempel rapat ke elemen sebelumnya tanpa jarak
   sama sekali — persis yang membuat tab Lapisan terasa padat/berantakan. */
.hint {
    display: block; margin-top: 8px;
    font-size: 11.5px; color: var(--teks-lembut); line-height: 1.5;
}
.hint:first-child { margin-top: 0; }
/* #period-hint dkk. kosong selagi belum ada status untuk dilaporkan (mis.
   "Tetapkan rentang tanggal sendiri" belum dinyalakan) — tanpa ini,
   span kosong tetap menyumbang margin-top begitu saja, celah janggal
   sebelum ada apa pun yang ditampilkan di sana. */
.hint:empty { display: none; margin-top: 0; }

input[type=text], input[type=password], input[type=number], input[type=date], select, textarea {
    width: 100%; padding: 8px 11px; font: inherit; font-size: 13.5px;
    border: 1px solid var(--garis); border-radius: var(--lengkung-s);
    background: var(--putih); color: var(--teks);
    transition: border-color .14s, box-shadow .14s;
}
input:focus, select:focus, textarea:focus {
    outline: 0; border-color: var(--biru-terang);
    box-shadow: 0 0 0 3px rgba(43,127,212,.14);
}
input.changed, select.changed { border-color: var(--jingga); background: var(--jingga-latar); }

.switch { display: flex; align-items: center; gap: 9px; cursor: pointer; }
.switch input { display: none; }
.switch .track {
    width: 36px; height: 20px; border-radius: 999px; background: var(--switch-latar);
    position: relative; transition: background .16s; flex: none;
}
.switch .track::after {
    content: ''; position: absolute; top: 2px; left: 2px;
    width: 16px; height: 16px; border-radius: 50%; background: #fff;
    box-shadow: 0 1px 3px rgba(0,0,0,.22); transition: transform .16s;
}
.switch input:checked + .track { background: var(--biru-terang); }
.switch input:checked + .track::after { transform: translateX(16px); }

button.btn {
    padding: 9px 17px; border-radius: var(--lengkung-s); border: 1px solid transparent;
    font: inherit; font-size: 13.5px; font-weight: 700; cursor: pointer;
    transition: background .14s, border-color .14s, color .14s;
}
button.btn.primary { background: var(--biru); color: #fff; }
button.btn.primary:hover { background: var(--biru-tua); }
button.btn.secondary { background: var(--putih); border-color: var(--garis); color: var(--teks-lembut); }
button.btn.secondary:hover { border-color: var(--biru-terang); color: var(--biru); }
/* Dipakai tombol "Hapus" pada modal konfirmasi custom (lihat modal.js
   confirmDialog()) — pengganti window.confirm() bawaan peramban. */
button.btn.danger { background: var(--merah-latar); border-color: var(--merah-tepi); color: var(--merah-teks); }
button.btn.danger:hover { background: var(--merah-latar-hover); border-color: var(--merah); }
button.btn:disabled { opacity: .5; cursor: not-allowed; }
.btn-row { display: flex; gap: 9px; flex-wrap: wrap; }
/* Butir berbagi lebar rata — dulu tombol primer selebar tulisannya saja
   dan sekunder terjepit kecil di sampingnya, terasa tak seimbang. Berlaku
   di seluruh .btn-row (bukan cuma Mulai Pengolahan/Hentikan) supaya
   konsisten di mana pun pola ini dipakai. min-width:0 karena butir flex
   juga tak menyusut di bawah lebar tulisannya sendiri secara baku — tanpa
   itu tombol dengan label panjang bisa mendorong barisnya melebar. */
.btn-row > .btn { flex: 1; min-width: 0; }

/* Sidebar kelompok pengaturan — lihat blok .modal-settings/.settings-*
   di bawah untuk tata letak dua kolom (sidebar + isi) modal pengaturan. */
.settings-tab {
    display: flex; align-items: center; gap: 10px;
    width: 100%; border: 1px solid transparent; background: transparent; cursor: pointer;
    padding: 9px 12px; border-radius: var(--lengkung-s); font: inherit;
    font-size: 12.5px; font-weight: 600; color: var(--teks-lembut);
    text-align: left; transition: background .12s, color .12s;
}
.settings-tab .ic { flex: none; color: var(--teks-samar); transition: color .12s; }
.settings-tab:hover { background: var(--putih); color: var(--teks); }
.settings-tab.active {
    background: var(--biru); border-color: var(--biru); color: #fff;
    box-shadow: var(--bayang-1);
}
.settings-tab.active .ic { color: #fff; }

/* ==========================================================================
   KEMAJUAN
   ========================================================================== */
.stage { display: flex; align-items: center; gap: 10px; padding: 7px 0; font-size: 13px; }
.stage .dot { width: 9px; height: 9px; border-radius: 50%; background: var(--garis); flex: none; }
.stage.running  .dot { background: var(--biru-terang); animation: pulse 1.1s infinite; }
.stage.done   .dot { background: var(--hijau-jam); }
.stage.skipped  .dot { background: #b9cbdc; }
.stage.failed     .dot { background: var(--merah); }
.stage.cancelled  .dot { background: var(--teks-samar); }
.stage .name { flex: 1; color: var(--teks-lembut); white-space: nowrap;
    overflow: hidden; text-overflow: ellipsis; }
.stage.running .name, .stage.done .name { color: var(--teks); font-weight: 600; }
.stage .ticks { font-size: 11.5px; color: var(--teks-samar); font-variant-numeric: tabular-nums; }

.progress-bar { height: 6px; border-radius: 999px; background: var(--garis); overflow: hidden; margin: 4px 0 12px; }
.progress-bar > i { display: block; height: 100%; border-radius: 999px;
    background: linear-gradient(90deg, var(--biru-terang), var(--biru));
    transition: width .3s ease; }

.log {
    font-family: 'JetBrains Mono', ui-monospace, monospace; font-size: 11.5px;
    background: #0f1c29; color: #b9d4ec; border-radius: var(--lengkung-s);
    padding: 11px 13px; max-height: 190px; overflow: auto; line-height: 1.65;
}
.log .error { color: #ff9b9b; }
.log .ok  { color: #8fe3b4; }
.log .ts { color: #5d7a94; }

/* ==========================================================================
   LAPISAN PETA
   ========================================================================== */
.layer-list { display: flex; flex-direction: column; gap: 3px; }
.layer {
    display: flex; align-items: center; gap: 10px; padding: 7px 9px;
    border-radius: var(--lengkung-s); cursor: pointer; font-size: 13.5px;
    transition: background .12s;
}
.layer:hover { background: var(--biru-pucat); }
.layer .swatch { width: 13px; height: 13px; border-radius: 3px; flex: none; }
.layer .name { flex: 1; }
.layer .count { font-size: 11.5px; color: var(--teks-samar); font-variant-numeric: tabular-nums; }

.colorbar .gradient { height: 11px; border-radius: 3px; margin-bottom: 5px; }
/* 13 label batas kelas (bukan ~6 seperti skema lama) — huruf diperkecil
   dan spasi antar-angka dirapatkan supaya tetap muat berdampingan di
   dok selebar ~350px tanpa saling tumpang tindih. */
.colorbar .ticks {
    display: flex; justify-content: space-between;
    font-size: 9px; color: var(--teks-lembut); font-variant-numeric: tabular-nums;
    letter-spacing: -.02em;
}

/* Penanda titik semai pada peta */
.seed-point {
    width: 9px; height: 9px; border-radius: 50%;
    background: var(--merah); border: 1.6px solid #fff;
    box-shadow: 0 1px 3px rgba(0,0,0,.3);
}

/* ==========================================================================
   PEMBERITAHUAN
   ========================================================================== */
.toast-area {
    position: fixed; right: 20px; bottom: 20px; z-index: 900;
    display: flex; flex-direction: column-reverse; gap: 9px; max-width: 380px;
}
.toast {
    background: var(--putih); border: 1px solid var(--garis);
    border-left: 3px solid var(--biru-terang);
    border-radius: var(--lengkung-s); box-shadow: var(--bayang-2);
    padding: 12px 15px; font-size: 13.5px; line-height: 1.5;
    animation: slide-in .22s ease;
}
.toast.ok  { border-left-color: var(--hijau-jam); }
.toast.error { border-left-color: var(--merah); }
.toast.warn { border-left-color: var(--kuning); }
.toast .title { font-weight: 700; margin-bottom: 2px; }
.toast .body { color: var(--teks-lembut); }
@keyframes slide-in { from { opacity: 0; transform: translateY(10px) } }

/* ==========================================================================
   AREA UNGGAH
   ========================================================================== */
.dropzone {
    border: 2px dashed var(--permukaan-2-tepi); border-radius: var(--lengkung);
    padding: 26px 18px; text-align: center; cursor: pointer;
    background: var(--permukaan-2); transition: border-color .14s, background .14s;
}
.dropzone:hover, .dropzone.over { border-color: var(--biru-terang); background: var(--biru-pucat); }
.dropzone .icon { font-size: 26px; margin-bottom: 7px; opacity: .55; }
.dropzone .primary { font-weight: 700; font-size: 13.5px; margin-bottom: 3px; }
.dropzone .sub { font-size: 12px; color: var(--teks-lembut); line-height: 1.5; }

.file-row {
    display: flex; align-items: center; gap: 10px; padding: 8px 10px;
    border: 1px solid var(--garis); border-radius: var(--lengkung-s);
    font-size: 12.5px; margin-top: 7px; background: var(--putih);
}
.file-row .name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.file-row .size { color: var(--teks-samar); font-variant-numeric: tabular-nums; }

/* Tanda peringatan hasil pengenalan */
.warning {
    background: var(--peringatan-latar); border: 1px solid var(--peringatan-tepi);
    border-radius: var(--lengkung-s);
    padding: 10px 12px; font-size: 12.5px; color: var(--peringatan-teks); line-height: 1.55;
    margin-top: 9px;
}

::-webkit-scrollbar { width: 9px; height: 9px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--gulir); border-radius: 5px; }
::-webkit-scrollbar-thumb:hover { background: var(--gulir-hover); }

.leaflet-container { font-family: inherit; }
.empty { text-align: center; padding: 22px 12px; color: var(--teks-samar); font-size: 13px; line-height: 1.6; }

/* Leaflet dimuat dari CDN dengan warnanya SENDIRI, tetap dan tidak
   mengikuti peubah tema kita — kotak info kotak semai jadi berupa tambalan
   putih terang di atas peta gelap kecuali ditimpa di sini. */
:root[data-theme="dark"] .leaflet-popup-content-wrapper,
:root[data-theme="dark"] .leaflet-popup-tip {
    background: var(--putih);
    color: var(--teks);
    box-shadow: var(--bayang-2);
}
:root[data-theme="dark"] .leaflet-popup-close-button {
    color: var(--teks-samar) !important;
}
:root[data-theme="dark"] .leaflet-popup-close-button:hover {
    color: var(--teks) !important;
}
:root[data-theme="dark"] .leaflet-control-attribution {
    background: rgba(20, 30, 42, .8) !important;
    color: var(--teks-samar) !important;
}
:root[data-theme="dark"] .leaflet-control-attribution a { color: var(--biru) !important; }

/* ==========================================================================
   MODAL
   --------------------------------------------------------------------------
   Dipakai untuk Pengaturan Perhitungan. Daftar parameternya panjang dan
   bertab; sebagai panel melayang selebar 360 px isinya terpotong dan harus
   digulir terus-menerus. Sebagai modal di tengah, seluruh satu kelompok
   muat sekaligus.
   ========================================================================== */
.modal-backdrop {
    position: fixed; inset: 0; z-index: 1000;
    display: grid; place-items: center;
    padding: 24px;
    background: var(--modal-latar);
    backdrop-filter: blur(2px);
    animation: fade-in .16s ease;
}
.modal-backdrop[hidden] { display: none !important; }
@keyframes fade-in { from { opacity: 0 } }

.modal {
    width: min(760px, 100%);
    max-height: min(78vh, 720px);
    display: flex; flex-direction: column;
    background: var(--putih);
    border-radius: var(--lengkung);
    box-shadow: var(--bayang-3);
    overflow: hidden;
    animation: modal-rise .18s cubic-bezier(.2, .8, .3, 1);
}
@keyframes modal-rise { from { opacity: 0; transform: translateY(12px) scale(.98) } }

/* Variasi kecil — dipakai pop-up "Pengolahan Selesai", yang cuma memuat
   satu angka utama dan ajakan membuka tab Hasil, bukan rincian lengkap. */
.modal.modal-sm { width: min(420px, 100%); max-height: none; }
/* ".modal-body.modal-body-center", bukan ".modal-body-center" saja — dua
   kelas menaikkan spesifisitasnya di atas ".modal-body" (grid) yang
   dideklarasikan BELAKANGAN di berkas ini. Dengan spesifisitas yang SAMA,
   urutan deklarasi menang, dan "display: grid" dari ".modal-body" diam-diam
   mengalahkan "display: block" di sini — memaksa isi (termasuk gambar peta
   di #plot-viewer-body) ke dalam SATU SEL grid selebar minmax(300px, 1fr)
   alih-alih blok biasa, itulah sebabnya gambarnya tampak tidak proporsional. */
.modal-body.modal-body-center { display: block; text-align: center; padding: 28px 20px; }
.modal-body-center .headline { text-align: left; }

/* Variasi besar — lembar peta spasial butuh ruang untuk resolusi tinggi. */
.modal.modal-lg { width: min(1100px, 96vw); max-height: min(92vh, 940px); }
#plot-viewer-body { padding: 12px; background: var(--permukaan-2); }
#plot-viewer-img {
    display: block; margin: 0 auto;
    max-width: 100%; max-height: min(82vh, 860px);
    width: auto; height: auto;
    border-radius: 8px; box-shadow: var(--bayang-2);
}

.modal-head {
    display: flex; align-items: center; gap: 10px;
    padding: 14px 16px;
    border-bottom: 1px solid var(--garis);
    background: linear-gradient(var(--putih), var(--permukaan-2));
    flex: none;
}
.modal-title {
    flex: 1; font-size: 13px; font-weight: 800;
    letter-spacing: .05em; text-transform: uppercase; color: var(--biru-tua);
}
.modal-btn {
    border: 0; background: transparent; cursor: pointer;
    width: 30px; height: 30px; border-radius: 7px;
    display: grid; place-items: center;
    color: var(--teks-samar); font-size: 19px; line-height: 1;
    transition: background .14s, color .14s;
}
.modal-btn:hover { background: var(--biru-pucat); color: var(--biru); }

.modal-body {
    padding: 16px;
    overflow: auto;
    flex: 1;
}
.modal-body > .empty { grid-column: 1 / -1; }

/* ── Modal pengaturan: sidebar + isi ─────────────────────────────────────
   Struktur: .modal-body.settings-shell (baris flex) berisi
   .settings-sidebar (nav vertikal kelompok) dan .settings-content (judul
   kelompok aktif + kolom pengaturannya, digulung sendiri). Dipisah dari
   .modal-body baku di atas supaya modal LAIN (plot, ringkasan) tidak ikut
   terpengaruh perubahan tata letak ini. */
/* height TETAP (bukan max-height) — dengan max-height, modal ikut
   menyusut mengikuti isi kelompok pengaturan yang aktif, jadi ukurannya
   berubah-ubah tiap pengguna pindah tab (kelompok dengan 2 kolom terasa
   jauh lebih pendek dari yang 7 kolom). height tetap memaksa satu ukuran
   yang sama selalu, terlepas dari berapa banyak kolom kelompok yang
   sedang tampil — .settings-fields di dalamnya yang menggulung sendiri
   kalau isinya lebih tinggi dari itu. */
.modal.modal-settings { width: min(900px, 96vw); height: min(88vh, 760px); }

.settings-shell {
    display: flex;
    padding: 0;
    overflow: hidden;
}

.settings-sidebar {
    flex: none; width: 232px;
    display: flex; flex-direction: column; gap: 3px;
    padding: 14px 10px;
    background: var(--permukaan-2);
    border-right: 1px solid var(--garis);
    overflow-y: auto;
}

.settings-content {
    flex: 1; min-width: 0;
    display: flex; flex-direction: column;
}

.settings-toolbar {
    display: flex; align-items: center; justify-content: flex-end;
    padding: 12px 20px;
    border-bottom: 1px solid var(--garis);
    flex: none;
}

.settings-fields {
    padding: 18px 20px;
    overflow: auto;
    flex: 1;
    /* Dua kolom pada layar lebar: sebagian besar kelompok memuat 5–7
       parameter, dan satu kolom membuat modal jauh lebih tinggi daripada
       perlunya. */
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
    gap: 0 22px;
    align-content: start;
}
.settings-fields > .empty { grid-column: 1 / -1; }

.modal-foot {
    display: flex; align-items: center; justify-content: space-between;
    gap: 16px; flex-wrap: wrap;
    padding: 13px 16px;
    border-top: 1px solid var(--garis);
    background: var(--permukaan-2);
    flex: none;
}
.modal-foot .hint { margin: 0; flex: 1; min-width: 180px; }

/* ==========================================================================
   BARIS UNGGAHAN PER JENIS
   --------------------------------------------------------------------------
   Menggantikan satu kotak jatuh besar untuk semua jenis berkas. Tiap baris
   menerima jatuhan sendiri, sehingga jenis berkasnya sudah diketahui sejak
   sebelum dikirim.
   ========================================================================== */
.drop-row {
    display: flex; align-items: center; gap: 10px;
    padding: 9px 10px 9px 12px;
    border: 1px dashed var(--permukaan-2-tepi); border-radius: var(--lengkung-s);
    background: var(--permukaan-2); margin-top: 7px;
    transition: border-color .14s, background .14s;
}
.drop-row.over { border-color: var(--biru-terang); background: var(--biru-pucat); }
.drop-row.filled { border-style: solid; border-color: var(--permukaan-2-terisi); background: var(--putih); }

.drop-info { flex: 1; min-width: 0; }
.drop-name { display: block; font-size: 12.5px; font-weight: 700; color: var(--teks); }
.drop-ext  { display: block; font-size: 11px; color: var(--teks-samar); margin-top: 1px; }

.btn.tiny { padding: 5px 12px; font-size: 12px; border-radius: 7px; }

.drop-files:not(:empty) { margin-top: 4px; }
.drop-files .file-row { margin-top: 4px; padding: 5px 9px; font-size: 11.5px; }
.drop-files .file-row .drop-x {
    border: 0; background: transparent; cursor: pointer;
    color: var(--teks-samar); font-size: 14px; line-height: 1;
    padding: 0 2px; border-radius: 4px;
}
.drop-files .file-row .drop-x:hover { color: var(--merah); background: var(--merah-latar); }

/* Sepasang kolom berdampingan — dipakai tanggal mulai/akhir.
   minmax(0, 1fr), bukan "1fr" polos — lihat catatan panjang di .stat-grid. */
.field-pair { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 10px; }
.field-pair .field { margin-bottom: 0; }

/* ==========================================================================
   EDITOR KOTAK SEMAI
   ========================================================================== */
/* Penanda sudut yang dapat digeser untuk mengubah ukuran kotak.
   box-sizing: border-box membuat lebar/tinggi TERMASUK bingkainya, sehingga
   ukurannya sama persis dengan iconSize divIcon di seeding.js — divIcon itu
   sendiri sudah dijangkarkan Leaflet tepat di tengah, jadi tidak perlu lagi
   margin negatif untuk memusatkannya pada titik sudut kotak. */
.box-handle {
    box-sizing: border-box;
    width: 12px; height: 12px;
    background: #fff;
    border: 2px solid var(--merah, #d94141);
    border-radius: 3px;
    box-shadow: 0 1px 3px rgba(0, 0, 0, .35);
    cursor: grab;
}
.box-handle:active { cursor: grabbing; }

/* Kotak yang sedang dipilih (penanda sudutnya tampil) — kursor "move" pada
   badannya menandai bisa digeser, bukan hanya sudutnya. */
.box-selected { cursor: move !important; }

.box-popup { font-size: 12.5px; line-height: 1.5; }
.box-popup b { color: var(--biru-tua, #14395e); }
.box-popup .hint { display: block; margin-top: 4px; font-size: 11px; }
.box-popup .box-del {
    margin-top: 8px; width: 100%;
    border: 1px solid var(--merah-tepi); background: var(--merah-latar);
    color: var(--merah-teks); border-radius: 6px;
    padding: 5px 8px; font: inherit; font-size: 12px; cursor: pointer;
}
.box-popup .box-del:hover { background: var(--merah-latar-hover); }

/* Tombol "Tambah Kotak Baru" — kondisi aktif saat mode gambar sedang
   menyala, supaya pengguna tahu klik peta berikutnya menggambar kotak. */
#btn-draw-box.active {
    background: var(--biru); border-color: var(--biru); color: #fff;
}

#box-totals:not(:empty) { margin-top: 10px; }

/* ==========================================================================
   WADAH BAWAH PETA — legenda + linimasa
   --------------------------------------------------------------------------
   Satu wadah mengambang di bawah peta menaungi KEDUANYA. column-reverse
   dipakai supaya legenda (anak KEDUA dalam DOM) tampil DI ATAS linimasa
   (anak PERTAMA) secara visual, sementara urutan DOM-nya sendiri tetap
   linimasa dulu — itu yang membuat selektor ":not([hidden]) ~" di bawah
   bisa menyorot legenda mengikuti linimasa tanpa javascript terpisah.
   ========================================================================== */
.map-bottom-overlay {
    position: absolute; left: 12px; right: 12px; bottom: 12px;
    z-index: 455;
    display: flex; flex-direction: column-reverse; gap: 8px;
    pointer-events: none;   /* celah di antara keduanya tak menghalangi peta */
}
.map-bottom-overlay > * { pointer-events: auto; }

/* ==========================================================================
   LINIMASA TANGGAL
   --------------------------------------------------------------------------
   Muncul begitu tanggal kegiatan dikenali, jauh sebelum perhitungan
   selesai — tiap tanggal berupa tab yang dapat diklik, dengan penanda
   keadaan: menunggu, sedang dihitung, atau selesai.
   ========================================================================== */
.timeline {
    background: var(--putih);
    border: 1px solid var(--garis);
    border-radius: var(--lengkung-s);
    box-shadow: var(--bayang-1);
    padding: 8px 10px;
    display: flex; align-items: center; gap: 10px;
}

/* Legenda warna hujan mengambang — tampil HANYA selagi linimasa juga
   tampil (dua-duanya berarti "ada hasil untuk ditafsirkan"), lewat CSS
   semata, bukan javascript tambahan yang harus mengingat menyalakan/
   mematikannya di tiap tempat linimasa itu sendiri disembunyikan/
   ditampilkan. */
.map-legend { display: none; }
#timeline:not([hidden]) ~ .map-legend {
    display: block;
    background: var(--putih);
    border: 1px solid var(--garis);
    border-radius: var(--lengkung-s);
    box-shadow: var(--bayang-1);
    padding: 9px 12px;
    max-width: 320px;
}
.map-legend-title {
    font-size: 10.5px; font-weight: 800; letter-spacing: .06em;
    text-transform: uppercase; color: var(--teks-samar); margin-bottom: 6px;
}
.timeline-label {
    font-size: 11px; font-weight: 700; text-transform: uppercase;
    letter-spacing: .04em; color: var(--teks-samar);
    white-space: nowrap; flex: none;
}
.timeline-tabs {
    display: flex; gap: 6px; overflow-x: auto; flex: 1;
    padding-bottom: 2px;
}
.tl-tab {
    flex: none; cursor: pointer;
    border: 1px solid var(--garis); background: var(--putih);
    border-radius: 7px; padding: 5px 11px 5px 9px;
    font: inherit; font-size: 12px; font-weight: 600; color: var(--teks);
    display: flex; align-items: center; gap: 6px;
    transition: background .12s, border-color .12s, transform .12s;
    white-space: nowrap;
    animation: rise-fade .26s ease backwards;
    animation-delay: calc(var(--i, 0) * 30ms);
}
.tl-tab:hover:not(:disabled) { background: var(--biru-pucat); transform: translateY(-1px); }
.tl-tab.active { background: var(--biru-pucat); border-color: var(--biru); color: var(--biru); }
.tl-tab:disabled { cursor: default; opacity: .85; }
.tl-lbl { line-height: 1; }

/* Penanda keadaan tiap tanggal. */
.tl-dot {
    width: 9px; height: 9px; border-radius: 50%;
    flex: none; background: var(--garis);
}
.tl-tab[data-state="waiting"]  .tl-dot { background: #c4ccd4; }
.tl-tab[data-state="running"]  .tl-dot { background: #f0a03c;
    animation: tl-pulse 1s ease-in-out infinite; }
.tl-tab[data-state="done"]     .tl-dot { background: #3fae6a; }
.tl-tab[data-state="failed"]   .tl-dot { background: var(--merah); }

@keyframes tl-pulse { 0%,100% { opacity: 1; } 50% { opacity: .35; } }

/* Keterangan kecil saat perhitungan tanggal masih menunggu unduhan. */
.tl-note {
    font-size: 11px; color: var(--teks-samar); white-space: nowrap;
    flex: none; padding-left: 4px;
}

/* ==========================================================================
   PEMILIH SUMBER HUJAN
   ========================================================================== */
.rain-source {
    display: flex; gap: 6px; margin-top: 6px;
}
.rain-source button {
    flex: 1; cursor: pointer;
    border: 1px solid var(--garis); background: var(--putih);
    border-radius: 7px; padding: 7px 8px;
    font: inherit; font-size: 12.5px; font-weight: 700; color: var(--teks);
    transition: background .12s, border-color .12s, color .12s;
}
.rain-source button:hover:not(:disabled) { background: var(--biru-pucat); }
.rain-source button.active {
    background: var(--biru-pucat); border-color: var(--biru); color: var(--biru);
}
.rain-source button:disabled {
    opacity: .4; cursor: default;
}

/* Kanvas hujan berada di lapisan overlay Leaflet; tidak menangkap klik. */
/* image-rendering: pixelated — SEBALIKNYA dari sebelumnya (auto), yang
   sengaja membuat peramban menyekalakan bitmap kecil ini dengan
   interpolasi mulus (bilinear/bikubik) saat direntangkan menutupi area
   peta. Hasilnya justru dikeluhkan tampak "blur transparan" — sel-sel
   hujan tidak tegas batasnya, warnanya memudar di tepi. pixelated
   mempertahankan tepi sel yang tajam persis mengikuti resolusi asli
   GSMaP/model, bukan digambar ulang lebih tinggi — datanya sendiri
   TIDAK berubah, cuma cara peramban menyekalakannya saat diperbesar.
   crisp-edges sebagai jatuhan Firefox lama yang belum kenal "pixelated". */
.rain-overlay-img {
    image-rendering: pixelated;
    image-rendering: -moz-crisp-edges;
    image-rendering: crisp-edges;
}

/* ==========================================================================
   GRAFIK & INFORMASI HASIL
   ========================================================================== */
.chart-block { margin-top: 14px; }
.chart-block svg { margin-top: 4px; }

/* Wadah grafik — relative supaya tooltip mengambang (absolute) dan tombol
   unduh di pojoknya diposisikan relatif terhadap grafik ini, bukan seluruh
   halaman. */
.chart-wrap { position: relative; }

/* Selalu tampak (bukan cuma saat hover) — grafik ini juga dibuka di layar
   sentuh yang tak punya keadaan hover sama sekali, dan tombol unduh salah
   satu fitur yang justru diminta terlihat, bukan disembunyikan. */
.chart-download {
    position: absolute; top: 2px; right: 2px; z-index: 2;
    width: 26px; height: 26px; display: grid; place-items: center;
    border: 1px solid var(--garis); background: var(--putih); border-radius: var(--lengkung-s);
    color: var(--teks-samar); cursor: pointer; transition: color .14s, border-color .14s, background .14s;
}
.chart-download .ic { width: 14px; height: 14px; }
.chart-download:hover { color: var(--biru); border-color: var(--biru-pucat-tepi); background: var(--biru-pucat); }

/* Tooltip hover — mengikuti titik/batang yang disorot lewat JS
   (charts.js:_tampilkanTooltip), disembunyikan lewat opacity (bukan
   display:none) supaya transisinya lembut, bukan berkedip muncul. */
.chart-tooltip {
    position: absolute; z-index: 3; pointer-events: none;
    transform: translate(-50%, calc(-100% - 10px));
    background: var(--biru-tua); color: #fff;
    padding: 6px 10px; border-radius: 7px; font-size: 11px; line-height: 1.6;
    white-space: nowrap; box-shadow: var(--bayang-2);
    opacity: 0; transition: opacity .12s ease;
}
.chart-tooltip.show { opacity: 1; }
.chart-tooltip::after {
    content: ''; position: absolute; left: 50%; top: 100%;
    transform: translateX(-50%); border: 5px solid transparent;
    border-top-color: var(--biru-tua);
}
.chart-tooltip-title { font-weight: 700; margin-bottom: 2px; opacity: .85; }
.chart-tooltip-dot {
    display: inline-block; width: 7px; height: 7px; border-radius: 50%;
    margin-right: 5px;
}

.chart-legend {
    display: flex; gap: 14px; margin-top: 6px; flex-wrap: wrap;
    font-size: 11px; color: var(--teks-samar);
}
.chart-legend span { display: inline-flex; align-items: center; gap: 5px; }
.chart-legend i {
    width: 11px; height: 11px; border-radius: 3px; display: inline-block;
}

/* Jarak antar WADAH tab Hasil (#hasil-stats, #hasil-tanggal, #hasil-charts,
   dst.) — dulu tak ada sama sekali, cuma .card+.card DI DALAM satu wadah
   yang punya margin-top; antar wadahnya sendiri menempel rapat. :empty
   disembunyikan supaya wadah yang belum terisi (mis. #hasil-export sebelum
   pekerjaannya selesai) tidak ikut menyumbang celah kosong. */
#hasil-stats, #hasil-tanggal, #hasil-charts,
#hasil-table, #hasil-ingest, #hasil-export {
    margin-top: 18px;
}
#hasil-stats:empty, #hasil-tanggal:empty, #hasil-charts:empty,
#hasil-table:empty, #hasil-ingest:empty, #hasil-export:empty {
    display: none;
}

/* ==========================================================================
   KARTU — unit dasar tab Hasil
   --------------------------------------------------------------------------
   Satu bahasa rupa dipakai berulang: kartu putih bersudut tumpul, judul
   kecil huruf besar dengan ikon, isi berupa baris label/nilai. Wadah
   #hasil-* di index.php masing-masing diisi nol atau lebih kartu begini
   oleh main.js — bukan satu blok HTML raksasa yang ditulis tangan.
   ========================================================================== */
.card {
    background: var(--putih); border: 1px solid var(--garis);
    border-radius: var(--lengkung); box-shadow: var(--bayang-1);
    padding: 15px 16px; margin-top: 14px;
    animation: rise-fade .28s ease;
}
.card:first-child { margin-top: 0; }
.card-title {
    display: flex; align-items: center; gap: 8px;
    font-size: 11.5px; font-weight: 800; letter-spacing: .06em;
    text-transform: uppercase; color: var(--biru-tua); margin-bottom: 10px;
}
.card-title .ic { color: var(--biru); }

/* Judul kartu + satu tombol aksi di kanannya (mis. "Tambah" pada kartu
   Kotak Area Semai) — .card-title sendiri dipertahankan tanpa
   margin-bottom di sini supaya sejajar tepat dengan tombolnya. */
.card-title-row {
    display: flex; align-items: center; justify-content: space-between;
    gap: 10px; margin-bottom: 10px;
}
.card-title-row .card-title { margin-bottom: 0; }
.btn-add-box {
    display: flex; align-items: center; gap: 5px; flex: none;
    border: 1px solid var(--biru-pucat-tepi); background: var(--biru-pucat);
    color: var(--biru); border-radius: 999px; cursor: pointer;
    padding: 5px 12px 5px 9px; font: inherit; font-size: 11.5px; font-weight: 700;
    transition: background .14s, border-color .14s, transform .12s;
}
.btn-add-box .ic { width: 13px; height: 13px; }
.btn-add-box:hover { background: var(--biru-terang); border-color: var(--biru-terang); color: #fff; }
.btn-add-box:active { transform: scale(.96); }
.btn-add-box.active {
    background: var(--biru); border-color: var(--biru); color: #fff;
}

.empty-inline {
    padding: 10px 0; font-size: 12px; color: var(--teks-samar);
    line-height: 1.5;
}

.card-subtitle {
    font-size: 11px; font-weight: 800; letter-spacing: .05em;
    text-transform: uppercase; color: var(--teks-samar);
    margin: 14px 0 6px; padding-top: 12px; border-top: 1px solid var(--garis);
}
/* Garis aksen biru di kiri — kartu "tanggal terpilih" perlu langsung
   terlihat berbeda dari kartu netral di sekelilingnya. */
.card-accent { border-left: 3px solid var(--biru-terang); }

.row-total { border-top: 1px dashed var(--garis); margin-top: 4px; padding-top: 8px; font-weight: 700; }
.hint-inline { font-size: 10.5px; color: var(--teks-samar); font-weight: 500; margin-left: 4px; }

/* Kelompok tombol untuk membuka lembar peta spasial (GSMaP/Model/
   perbandingan) dalam modal — lihat renderDateDetail() di main.js. Tiap
   kelompok punya DUA tombol yang SETARA bobot visualnya: "Lengkap" (judul +
   kartu keterangan + catatan kaki) dan "Polos" (peta & komponennya saja) —
   sengaja tidak dibuat satu utama + satu kecil, sebab keduanya produk yang
   sama pentingnya, cuma beda kelengkapan informasinya. */
.plot-group { margin-top: 12px; }
.plot-group:first-of-type { margin-top: 0; }
.plot-group-label {
    font-size: 11.5px; font-weight: 700; color: var(--teks-samar);
    margin-bottom: 6px;
}
.plot-variant-row { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 8px; }
.plot-variant-btn {
    display: flex; flex-direction: column; align-items: center; gap: 4px;
    padding: 12px 8px; border: 1px solid var(--garis); border-radius: 10px;
    background: var(--permukaan-2); cursor: pointer; text-align: center;
    font-size: 12px; font-weight: 700; color: var(--teks);
    transition: background .14s, border-color .14s, transform .14s;
}
.plot-variant-btn:hover { background: var(--biru-pucat); border-color: var(--biru-terang); transform: translateY(-1px); }
.plot-variant-icon { color: var(--biru); }
.plot-variant-btn .hint-inline {
    display: block; margin-left: 0; font-weight: 500; font-size: 10px;
    white-space: normal; line-height: 1.3;
}

.delta { font-weight: 800; }
.delta.up   { color: #3fae6a; }
.delta.down { color: var(--merah); }

/* ==========================================================================
   KARTU RINGKASAN (stat cards)
   ========================================================================== */
/* minmax(0, 1fr) — BUKAN "1fr" polos. Jalur grid "1fr" tanpa itu punya
   lebar minimum bawaan "auto" (mengikuti lebar isinya, bukan menyusut),
   jadi angka/label panjang tetap mendorong .stat-grid lebih lebar dari
   dok-nya walau .stat-value sendiri sudah diberi overflow-wrap — persis
   yang memaksa gulir mendatar pada tab Hasil. */
.stat-grid {
    display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px;
}
.stat-card {
    display: flex; align-items: center; gap: 11px;
    background: var(--putih); border: 1px solid var(--garis);
    border-radius: var(--lengkung-s); padding: 10px 12px;
    animation: rise-fade .3s ease backwards;
    animation-delay: calc(var(--i, 0) * 45ms);
    transition: transform .16s ease, box-shadow .16s ease, border-color .16s ease;
}
.stat-grid .stat-card:nth-child(1) { --i: 0; } .stat-grid .stat-card:nth-child(2) { --i: 1; }
.stat-grid .stat-card:nth-child(3) { --i: 2; } .stat-grid .stat-card:nth-child(4) { --i: 3; }
.stat-grid .stat-card:nth-child(5) { --i: 4; } .stat-grid .stat-card:nth-child(6) { --i: 5; }
.stat-card:hover {
    transform: translateY(-2px);
    box-shadow: var(--bayang-1); border-color: var(--biru-pucat-tepi);
}
.stat-card.hero {
    grid-column: 1 / -1;
    background: linear-gradient(135deg, var(--biru-pucat), var(--putih));
    border-color: var(--biru-pucat-tepi);
}
.stat-icon {
    display: grid; place-items: center; flex: none;
    width: 36px; height: 36px; border-radius: 10px;
    background: var(--biru-pucat); color: var(--biru);
}
.stat-card.hero .stat-icon { width: 42px; height: 42px; background: var(--putih); }
.stat-body { min-width: 0; }
.stat-label {
    font-size: 10.5px; font-weight: 700; letter-spacing: .04em;
    text-transform: uppercase; color: var(--teks-samar);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* overflow-wrap:anywhere — jaring pengaman kalau nilainya tetap tak muat
   (mis. volume beberapa juta m³), tapi pertahanan UTAMA sekarang ikon
   kartu kecil dihapus (lihat _statCard() di main.js) supaya nilainya
   sendiri kebagian hampir seluruh lebar kartu, bukan cuma separuhnya
   setelah dipotong ikon+celah — 13.5px dipilih supaya angka/satuan
   sepanjang "12.458.302 m³" tetap muat sebaris pada kartu dok selebar
   384px, bukan sekadar tak meluber lalu terpotong dua baris. */
.stat-value {
    font-size: 13.5px; font-weight: 800; color: var(--teks);
    font-variant-numeric: tabular-nums; line-height: 1.3;
    overflow-wrap: anywhere;
}
.stat-card.hero .stat-value { font-size: 20px; color: var(--biru-tua); }
.stat-value small { font-size: 11px; font-weight: 600; color: var(--teks-lembut); }

/* ==========================================================================
   TABEL RINCIAN PER TANGGAL
   ========================================================================== */
.table-wrap { overflow-x: auto; margin: 0 -4px; }
.data-table { width: 100%; border-collapse: collapse; font-size: 12.5px; white-space: nowrap; }
.data-table th {
    text-align: left; font-size: 10.5px; font-weight: 800; letter-spacing: .04em;
    text-transform: uppercase; color: var(--teks-samar);
    padding: 6px 10px; border-bottom: 1px solid var(--garis);
}
.data-table th.num, .data-table td.num { text-align: right; font-variant-numeric: tabular-nums; }
.data-table td { padding: 8px 10px; border-bottom: 1px solid var(--garis); }
.data-table tbody tr { cursor: pointer; transition: background .12s; }
.data-table tbody tr:hover { background: var(--biru-pucat); }
.data-table tbody tr:focus-visible { outline: 2px solid var(--biru-terang); outline-offset: -2px; }
.data-table tbody tr:last-child td { border-bottom: 0; }

/* flex, bukan lagi display:block polos — tombol unduh hasil (dan sejenis)
   menaruh ikon SVG (.ic, display:block) LANGSUNG di sebelah tulisan tanpa
   pembungkus; tanpa flex di sini, ikon block itu memutus alur baris dan
   tulisannya jatuh ke baris berikutnya sendirian, bukan sejajar dengan
   ikonnya. justify-content:center tetap menengahkan isinya sama seperti
   text-align:center sebelumnya untuk tombol tanpa ikon. */
.btn-block {
    display: flex; align-items: center; justify-content: center; gap: 8px;
    width: 100%; text-align: center;
}

/* ==========================================================================
   ARSIP PEKERJAAN
   ========================================================================== */
.archive-card {
    display: flex; align-items: center; gap: 11px;
    padding: 11px 12px; margin-top: 8px;
    border: 1px solid var(--garis); border-radius: var(--lengkung-s);
    background: var(--putih); cursor: pointer;
    animation: rise-fade .3s ease backwards; animation-delay: calc(var(--i, 0) * 40ms);
    transition: transform .14s ease, box-shadow .14s ease, border-color .14s ease;
}
.archive-card:first-child { margin-top: 0; }
.archive-card:hover, .archive-card:focus-visible {
    transform: translateX(2px);
    border-color: var(--biru-pucat-tepi); box-shadow: var(--bayang-1);
    outline: none;
}
.archive-icon {
    display: grid; place-items: center; flex: none;
    width: 34px; height: 34px; border-radius: 9px;
    background: var(--biru-pucat); color: var(--biru);
}
.archive-body { flex: 1; min-width: 0; }
.archive-name {
    font-size: 13px; font-weight: 700; color: var(--teks);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.archive-meta { font-size: 11px; color: var(--teks-samar); margin-top: 1px; }

.badge {
    flex: none; font-size: 10.5px; font-weight: 800; letter-spacing: .03em;
    padding: 4px 9px; border-radius: 999px; text-transform: uppercase;
    background: var(--biru-pucat); color: var(--biru);
}
.badge-done    { background: #e3f5ea; color: #2f8f5b; }
.badge-failed    { background: var(--merah-latar); color: var(--merah-teks); }
.badge-running   { background: var(--biru-pucat); color: var(--biru); }
.badge-cancelled,
.badge-skipped   { background: var(--garis); color: var(--teks-samar); }
:root[data-theme="dark"] .badge-done { background: #163829; color: #6fe0a0; }

.archive-actions { display: flex; gap: 4px; flex: none; }
.archive-action-btn {
    display: grid; place-items: center; flex: none;
    width: 28px; height: 28px; border-radius: 7px;
    border: 1px solid transparent; background: transparent; cursor: pointer;
    color: var(--teks-samar);
    transition: background .14s, color .14s, border-color .14s;
}
.archive-action-btn .ic { width: 15px; height: 15px; }
.archive-action-btn:hover { background: var(--biru-pucat); color: var(--biru); border-color: var(--biru-pucat-tepi); }
.archive-action-btn.danger:hover { background: var(--merah-latar); color: var(--merah-teks); border-color: var(--merah-teks); }
.archive-action-btn:disabled { opacity: .5; cursor: default; pointer-events: none; }

/* ==========================================================================
   RESPONSIF
   --------------------------------------------------------------------------
   Di atas ~980px tata letak memakai bentuk aslinya: sidebar tetap di kiri,
   dok tetap di kanan, peta mengisi sisanya. Di bawah itu, ruang tak lagi
   cukup untuk ketiganya sekaligus:

     • navigasi kepala (enam tombol) dilipat menjadi menu tarik-turun,
     • sidebar Data Masukan DAN dok Proses/Hasil/Lapisan/Arsip sama-sama
       menjadi laci layar-penuh (bukan kolom tetap) — simetris, hanya
       berlawanan arah geser (kiri vs kanan), dan main.js memastikan
       cuma satu yang terbuka pada satu waktu (lihat wireSidebar/dock.wire).
   ========================================================================== */
@media (max-width: 980px) {
    .brand .name .sub { display: none; }
    .dock { width: 340px; }
}

@media (max-width: 760px) {
    /* Menu tarik-turun adalah turunan .header, yang membentuk konteks
       tumpukannya SENDIRI (position + z-index) — akibatnya z-index menu
       (di bawah) dibandingkan terhadap laci sidebar/dok HANYA lewat
       z-index .header itu sendiri, bukan z-index menu. .header dinaikkan
       di sini supaya menu tetap terjangkau walau salah satu laci sedang
       terbuka menutupi layar. */
    .header { z-index: 750; }

    /* ── Navigasi kepala → menu tarik-turun ── */
    .nav-toggle { display: grid; }
    .nav {
        display: none;
        position: absolute; top: 100%; left: 0; right: 0;
        flex-direction: column; gap: 2px;
        background: var(--putih); border-bottom: 1px solid var(--garis);
        box-shadow: var(--bayang-2); padding: 8px; z-index: 399;
    }
    .nav.open { display: flex; }
    .nav button { text-align: left; padding: 11px 14px; }
    /* Di layar sempit, menu tarik-turun ini SATU-SATUNYA jalan membuka
       laci sidebar/dok (keduanya mulai terlipat penuh di luar layar) — jadi
       tombol yang disembunyikan di layar lebar (lihat aturan dasar .nav
       button[data-sidebar]/[data-tab]) dikembalikan tampil di sini. */
    .nav button[data-sidebar],
    .nav button[data-tab] {
        display: flex;
    }

    /* ── Sidebar Data Masukan → laci layar-penuh, geser dari KIRI ──
       position:fixed mengeluarkannya dari alur flex .body-area, sehingga
       peta otomatis memakai lebar penuh apa pun keadaan laci ini — terbuka
       atau terlipat. */
    #panel-data.sidebar {
        position: fixed;
        top: calc(var(--bilah-tinggi) + var(--kepala-tinggi));
        left: 0; right: 0; bottom: 0;
        width: 100% !important; max-width: 100%;
        z-index: 700;
        transform: translateX(0);
        transition: transform .22s ease;
    }
    #panel-data.sidebar.collapsed {
        width: 100% !important;      /* timpa width:0 bawaan layar lebar */
        transform: translateX(-100%);
        border-right: 0;
    }
    #panel-data.sidebar.collapsed .panel-body,
    #panel-data.sidebar.collapsed .panel-head .panel-title {
        display: block;              /* timpa display:none bawaan layar lebar */
    }

    /* ── Dok → laci layar-penuh, geser dari KANAN — pasangan sidebar ── */
    .dock {
        position: fixed;
        top: calc(var(--bilah-tinggi) + var(--kepala-tinggi));
        left: 0; right: 0; bottom: 0;
        width: 100% !important; max-width: 100%;
        z-index: 700;
        transform: translateX(0);
        transition: transform .22s ease;
        border-left: 0;
    }
    .dock.collapsed {
        width: 100% !important;
        transform: translateX(100%);
    }
    .dock.collapsed .dock-tabs { display: flex; }   /* timpa display:none bawaan layar lebar */
    .dock.collapsed .dock-body { display: block; }

    .settings-fields { grid-template-columns: 1fr; }

    /* Sidebar vertikal tak muat berdampingan dengan isi di layar sempit —
       jadi baris ikon-saja yang bisa digulung mendatar, isi kelompok
       aktif mengisi sisa tinggi di bawahnya. */
    .settings-shell { flex-direction: column; }
    .settings-sidebar {
        flex-direction: row; width: auto; overflow-x: auto; overflow-y: hidden;
        border-right: 0; border-bottom: 1px solid var(--garis);
        padding: 8px;
    }
    .settings-tab { flex: none; width: auto; }
    .settings-tab span { display: none; }   /* ikon saja — label penuh tak muat sebaris */
}

@media (max-width: 640px) {
    .header { padding: 0 14px; }
    .time-bar { padding: 0 14px; font-size: 11.5px; }
    .time-bar .label { display: none; }   /* "Standar Waktu Indonesia" — jam sendiri cukup */
    .brand .name { font-size: 11.5px; }
    .timeline-label { display: none; }
}

@media (max-width: 480px) {
    .toast-area { left: 12px; right: 12px; max-width: none; }

    .modal-backdrop { padding: 0; }
    .modal {
        width: 100%; height: 100%; max-height: 100%;
        border-radius: 0;
    }

    .conn span:not(.led) { display: none; }   /* lencana jadi sekadar titik keadaan */
}
