@import url('https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700;800&family=IBM+Plex+Mono:wght@400;500&family=Noto+Naskh+Arabic:wght@400;500;700&display=swap');

  :root{
    /* Skema warna Salam Setara (2026-09-09, diminta user): warna utama
       putih, dua warna aksen brand #EB2677 (pink/magenta) dan #113BAD
       (navy blue) -- --accent dipakai untuk tombol utama/link/status aktif,
       --accent-2 untuk aksen sekunder (judul section dashboard, separuh
       logo brand di index.html). */
    --bg:#fbfeff; --panel:#f3f5f7; --panel-2:#faf7fa; --border:#e7e3e6;
    --text:#1e1c19; --text-dim:#6b665c; --text-faint:#9a9488;
    --accent:#EB2677; --accent-ink:#ffffff; --accent-soft:#fbe3ee;
    --accent-2:#113BAD; --accent-2-ink:#ffffff; --accent-2-soft:#e3e8f7;
    /* --accent-3 (Ronde 48, 2026-09-26) -- oranye/peach diambil dari logo
       Simpul Setara (elemen ke-3 di logo, di luar --accent pink & --accent-2
       navy blue yang sudah ada) -- dipakai KHUSUS gradient panel kiri
       halaman login (.gate-left) supaya warnanya sesuai logo asli, TIDAK
       dipakai di tempat lain di app ini. */
    --accent-3:#F2A65C;
    --amber:#b9791b; --amber-soft:#f6ecd9;
    --success:#1e7a4c; --success-soft:#e2f3e8;
    --warning:#b9791b; --warning-soft:#f6ecd9;
    --critical:#b3372c; --critical-soft:#fbeae7;
    --info:#2a5f96; --info-soft:#e8f0f9;
    --neutral:#6b665c; --neutral-soft:#eeece6;
    --shadow: 0 1px 2px rgba(30,28,25,.06), 0 8px 24px -12px rgba(30,28,25,.15);
    --radius: 10px;
    --font-display: 'Plus Jakarta Sans', system-ui, sans-serif;
    --font-body: 'Plus Jakarta Sans', system-ui, sans-serif;
    --font-mono: 'IBM Plex Mono', ui-monospace, monospace;
  }
  *{box-sizing:border-box;}
  html,body{margin:0;padding:0;background:var(--bg);color:var(--text);font-family:var(--font-body);font-size:14px;line-height:1.5;}
  h1,h2,h3{font-family:var(--font-display);font-weight:600;margin:0 0 4px;}
  a{color:var(--accent);}
  button{font-family:inherit;}
  input,select,textarea{font-family:inherit;font-size:14px;color:var(--text);background:var(--panel);border:1px solid var(--border);border-radius:7px;padding:8px 10px;width:100%;}
  input:focus,select:focus,textarea:focus{outline:2px solid var(--accent);outline-offset:-1px;}
  textarea{resize:vertical;min-height:60px;}
  label{font-size:12.5px;color:var(--text-dim);font-weight:500;display:block;margin-bottom:4px;}

  .btn{border:1px solid var(--border);background:var(--panel);color:var(--text);border-radius:8px;padding:9px 14px;font-size:13.5px;font-weight:500;cursor:pointer;transition:background .12s,transform .12s,box-shadow .12s;}
  .btn:hover{background:var(--panel-2);transform:translateY(-1px);box-shadow:0 3px 8px rgba(30,28,25,.08);}
  .btn:disabled{opacity:.45;cursor:not-allowed;transform:none;box-shadow:none;}
  .btn-primary{background:var(--accent);border-color:var(--accent);color:var(--accent-ink);}
  /* Perbaikan (2026-09-09): sebelumnya hover tombol primary "ketimpa" jadi
     warna --panel-2 (nyaris putih) oleh aturan .btn:hover generik di atas --
     spesifisitas CSS-nya sama-sama 2, jadi cuma filter brightness yang
     kepasang, background-nya balik pucat. Sekarang background aksen
     ditegaskan ulang di sini (menang karena dideklarasikan belakangan). */
  .btn-primary:hover{background:var(--accent);border-color:var(--accent);filter:brightness(1.08);transform:translateY(-1px);box-shadow:0 4px 12px rgba(235,38,119,.28);}
  /* Tombol "Tandai Selesai" di modal Edit Tugas Visual (2026-09-03, ronde 10) */
  .btn-success{background:var(--success);border-color:var(--success);color:#fff;}
  .btn-success:hover{background:var(--success);border-color:var(--success);filter:brightness(1.08);transform:translateY(-1px);box-shadow:0 4px 12px rgba(30,122,76,.28);}
  .btn-ghost{background:transparent;}
  .btn-danger{color:var(--critical);}
  .btn-block{width:100%;text-align:left;}
  .btn-sm{padding:6px 10px;font-size:12.5px;}

  /* ---------- Gate ---------- */
  /* Ronde 48 (2026-09-26, diminta user: "buat jadi dua kolom gitu seperti
     contoh yg hayaa") -- gate DIROMBAK TOTAL dari "2 kartu melayang di
     tengah layar" (lama) jadi 2 KOLOM PENUH TINGGI LAYAR: .gate-left
     (panel warna brand, gradient biru->oranye->pink diambil dari logo
     Simpul Setara lewat --accent-2/--accent-3/--accent yang sudah ada)
     + .gate-right (panel putih polos berisi kartu form login, mirip
     kartu lama tapi TANPA logo/brand duplikat di dalamnya karena brand
     sudah tampil besar di .gate-left). Di layar sempit (<900px)
     .gate-left disembunyikan, .gate-right jadi full width -- form login
     TETAP jalan normal, cuma panel brand yang hilang. */
  .gate{position:fixed;inset:0;display:flex;z-index:50;background:var(--bg);}
  .gate-left{flex:1 1 46%;max-width:640px;min-width:0;background:linear-gradient(160deg, var(--accent-2) 0%, var(--accent-3) 48%, var(--accent) 88%);color:#fff;display:flex;align-items:center;padding:56px;position:relative;overflow:hidden;}
  .gate-left::after{content:'';position:absolute;inset:0;background:radial-gradient(circle at 88% 6%, rgba(255,255,255,.18), transparent 45%),radial-gradient(circle at 6% 96%, rgba(0,0,0,.14), transparent 50%);pointer-events:none;}
  .gate-left-inner{position:relative;z-index:1;max-width:420px;}
  .gate-logo-img{width:60px;height:auto;display:block;margin-bottom:22px;filter:drop-shadow(0 6px 16px rgba(0,0,0,.18));}
  .gate-left-brand{font-family:var(--font-display);font-size:27px;font-weight:700;line-height:1.2;}
  .gate-left-tagline{font-family:var(--font-display);font-size:16px;font-weight:600;opacity:.92;margin-bottom:16px;}
  .gate-left-desc{font-size:13px;line-height:1.65;opacity:.88;margin-bottom:30px;max-width:360px;}
  .gate-right{flex:1 1 54%;display:flex;align-items:center;justify-content:center;padding:20px;}
  .gate-card{width:100%;max-width:380px;background:var(--panel);border:1px solid var(--border);border-radius:16px;padding:32px 28px 28px;box-shadow:0 2px 8px rgba(30,28,25,.06);position:relative;}
  .gate-card-title{font-family:var(--font-display);font-size:20px;font-weight:700;margin-bottom:4px;}
  .gate-sub{color:var(--text-dim);font-size:12.5px;margin-bottom:22px;}
  .gate-label{margin-top:14px;font-size:12px;font-weight:600;color:var(--text-dim);display:block;margin-bottom:5px;}
  .gate-input{margin-bottom:0;min-height:41px;border-radius:8px;transition:border-color .12s,box-shadow .12s;}
  .gate-input:focus{outline:none;border-color:var(--accent-2);box-shadow:0 0 0 3px var(--accent-2-soft);}
  .password-wrap{position:relative;}
  .password-wrap .gate-input{padding-right:64px;}
  .password-toggle{position:absolute;right:8px;top:50%;transform:translateY(-50%);border:0;background:transparent;color:var(--accent-2);font:600 11.5px var(--font-body);cursor:pointer;padding:5px;}
  .password-toggle:hover{text-decoration:underline;}
  .gate-error{min-height:18px;margin-top:8px;color:var(--critical);font-size:12px;}
  .gate-go{width:100%;margin-top:14px;padding:11px 14px;font-size:14px;border-radius:9px;}
  /* Ronde 48 -- kutipan sekarang STATIS (1x tampil, tidak auto-ganti) dan
     ditaruh DI DALAM .gate-left (bg gradient warna brand), jadi restyle
     ke teks TERANG (bukan lagi teks gelap di atas panel putih seperti
     desain lama). .gate-quote-inner TIDAK PERLU animasi fade lagi (dulu
     dipakai transisi antar kutipan yg berganti-ganti), tapi class `show`
     TETAP dipertahankan (dipasang langsung di HTML & tidak pernah
     dilepas lagi oleh app.js) supaya tidak perlu ubah app.js sama sekali. */
  .gate-quote-panel{max-width:400px;border-top:1px solid rgba(255,255,255,.28);padding-top:20px;}
  .gate-quote-inner{opacity:1;}
  .gate-quote-arabic{font-family:'Noto Naskh Arabic', serif;direction:rtl;text-align:right;font-size:21px;line-height:1.9;color:#fff;margin-bottom:12px;}
  .gate-quote-arabic:empty{display:none;}
  .gate-quote-translation{font-size:13.5px;line-height:1.7;color:rgba(255,255,255,.92);margin-bottom:6px;}
  .gate-quote-reference{font-size:11.5px;font-weight:600;color:rgba(255,255,255,.72);}
  @media (max-width: 900px){ .gate-left{display:none;} .gate-right{width:100%;} }
  /* Teks Arab di form "Kelola Quotes" (field arabicText, opsional) -- lihat
     f.rtl di fieldInputHtml() (app.js). Textarea lain TIDAK terpengaruh. */
  textarea.field-arabic{font-family:'Noto Naskh Arabic', serif;font-size:16px;line-height:1.9;}

  /* ---------- App shell ---------- */
  .app{display:flex;min-height:100vh;}
  .sidebar{width:220px;flex:none;background:var(--panel);border-right:1px solid var(--border);display:flex;flex-direction:column;padding:18px 14px;gap:6px;position:sticky;top:0;height:100vh;}
  .brand{font-family:var(--font-display);font-size:17px;font-weight:600;margin-bottom:2px;}
  .brand span.brand-c1{color:var(--accent-2);}
  .brand span.brand-c2{color:var(--accent);}
  .role-badge{font-size:11.5px;color:var(--text-dim);margin-bottom:14px;}
  .side-nav{display:flex;flex-direction:column;gap:3px;flex:1;overflow-y:auto;}
  .side-item{border:none;background:transparent;text-align:left;padding:8px 10px;border-radius:7px;font-size:13px;cursor:pointer;color:var(--text);position:relative;display:flex;align-items:center;justify-content:space-between;gap:8px;}
  .side-item-label{flex:1;min-width:0;}
  .side-badge{flex:none;min-width:18px;height:18px;padding:0 5px;border-radius:9px;background:var(--critical);color:#fff;font-size:10.5px;font-weight:700;display:flex;align-items:center;justify-content:center;line-height:1;}
  .side-item:hover{background:var(--panel-2);}
  .side-item.active{background:var(--accent-soft);color:var(--accent);font-weight:600;}
  .side-item.active::before{content:'';position:absolute;left:-4px;top:16%;bottom:16%;width:3px;border-radius:3px;background:var(--accent);}
  .side-section-label{font-size:10.5px;text-transform:uppercase;letter-spacing:.04em;color:var(--text-faint);padding:10px 10px 2px;margin-top:2px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
  .side-item-sub{padding-left:20px;font-size:12.5px;}
  /* Ikon sidebar monokrom (2026-09-25, diminta user -- ganti emoji
     berwarna) -- flex:none supaya tidak ikut menyusut/melar mengikuti
     .side-item-label yang flex:1, stroke ikut warna currentColor (otomatis
     berubah jadi warna --accent waktu .side-item.active, sama seperti
     teksnya, tanpa aturan tambahan). */
  .side-item-icon{flex:none;width:18px;height:18px;}
  .side-item-sub .side-item-icon{width:16px;height:16px;}
  /* Grup "Superadmin" (2026-09-25) -- label section + garis pemisah di atas
     supaya kelihatan jelas ini area terpisah dari nav biasa, bukan cuma
     .side-section-label polos seperti nama campaign. */
  .side-section-label-admin{display:flex;align-items:center;gap:6px;margin-top:14px;padding-top:12px;border-top:1px solid var(--border);}
  .side-section-label-admin svg{flex:none;width:14px;height:14px;}
  /* Dropdown "Superadmin" (2026-09-25, ronde 36, diminta user: "buat jadi
     dropdown") -- label section di atas sekarang tombol (data-action=
     "toggle-superadmin"), chevron ini menandakan status buka/tutup, ikut
     berputar 180° pas terbuka (state.superadminNavOpen, lihat
     renderSideNav() di app.js). margin-left:auto dorong dia ke ujung kanan
     tombol walau .side-item-label di tengah sudah flex:1. */
  .side-item-chevron{margin-left:auto;transition:transform .15s ease;}
  .side-item-chevron.open{transform:rotate(180deg);}
  .side-foot{display:flex;flex-direction:column;gap:6px;padding-top:10px;border-top:1px solid var(--border);}
  .side-foot-new-campaign{background:linear-gradient(135deg, var(--accent), var(--accent-2));color:#fff;border:none;font-weight:600;display:flex;align-items:center;justify-content:center;gap:6px;box-shadow:0 3px 10px rgba(235,38,119,.25);margin-bottom:2px;}
  .side-foot-new-campaign:hover{background:linear-gradient(135deg, var(--accent), var(--accent-2));color:#fff;filter:brightness(1.06);transform:translateY(-1px);box-shadow:0 5px 14px rgba(235,38,119,.32);}
  .side-foot-new-campaign.active{filter:brightness(0.94);}
  .sync-note{font-size:10.5px;color:var(--text-faint);text-align:center;font-family:var(--font-mono);}

  /* Pencarian cepat sidebar (Ronde 50, 2026-09-26, diminta user: "buat kolom
     untuk pencarian... yg di cari itu link campaign atau aurum atau
     partner") -- kotak input + daftar hasil melayang tepat di bawahnya.
     `position:relative` di wrapper supaya `.sidebar-search-results` (absolute)
     mengambang pas di bawah input, tidak mendorong konten nav di bawahnya. */
  .sidebar-search{position:relative;margin-bottom:12px;}
  .sidebar-search-input{font-size:12.5px;padding:7px 9px;min-height:34px;margin-bottom:0;}
  .sidebar-search-results{position:absolute;top:100%;left:0;right:0;margin-top:4px;background:var(--panel);border:1px solid var(--border);border-radius:8px;box-shadow:var(--shadow);max-height:280px;overflow-y:auto;z-index:10;}
  .sidebar-search-result{padding:8px 10px;cursor:pointer;border-bottom:1px solid var(--border);}
  .sidebar-search-result:last-child{border-bottom:none;}
  .sidebar-search-result:hover{background:var(--panel-2);}
  .sidebar-search-result-title{font-size:12.5px;font-weight:600;color:var(--text);}
  .sidebar-search-result-sub{font-size:11px;color:var(--text-dim);margin-top:1px;}
  .sidebar-search-empty{padding:10px;font-size:12px;color:var(--text-faint);}

  main{flex:1;padding:26px 30px;max-width:1300px;overflow-x:hidden;}

  /* Topbar + drawer sidebar buat HP (Ronde 49, 2026-09-26, diminta user:
     "pastikan ini juga responsif diakses melalui HP") -- sebelumnya
     .sidebar lebar TETAP 220px di layar seberapa pun sempitnya, jadi di HP
     (<880px) konten utama kegencet jadi kurang dari separuh lebar layar.
     Sekarang di bawah 880px: .mobile-topbar (tombol hamburger) muncul,
     .sidebar disembunyikan default lalu dibuka sbg drawer dari kiri lewat
     class .is-open (lihat openMobileSidebar()/closeMobileSidebar(), app.js).
     Di atas 880px (desktop/tablet lanskap) elemen2 baru ini semua
     display:none / tidak berefek -- tampilan lama TIDAK berubah sama
     sekali. */
  .mobile-topbar{display:none;align-items:center;gap:14px;padding:12px 14px;background:var(--panel);border-bottom:1px solid var(--border);position:sticky;top:0;z-index:40;}
  .mobile-menu-btn{border:none;background:transparent;padding:6px;margin:-6px;border-radius:8px;color:var(--text);cursor:pointer;display:flex;flex:none;}
  .mobile-menu-btn:hover{background:var(--panel-2);}
  .mobile-topbar-brand{font-family:var(--font-display);font-size:15.5px;font-weight:600;}
  .sidebar-backdrop{display:none;position:fixed;inset:0;background:rgba(20,18,15,.42);z-index:55;}
  .sidebar-close-btn{display:none;}
  @media (max-width: 880px){
    .mobile-topbar{display:flex;}
    body.yayasan-mode .mobile-topbar{display:none;}
    .app{display:block;}
    .sidebar{position:fixed;top:0;left:0;width:260px;max-width:82vw;height:100vh;z-index:60;transform:translateX(-100%);transition:transform .22s ease;box-shadow:0 0 30px rgba(20,18,15,.22);}
    .sidebar.is-open{transform:translateX(0);}
    .sidebar-close-btn{display:flex;align-items:center;justify-content:center;position:absolute;top:12px;right:12px;width:28px;height:28px;border:none;background:var(--panel-2);border-radius:8px;color:var(--text-dim);cursor:pointer;font-size:13px;}
    .sidebar-backdrop.show{display:block;}
    main{padding:16px 14px;max-width:100%;}
    /* Baris tombol/filter header Home & grid "Data Master" read-only (yg
       sebelumnya lebar/nowrap tetap, aman di desktop tapi kepotong di HP
       sempit) -- dilonggarkan supaya boleh turun baris / menyusut penuh,
       BUKAN redesign, cuma jaga2 supaya tidak ada yang kepotong di layar
       sempit. */
    .home-actions{flex-wrap:wrap;}
    .master-ro-groups{width:100%;}
  }

  /* ---------- Campaign picker (home) ---------- */
  .home-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:18px;flex-wrap:wrap;gap:10px;}
  .home-actions{display:flex;align-items:center;gap:8px;flex-wrap:nowrap;}
  /* Jarak antar grup & baris campaign dipersempit (2026-09-26, diminta
     user: "ruang jarak antar list campaign masih terlalu berjarak
     tingginya, coba perdekat lagi") -- month-group 26px->16px,
     .campaign-list td 6px->4px (lihat juga aturan .btn/.chip khusus di
     dalam .campaign-list td di bawah, biar tombol Aksi ikut menyusut). */
  .month-group{margin-bottom:16px;}
  .month-title{font-family:var(--font-display);font-size:17px;margin-bottom:8px;padding-bottom:6px;border-bottom:1px solid var(--border);}
  /* Judul grup collapsible (2026-09-26, diminta user: "kalau udah banyak
     gak perlu sampai scrolldown kebawah") -- dipakai Home (per bulan) &
     Rekap Semua Supply (per PIC), lihat groupTitleHtml() di app.js. Waktu
     dirender sbg <button> (bukan <div>, cuma kalau toggleable), reset
     tampilan bawaan tombol browser (background/border/padding) supaya
     kelihatan identik dgn versi <div> lama, ditambah layout flex utk
     chevron+jumlah campaign di kanan. Compound selector button.month-title
     sengaja dipakai (bukan cuma .month-title) supaya specificity-nya
     menang atas gaya bawaan <button> milik browser.
  */
  button.month-title{display:flex;align-items:center;gap:8px;width:100%;background:none;border:none;border-bottom:1px solid var(--border);cursor:pointer;color:var(--text);font:inherit;font-family:var(--font-display);font-size:17px;text-align:left;padding:0 0 6px;}
  button.month-title:hover .month-title-label{color:var(--accent);}
  .month-title-label{flex:none;}
  .month-count{margin-left:auto;font-size:12px;font-weight:500;color:var(--text-faint);font-family:var(--font-body,inherit);}
  .month-chevron{flex-shrink:0;color:var(--text-faint);transition:transform .15s ease;}
  .month-chevron.open{transform:rotate(180deg);}
  .campaign-list-wrap{overflow-x:auto;border:1px solid var(--border);border-radius:10px;background:var(--panel);box-shadow:var(--shadow);}
  .campaign-list{width:100%;min-width:1000px;border-collapse:collapse;table-layout:fixed;}
  .campaign-list th{padding:6px 10px;background:var(--panel-2);border-bottom:1px solid var(--border);color:var(--text-dim);font-size:11px;font-weight:600;text-align:left;letter-spacing:.02em;}
  .campaign-list th:nth-child(1){width:9%;}
  .campaign-list th:nth-child(2){width:17%;}
  .campaign-list th:nth-child(3){width:14%;}
  .campaign-list th:nth-child(4){width:10%;}
  .campaign-list th:nth-child(5){width:15%;}
  .campaign-list th:nth-child(6){width:11%;}
  .campaign-list th:nth-child(7){width:8%;}
  .campaign-list th:nth-child(8){width:8%;}
  .campaign-list th:nth-child(9){width:8%;}
  .campaign-list th.col-aksi{width:64px;}
  .campaign-list td.col-aksi{white-space:nowrap;overflow:visible;text-overflow:clip;}
  /* Filter "Pilih Bulan" di header Home (2026-09-10, diminta user: dropdown
     TUNGGAL di samping tombol Import Excel/+ Campaign Baru, BUKAN dropdown
     per-baris di tabel -- lihat wireGlobalActions()/renderHome() utk
     logikanya). Murni filter tampilan, tidak menyentuh data apa pun. */
  .home-month-filter{padding:9px 14px;border:1px solid var(--border);border-radius:8px;background:var(--panel);color:var(--text);font-size:13.5px;font-weight:500;}
  .campaign-list td{padding:4px 10px;border-bottom:1px solid var(--border);color:var(--text-dim);font-size:12px;line-height:1.25;vertical-align:middle;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
  /* Tombol Aksi (End/Hapus) & chip status di dalam tabel campaign dibikin
     lebih mungil (2026-09-26) -- .btn/.chip biasa (dipakai di tempat lain
     jg) sengaja TIDAK diubah globalnya, scoped ke ".campaign-list td" saja
     supaya baris tabel Home/Rekap Semua Supply lebih rapat tanpa mengubah
     tampilan tombol/chip di halaman lain. */
  .campaign-list td .btn{padding:3px 8px;font-size:11.5px;}
  .campaign-list td .chip{padding:1px 8px;}
  .campaign-list-row:last-child td{border-bottom:0;}
  .campaign-list-row{cursor:pointer;transition:background .12s;}
  .campaign-list-row:hover,.campaign-list-row:focus{background:var(--accent-soft);outline:none;}
  .campaign-list-link{display:block;color:var(--accent);font-family:var(--font-mono);font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-decoration:none;}
  .campaign-list-link:hover{text-decoration:underline;}
  .list-primary{color:var(--text);font-weight:600;}
  .list-empty{color:var(--text-faint);}
  .empty-note{color:var(--text-faint);font-size:13px;padding:30px 0;text-align:center;}

  /* ---------- Campaign detail ---------- */
  .crumb{font-size:12.5px;color:var(--text-dim);cursor:pointer;margin-bottom:10px;}
  .crumb:hover{color:var(--accent);}
  .detail-page{}
  .detail-main{min-width:0;}
  .meta-strip{display:flex;flex-wrap:wrap;gap:18px;background:var(--panel);border:1px solid var(--border);border-radius:10px;padding:14px 18px;margin-bottom:16px;box-shadow:var(--shadow);}
  .meta-item .mi-label{font-size:10.5px;text-transform:uppercase;letter-spacing:.04em;color:var(--text-faint);}
  .meta-item .mi-value{font-size:13.5px;font-weight:600;margin-top:1px;}
  .meta-item .mi-value.mono{font-family:var(--font-mono);font-weight:500;}

  .detail-grid{display:grid;grid-template-columns:340px 1fr;gap:22px;align-items:start;}
  @media (max-width: 880px){ .detail-grid{grid-template-columns:1fr;} }
  .detail-grid-single{grid-template-columns:1fr;}
  .konten-running-block{border:1px solid var(--success);background:var(--success-soft);border-radius:var(--radius);padding:14px 16px;margin:14px 0;box-shadow:var(--shadow);}
  .konten-running-head{display:flex;align-items:flex-start;gap:10px;margin-bottom:10px;}
  .konten-running-badge{flex:0 0 auto;width:26px;height:26px;border-radius:50%;background:var(--success);color:#fff;display:flex;align-items:center;justify-content:center;font-size:13px;}
  .konten-running-block h4{margin:0 0 3px;color:var(--success);font-size:14px;}
  .konten-running-sub{font-size:12.5px;color:var(--text-dim);}
  .konten-running-btn{display:inline-flex;align-items:center;gap:7px;background:var(--success);border-color:var(--success);color:#fff;font-weight:600;}
  .konten-running-btn:hover{filter:brightness(1.1);transform:translateY(-1px);box-shadow:0 4px 12px rgba(30,122,76,.28);}
  .konten-running-readonly{font-size:12.5px;font-weight:600;color:var(--success);background:#fff;border:1px dashed var(--success);border-radius:7px;padding:8px 10px;display:inline-block;}
  .form-panel{background:var(--panel);border:1px solid var(--border);border-radius:10px;padding:16px;position:sticky;top:20px;box-shadow:var(--shadow);}
  .form-panel h3{font-size:14.5px;margin-bottom:12px;}
  /* Panel berdiri sendiri (Data Master, Konten recap, Campaign Baru) tidak
     punya "kolom sebelah" untuk di-scroll lewat, jadi tidak perlu sticky —
     kalau sticky, panel ikut menempel di atas layar saat form-nya panjang. */
  .form-panel-solo{max-width:none;position:static;}
  /* Grid Data Master/Konten recap/Campaign Baru dirapatkan 2026-09-03: kolom
     min-width diturunkan (200px->150px) supaya lebih banyak kolom muat per
     baris (makin sedikit baris = makin sedikit perlu di-scroll), dan label
     + value tiap field-item dirapatkan (lihat 2 aturan baru di bawah). */
  .form-panel-solo .field-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:10px 16px;align-items:start;}
  .form-panel-solo .field-item label{margin-bottom:2px;}
  .form-panel-solo .ro-value{padding:3px 0;}
  /* panel-head sekarang bisa punya 3 anak (h3, .master-flags-row, tombol
     aksi) — flex-wrap dinyalakan supaya di layar sempit baris flag pindah
     ke bawah judul, bukan memaksa satu baris jadi kepenuhan. */
  .panel-head{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:8px 14px;margin-bottom:12px;}
  .panel-head h3{margin-bottom:0;}
  .panel-head-actions{display:flex;align-items:center;gap:8px;}
  .field-grid{display:flex;flex-direction:column;gap:10px;}
  .field-help{font-size:11px;color:var(--text-faint);margin-top:2px;}
  .field-item{display:flex;flex-direction:column;}
  .field-item-checkbox{flex-direction:row;align-items:center;gap:8px;}
  /* Pseudo-field 'section' + blok Rincian Salset otomatis (ronde 12,
     2026-09-03) -- lihat fieldInputHtml()/renderPencairanSalsetBox() di
     app.js, dipakai di modal Edit Tugas Pencairan Utama. */
  .field-section-header{font-size:11.5px;font-weight:700;color:var(--text-dim);text-transform:uppercase;letter-spacing:.03em;margin-top:8px;padding-top:10px;border-top:1px dashed var(--border);}
  .salset-box{background:var(--panel-2);border:1px solid var(--border);border-radius:8px;padding:10px 12px;margin-top:6px;}
  .salset-box h4{font-size:12px;margin-bottom:6px;color:var(--text-dim);}
  .salset-row{display:flex;justify-content:space-between;gap:10px;padding:3px 0;border-bottom:1px dashed var(--border);font-size:12.5px;}
  .salset-row:last-child{border-bottom:0;}
  .salset-row-label{color:var(--text-faint);}
  .salset-row-total{font-weight:700;}
  .salset-row-total .salset-row-label{color:var(--text-dim);}
  .field-item-checkbox .field-help{margin-top:0;}
  /* Tim Approval (2026-09-04) -- catatan revisi dari Supply, ditampilkan
     di kotak Status Approval Konten (renderKontenApprovalStatus). */
  .approval-feedback{margin-top:6px;font-size:12.5px;color:var(--text-dim);font-style:italic;}
  .approval-feedback-done{color:var(--success);font-style:normal;font-weight:600;}
  .field-checkbox{width:16px;height:16px;accent-color:var(--accent);cursor:pointer;}
  /* Baris flag ringkas (Assign Region/Pencairan/Subsidi Mitra/Kabar Terbaru),
     dipindah ke panel-head 2026-09-03 (ronde 2 rapikan) — lihat
     renderMasterFlagsHtml()/renderMasterTab() di app.js. Bukan lagi bagian
     dari field-grid sama sekali. */
  .master-flags-row{display:flex;flex-wrap:wrap;align-items:center;gap:6px 8px;}
  .flag-chip{display:inline-block;padding:3px 10px;border-radius:20px;font-size:11px;font-weight:600;white-space:nowrap;background:var(--neutral-soft);color:var(--text-faint);}
  .flag-chip.on{background:var(--success-soft);color:var(--success);}
  /* Kotak field gabungan (ronde 2 rapikan, 2026-09-03) — beberapa nilai yang
     berkaitan (mis. Status/Link/Ready Date Consent Letter) ditaruh dalam 1
     "kolom" grid saja, lihat fieldGroupHtml() di app.js. Border tipis +
     background sedikit beda supaya terlihat sebagai 1 kesatuan, bukan
     nyampur dengan field-item biasa di sekelilingnya. */
  /* Layout Data Master read-only dipisah 2 region independen (ronde 5,
     2026-09-03) -- lihat komentar renderMasterReadOnlyFields() di app.js
     untuk alasan lengkapnya (CSS Grid menyamakan tinggi 1 baris kalau
     kotak gabungan + field pendek dicampur di 1 grid yang sama). */
  .master-ro-layout{display:flex;gap:16px;align-items:flex-start;flex-wrap:wrap;}
  /* 2026-09-03 ronde 6: .master-ro-groups jadi grid 2 kolom (dulu 1 kolom
     ditumpuk 3 baris) -- "Input & Progress" melebar 2 kolom
     (.field-item-group-wide, lihat fieldGroupHtml() di app.js), "Consent
     Letter"/"Nominal Campaign" bersebelahan di baris bawahnya, sesuai
     permintaan user ("nominal campaign geser kolomnya di samping consent
     letter, jadi dua baris"). */
  .master-ro-groups{display:grid;grid-template-columns:repeat(2,1fr);gap:10px;width:340px;flex-shrink:0;align-items:start;}
  .master-ro-groups .field-item-group-wide{grid-column:1/-1;}
  .master-ro-fields{flex:1;min-width:240px;}
  /* Ronde 30 (2026-09-25, diminta Supply -- "ada area kosong di samping
     kolom Nominal Campaign") -- dulu region ini pakai grid auto-fill biasa
     (aturan .form-panel-solo .field-grid di atas), yang wrap jadi
     SEDIKIT baris lebar (mis. 5 kolom x 3 baris utk 12 field) -- jauh
     lebih pendek dari 2 kotak bertumpuk di .master-ro-groups sebelahnya,
     jadi nyisa banyak ruang kosong. CSS multi-column (BUKAN grid) dipakai
     di sini SENGAJA: browser otomatis MENYEIMBANGKAN total tinggi antar
     kolom (column-fill:balance, default browser), tanpa memaksakan tinggi
     antar ITEM supaya SAMA seperti grid row -- itu justru masalah yang
     sudah dihindari sejak ronde 5 dengan memisah region ini dari
     .master-ro-groups (lihat komentar renderMasterReadOnlyFields() di
     app.js), jadi solusi ini tidak membuka lagi masalah lama itu.
     break-inside:avoid-column supaya label+value 1 field tidak kepotong
     pindah kolom di tengah. */
  .master-ro-fields.field-grid{display:block;columns:3 190px;column-gap:16px;}
  .master-ro-fields.field-grid .field-item{break-inside:avoid-column;margin-bottom:10px;}
  .field-item-group{background:var(--panel-2);border:1px solid var(--border);border-radius:8px;padding:8px 10px;}
  .field-group-body{display:flex;flex-direction:column;gap:6px;margin-top:2px;}
  .fg-row{display:flex;flex-direction:column;gap:1px;font-size:12.5px;}
  .fg-label{color:var(--text-faint);font-size:11px;}
  .fg-value{text-align:left;word-break:break-word;}
  .link-chip{display:inline-block;padding:2px 8px;border-radius:12px;background:var(--accent-soft,rgba(99,102,241,.12));color:var(--accent,#6366f1);font-size:11.5px;font-weight:600;white-space:nowrap;text-decoration:none;}
  .link-chip:hover{text-decoration:underline;}

  .checklist-group{display:flex;flex-wrap:wrap;gap:6px 14px;padding:2px 0;}
  .checklist-item{display:flex;align-items:center;gap:6px;font-size:13px;cursor:pointer;}
  .checklist-item input{width:15px;height:15px;accent-color:var(--accent);cursor:pointer;}
  .field-item-checklist .field-help{margin-top:2px;}
  /* Jumlah per jenis subtask (2026-09-28, diminta user: bisa >1 subtask
     sejenis dalam 1 request, mis. 2x CC) -- input angka kecil di samping
     tiap item checklist, cuma aktif kalau item-nya dicentang (wiring di
     openModal(), app.js). Spesifisitas 2-class sengaja dipakai supaya
     menang di atas ".checklist-item input" generik (yang menyasar checkbox)
     tanpa perlu !important. */
  .checklist-item .checklist-qty-input{width:44px;height:auto;padding:2px 4px;font-size:12px;text-align:center;cursor:text;accent-color:initial;}
  .checklist-qty-input:disabled{opacity:.35;cursor:not-allowed;}
  .ro-value{font-size:13px;padding:6px 0;border-bottom:1px dashed var(--border);word-break:break-word;}
  .mono{font-family:var(--font-mono);}
  .form-actions{display:flex;gap:8px;margin-top:14px;}

  .request-block{margin-bottom:16px;padding-bottom:14px;border-bottom:1px dashed var(--border);}
  .cl-warning-note{margin-top:10px;font-size:12px;color:var(--warning);background:var(--warning-soft);border:1px solid var(--warning);border-radius:8px;padding:8px 10px;}
  .cl-lock-note{font-size:11.5px;color:var(--warning);background:var(--warning-soft);border-radius:6px;padding:5px 8px;margin:4px 0 2px;}
  .request-block h4{font-size:12px;text-transform:uppercase;letter-spacing:.03em;color:var(--text-dim);margin:0 0 8px;}
  .request-row{display:grid;grid-template-columns:repeat(auto-fit,minmax(170px,1fr));gap:8px 8px;align-items:start;}
  /* Ronde 30 (2026-09-25) -- tiap tombol Kirim Request sekarang dibungkus
     .request-btn-wrap (tombol + 1 baris keterangan kecil di bawahnya:
     sudah/belum direquest, atau kenapa terkunci). Lihat renderRequestBlock(). */
  .request-btn-wrap{display:flex;flex-direction:column;gap:4px;}
  .request-btn.is-locked{opacity:.55;cursor:not-allowed;}
  .request-btn.is-locked:hover{border-color:var(--border);background:var(--panel-2);transform:none;}
  .req-status-note{font-size:11px;color:var(--text-faint);padding:0 2px;}
  .req-status-note.req-status-done{color:var(--success);}
  /* Blok "Data dari Master (referensi)" + judul "Tugas Tim Konten" di tab
     Konten (2026-09-03, ronde 7) -- reuse gaya heading kecil .request-block
     h4 supaya konsisten, dipisah garis putus-putus dari bagian tugas
     Konten sendiri. Lihat renderKontenMasterContext()/renderKontenTab(). */
  .konten-context-block{margin-bottom:16px;padding-bottom:14px;border-bottom:1px dashed var(--border);}
  .konten-context-block h4, .konten-task-heading{font-size:12px;text-transform:uppercase;letter-spacing:.03em;color:var(--text-dim);margin:0 0 8px;}
  /* "Draft CL Otomatis" (2026-09-26, Ronde 41) -- catatan kecil di atas
     tombol "Buat Draft CL", dipakai modal "Kerjakan Consent Letter" (kolom
     2, lihat .cl-support-columns di bawah) + panel "Kelola Template CL"
     (renderManageClTemplate(), TIDAK ikut dipengaruhi perubahan apa pun di
     bawah ini). */
  .cl-draft-note{font-size:12px;color:var(--text-dim);margin-bottom:10px;line-height:1.5;}

  /* Layout 3 kolom modal "Kerjakan Consent Letter" (Ronde 44, 2026-09-26,
     diminta user: "besarin lagi, terus bagi jadi 3 kolom") -- lihat
     openEditSupportTaskModal() (app.js) utk struktur HTML lengkapnya.
     Kolom 1 (Data dari Supply) + 2 (Draft Otomatis+No Surat) lebar sama,
     kolom 3 (Detail Pengerjaan, isinya 2 field sebaris tiap sub-grup) sedikit
     lebih lebar (fr 1.3) supaya field urlnya tidak terlalu sempit. Turun
     jadi 1 kolom bertumpuk di layar sempit (tablet potrait/HP) -- modal ini
     memang didesain utk layar lebar (opts.xwide, lihat .modal-box-xwide),
     jadi ambang batasnya sengaja lebih tinggi (900px) drpd @media lain di
     file ini (640px) yang biasanya cuma perlu ganti modal biasa. */
  .cl-support-columns{display:grid;grid-template-columns:1fr 1fr 1.3fr;gap:0 22px;margin-bottom:14px;}
  .cl-support-col{padding-left:18px;border-left:1px dashed var(--border);min-width:0;}
  .cl-support-col:first-child{padding-left:0;border-left:none;}
  .cl-support-col h4{font-size:12px;text-transform:uppercase;letter-spacing:.03em;color:var(--text-dim);margin:0 0 10px;}
  .cl-support-col .field-item{margin-bottom:10px;}
  .cl-support-col .field-item:last-child{margin-bottom:0;}
  .cl-support-col-gap{margin-top:14px;}
  /* Sub-grup "Draft CL" / "CL Final Update" di kolom 3 -- dipisah garis
     putus-putus tipis supaya ke-2 tahap kerja (kirim ke partner vs upload
     final) tetap kebaca jelas walau sekarang berdekatan dlm 1 kolom. */
  .cl-support-subgroup{margin-bottom:14px;padding-bottom:14px;border-bottom:1px dashed var(--border);}
  .cl-support-subgroup:last-child{margin-bottom:0;padding-bottom:0;border-bottom:none;}
  .cl-support-subgroup-title{font-size:11px;font-weight:700;color:var(--text-faint);text-transform:uppercase;letter-spacing:.02em;margin-bottom:8px;}
  /* Caption timestamp kecil (Ronde 44) -- lihat tsCaptionHtml() (app.js). */
  .field-ts-caption{font-size:11px;color:var(--text-faint);margin-top:-2px;margin-bottom:8px;}
  .field-ts-caption:last-child{margin-bottom:0;}
  /* Catatan Permintaan (textarea generik) -- SENGAJA di luar 3 kolom, lihat
     komentar di openEditSupportTaskModal(). */
  .cl-support-catatan{padding-top:14px;border-top:1px dashed var(--border);}
  @media (max-width: 900px){
    .cl-support-columns{grid-template-columns:1fr;gap:18px 0;}
    .cl-support-col{padding-left:0;padding-top:14px;border-left:none;border-top:1px dashed var(--border);}
    .cl-support-col:first-child{padding-top:0;border-top:none;}
  }
  .request-btn{display:flex;align-items:center;gap:9px;border:1px solid var(--border);background:var(--panel-2);border-radius:10px;padding:10px 12px;cursor:pointer;font-size:12.5px;font-weight:600;text-align:left;color:var(--text);transition:border-color .12s,background .12s,transform .1s;}
  .request-btn:hover{border-color:var(--amber);background:var(--amber-soft);transform:translateY(-1px);}
  .request-btn-icon{flex-shrink:0;width:26px;height:26px;display:flex;align-items:center;justify-content:center;background:var(--panel);border-radius:8px;font-size:14px;}

  .table-wrap{background:var(--panel);border:1px solid var(--border);border-radius:10px;overflow:hidden;box-shadow:var(--shadow);}
  .table-wrap .tw-head{display:flex;align-items:center;justify-content:space-between;padding:10px 14px;border-bottom:1px solid var(--border);}
  .tw-head h3{font-size:13.5px;}
  table{width:100%;border-collapse:collapse;font-size:12.5px;}
  th,td{padding:9px 12px;text-align:left;border-bottom:1px solid var(--border);white-space:nowrap;}
  th{background:var(--panel-2);color:var(--text-dim);font-weight:600;font-size:11px;text-transform:uppercase;letter-spacing:.03em;position:sticky;top:0;}
  tbody tr{cursor:pointer;}
  tbody tr:hover{background:var(--panel-2);}
  tbody tr.editing-row{background:var(--accent-soft);}
  td.wrap{white-space:normal;max-width:260px;}
  .table-scroll{overflow-x:auto;}
  .cell-muted{color:var(--text-faint);}

  .chip{display:inline-block;padding:2px 9px;border-radius:20px;font-size:11px;font-weight:600;white-space:nowrap;}
  .chip::before{content:'';display:inline-block;width:6px;height:6px;border-radius:50%;background:currentColor;margin-right:5px;vertical-align:middle;opacity:.85;}
  .chip.success{background:var(--success-soft);color:var(--success);}
  .chip.warning{background:var(--warning-soft);color:var(--warning);}
  .chip.critical{background:var(--critical-soft);color:var(--critical);}
  .chip.info{background:var(--info-soft);color:var(--info);}
  .chip.accent{background:var(--accent-soft);color:var(--accent);}
  .chip.neutral{background:var(--neutral-soft);color:var(--neutral);}

  /* ---------- Kanban Tugas Visual (ronde 9) ---------- */
  .kanban-board{display:flex;gap:14px;overflow-x:auto;padding-bottom:6px;align-items:flex-start;}
  .kanban-col{flex:none;width:300px;background:var(--panel-2);border:1px solid var(--border);border-radius:10px;display:flex;flex-direction:column;max-height:calc(100vh - 140px);}
  .kanban-col-head{display:flex;align-items:center;justify-content:space-between;padding:10px 12px;font-size:12.5px;font-weight:600;color:var(--text-dim);border-bottom:1px solid var(--border);position:sticky;top:0;background:var(--panel-2);border-radius:10px 10px 0 0;}
  .kanban-count{background:var(--panel);border:1px solid var(--border);border-radius:20px;padding:1px 8px;font-size:11px;color:var(--text-dim);}
  .kanban-col-body{padding:10px;display:flex;flex-direction:column;gap:10px;overflow-y:auto;}
  .kanban-empty{color:var(--text-faint);font-size:12.5px;padding:8px 2px;}
  .kanban-card{background:var(--panel);border:1px solid var(--border);border-radius:10px;padding:10px 12px;cursor:pointer;transition:box-shadow .12s,border-color .12s;box-shadow:var(--shadow);}
  .kanban-card:hover{border-color:var(--accent);}

  /* ---------- Ringkasan Tim Lain di Data Master (Ronde 29, 2026-09-25) ----------
     Grid kartu ringkas per tim, reuse .kanban-card apa adanya (kartu, hover,
     shadow semua sama) -- cuma layout grid + isi dalamnya yang baru, supaya
     tetap satu bahasa visual dengan kanban card lain di app ini. */
  .team-summary-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));gap:12px;margin-top:6px;}
  .team-summary-card{display:flex;flex-direction:column;gap:2px;}
  .tsc-title{display:flex;align-items:center;gap:6px;}
  .tsc-empty{color:var(--text-faint);font-size:12px;font-style:italic;padding:2px 0;}
  .tsc-hint{font-size:11px;color:var(--text-faint);text-align:right;margin-top:6px;}
  .team-summary-card:hover .tsc-hint{color:var(--accent);font-weight:600;}

  .request-approval-list{display:flex;flex-direction:column;gap:10px;max-width:480px;}
  .request-approval-card{background:var(--panel);border:1px solid var(--border);border-radius:10px;padding:12px 14px;cursor:pointer;transition:border-color .12s,background .12s,transform .1s;box-shadow:var(--shadow);}
  .request-approval-card:hover{border-color:var(--amber);background:var(--amber-soft);transform:translateY(-1px);}
  .request-approval-card.is-revisi{border-color:var(--critical);}
  .request-approval-card.is-revisi:hover{border-color:var(--critical);background:var(--critical-soft);}
  .request-approval-card.is-static{cursor:default;}
  .request-approval-card.is-static:hover{transform:none;}
  .request-approval-cta{margin-top:8px;font-size:12px;font-weight:700;color:var(--amber);}
  .kanban-card-head{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-bottom:6px;}
  .kanban-field{display:flex;justify-content:space-between;gap:8px;padding:3px 0;border-bottom:1px dashed var(--border);font-size:12px;}
  .kanban-field:last-of-type{border-bottom:0;}
  .kanban-field-label{color:var(--text-faint);flex:none;}
  .kanban-field-value{color:var(--text-dim);text-align:right;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:62%;}
  .kanban-card-actions{display:flex;gap:6px;margin-top:9px;flex-wrap:wrap;}
  .kanban-card-actions .btn{flex:1;}
  @media (max-width: 720px){ .kanban-col{width:82vw;} }

  /* Kanban Tugas Visual dipadatkan (2026-09-10, ronde 7, diminta user:
     "terlalu besar, diperkecil, tapi jangan terlalu kecil") -- scoped ke
     .kanban-board-compact (cuma dipasang di renderVisualTasks()) supaya papan
     kanban lain (Pencairan Utama, Review Approval, dst, style sama) tidak
     ikut berubah karena tidak diminta. */
  .kanban-board-compact{gap:10px;}
  /* Ronde 45 (2026-09-26, diminta user): kolom 260px kena kepotong -- chip
     status seperti "Terkirim ke Partner" nembus keluar kartu. Dilebarkan +
     card-head dikasih flex-wrap supaya judul panjang & chip tidak pernah
     saling menimpa lagi, seberapa pun panjang teksnya. */
  .kanban-board-compact .kanban-col{width:300px;max-height:calc(100vh - 150px);}
  .kanban-board-compact .kanban-col-head{padding:7px 10px;font-size:11.5px;}
  .kanban-board-compact .kanban-col-body{padding:7px;gap:7px;}
  .kanban-board-compact .kanban-card{padding:7px 9px;border-radius:8px;}
  .kanban-board-compact .kanban-card-head{margin-bottom:4px;gap:6px;flex-wrap:wrap;}
  .kanban-board-compact .kanban-card-head .list-primary{font-size:12.5px;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1 1 auto;}
  .kanban-board-compact .kanban-card-head .chip{padding:1px 7px;font-size:10px;flex:none;}
  .kanban-board-compact .kanban-field{padding:2px 0;font-size:11px;}
  .kanban-board-compact .kanban-card-actions{margin-top:6px;gap:4px;}
  .kanban-board-compact .kanban-card-actions .btn{font-size:11px;padding:5px 6px;}
  @media (max-width: 720px){ .kanban-board-compact .kanban-col{width:78vw;} }

  /* Kartu kanban Tugas Visual disederhanakan drastis (2026-09-10, ronde 8,
     diminta user lewat mockup: cuma judul + badge Subtask Type, TANPA status
     chip/baris field/tombol) -- lihat renderVisualTaskCard() di app.js. */
  .visual-task-wrap{overflow-x:auto;background:var(--panel);border:1px solid var(--border);border-radius:10px;box-shadow:var(--shadow);}
  .visual-task-table{width:100%;border-collapse:collapse;font-size:12.5px;}
  .visual-task-table th{text-align:left;padding:10px 12px;font-size:11.5px;font-weight:700;color:var(--text-faint);border-bottom:1px solid var(--border);white-space:nowrap;}
  .visual-task-table td{padding:10px 12px;border-bottom:1px solid var(--border);vertical-align:top;}
  .visual-task-table tr:last-child td{border-bottom:none;}
  .visual-task-link-cell{font-weight:700;white-space:nowrap;}
  .visual-task-row{cursor:pointer;transition:background .12s;}
  .visual-task-row:hover{background:var(--panel-2);}
  .visual-task-count-cell{white-space:nowrap;font-size:11.5px;font-weight:600;color:var(--text-faint);}
  .visual-task-masuk-cell{white-space:nowrap;font-size:11.5px;color:var(--text-faint);}
  .visual-modal-topbar-side{display:flex;justify-content:flex-end;margin-bottom:14px;}
  .visual-modal-checklist-heading{font-size:12.5px;font-weight:700;color:var(--text-faint);margin:16px 0 8px;}
  .visual-modal-checklist{display:flex;flex-direction:column;gap:4px;}
  .visual-checklist-row{display:flex;align-items:center;gap:10px;padding:7px 8px;border-radius:8px;background:var(--panel-2);border:1px solid var(--border);}
  .visual-checklist-row.is-done{opacity:.65;}
  .visual-checklist-box{flex:none;width:20px;font-size:16px;line-height:1;cursor:pointer;color:var(--text-faint);}
  .visual-checklist-box.is-done{cursor:default;color:var(--success);}
  .visual-checklist-label{flex:1;font-size:12.5px;font-weight:600;color:var(--text);cursor:pointer;}
  .visual-checklist-label:hover{text-decoration:underline;color:var(--accent);}
  .kanban-card.kanban-card-mini{display:flex;align-items:center;justify-content:space-between;gap:10px;}
  .kanban-card-mini-title{font-size:12.5px;font-weight:600;color:var(--text);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
  .kanban-card-mini-badge{flex:none;border-radius:6px;padding:2px 8px;font-size:11px;font-weight:600;}
  .kanban-card-mini-badge.success{background:var(--success-soft);color:var(--success);}
  .kanban-card-mini-badge.warning{background:var(--warning-soft);color:var(--warning);}
  .kanban-card-mini-badge.critical{background:var(--critical-soft);color:var(--critical);}
  .kanban-card-mini-badge.info{background:var(--info-soft);color:var(--info);}
  .kanban-card-mini-badge.accent{background:var(--accent-soft);color:var(--accent);}
  .kanban-card-mini-badge.neutral{background:var(--neutral-soft);color:var(--neutral);}

  /* ---------- Tugas Pencairan Utama, flat list (ronde 11) ---------- */
  .pencairan-task-list{display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:12px;}
  .overdue-pencairan-card{border-left:4px solid var(--warning);}
  .overdue-pencairan-note{font-size:12px;color:var(--warning);margin-top:6px;}

  /* ---------- Dashboard ---------- */
  .dash-search{max-width:320px;margin-bottom:14px;}
  .stat-row{display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:10px;margin-bottom:18px;}
  .stat-card{background:var(--panel);border:1px solid var(--border);border-top:3px solid var(--accent);border-radius:10px;padding:12px 14px;box-shadow:var(--shadow);transition:transform .12s,box-shadow .12s;}
  .stat-card:hover{transform:translateY(-2px);box-shadow:0 4px 10px rgba(30,28,25,.10),0 16px 32px -16px rgba(30,28,25,.22);}
  /* Aksen gantian pink/navy per kartu dalam 1 baris (2026-09-09) -- murni
     visual, tidak butuh perubahan JS karena diatur lewat urutan anak. */
  .stat-row .stat-card:nth-child(even){border-top-color:var(--accent-2);}
  .stat-card .sc-label{font-size:11px;color:var(--text-faint);text-transform:uppercase;letter-spacing:.03em;}
  .stat-card .sc-value{font-family:var(--font-mono);font-size:19px;font-weight:600;margin-top:2px;}
  .stat-card-critical{border-color:var(--critical);background:var(--critical-soft);}
  .stat-card-critical .sc-value{color:var(--critical);}
  .stat-row .stat-card.stat-card-critical{border-top-color:var(--critical);}
  .dash-section{margin:24px 0 10px;color:var(--accent-2);}
  .dash-subhead{font-size:12px;font-weight:600;color:var(--text-dim);text-transform:uppercase;letter-spacing:.03em;margin:16px 0 8px;}

  /* ---------- "Semua hal bisa diklik" di Dashboard (2026-09-26, item 3) ----------
     Kartu statistik & angka rekap yang sekarang bisa diklik utk buka daftar
     campaign terkait (lihat statCard()/clmCell()/openCampaignListModal() di
     app.js) dikasih penanda visual jelas: cursor pointer + label kecil
     "klik utk detail" yang muncul pas di-hover, supaya user tahu ini
     BEDA dari kartu statis biasa tanpa perlu coba klik dulu. */
  .stat-card-clickable{cursor:pointer;position:relative;}
  .stat-card-clickable::after{content:'Klik utk detail →';position:absolute;right:14px;bottom:8px;font-size:9.5px;color:var(--accent);opacity:0;transition:opacity .12s;}
  .stat-card-clickable:hover::after{opacity:1;}
  .stat-card-clickable:hover{border-color:var(--accent);}
  .clm-link{color:var(--accent-2);cursor:pointer;text-decoration:underline;text-decoration-style:dotted;text-underline-offset:2px;}
  .clm-link:hover{color:var(--accent);text-decoration-style:solid;}

  /* Modal "Daftar Campaign" generik -- openCampaignListModal() di app.js. */
  .clm-body{max-height:56vh;overflow-y:auto;display:flex;flex-direction:column;gap:8px;margin:12px 0;padding-right:2px;}
  .clm-row{display:flex;align-items:center;justify-content:space-between;gap:10px;background:var(--panel-2);border:1px solid var(--border);border-radius:9px;padding:9px 12px;cursor:pointer;transition:border-color .12s,background .12s;}
  .clm-row:hover{border-color:var(--accent);background:var(--accent-soft);}
  .clm-row-main{display:flex;flex-direction:column;gap:2px;min-width:0;}
  .clm-row-sub{font-size:11.5px;color:var(--text-faint);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}

  /* Task Macet/CL Macet/Seharusnya Pencairan (2026-09-26, item 5, diminta
     user: "jangan dibuat tampil semuanya, buat dropdown saja atau buat pop
     up") -- <details>/<summary> native, default tertutup. Summary distyle
     supaya terlihat jelas sebagai tombol yang bisa diklik (bukan teks biasa),
     dengan sedikit border/background biar tidak polos. */
  .dash-collapsible{margin:4px 0 16px;}
  .dash-collapsible summary{cursor:pointer;list-style:none;font-size:13px;font-weight:600;color:var(--accent-2);background:var(--panel-2);border:1px solid var(--border);border-radius:9px;padding:9px 14px;user-select:none;}
  .dash-collapsible summary::-webkit-details-marker{display:none;}
  .dash-collapsible summary::before{content:'▸ ';display:inline-block;transition:transform .12s;}
  .dash-collapsible[open] summary::before{transform:rotate(90deg);}
  .dash-collapsible[open] summary{border-radius:9px 9px 0 0;border-bottom:0;}
  .dash-collapsible .table-wrap{margin-top:0;border-top:0;border-top-left-radius:0;border-top-right-radius:0;}
  .dash-collapsible summary:hover{border-color:var(--accent);}

  /* Panel "Atur Akses Menu" (2026-09-26, item 1) -- renderMenuPermissions(). */
  .menuperm-role{background:var(--panel);border:1px solid var(--border);border-radius:10px;padding:14px 16px;margin-bottom:14px;box-shadow:var(--shadow);}
  .menuperm-role h4{margin:0 0 10px;color:var(--accent-2);}
  .menuperm-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:8px 16px;}
  .menuperm-item{display:flex;align-items:center;gap:8px;font-size:13px;cursor:pointer;padding:4px 0;}
  .menuperm-item input{width:16px;height:16px;cursor:pointer;flex:none;}
  /* Modal pemetaan kolom import Excel (2026-09-07) */
  .import-map-list{max-height:50vh;overflow-y:auto;display:flex;flex-direction:column;gap:8px;margin:12px 0;padding-right:4px;}
  .import-map-row{display:flex;align-items:center;gap:12px;}
  .import-map-row label{flex:0 0 190px;font-size:13px;color:var(--text-dim);}
  .import-map-row select, .import-map-row input{flex:1;min-width:0;}
  /* Modal Pratinjau Import (ronde 10, 2026-09-10, diminta user: "kasih
     pilihan baris ini mau di import atau tidak") -- toolbar Pilih
     Semua/Batal Semua + tabel baris dgn checkbox per baris. */
  .import-preview-toolbar{display:flex;align-items:center;gap:8px;margin:10px 0;}
  .import-preview-count{margin-left:auto;font-size:12px;color:var(--text-dim);}
  .import-preview-list{max-height:45vh;overflow-y:auto;overflow-x:auto;border:1px solid var(--border);border-radius:10px;margin-bottom:14px;}
  .import-preview-table{width:100%;border-collapse:collapse;font-size:12.5px;}
  .import-preview-table th{position:sticky;top:0;background:var(--panel-2);padding:7px 8px;text-align:left;font-size:11px;color:var(--text-dim);font-weight:600;border-bottom:1px solid var(--border);}
  .import-preview-table td{padding:6px 8px;border-bottom:1px solid var(--border);color:var(--text-dim);vertical-align:middle;}
  .import-preview-table tr:last-child td{border-bottom:none;}
  .import-preview-cell-link{max-width:220px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
  .req-mark{color:var(--critical);}

  /* ---------- Modal ---------- */
  .modal-overlay{position:fixed;inset:0;background:rgba(20,18,16,.45);display:none;align-items:center;justify-content:center;z-index:80;padding:20px;}
  .modal-overlay.open{display:flex;}
  .modal-box{background:var(--panel);border-radius:12px;width:100%;max-width:460px;max-height:88vh;overflow-y:auto;padding:22px;box-shadow:var(--shadow);}
  .modal-box.modal-box-wide{max-width:700px;}
  /* modal-box-xwide (Ronde 44, 2026-09-26, redesign popup "Kerjakan Consent
     Letter", diminta user: "besarin lagi") -- EXTRA lebar drpd
     modal-box-wide, dipakai modal dgn layout custom sepenuhnya (bukan
     field-grid 2 kolom otomatis) -- lihat opts.xwide di openModal()
     (app.js) + .cl-support-columns di bawah. */
  .modal-box.modal-box-xwide{max-width:980px;}
  .field-grid.field-grid-2col{display:grid;grid-template-columns:1fr 1fr;gap:4px 18px;}
  /* Field yang butuh selebar 2 kolom (textarea, checklist, pemisah section)
     dilebarkan lewat grid-column, sisanya (select/input biasa) natural 1
     kolom -- lihat field-item-wide di fieldInputHtml() (app.js). */
  .field-grid-2col .field-item-wide,
  .field-grid-2col .field-item-checklist,
  .field-grid-2col .field-section-header{grid-column:1/-1;}
  @media (max-width: 640px){
    .modal-box.modal-box-wide{max-width:94vw;}
    .modal-box.modal-box-xwide{max-width:96vw;}
    .field-grid.field-grid-2col{grid-template-columns:1fr;}
  }
  .modal-box h3{font-size:16px;margin-bottom:2px;}
  .modal-sub{font-size:12.5px;color:var(--text-dim);margin-bottom:14px;}
  .modal-actions{display:flex;justify-content:flex-end;gap:8px;margin-top:16px;}
  /* opts.hideActions (ronde 10) -- dipakai openEditVisualTaskModal() yang
     pindahkan tombol aksi ke topbar atas, jadi modal-actions bawaan di
     bawah (Batal+submit) disembunyikan supaya tidak dobel. */
  .modal-hide-actions .modal-actions{display:none;}
  /* Topbar tombol aksi di ATAS modal (ronde 10, 2026-09-10, diminta user
     "mulai dikerjakannya diletak dibagian atasnya") -- dipakai
     openEditVisualTaskModal(), disisipkan lewat extraHtml sebelum field-grid. */
  .visual-modal-topbar{display:flex;gap:8px;margin-bottom:14px;}
  .visual-modal-topbar .btn{flex:1;}
  .visual-modal-topbar #visualTopCancelBtn{flex:none;padding-left:18px;padding-right:18px;}
  /* Info read-only label+value SEBARIS, bukan bertumpuk ke bawah (ronde 10,
     2026-09-10, diminta user "ubah ke samping saja") -- dipakai
     openEditVisualTaskModal() lewat class tambahan di field-grid, TIDAK
     memengaruhi field-grid/.ro-value di tempat lain (Data Master, tab
     Konten, dst -- itu semua tetap layout lama). Textarea (Catatan
     Permintaan, field-item-wide) dikecualikan -- tetap label-diatas-value
     supaya teks panjang tidak sempit. */
  .visual-info-compact .field-item{display:flex;flex-direction:row;align-items:center;justify-content:space-between;gap:10px;padding:6px 0;border-bottom:1px dashed var(--border);}
  .visual-info-compact .field-item label{margin:0;flex:none;font-size:11.5px;color:var(--text-dim);font-weight:600;}
  .visual-info-compact .field-item .ro-value{flex:1;min-width:0;text-align:right;padding:0;border-bottom:none;font-size:13px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
  .visual-info-compact .field-item.field-item-wide{flex-direction:column;align-items:stretch;}
  .visual-info-compact .field-item.field-item-wide .ro-value{text-align:left;white-space:normal;overflow:visible;text-overflow:clip;}

  /* ---------- Toast ---------- */
  .toast{position:fixed;bottom:22px;left:50%;transform:translateX(-50%) translateY(20px);background:var(--text);color:var(--bg);padding:10px 18px;border-radius:8px;font-size:13px;opacity:0;pointer-events:none;transition:opacity .2s, transform .2s;z-index:100;}
  .toast.show{opacity:1;transform:translateX(-50%) translateY(0);}

  .loading-note{color:var(--text-faint);font-size:12.5px;padding:20px 0;}

  /* ---------- Tampilan Yayasan (tanpa login, ?yl=<token>) ---------- */
  /* (2026-09-25, diminta user) -- sidebar SPA biasa disembunyikan total di
     mode ini (lihat enterYayasanView() di app.js), diganti header sendiri
     di dalam #main (.yayasan-header) supaya halaman ini tidak terlihat
     seperti dashboard internal yang "kurang lengkap", tapi tampilan
     tersendiri yang memang dibuat khusus untuk partner. */
  body.yayasan-mode .sidebar{display:none;}
  .yayasan-header{padding-bottom:16px;margin-bottom:16px;border-bottom:1px solid var(--border);}
  .yayasan-partner-name{font-family:var(--font-display);font-size:20px;font-weight:700;margin:4px 0 6px;}
  /* 2 tab "Daftar Campaign"/"Approval" (2026-09-25, ronde 37, diminta user:
     tampilan yayasan disederhanakan jadi list + tab Approval terpisah,
     bukan lagi drill-down ke Data Master lengkap) -- reuse class .btn/
     .btn-primary/.btn-ghost yang sudah ada, tidak perlu style tombol baru. */
  .yayasan-tabs{display:flex;gap:8px;margin-bottom:16px;}

  /* Subtab "Tugas Consent Letter" (2026-09-26, koreksi user atas Ronde 41) --
     dipakai renderSupportTasksHome() buat tombol "Semua Tugas CL"/"CL Belum
     Balik". Pola sama dengan .yayasan-tabs di atas, cuma nama class generik
     karena dipakai halaman lain juga kalau perlu nanti. */
  .subtab-row{display:flex;gap:8px;margin-bottom:16px;flex-wrap:wrap;}

  /* ---------- Riwayat Perubahan (Superadmin, 2026-09-25) ---------- */
  /* Awalnya cuma judul tanggal polos + bullet list bawaan browser. Ronde 40
     (2026-09-26, diminta user: "UI/UX-nya terlalu biasa dan simpel... coba
     dibuat lebih bagus") -- dirombak jadi tampilan timeline vertikal:
     garis+dot gradient accent di kiri per tanggal, tiap grup jadi kartu
     (border+shadow, konsisten .table-wrap dkk), badge "Terbaru" utk grup
     paling atas, badge jumlah pembaruan, bullet custom ikon centang
     pengganti bullet bawaan. */
  .changelog-search{max-width:420px;margin-bottom:20px;}
  /* Ronde 47 (2026-09-26, diminta user: "dibuat kolom kolom aja pertanggal,
     nanti pas diklik baru muncul pop up detailnya") -- ganti timeline
     (semua poin langsung tampil, panjang ke bawah) jadi GRID kartu ringkas
     per tanggal; poin lengkapnya baru muncul di modal popup begitu
     kartunya diklik (lihat openChangelogDetail() di app.js). .changelog-items
     dipakai ulang di DALAM modal popup itu (bukan lagi di halaman utama). */
  .changelog-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(190px,1fr));gap:12px;}
  .changelog-tile{position:relative;background:var(--panel);border:1px solid var(--border);border-radius:var(--radius);box-shadow:var(--shadow);padding:16px 18px;text-align:left;cursor:pointer;font:inherit;color:inherit;transition:border-color .12s ease, transform .12s ease;}
  .changelog-tile:hover{border-color:var(--accent);transform:translateY(-1px);}
  .changelog-tile-latest{border-color:var(--accent);box-shadow:0 1px 2px rgba(235,38,119,.08), 0 8px 24px -14px rgba(235,38,119,.35);}
  .changelog-tile-date{font-family:var(--font-display);font-size:14.5px;font-weight:700;margin-bottom:4px;padding-right:56px;}
  .changelog-tile-count{font-size:11.5px;color:var(--text-faint);font-weight:500;}
  .changelog-badge-latest{position:absolute;top:14px;right:14px;background:var(--accent);color:var(--accent-ink);font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.03em;padding:2.5px 9px;border-radius:999px;}
  .changelog-items{list-style:none;margin:0;padding:0;}
  .changelog-items li{display:flex;align-items:flex-start;gap:8px;padding:7px 0;line-height:1.5;color:var(--text);}
  .changelog-items li:not(:last-child){border-bottom:1px dashed var(--border);}
  .changelog-item-icon{flex:none;margin-top:2px;color:var(--success);}
  .changelog-empty{padding:22px 4px;}

  /* ---------- Banner "Login as" (2026-09-25) ---------- */
  /* #impersonationBar sendiri SENGAJA tidak diberi `display` di sini --
     supaya atribut `hidden` bawaan browser (display:none) tetap berlaku
     tanpa perlu diadu specificity-nya; layout flex dipasang di div
     `.impersonation-bar-inner` di DALAMNYA (lihat renderImpersonationBar()
     di app.js), sama pola dgn .gate-quote-panel/.side-foot-new-campaign. */
  .impersonation-bar{background:var(--accent-2);color:var(--accent-2-ink);}
  .impersonation-bar-inner{display:flex;align-items:center;justify-content:center;gap:12px;flex-wrap:wrap;padding:8px 16px;font-size:12.5px;}
  .impersonation-bar-inner svg{flex:none;}
  .impersonation-bar-inner .btn{flex:none;background:#fff;color:var(--accent-2);border:none;font-weight:600;}
  .impersonation-bar-inner .btn:hover{filter:brightness(0.96);}
