/* ============================================================
   Dashboard Live v2 — token dari DESIGN-apple.md
   Aksen diganti hijau per keputusan 2026-07-21 (khusus Sell-In).
   ============================================================ */
:root{
  /* --brand dipakai untuk chart & fill besar  -> kontras 3,38:1 (lolos 3:1 grafis)
     --brand-strong untuk teks/tombol/link/focus -> kontras 4,64:1 (lolos AA 4,5:1) */
  --brand:#4A9E24;
  --brand-strong:#3E8420;
  --brand-wash:rgba(74,158,36,.08);
  /* Sorotan tombol Apply saat filter berubah. Dijadikan token
     karena dulu ditulis keras hijau — akibatnya filter bar di
     Sell-Through tetap menyala hijau padahal temanya navy. */
  --brand-glow:rgba(74,158,36,.22);

  --ink:#1d1d1f;
  --ink-muted-80:#333333;
  --ink-secondary:#6e6e73;
  --ink-muted-48:#7a7a7a;

  --canvas:#ffffff;
  --parchment:#f5f5f7;
  --pearl:#fafafc;
  --black:#000000;

  --hairline:#e0e0e0;
  --divider-soft:#f0f0f0;

  --pos:#1d7a3e;
  --neg:#c4281c;

  --r-sm:8px; --r-md:11px; --r-lg:18px; --r-pill:9999px;
  --s-xxs:4px; --s-xs:8px; --s-sm:12px; --s-md:17px;
  --s-lg:24px; --s-xl:32px; --s-xxl:48px;
  --nav-h:44px; --subnav-h:52px;
  --ease:cubic-bezier(.4,0,.2,1);
}

*{box-sizing:border-box}
html,body{margin:0;padding:0}
body{
  font-family:system-ui,-apple-system,"SF Pro Text","Inter",BlinkMacSystemFont,sans-serif;
  background:var(--parchment);color:var(--ink);
  -webkit-font-smoothing:antialiased;font-size:14px;
}
.num,.kpi-val,.tbl td,.tbl th.num,.btn-count{
  font-variant-numeric:tabular-nums;font-feature-settings:"tnum";
}

/* ---------- 1-2. Nav ----------
   Bar hitam global dihapus; sub-nav naik ke atas jadi satu-satunya chrome.
   Judul halaman + tab + aksi semuanya di satu baris 52px. */
.tbl-wrap{max-height:calc(100vh - 210px)}   /* tanpa bar hitam, ruangnya bertambah */
.sub-nav{
  height:var(--subnav-h);
  background:rgba(245,245,247,.82);
  -webkit-backdrop-filter:saturate(180%) blur(20px);
  backdrop-filter:saturate(180%) blur(20px);
  border-bottom:1px solid var(--hairline);
  display:flex;align-items:center;gap:var(--s-xs);
  padding:0 var(--s-lg);position:sticky;top:0;z-index:99;
}
.nav-meta{
  font-size:12px;color:var(--ink-secondary);letter-spacing:-.12px;
  margin-left:auto;padding-right:var(--s-xs);white-space:nowrap;
}
.sub-nav .page-name{
  font-size:21px;font-weight:600;letter-spacing:.231px;
  margin-right:var(--s-lg);white-space:nowrap;
}
.tabs{display:flex;gap:2px}
.tab{
  appearance:none;border:0;background:transparent;font:inherit;
  font-size:14px;letter-spacing:-.224px;color:var(--ink-secondary);
  padding:8px 16px;border-radius:var(--r-pill);cursor:pointer;
  transition:background 200ms var(--ease),color 200ms var(--ease);
  min-height:36px;white-space:nowrap;
}
.tab:hover:not([aria-selected="true"]):not([disabled]){
  background:rgba(0,0,0,.045);color:var(--ink);
}
/* Halaman aktif dibuat tegas: pil hijau penuh, bukan sekadar teks tebal.
   Warna aksen di sini menyatakan STATUS (di mana saya berada), bukan hiasan. */
.tab[aria-selected="true"]{
  background:var(--brand-strong);color:#fff;font-weight:600;
}
.tab[disabled]{opacity:.4;cursor:not-allowed}
.tab:focus-visible{outline:2px solid var(--brand-strong);outline-offset:2px}
.tab:active:not([aria-selected="true"]){transform:scale(.96)}

/* ---------- 3. Tombol ---------- */
.btn{
  appearance:none;font:inherit;cursor:pointer;
  display:inline-flex;align-items:center;justify-content:center;gap:6px;
  transition:background 200ms var(--ease),transform 120ms,border-color 200ms;
}
.btn:active{transform:scale(.95)}
.btn:focus-visible{outline:2px solid var(--brand-strong);outline-offset:2px}
.btn[disabled]{opacity:.45;cursor:not-allowed}
.btn-pill{
  background:var(--brand-strong);color:#fff;border:0;border-radius:var(--r-pill);
  padding:9px 20px;font-size:14px;letter-spacing:-.224px;min-height:36px;
}
.btn-pill:hover:not([disabled]){background:#357017}
.btn-ghost-pill{
  background:transparent;color:var(--brand-strong);border:1px solid var(--brand-strong);
  border-radius:var(--r-pill);padding:8px 20px;font-size:14px;
  letter-spacing:-.224px;min-height:36px;
}
.btn-ghost-pill:hover{background:var(--brand-wash)}
.btn-utility{
  background:var(--canvas);color:var(--ink-muted-80);border:1px solid var(--hairline);
  border-radius:var(--r-sm);width:36px;height:36px;padding:0;
}
.btn-utility:hover{background:var(--pearl)}
.btn-utility svg{width:16px;height:16px;stroke:currentColor;fill:none;
  stroke-width:1.75;stroke-linecap:round;stroke-linejoin:round}
.btn-count{
  background:#fff;color:var(--brand-strong);border-radius:var(--r-pill);
  font-size:11px;font-weight:700;line-height:1;padding:3px 6px;margin-left:2px;
}

/* ---------- 4. Filter bar yang bisa ditekan ---------- */
/* Tata letak: satu baris kontrol (dropdown kiri, aksi kanan), chip di bawahnya. */
.filter-bar{
  position:relative;
  padding:var(--s-sm) var(--s-lg);
  background:var(--parchment);border-bottom:1px solid var(--divider-soft);
}
.fbar-row{
  display:flex;align-items:center;gap:var(--s-sm);
}
/* Satu baris di desktop; baru membungkus kalau layar benar-benar sempit. */
.fbar-drops{
  display:flex;flex-wrap:wrap;gap:6px;flex:1;min-width:0;
}
.fbar-actions{
  display:flex;align-items:center;gap:var(--s-xs);flex:none;
  /* sejajar dengan baris pertama dropdown walau dropdown-nya membungkus */
  padding-left:var(--s-xs);
  border-left:1px solid var(--hairline);
}
/* Ada perubahan yang belum diterapkan — tegaskan tombol Apply. */
.filter-bar.is-dirty [data-apply]{box-shadow:0 0 0 3px var(--brand-glow)}
.btn-ghost-neutral{
  background:transparent;color:var(--ink-secondary);
  border:1px solid var(--hairline);border-radius:var(--r-pill);
  padding:8px 16px;font-size:13px;letter-spacing:-.224px;min-height:36px;
}
.btn-ghost-neutral:hover{background:var(--canvas);color:var(--ink)}
.filter-bar .lead{
  font-size:12px;color:var(--ink-secondary);letter-spacing:-.12px;margin-right:var(--s-xxs);
}
.fdrop{position:relative}
.fbtn{
  appearance:none;font:inherit;cursor:pointer;
  display:inline-flex;align-items:center;gap:6px;
  background:var(--canvas);border:1px solid var(--hairline);
  border-radius:var(--r-pill);padding:6px 12px;min-height:34px;
  font-size:13px;letter-spacing:-.224px;color:var(--ink);white-space:nowrap;
  transition:border-color 200ms var(--ease),background 200ms var(--ease);
}
/* nilai terpilih dipotong kalau kepanjangan, supaya baris tidak melebar */
.fbtn .v{max-width:160px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.fbtn .v[hidden]{display:none}
.fbtn:hover{background:var(--pearl)}
.fbtn:focus-visible{outline:2px solid var(--brand-strong);outline-offset:2px}
.fbtn[aria-expanded="true"]{border-color:var(--brand-strong)}
.fbtn.has-value{border-color:var(--brand-strong);background:var(--brand-wash)}
.fbtn .k{color:var(--ink-secondary)}
.fbtn .v{font-weight:600}
.fbtn .chev{width:12px;height:12px;stroke:var(--ink-secondary);fill:none;
  stroke-width:2;stroke-linecap:round;stroke-linejoin:round;transition:transform 200ms var(--ease)}
.fbtn[aria-expanded="true"] .chev{transform:rotate(180deg)}

.fpop{
  position:absolute;top:calc(100% + 6px);left:0;z-index:120;
  width:max-content;min-width:280px;max-width:420px;
  background:var(--canvas);border:1px solid var(--hairline);
  border-radius:var(--r-md);padding:var(--s-xs);
  display:flex;flex-direction:column;max-height:400px;
  /* satu-satunya bayangan di sistem ini: popover butuh terangkat dari konten */
  box-shadow:0 8px 30px rgba(0,0,0,.12);
}
.fpop[hidden]{display:none}

/* --- pencarian di dalam popover --- */
.fsearch{padding:2px 2px 8px;flex:none}
.fsearch input{
  width:100%;font:inherit;font-size:13px;letter-spacing:-.224px;color:var(--ink);
  background:var(--parchment);border:1px solid transparent;
  border-radius:var(--r-pill);padding:8px 14px;min-height:36px;
}
.fsearch input:focus{outline:2px solid var(--brand-strong);outline-offset:-1px;
  background:var(--canvas);border-color:var(--hairline)}

/* --- pohon --- */
.ftree{overflow:auto;flex:1;min-height:0}
.tnode{display:flex;align-items:center;gap:2px}
.tchev{
  appearance:none;border:0;background:transparent;cursor:pointer;padding:0;
  width:22px;height:32px;flex:none;color:var(--ink-secondary);
  display:inline-flex;align-items:center;justify-content:center;
  transition:transform 180ms var(--ease);
}
.tchev:hover{color:var(--ink)}
.tchev:focus-visible{outline:2px solid var(--brand-strong);outline-offset:-2px;border-radius:4px}
.tchev svg{width:14px;height:14px;stroke:currentColor;fill:none;stroke-width:2;
  stroke-linecap:round;stroke-linejoin:round;transition:transform 180ms var(--ease)}
.tchev.open svg{transform:rotate(180deg)}
.tchev-spacer{width:22px;flex:none}
.topt{
  display:flex;align-items:center;gap:9px;flex:1;min-width:0;
  appearance:none;border:0;background:transparent;font:inherit;
  font-size:13px;letter-spacing:-.224px;color:var(--ink);
  padding:6px 8px;border-radius:var(--r-sm);cursor:pointer;text-align:left;
  min-height:32px;
}
.topt:hover{background:var(--parchment)}
.topt:focus-visible{outline:2px solid var(--brand-strong);outline-offset:-2px}
.topt .tlabel{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.topt .box{
  width:17px;height:17px;flex:none;border-radius:5px;
  border:1.5px solid var(--hairline);
  display:inline-flex;align-items:center;justify-content:center;
}
.topt[aria-checked="true"] .box{background:var(--brand-strong);border-color:var(--brand-strong)}
.topt .box svg{width:11px;height:11px;stroke:#fff;fill:none;stroke-width:3;
  stroke-linecap:round;stroke-linejoin:round;opacity:0}
.topt[aria-checked="true"] .box svg{opacity:1}
/* tercakup oleh pilihan induk: terlihat tercentang tapi tidak bisa diubah */
.topt[data-implied]{cursor:default;color:var(--ink-secondary)}
.topt[data-implied] .box{background:var(--ink-secondary);border-color:var(--ink-secondary);opacity:.45}
.topt[data-implied]:hover{background:transparent}
.fempty{padding:14px 10px;color:var(--ink-secondary);font-size:13px}
.fpop-foot{
  display:flex;gap:var(--s-xs);padding:var(--s-xs) 10px 4px;flex:none;
  border-top:1px solid var(--divider-soft);margin-top:var(--s-xxs);
}

/* Baris chip dihapus — tombol filter sendiri sudah menunjukkan pilihan aktif,
   dan barisnya cuma mendorong chart turun. Reset mengosongkan semuanya. */
.link-btn{
  appearance:none;border:0;background:none;font:inherit;cursor:pointer;
  font-size:13px;color:var(--brand-strong);letter-spacing:-.224px;padding:6px 2px;
}
.link-btn:hover{text-decoration:underline}

/* ---------- 5. Layout ---------- */
main{padding:var(--s-xl) var(--s-lg) var(--s-xxl)}
.kpi-strip{display:grid;grid-template-columns:repeat(4,1fr);gap:var(--s-sm);margin-bottom:var(--s-lg)}
.kpi{background:var(--canvas);border:1px solid var(--hairline);
  border-radius:var(--r-lg);padding:var(--s-md) var(--s-lg)}
.kpi-head{display:flex;align-items:center;gap:7px;margin-bottom:6px}
/* Ikon dibuat redup: penanda cepat, bukan yang harus dibaca lebih dulu. */
.kpi-ico{
  width:22px;height:22px;flex:none;border-radius:var(--r-sm);
  display:inline-flex;align-items:center;justify-content:center;
  background:var(--parchment);color:var(--ink-secondary);
}
.kpi-ico svg{width:13px;height:13px;stroke:currentColor;fill:none;stroke-width:1.9;
  stroke-linecap:round;stroke-linejoin:round}
.kpi-lbl{font-size:12px;letter-spacing:-.12px;color:var(--ink-secondary)}

/* Angka MTD mengikuti ambang pencapaian yang sama dengan gauge; Retur selalu
   merah karena selalu mengurangi. Ikonnya ikut berwarna supaya satu isyarat. */
.kpi-val.is-ach-hijau{color:#3E8420}
.kpi-val.is-ach-kuning{color:#8A5A00}
.kpi-val.is-ach-merah{color:#C4281C}
.kpi-val.is-retur{color:#C4281C}
.kpi.tone-hijau  .kpi-ico{background:rgba(74,158,36,.12);color:#3E8420}
.kpi.tone-kuning .kpi-ico{background:rgba(245,165,36,.14);color:#8A5A00}
.kpi.tone-merah  .kpi-ico{background:rgba(229,72,77,.12);color:#C4281C}
.kpi.tone-retur  .kpi-ico{background:rgba(229,72,77,.10);color:#C4281C}
/* Rupiah ditulis penuh (mis. Rp36.389.421.000 = 16 karakter), jadi ukuran
   display 34px dari DESIGN-apple.md tidak muat di kartu selebar 1/4.
   clamp menjaga angka tetap satu baris di semua lebar layar. */
.kpi-val{
  font-size:clamp(17px,1.62vw,26px);
  font-weight:600;line-height:1.15;letter-spacing:-.374px;white-space:nowrap;
}
.kpi-sub{display:flex;align-items:center;gap:5px;margin-top:6px;flex-wrap:wrap;
  font-size:12px;letter-spacing:-.12px;color:var(--ink-secondary)}
.delta{display:inline-flex;align-items:center;gap:3px;font-weight:600}
.delta.up{color:var(--pos)} .delta.down{color:var(--neg)}
.delta svg{width:11px;height:11px;stroke:currentColor;stroke-width:2.5;fill:none;
  stroke-linecap:round;stroke-linejoin:round}

/* Kanvas 20 x 10 */
.grid{
  display:grid;grid-template-columns:2fr 1fr 1fr;grid-template-rows:1fr 1fr;
  gap:var(--s-sm);aspect-ratio:2 / 1;
}
.cell-line { grid-column:1;          grid-row:1 / span 2 }
.cell-gauge{ grid-column:2;          grid-row:1 }
.cell-donut{ grid-column:3;          grid-row:1 }
.cell-bar  { grid-column:2 / span 2; grid-row:2 }

/* ------------------------------------------------------------
   Trend — kanvas 20 x 10
     ┌──────────────────────────┬──────────────┐
     │ Sell-In PO/Invoice/Target│ Group Status │
     │          14 x 6          │    6 x 5     │
     ├──────────────────────────┼──────────────┤
     │ Rasio Retur   14 x 4     │ Product Stat │
     │                          │    6 x 5     │
     └──────────────────────────┴──────────────┘
   Rasio Retur sengaja tepat di bawah chart utama dan SELEBAR itu juga —
   sumbu bulannya sejajar, jadi lonjakan retur terbaca berdampingan dengan
   bulan penjualannya. Rincian status ditumpuk di kolom kanan karena isinya
   batang horizontal pendek, tidak butuh lebar.

   Baris dipetak 10 unit supaya tinggi 6/4 (kiri) dan 5/5 (kanan) bisa
   berdampingan dalam satu grid tanpa wrapper tambahan.
   ------------------------------------------------------------ */
.grid-trend{
  grid-template-columns:14fr 6fr;
  grid-template-rows:repeat(10, 1fr);
  aspect-ratio:2 / 1;
}
.grid-trend .cell-hero    { grid-column:1; grid-row:1 / span 6 }
.grid-trend .cell-retur   { grid-column:1; grid-row:7 / span 4 }
.grid-trend .cell-gstatus { grid-column:2; grid-row:1 / span 5 }
.grid-trend .cell-pstatus { grid-column:2; grid-row:6 / span 5 }

@media (max-width:1068px){
  .grid-trend{
    aspect-ratio:auto;
    grid-template-columns:1fr;
    grid-template-rows:340px 240px repeat(2, 220px);
  }
  .grid-trend .cell-hero   {grid-column:1;grid-row:1}
  .grid-trend .cell-retur  {grid-column:1;grid-row:2}
  .grid-trend .cell-gstatus{grid-column:1;grid-row:3}
  .grid-trend .cell-pstatus{grid-column:1;grid-row:4}
}

.panel{display:none}
.panel.active{display:block}

.card{
  background:var(--canvas);border:1px solid var(--hairline);border-radius:var(--r-lg);
  padding:var(--s-lg);min-width:0;min-height:0;
  display:flex;flex-direction:column;overflow:hidden;
}
.card-title{margin:0 0 var(--s-sm);flex:none;font-size:17px;font-weight:600;
  line-height:1.24;letter-spacing:-.374px}
.card-title .sub{display:block;font-size:13px;font-weight:400;
  letter-spacing:-.224px;color:var(--ink-secondary);margin-top:3px}
.chart{flex:1;min-height:0}

/* ---------- 5b. Tabel matriks berhirarki ---------- */
/* flex-wrap supaya di layar sempit kotak cari dan tombol turun ke baris
   kedua, bukan mendorong toolbar melewati tepinya. Tanpa ini terukur luber
   104px di viewport 492px dan seluruh halaman jadi bisa digeser mendatar. */
.tbl-toolbar{
  display:flex;flex-wrap:wrap;align-items:center;
  gap:var(--s-sm);margin-bottom:var(--s-sm);
}
.tbl-title{font-size:17px;font-weight:600;letter-spacing:-.374px}
.tbl-meta{font-size:12px;color:var(--ink-secondary);letter-spacing:-.12px}
/* margin-left:auto supaya tombol SELALU di kanan. Di tabel yang punya kotak
   pencarian, kotak itu yang mendorongnya; tabel tanpa pencarian (SIT) dulu
   membuat tombolnya menempel di judul. */
.tbl-actions{display:flex;align-items:center;gap:var(--s-xxs);margin-left:auto}

/* Kotak cari: mendorong tombol aksi ke kanan lewat margin-left:auto */
.tbl-search{position:relative;margin-left:auto;flex:0 1 300px;min-width:180px}

/* Kalau kotak cari DAN tombol aksi sama-sama ada, hanya yang pertama boleh
   memakai margin-left:auto. Flexbox membagi ruang kosong RATA ke setiap
   margin auto, jadi dua margin auto menaruh kotak cari di tengah toolbar
   alih-alih merapat ke tombolnya. Keduanya harus jadi satu gerombolan di
   kanan, dipisah gap toolbar. */
.tbl-search + .tbl-actions{margin-left:0}
.tbl-search svg{
  position:absolute;left:12px;top:50%;transform:translateY(-50%);
  width:14px;height:14px;stroke:var(--ink-secondary);fill:none;stroke-width:2;
  stroke-linecap:round;pointer-events:none;
}
.tbl-search input{
  width:100%;font:inherit;font-size:13px;letter-spacing:-.224px;color:var(--ink);
  background:var(--canvas);border:1px solid var(--hairline);
  border-radius:var(--r-pill);padding:8px 14px 8px 34px;min-height:36px;
}
.tbl-search input::placeholder{color:var(--ink-secondary)}
.tbl-search input:focus{
  outline:2px solid var(--brand-strong);outline-offset:-1px;border-color:transparent;
}
.tbl-search input:not(:placeholder-shown){
  border-color:var(--brand-strong);background:var(--brand-wash);
}

.tbl-wrap{
  background:var(--canvas);border:1px solid var(--hairline);
  border-radius:var(--r-lg);overflow:auto;max-height:calc(100vh - 260px);
}
.tbl{border-collapse:separate;border-spacing:0;width:100%;font-size:13px}
.tbl th,.tbl td{
  padding:9px var(--s-sm);border-bottom:1px solid var(--divider-soft);
  white-space:nowrap;
}
.tbl thead th{
  position:sticky;top:0;z-index:2;background:var(--pearl);
  font-size:11px;font-weight:600;letter-spacing:-.12px;
  color:var(--ink-secondary);text-align:left;
  border-bottom:1px solid var(--hairline);
}
.tbl th.num,.tbl td.num{text-align:right;font-variant-numeric:tabular-nums}
.tbl th.txt,.tbl td.txt{text-align:left;color:var(--ink-muted-80)}
.tbl .sticky-col{
  position:sticky;left:0;z-index:1;background:var(--canvas);
  border-right:1px solid var(--divider-soft);min-width:300px;max-width:420px;
}
.tbl thead .sticky-col{z-index:3;background:var(--pearl)}
.tbl tbody tr:hover td{background:var(--parchment)}
.tbl tbody tr:hover .sticky-col{background:var(--parchment)}
.tbl tfoot td{
  position:sticky;bottom:0;z-index:2;background:var(--pearl);
  font-weight:600;border-top:1px solid var(--hairline);border-bottom:0;
}
.tbl tfoot .sticky-col{z-index:4}

/* Kedalaman ditandai bobot huruf & warna, bukan garis — indentasi sudah cukup. */
.tbl .lvl-0 .sticky-col{font-weight:600}
.tbl .lvl-1 .sticky-col{color:var(--ink-muted-80)}
.tbl .lvl-2 .sticky-col,.tbl .lvl-3 .sticky-col{color:var(--ink-muted-80)}
.tbl .lvl-4 .sticky-col{color:var(--ink-secondary)}
.tbl .lvl-0 td{background:var(--surface-row-0,#fbfbfd)}
.tbl .lvl-0:hover td{background:var(--parchment)}

.tw-caret{
  appearance:none;border:0;background:transparent;cursor:pointer;padding:0;
  width:18px;height:18px;margin-right:4px;vertical-align:-4px;
  display:inline-flex;align-items:center;justify-content:center;
  color:var(--ink-secondary);border-radius:4px;
}
.tw-caret:hover{background:var(--divider-soft);color:var(--ink)}
.tw-caret:focus-visible{outline:2px solid var(--brand-strong);outline-offset:1px}
.tw-caret svg{width:13px;height:13px;stroke:currentColor;fill:none;stroke-width:2.2;
  stroke-linecap:round;stroke-linejoin:round;transition:transform 180ms var(--ease)}
.tw-caret.open svg{transform:rotate(90deg)}
.tw-caret-spacer{display:inline-block;width:22px}
.tw-label{overflow:hidden;text-overflow:ellipsis}
.tw-empty{padding:28px var(--s-sm);color:var(--ink-secondary);text-align:center}

/* Persentase: hijau kalau memenuhi ambang, merah kalau tidak. */
.tbl td.num.pos{color:var(--pos)}
.tbl td.num.neg{color:var(--neg)}
.tbl tfoot td.num.pos,.tbl tfoot td.num.neg{font-weight:600}

/* ---------- 6. Skeleton & indikator muat ---------- */
.sk{background:linear-gradient(90deg,var(--divider-soft) 25%,#e8e8ea 37%,var(--divider-soft) 63%);
  background-size:400% 100%;animation:shimmer 1.4s ease-in-out infinite;border-radius:var(--r-sm)}
@keyframes shimmer{0%{background-position:100% 50%}100%{background-position:0 50%}}

/* Skeleton HANYA saat pemuatan pertama. Pemuatan berikutnya membiarkan konten
   apa adanya — menyembunyikan lalu memunculkan lagi bikin layar berkedip. */
body.first-load .live{visibility:hidden}
body:not(.first-load) .skel{display:none}

/* Umpan balik untuk muat ulang: garis tipis di bawah filter bar, konten diam. */
.floading{
  position:absolute;left:0;right:0;bottom:-1px;height:2px;
  overflow:hidden;display:none;pointer-events:none;
}
body.loading:not(.first-load) .floading{display:block}
.floading::after{
  content:'';position:absolute;top:0;bottom:0;width:35%;
  background:var(--brand);border-radius:2px;
  animation:sweep 900ms cubic-bezier(.4,0,.2,1) infinite;
}
@keyframes sweep{0%{left:-35%}100%{left:100%}}
.skel{position:absolute;inset:var(--s-lg);top:auto;bottom:var(--s-lg);height:60%}
.card{position:relative}
.kpi{position:relative}
.kpi .skel{inset:var(--s-md) var(--s-lg);height:auto}

/* ---------- 7. Error & empty ---------- */
.banner{
  display:none;align-items:flex-start;gap:10px;
  margin:0 var(--s-lg) var(--s-lg);padding:var(--s-sm) var(--s-md);
  border:1px solid #f0c9c5;background:#fdf3f2;border-radius:var(--r-md);
  font-size:13px;color:#8a231a;letter-spacing:-.224px;
}
.banner.show{display:flex}
.banner svg{width:16px;height:16px;flex:none;margin-top:1px;stroke:currentColor;
  fill:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
.empty{display:flex;align-items:center;justify-content:center;height:100%;
  color:var(--ink-secondary);font-size:13px;letter-spacing:-.224px}

/* ---------- 8. Responsif ---------- */
@media (max-width:1068px){
  .grid{aspect-ratio:auto;grid-template-columns:1fr 1fr;grid-template-rows:340px 240px 240px}
  .cell-line { grid-column:1 / span 2; grid-row:1 }
  .cell-gauge{ grid-column:1;          grid-row:2 }
  .cell-donut{ grid-column:2;          grid-row:2 }
  .cell-bar  { grid-column:1 / span 2; grid-row:3 }
  .kpi-strip{grid-template-columns:repeat(2,1fr)}
}
@media (max-width:734px){
  main{padding:var(--s-lg) var(--s-sm) var(--s-xl)}
  .grid{grid-template-columns:1fr;grid-template-rows:repeat(4,minmax(220px,auto))}
  .cell-line,.cell-gauge,.cell-donut,.cell-bar{grid-column:1}
  .cell-line{grid-row:1} .cell-gauge{grid-row:2}
  .cell-donut{grid-row:3} .cell-bar{grid-row:4}
  .kpi-strip{grid-template-columns:1fr}
  .sub-nav{overflow-x:auto}
  .sub-nav .page-name{display:none}
  .kpi-val{font-size:28px}
}
@media (prefers-reduced-motion:reduce){
  *{animation-duration:.01ms!important;transition-duration:.01ms!important}
}

/* ---------- Header tabel yang bisa diurutkan ---------- */
.tbl th.tw-sortable{cursor:pointer;user-select:none}
.tbl th.tw-sortable:hover{background:#f5f5f7}
.tbl th.tw-sortable:focus-visible{outline:2px solid var(--brand-strong);outline-offset:-2px}
.tbl th .tw-th{display:inline-flex;align-items:center;gap:5px}
.tbl th.num .tw-th{flex-direction:row-reverse}

/* Segitiga CSS: width/height WAJIB nol — kalau diberi ukuran, border-nya
   membentuk kotak, bukan segitiga. Lebarnya dijaga tetap 7px lewat
   border kiri-kanan transparan supaya kolom tidak melompat saat panahnya
   muncul atau hilang. */
.tbl th .tw-arrow{
  width:0;height:0;flex:none;opacity:0;
  border-left:3.5px solid transparent;
  border-right:3.5px solid transparent;
  border-top:4.5px solid transparent;
  border-bottom:0 solid transparent;
}
/* Tiap keadaan menyetel ULANG border atas DAN bawah. Versi pertama hanya
   menyetel salah satu, sehingga saat kolom yang aktif disorot, panah lama
   dan panah hover muncul bersamaan dan terlihat seperti jam pasir. */
.tbl th.tw-sortable:hover .tw-arrow{
  opacity:.4;
  border-top:4.5px solid currentColor;
  border-bottom:0 solid transparent;
}
.tbl th.turun .tw-arrow,
.tbl th.turun:hover .tw-arrow{
  opacity:1;
  border-top:4.5px solid var(--brand-strong);
  border-bottom:0 solid transparent;
}
.tbl th.naik .tw-arrow,
.tbl th.naik:hover .tw-arrow{
  opacity:1;
  border-top:0 solid transparent;
  border-bottom:4.5px solid var(--brand-strong);
}

