/* ============================================================
   SATUDATA · Universitas Sriwijaya — Material UI inspired design system
   Palette: yellow (#fbbf24) → orange (#ea580c), UNSRI brand colors
   Implements MUI tokens (spacing 8px, elevation, Roboto, 12-col Grid)
   without bundling React, per PRD §12/§13.
   ============================================================ */

/* Bilingual content — the server-side {{{tr foo}}} helper renders both ID and
   EN spans inline; this rule hides the inactive one based on <html lang>. The
   client i18n toggle flips <html lang> on language switch, instantly swapping
   every bilingual snippet without a re-render. */
html[lang="id"] [lang="en"],
html[lang="en"] [lang="id"] { display: none !important; }

:root, [data-theme="light"] {
  /* Universitas Sriwijaya palette — yellow → orange (light theme) */
  --primary: #f59e0b;        /* MUI primary.main (UNSRI amber) */
  --primary-dark: #d97706;   /* deep orange for hover/active */
  --accent: #fbbf24;         /* warm yellow accent */
  --accent-deep: #ea580c;    /* burnt orange */
  --bg: #ffffff;
  --bg-hero: #fff3d6;        /* soft yellow hero wash */
  --bg-soft: #fef9ef;        /* faint amber surface */
  --bg-blue: #fff5df;        /* warm panel fill (legacy name kept) */
  --surface: #ffffff;        /* card / panel surface */
  --surface-translucent: rgba(255,255,255,.92);
  --surface-translucent-strong: rgba(255,255,255,.97);
  --ink: #2b2110;            /* warm near-black */
  --ink-soft: #7a6a4f;       /* muted warm gray */
  --line: #f0e3c8;           /* warm hairline */
  --radius: 0px;             /* sharp, squared edges — formal academic report look */
  --shadow-1: 0 1px 3px rgba(120,80,10,.10), 0 1px 2px rgba(120,80,10,.06);
  --shadow-2: 0 4px 14px rgba(120,80,10,.16);
  --space: 8px;             /* MUI base spacing unit */
  --maxw: 1180px;
}

/* Dark theme — same hue keeps the warm UNSRI brand identity, with surfaces
   and inks inverted for low-light reading. Toggled via [data-theme="dark"]. */
[data-theme="dark"] {
  --primary: #fbbf24;        /* slightly lighter amber for contrast on dark */
  --primary-dark: #f59e0b;
  --accent: #fcd34d;
  --accent-deep: #fb923c;
  --bg: #15110a;             /* deep warm black */
  --bg-hero: #1f1810;
  --bg-soft: #1c1610;        /* sidebar / soft panel */
  --bg-blue: #221a10;
  --surface: #1a140c;        /* card surface */
  --surface-translucent: rgba(21,17,10,.88);
  --surface-translucent-strong: rgba(21,17,10,.95);
  --ink: #f7eedb;            /* warm off-white */
  --ink-soft: #b89f73;
  --line: #3a2e1c;
  --shadow-1: 0 1px 3px rgba(0,0,0,.4), 0 1px 2px rgba(0,0,0,.3);
  --shadow-2: 0 6px 18px rgba(0,0,0,.5);
}

/* Smooth fade when toggling themes — applies to all surface-bearing elements. */
body, .card, .appbar, .footer, .dash-sidebar, .dash-content, .chart-card,
.dash-empty, .dash-menu-item, .dash-menu-group__head, .dash-sidebar-toggle,
.dash-pager__btn, .nav-item__menu, .nav-item__btn {
  transition: background-color .25s ease, color .25s ease, border-color .25s ease;
}

* { box-sizing: border-box; }

/* Strip the browser focus ring on mouse/touch interactions across the whole
   app — buttons, links, headers, icon buttons, etc. Keyboard users still see
   a focus ring via :focus-visible (a11y preserved). Also kills the iOS/Android
   grey tap highlight on interactive elements. */
:focus { outline: none; }
:focus:not(:focus-visible) { outline: none; box-shadow: none; }
a, button, summary, [role="button"], [tabindex] {
  -webkit-tap-highlight-color: transparent;
}

html { scroll-behavior: smooth; }

body {
  margin: 0;
  font-family: 'Roboto', system-ui, -apple-system, sans-serif;
  color: var(--ink);
  background: var(--bg);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

/* Material Symbols spans are still emitted by HBS templates and dashboard.js
   for historical reasons — public/js/icons.js converts each into a Lucide
   SVG at DOMContentLoaded (and on every DOM mutation). The font is gone, so
   we zero out the pre-conversion glyph text to avoid a brief flash of the
   icon's raw name (e.g. "search") in the body font. */
.material-symbols-rounded {
  font-size: 0; line-height: 0; color: transparent;
  user-select: none; display: inline-block;
}

/* Lucide SVGs — created by lucide.createIcons() from <i data-lucide="name">.
   Default 18px so icons sit comfortably alongside 13–14px body text;
   per-context selectors below override the size where needed. */
.lucide {
  width: 18px; height: 18px;
  vertical-align: -3px;
  flex: none;
}

a { color: inherit; text-decoration: none; }

/* ---------- MUI Container ---------- */
.mui-container {
  width: 100%;
  max-width: var(--maxw);
  margin-inline: auto;
  padding-inline: 24px;
}

/* ---------- MUI Grid (12 columns) ---------- */
.mui-grid {
  display: flex;
  flex-wrap: wrap;
  margin: calc(-1 * var(--space) * 1.5);
}
.mui-grid > [class*="mui-col-"] { padding: calc(var(--space) * 1.5); }

[class*="mui-col-"] { flex: 0 0 100%; max-width: 100%; }

.mui-col-12 { flex-basis: 100%; max-width: 100%; }
.mui-col-6  { flex-basis: 50%;  max-width: 50%; }

.mui-center { display: flex; justify-content: center; }

/* spacing utilities (MUI 8px scale) */
.mt-1 { margin-top: 8px; }
.mt-2 { margin-top: 16px; }
.mt-3 { margin-top: 24px; }
.mt-4 { margin-top: 32px; }
.mt-5 { margin-top: 40px; }

/* sm breakpoint (tablet) */
@media (min-width: 600px) {
  .mui-col-6 { flex-basis: 50%; max-width: 50%; }
}
/* md breakpoint (desktop) */
@media (min-width: 900px) {
  .mui-col-md-2 { flex-basis: 16.666%; max-width: 16.666%; }
  .mui-col-md-3 { flex-basis: 25%;     max-width: 25%; }
  .mui-col-md-4 { flex-basis: 33.333%; max-width: 33.333%; }
  .mui-col-md-6 { flex-basis: 50%;     max-width: 50%; }
  .mui-col-md-7 { flex-basis: 58.333%; max-width: 58.333%; }
}

/* ---------- MUI Card ---------- */
.card {
  background: var(--surface);
  color: var(--ink);
  border-radius: var(--radius);
  box-shadow: var(--shadow-1);
  transition: box-shadow .2s ease, transform .2s ease, background-color .25s ease, color .25s ease;
}
.card:hover { box-shadow: var(--shadow-2); }

/* ---------- Buttons (MUI contained/outlined) ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font: 500 14px/1 'Roboto', sans-serif;
  padding: 12px 20px;
  border-radius: 2px;
  border: none;
  cursor: pointer;
  text-transform: none;
  transition: background .2s, box-shadow .2s;
}
.btn--sm { padding: 9px 16px; font-size: 13px; }
.btn--primary { background: var(--primary); color: #fff; box-shadow: var(--shadow-1); }
.btn--primary:hover { background: var(--primary-dark); }
.btn--success { background: #2e9e4f; color: #fff; }
.btn--login {
  background: var(--primary); color: #fff;
  padding: 8px 16px; border-radius: 2px;
}
.btn .material-symbols-rounded,
.btn .lucide { font-size: 18px; width: 18px; height: 18px; }

/* ============================================================
   AppBar (MUI AppBar + Toolbar)
   ============================================================ */
.appbar {
  position: sticky; top: 0; z-index: 100;
  background: var(--surface-translucent);
  color: var(--ink);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--line);
  transition: box-shadow .25s ease, background .25s ease;
}
.appbar__inner {
  display: flex; align-items: center; justify-content: space-between;
  width: 100%;
  height: 45px;
  padding-inline: 18px;
  transition: height .25s ease;
}
@media (max-width: 600px) {
  .appbar__inner { padding-inline: 12px; height: 48px; }
}
/* Shrink + lift the navbar once the page is scrolled (set by dashboard.js). */
.is-scrolled .appbar {
  background: var(--surface-translucent-strong);
  box-shadow: 0 2px 12px rgba(0,0,0,.08);
}
.is-scrolled .appbar__inner { height: 44px; }
.appbar .brand__logo-img { transition: width .25s ease, height .25s ease; }
.is-scrolled .appbar .brand__logo-img { width: 22px; height: 22px; }
.brand { display: inline-flex; align-items: center; gap: 8px; }
.brand__logo { color: var(--primary); font-size: 22px; display: inline-flex; align-items: center; }
.brand__logo-img { display: block; width: 26px; height: 26px; object-fit: contain; }

/* expert + UNSRI wordmark — single line, two font weights. */
.brand__block { display: inline-flex; flex-direction: column; gap: 1px; line-height: 1; min-width: 0; }
.brand__wordmark {
  display: inline-flex; align-items: baseline; gap: 1px;
  font-family: 'Roboto', system-ui, sans-serif;
  font-size: 18px; line-height: 1; letter-spacing: -.01em;
  color: var(--primary);
}
.brand__wordmark-light { font-weight: 300; color: var(--ink-soft); letter-spacing: 0; }
.brand__wordmark-bold  { font-weight: 800; color: var(--primary-dark); letter-spacing: .01em; }
.brand__wordmark--sm { font-size: 15px; }

/* Acronym expansion under the wordmark — quiet uppercase eyebrow. */
.brand__tagline {
  font-size: 8.5px; font-weight: 600; letter-spacing: .07em; text-transform: uppercase;
  color: var(--ink-soft); line-height: 1.1;
  white-space: nowrap;
  transition: opacity .2s ease, max-height .25s ease;
}
.brand__tagline--sm { font-size: 8px; letter-spacing: .05em; }
/* Hide tagline when the navbar shrinks on scroll to keep header compact. */
.is-scrolled .appbar .brand__tagline { opacity: 0; max-height: 0; overflow: hidden; }
/* Wrap to two lines on narrow viewports so it doesn't overflow the navbar. */
@media (max-width: 720px) {
  .appbar .brand__tagline { display: none; }
}

.appbar__nav { display: flex; align-items: center; gap: 4px; }
.appbar__toggle { display: none; background: none; border: none; cursor: pointer; color: var(--ink); }

/* Language dropdown — current language as trigger, options revealed below. */
.lang-toggle { position: relative; display: inline-flex; align-items: center; margin: 0 6px; }
.lang-toggle__trigger {
  display: inline-flex; align-items: center; gap: 5px;
  background: none; border: 1px solid transparent; cursor: pointer;
  padding: 4px 6px; border-radius: 2px;
  color: var(--ink-soft);
  font: 600 11px 'Roboto', sans-serif; letter-spacing: .04em; line-height: 1;
  transition: color .2s ease, background .2s ease, border-color .2s ease;
}
.lang-toggle__trigger:hover { color: var(--primary-dark); background: var(--bg-soft); border-color: var(--line); }
.lang-toggle__current { display: inline-flex; align-items: center; gap: 6px; }
.lang-toggle__chevron {
  font-size: 16px; color: var(--ink-soft);
  transition: transform .2s ease;
}
.lang-toggle.is-open .lang-toggle__chevron { transform: rotate(180deg); }
.lang-toggle.is-open .lang-toggle__trigger { color: var(--primary-dark); background: var(--bg-soft); border-color: var(--line); }

.lang-flag {
  display: block; border-radius: 2px; overflow: hidden;
  box-shadow: 0 0 0 1px rgba(0,0,0,.08);
  flex: none;
}

.lang-toggle__menu {
  position: absolute; top: calc(100% + 6px); right: 0;
  min-width: 200px; margin: 0; padding: 4px; list-style: none;
  background: var(--surface);
  border: 1px solid var(--line);
  box-shadow: var(--shadow-2);
  opacity: 0; visibility: hidden; transform: translateY(-4px);
  transition: opacity .18s ease, transform .18s ease, visibility .18s;
  z-index: 60;
}
.lang-toggle.is-open .lang-toggle__menu {
  opacity: 1; visibility: visible; transform: translateY(0);
}
.lang-toggle__option {
  display: inline-flex; align-items: center; gap: 10px;
  width: 100%; padding: 8px 10px;
  background: none; border: none; cursor: pointer;
  font: 500 13px 'Roboto', sans-serif; color: var(--ink);
  text-align: left;
  border-radius: 2px;
  transition: background .15s ease, color .15s ease;
}
.lang-toggle__option > span:not(.material-symbols-rounded):not(.lang-flag) { flex: 1; }
.lang-toggle__option:hover { background: var(--bg-soft); color: var(--primary-dark); }
.lang-toggle__check {
  font-size: 16px; color: var(--primary-dark); opacity: 0;
  transition: opacity .15s ease;
}
.lang-toggle__option.is-active .lang-toggle__check { opacity: 1; }
.lang-toggle__option.is-active { color: var(--primary-dark); font-weight: 600; }

/* Light/Dark theme toggle — icon swap, no chrome */
.theme-toggle {
  display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px;
  background: none; border: 1px solid transparent; cursor: pointer;
  color: var(--ink-soft); border-radius: 2px;
  margin: 0 2px;
  transition: color .2s ease, background .2s ease, border-color .2s ease;
}
.theme-toggle:hover { color: var(--primary-dark); background: var(--bg-soft); border-color: var(--line); }
.theme-toggle__icon { font-size: 18px; }
.theme-toggle__icon--dark { display: none; }
[data-theme="dark"] .theme-toggle__icon--light { display: none; }
[data-theme="dark"] .theme-toggle__icon--dark { display: inline-flex; }
/* Login is now a button — keep it visually identical to the old link. */
.btn--login { cursor: pointer; }

.nav-item { position: relative; }
.nav-item__btn {
  display: inline-flex; align-items: center; gap: 2px;
  background: none; border: none; cursor: pointer;
  font: 500 13px 'Roboto', sans-serif; color: var(--ink-soft);
  padding: 6px 10px; border-radius: 2px;
}
.nav-item__btn:hover { background: var(--bg-soft); color: var(--primary); }
.nav-item__chevron { font-size: 16px; }
.nav-item__menu {
  position: absolute; top: 100%; left: 0;
  min-width: 180px; background: var(--surface);
  border: 1px solid var(--line); border-radius: 2px;
  box-shadow: var(--shadow-2); padding: 6px;
  opacity: 0; visibility: hidden; transform: translateY(6px);
  transition: .18s; z-index: 10;
}
.nav-item:hover .nav-item__menu { opacity: 1; visibility: visible; transform: translateY(4px); }
.nav-item__menu a { display: block; padding: 9px 12px; border-radius: 2px; font-size: 14px; color: var(--ink-soft); }
.nav-item__menu a:hover { background: var(--bg-soft); color: var(--primary); }

/* ============================================================
   HERO
   ============================================================ */
.hero { background: var(--bg-hero); padding: 40px 0 32px; }
.hero__grid { align-items: stretch; }
.hero__card { border-radius: var(--radius); overflow: hidden; }

.hero__intro {
  background: #fff1cf;
  padding: 40px; display: flex; flex-direction: column; justify-content: center;
  min-height: 240px;
}
.hero__eyebrow { font-size: 13px; color: var(--ink-soft); margin: 0 0 12px; }
.hero__title { font-size: 38px; line-height: 1.15; font-weight: 700; margin: 0 0 24px; color: #3d2c08; }

/* WCU / SDGs achievement card (replaces the old JSON sample card). */
.hero__wcu {
  position: relative;
  background: #fff4dc;
  border: 1px solid #f3e2bd; padding: 24px;
  display: flex; flex-direction: column; gap: 16px;
}
.wcu__badge {
  position: absolute; top: 16px; right: 16px;
  width: 64px; height: 64px; object-fit: contain; pointer-events: none;
}
.wcu__head { padding-right: 76px; }
.wcu__eyebrow { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; color: var(--accent-deep, #b45309); }
.wcu__eyebrow-icon { opacity: .8; }
.wcu__title { margin: 6px 0 0; padding-bottom: 32px; font-size: 16px; font-weight: 700; color: #3d2c08; }

.wcu__ranks { display: grid; grid-template-columns: repeat(2, 1fr); gap: 8px; margin-top: 28px; }
.wcu__rank { background: #fff; border: 1px solid #f3e2bd; border-radius: 0; padding: 7px 10px; display: flex; align-items: center; gap: 9px; }
.wcu__rank-icon { flex: none; width: 30px; height: 30px; display: inline-flex; align-items: center; justify-content: center; border-radius: 50%; background: #fbf3df; color: #b8860b; }
.wcu__rank-icon svg { width: 18px; height: 18px; }
.wcu__rank-body { display: flex; flex-direction: column; gap: 0; min-width: 0; }
.wcu__rank-value { font-size: 18px; font-weight: 800; color: #16223f; line-height: 1.1; }
.wcu__rank-label { font-size: 11px; font-weight: 600; color: #6b5a36; }
.wcu__rank-sub { font-size: 10px; color: #a08a5e; }

.wcu__sdg-label { margin: 0; font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: .03em; color: #8a7a52; }
.wcu__sdg-chart { width: 100%; }
.wcu__sdg-chart svg { width: 100%; display: block; }
.wcu__sdg-chart .sdg-row { cursor: default; }

.wcu__source { margin: 0; font-size: 10px; color: #b09a6e; }

/* Hero mini-metric cards (replace decorative blocks with live data viz) */
.metric-card {
  background: #fff; box-shadow: var(--shadow-1);
  padding: 16px; min-height: 110px;
  display: flex; flex-direction: column; gap: 6px;
}
.metric-card__head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.metric-card__label { font-size: 12px; color: var(--ink-soft); }
.metric-card__delta { font-size: 11px; font-weight: 700; padding: 2px 6px; border-radius: 2px; }
.metric-card__delta.is-up { color: #1d8a44; background: #e3f5ea; }
.metric-card__delta.is-down { color: #c0392b; background: #fbe7e4; }
.metric-card__value { display: flex; align-items: center; gap: 8px; font-size: 24px; font-weight: 700; color: #16223f; line-height: 1.1; }
.metric-card__icon { flex: 0 0 auto; color: #9ca3af; }
.metric-card__sub { font-size: 12px; color: #97a0b0; }
.metric-card__viz { flex: 1; min-height: 56px; display: flex; align-items: flex-end; }
.metric-card__viz svg { width: 100%; height: 56px; overflow: visible; }

/* ============================================================
   Ticker
   ============================================================ */
.ticker { background: var(--accent-deep); color: #fff4dc; overflow: hidden; padding: 9px 0; font-size: 12px; }
.ticker__track { display: flex; gap: 36px; white-space: nowrap; width: max-content; animation: ticker 80s linear infinite; }
.ticker:hover .ticker__track { animation-play-state: paused; }
.ticker__item { display: inline-flex; align-items: center; gap: 8px; }
.ticker__item--stat b { color: #fff; }
/* News headlines pulled from the UNSRI RSS feed (title + date). */
.ticker__item--news { color: #fff4dc; text-decoration: none; padding-left: 36px; border-left: 1px solid rgba(255,255,255,.28); }
.ticker__item--news:hover .ticker__news-title { text-decoration: underline; }
.ticker__icon { flex: 0 0 auto; opacity: .85; }
.ticker__news-title { font-weight: 600; color: #fff; max-width: 46ch; overflow: hidden; text-overflow: ellipsis; }
.ticker__news-date { color: #ffe2b8; font-size: 11px; opacity: .9; }
.ticker__news-date::before { content: '·'; margin-right: 6px; }
@keyframes ticker { from { transform: translateX(0); } to { transform: translateX(-50%); } }

/* ============================================================
   Sections
   ============================================================ */
.section { padding: 56px 24px; }
.section__title {
  display: flex; align-items: center; gap: 10px;
  font-size: 26px; font-weight: 700; margin: 0 0 14px; color: var(--ink);
}
.section__accent { width: 5px; height: 26px; background: var(--accent-deep); border-radius: 3px; }
.section__title--light { color: #fff; }
.section__title--center { justify-content: center; }
.section__body { color: var(--ink-soft); max-width: 720px; margin: 0 0 28px; }
.section__body--light { color: #fdebc8; }
.section__body--center { text-align: center; margin-inline: auto; }

/* Panels (soft warm containers) */
.panel { background: var(--bg-blue); border-radius: 8px; padding: 32px; margin-top: 8px; }
.panel__label { font-size: 13px; font-weight: 500; color: var(--ink); margin: 0 0 16px; }
.panel .btn { margin-top: 18px; }

/* "At a Glance" panel — no wrapper surface; cards carry their own color. */
.panel--glance {
  background: none;
  border: none;
  padding: 24px 0 28px;
}
.panel--glance .panel__label {
  display: flex; align-items: center; gap: 8px;
  font-size: 12px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
  color: var(--ink-soft); margin: 0 0 14px;
}
.panel--glance .panel__label::before {
  content: ""; width: 18px; height: 3px; border-radius: 2px;
  background: var(--accent-deep);
}
.panel--glance .panel__label.mt-5 { margin-top: 22px; }
.panel--glance .btn.mt-5 { margin-top: 20px; }

/* ---------- Consultant panel (redesigned) ---------- */
.panel--consultant {
  background: #fdecc8;
  border: 1px solid var(--line);
  padding: 40px;
  display: flex;
  flex-direction: column;
  gap: 36px;
}
.panel--consultant .section__title { margin-bottom: 12px; }
.panel--consultant .section__body { margin-bottom: 0; }
/* Intro + chat sit in a top row, services in their own row with clear separation */
.consultant__intro { display: flex; flex-direction: column; justify-content: center; }
.consultant__services { row-gap: 0; }
.consultant__services .section__subtitle {
  width: 100%; font-size: 13px; font-weight: 600; letter-spacing: .4px;
  text-transform: uppercase; color: var(--primary-dark); margin: 0 0 4px;
}

/* ---------- Product cards (compact) ---------- */
.product-card { display: flex; gap: 12px; padding: 12px; height: 100%; }
.product-card__icon {
  flex: 0 0 auto; width: 34px; height: 34px; border-radius: 6px;
  display: inline-flex; align-items: center; justify-content: center; font-size: 19px;
}
.product-card__name { margin: 0 0 2px; font-size: 14px; font-weight: 700; }
.product-card__desc { margin: 0 0 6px; font-size: 12px; line-height: 1.45; color: var(--ink-soft); }
.product-card__tag { font-size: 11px; color: #97a0b0; }

/* ---------- Data-domain menu grid (login-gated category shortcuts) ---------- */
/* Compact: smaller flat-tint icons + denser grid so more categories show. */
.menu-grid {
  display: grid; gap: 10px;
  /* minmax(0,1fr) lets tracks shrink below content width so long names/icons
     don't push cards past their column and overlap on narrow screens.
     Mobile: single full-width column; multi-column from the sm breakpoint up. */
  grid-template-columns: minmax(0, 1fr);
}
@media (min-width: 600px) { .menu-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 900px) { .menu-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

.menu-card {
  --cat: var(--primary); /* per-card color (overridden inline) */
  position: relative; display: flex; align-items: center; gap: 12px; text-align: left;
  background: var(--cat); border: none; border-radius: 0;
  padding: 16px; color: #fff; box-shadow: var(--shadow-1);
  min-width: 0; overflow: hidden;
  transition: box-shadow .2s ease, transform .2s ease, filter .2s ease;
}
.menu-card:hover {
  box-shadow: 0 8px 20px color-mix(in srgb, var(--cat) 38%, transparent);
  transform: translateY(-2px);
  filter: brightness(1.06);
}

.menu-card__icon {
  flex: 0 0 auto; width: 40px; height: 40px; border-radius: 0;
  display: inline-flex; align-items: center; justify-content: center; font-size: 22px;
  color: #fff; background: rgba(255, 255, 255, .18);
}

/* Text column: vertically centered against the icon, name above desc. */
.menu-card__text { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1 1 auto; }
.menu-card__name { font-size: 13px; font-weight: 700; line-height: 1.25; color: #fff; overflow-wrap: anywhere; }
.menu-card__desc {
  font-size: 11px; line-height: 1.4; color: rgba(255, 255, 255, .82);
  display: -webkit-box; -webkit-line-clamp: 1; -webkit-box-orient: vertical; overflow: hidden;
}

/* Outward arrow. */
.menu-card__arrow {
  flex: 0 0 auto; font-size: 18px; color: #fff; opacity: .7;
  transition: opacity .2s ease, transform .2s ease;
}
.menu-card:hover .menu-card__arrow { opacity: 1; transform: translate(2px, -2px); }

/* ---------- Consultant chat bubble ---------- */
.section--consultant { padding-top: 0; }
.chat-bubble {
  background: #fff; border-radius: 2px; padding: 20px; box-shadow: var(--shadow-2);
  position: relative; display: flex; flex-direction: column; align-items: flex-start;
}
.chat-bubble__avatar { position: absolute; top: -14px; left: -14px; font-size: 40px; color: var(--primary-dark); background: var(--bg-soft); border-radius: 50%; }
.chat-bubble p { margin: 8px 0 16px; font-size: 14px; color: var(--ink-soft); }
.chat-bubble .btn { align-self: flex-end; margin-top: 0; }

/* ---------- Service cards ---------- */
.service-card { overflow: hidden; height: 100%; }
.service-card__bar { height: 38px; display: flex; align-items: center; padding: 0 14px; color: #fff; }
.service-card__bar .material-symbols-rounded,
.service-card__bar .lucide { font-size: 20px; width: 20px; height: 20px; }
.service-card__body { padding: 16px; }
.service-card__title { margin: 0 0 8px; font-size: 16px; font-weight: 700; }
.service-card__desc { margin: 0; font-size: 13px; color: var(--ink-soft); }

/* ---------- Facts (warm orange band) ---------- */
.section--facts { background: var(--primary-dark); }
.stat-card { padding: 20px; text-align: center; height: 100%; }
.stat-card__icon { font-size: 30px; }
.stat-card__value { font-size: 30px; font-weight: 700; margin: 8px 0 2px; color: var(--ink); }
.stat-card__label { font-size: 13px; color: var(--ink-soft); }
.facts__highlights { margin-top: 8px; }
.facts__charts { margin-top: 8px; }
.chart-card { padding: 12px 14px 14px; height: 100%; }
.chart-card__head { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; margin-bottom: 4px; flex-wrap: wrap; }
.chart-card__title { margin: 0; font-size: 14.5px; font-weight: 700; color: var(--ink); line-height: 1.25; }
.chart-card__kpi { font-size: 11px; color: var(--ink-soft); white-space: nowrap; }
.chart-card__kpi b { color: var(--accent-deep); }
.chart-card canvas { width: 100% !important; height: 220px !important; }
/* D3 viz host. Width is 100% — height is governed by the card's flex column
   layout below (uniform 365px card) rather than a min-height floor, so dense
   charts (heatmaps, grouped bars) fit instead of pushing the card taller. */
.chart-card__viz { width: 100%; }
.chart-card__viz svg { display: block; width: 100%; overflow: visible; }
.chart-card__viz .domain, .chart-card__viz .tick line { stroke: var(--line); }
.chart-card__viz .tick text { fill: var(--ink-soft); }
/* Legend for grouped/multi-series charts (rendered above the SVG). */
.chart-legend { display: flex; flex-wrap: wrap; gap: 4px 14px; margin-bottom: 6px; }
.chart-legend__item { display: inline-flex; align-items: center; gap: 5px; font-size: 11px; color: var(--ink-soft); }
.chart-legend__item i { width: 10px; height: 10px; border-radius: 2px; flex: none; }
.facts__drillnote { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: #fff4dc; margin: 4px 0 18px; opacity: .92; }
.facts__drillnote .material-symbols-rounded,
.facts__drillnote .lucide { font-size: 16px; width: 16px; height: 16px; }

/* D3 shared tooltip — z-index sengaja di atas .collab-modal (9999) supaya
   tooltip hover di dalam modal (bar chart per-tahun) tetap kelihatan
   mengambang di atas backdrop, bukan ter-cover. */
.d3-tip {
  position: fixed; z-index: 9998; pointer-events: none; opacity: 0;
  background: #2b2110; color: #fff; font-size: 12px; line-height: 1.3;
  padding: 6px 9px; border-radius: 4px; box-shadow: var(--shadow-2);
  transition: opacity .12s ease;
  max-width: 220px;
}
.d3-tip b { color: var(--accent); }
/* Sparkline mini-chart di tooltip hover peta kolaborasi internasional. */
.collab-spark { margin: 4px 0 2px; }
.collab-spark__svg { display: block; }
.collab-spark__yr { font-size: 9px; fill: #d4c5a8; }
.highlight-card { display: flex; align-items: center; gap: 12px; padding: 16px; font-size: 14px; color: var(--ink); height: 100%; }
.highlight-card .material-symbols-rounded,
.highlight-card .lucide { color: #2e9e4f; }

/* ---------- Insight ---------- */
.section--insight { text-align: center; }
.insight__featured { max-width: 720px; margin: 0 auto 24px; text-align: left; }
.insight-list__head {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: 12px;
}
.insight-list__heading { margin: 0; font-size: 1rem; }
.insight-list__more { font-size: .85rem; font-weight: 600; color: var(--primary, #1976d2); text-decoration: none; }
.insight-list__more:hover { text-decoration: underline; }
.insight-list { list-style: none; margin: 0; padding: 0; }
.insight-list__item {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  padding: 12px 0; border-bottom: 1px solid var(--line);
}
.insight-list__item:last-child { border-bottom: none; }
.insight-list__title { font-size: .95rem; }
.insight-list__meta { flex-shrink: 0; font-size: .8rem; color: var(--muted, #6b7280); }
.news-card--center { text-align: left; }

/* ---------- News cards ---------- */
.news-card {
  display: flex; flex-direction: column; overflow: hidden; height: 100%;
  border-radius: 10px; border: 1px solid var(--line);
}
.news-card:hover { transform: translateY(-3px); }
.news-card--featured { grid-column: span 12; flex-direction: row; }
.news-card__thumb {
  position: relative;
  background: var(--accent-deep); color: #fff4dc;
  display: flex; align-items: center; justify-content: center; font-size: 40px;
}
.news-card--featured .news-card__thumb { flex: 0 0 300px; }
.news-card:not(.news-card--featured) .news-card__thumb { height: 168px; }
.news-card__thumb--img { background-size: cover; background-position: center; color: transparent; }
/* readability scrim so the floating tag stays legible over photos —
   solid translucent black at top, sized so it covers the tag area. */
.news-card__thumb--img::after {
  content: ""; position: absolute; inset: 0 0 auto 0;
  height: 64px;
  background: rgba(0,0,0,.28);
}
.news-card__cat {
  position: absolute; top: 12px; left: 12px; z-index: 1;
  background: rgba(255,255,255,.94); color: var(--accent-deep);
  font-size: 11px; font-weight: 700; letter-spacing: .3px;
  padding: 4px 10px; border-radius: 999px;
  display: inline-flex; align-items: center; gap: 5px;
}
.news-card__cat .material-symbols-rounded,
.news-card__cat .lucide { font-size: 14px; width: 14px; height: 14px; }
.news-card__body { padding: 18px 18px 20px; flex: 1; display: flex; flex-direction: column; }
.news-card__title { margin: 0 0 10px; font-size: 16px; font-weight: 700; line-height: 1.35; color: var(--ink); }
.news-card--featured .news-card__title { font-size: 22px; }
.news-card__excerpt { margin: 0 0 16px; font-size: 13px; line-height: 1.6; color: var(--ink-soft); }
.news-card__meta { display: flex; align-items: center; flex-wrap: wrap; gap: 12px; margin-top: auto; padding-top: 8px; border-top: 1px solid var(--line); }
.news-card__tag { background: var(--bg-soft); color: var(--primary-dark); font-size: 11px; padding: 4px 10px; border-radius: 999px; font-weight: 600; }
.news-card__date { font-size: 12px; color: var(--ink-soft); display: inline-flex; align-items: center; gap: 4px; }
.news-card__date .material-symbols-rounded { font-size: 15px; }
.news-card__read { margin-left: auto; font-size: 12px; font-weight: 600; color: var(--primary-dark); display: inline-flex; align-items: center; gap: 3px; }
.news-card__read .material-symbols-rounded { font-size: 16px; }

/* ---------- News list (clean, borderless — university landing style) ---------- */
.news-list { list-style: none; margin: 8px 0 0; padding: 0; }
.news-list__item { border-bottom: 1px solid var(--line); }
.news-list__item:last-child { border-bottom: none; }
.news-row {
  display: flex; align-items: center; gap: 20px;
  padding: 20px 8px; transition: background .15s ease, padding .15s ease;
}
.news-row:hover { background: var(--bg-soft); }
.news-row__thumb {
  flex: 0 0 132px; height: 84px; border-radius: 8px;
  background-size: cover; background-position: center; background-color: var(--bg-soft);
}
.news-row__thumb--icon {
  display: flex; align-items: center; justify-content: center; font-size: 34px;
  color: #fff4dc; background: var(--accent-deep);
}
.news-row__body { flex: 1; min-width: 0; }
.news-row__meta { display: flex; align-items: center; flex-wrap: wrap; gap: 14px; margin-bottom: 6px; }
.news-row__cat { font-size: 11px; font-weight: 700; letter-spacing: .3px; text-transform: uppercase; color: var(--accent-deep); }
.news-row__date, .news-row__read { font-size: 12px; color: var(--ink-soft); display: inline-flex; align-items: center; gap: 4px; }
.news-row__date .material-symbols-rounded, .news-row__read .material-symbols-rounded { font-size: 15px; }
.news-row__title { margin: 0 0 5px; font-size: 17px; font-weight: 700; line-height: 1.35; color: var(--ink); }
.news-row:hover .news-row__title { color: var(--primary-dark); }
.news-row__excerpt {
  margin: 0; font-size: 13px; line-height: 1.55; color: var(--ink-soft);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.news-row__arrow { flex: 0 0 auto; color: var(--ink-soft); font-size: 22px; transition: transform .15s ease, color .15s ease; }
.news-row:hover .news-row__arrow { color: var(--accent-deep); transform: translateX(4px); }

/* ============================================================
   Footer — compact, full-width (no container constraint)
   ============================================================ */
.footer {
  background: var(--bg-soft);
  border-top: 1px solid var(--line);
  padding: 24px 24px 0;
  margin-top: 0;
  color: var(--ink);
}
.footer__brand { display: flex; align-items: center; gap: 8px; margin-bottom: 12px; }
.footer__brand .brand__logo { display: inline-flex; color: var(--primary); }
.footer__grid {
  display: flex; flex-wrap: wrap; gap: 18px 40px;
  padding-bottom: 18px;
}
.footer__col { flex: 1 1 200px; min-width: 0; }
.footer__col--about { flex: 1.6 1 300px; }
.footer__col h4 {
  display: flex; align-items: center; gap: 6px;
  font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .4px;
  margin: 0 0 8px; color: var(--ink);
}
.footer__dot { width: 8px; height: 8px; border-radius: 2px; display: inline-block; }
.footer__col p { font-size: 12px; line-height: 1.55; color: var(--ink-soft); margin: 0; }
.footer__col ul { list-style: none; padding: 0; margin: 0; }
.footer__col li { font-size: 12px; line-height: 1.5; color: var(--ink-soft); margin-bottom: 4px; }

/* Sitemap column — two-up grid so the navigation links read as a compact map
   instead of one long vertical column. */
.footer__col--sitemap { flex: 1.4 1 240px; }
.footer__sitemap {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 2px 16px;
}
.footer__sitemap li { margin-bottom: 0; }
.footer__sitemap a {
  color: var(--ink-soft);
  border-bottom: 1px solid transparent;
  transition: color .15s ease, border-color .15s ease;
}
.footer__sitemap a:hover { color: var(--primary-dark); border-bottom-color: var(--primary); }
@media (max-width: 560px) {
  .footer__sitemap { grid-template-columns: 1fr; }
}
/* Heroicons render as inline SVG; tint via currentColor + a soft chip */
.hicon { display: inline-block; vertical-align: middle; }
.footer__bar {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: center;
  gap: 6px 16px;
  border-top: 1px solid var(--line);
  padding: 10px 0 12px;
  font-size: 11px; color: var(--ink-soft);
  text-align: center;
}
.footer__legal { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; }
.footer__legal a {
  color: var(--ink-soft);
  border-bottom: 1px solid transparent;
  transition: color .15s ease, border-color .15s ease;
}
.footer__legal a:hover { color: var(--primary-dark); border-bottom-color: var(--primary); }
.footer__legal-sep { color: var(--line); }
@media (max-width: 600px) {
  .footer { padding: 20px 16px 0; }
  .footer__grid { gap: 16px 24px; padding-bottom: 14px; }
}

/* ============================================================
   MUI-style Snackbar / Alert toast
   ============================================================ */
.mui-snackbar-host {
  position: fixed; left: 24px; bottom: 24px; z-index: 1400;
  display: flex; flex-direction: column; gap: 10px;
}
.mui-snackbar {
  display: flex; align-items: center; gap: 10px;
  min-width: 288px; max-width: 420px;
  padding: 12px 14px; border-radius: 2px;
  color: #fff; background: #313a4b;
  box-shadow: 0 6px 20px rgba(16,24,40,.28);
  font-size: 14px;
  transform: translateY(16px); opacity: 0;
  transition: transform .22s ease, opacity .22s ease;
}
.mui-snackbar.is-open { transform: translateY(0); opacity: 1; }
.mui-snackbar--info { background: #b8770f; }
.mui-snackbar--success { background: #1d8a44; }
.mui-snackbar--warning { background: #b8770f; }
.mui-snackbar--error { background: #c0392b; }
.mui-snackbar__icon { font-size: 20px; }
.mui-snackbar__msg { flex: 1; }
.mui-snackbar__close {
  background: none; border: none; color: rgba(255,255,255,.85);
  cursor: pointer; font-size: 18px; padding: 0; line-height: 1;
}
.mui-snackbar__close:hover { color: #fff; }

@media (max-width: 599px) {
  .mui-snackbar-host { left: 12px; right: 12px; bottom: 12px; }
  .mui-snackbar { min-width: 0; max-width: none; }
  .menu-grid {
    grid-template-columns: repeat(1, 1fr);
  }
}

/* ============================================================
   Login
   ============================================================ */
.login__card { padding: 32px; }
.login__form { display: flex; flex-direction: column; gap: 16px; margin-top: 16px; }
.login__form label { display: flex; flex-direction: column; gap: 6px; font-size: 13px; color: var(--ink-soft); }
.login__form input { padding: 12px; border: 1px solid var(--line); border-radius: 2px; font-size: 14px; }
.login__back { display: inline-block; margin-top: 16px; font-size: 13px; color: var(--primary); }

/* ============================================================
   Responsive — Drawer-style mobile nav (MUI Drawer behavior)
   ============================================================ */
@media (max-width: 899px) {
  .hero__title { font-size: 30px; }
  .appbar__toggle { display: inline-flex; }
  .appbar__nav {
    position: fixed; inset: 64px 0 auto 0;
    flex-direction: column; align-items: stretch; gap: 0;
    background: var(--surface); border-bottom: 1px solid var(--line);
    padding: 8px 16px 16px; box-shadow: var(--shadow-2);
    transform: translateY(-120%); transition: transform .25s ease;
  }
  .appbar__nav.is-open { transform: translateY(0); }
  .nav-item__menu { position: static; opacity: 1; visibility: visible; transform: none; box-shadow: none; border: none; padding-left: 12px; }
  .btn--login { justify-content: center; margin-top: 8px; }
  .news-card--featured { flex-direction: column; }
  .news-card--featured .news-card__thumb { flex: none; height: 160px; }
  /* News list: stack thumb above text, hide trailing arrow */
  .news-row { flex-wrap: wrap; gap: 12px; padding: 18px 4px; }
  .news-row__thumb { flex-basis: 100%; height: 150px; }
  .news-row__arrow { display: none; }
  .news-row__excerpt { -webkit-line-clamp: 3; }

 .menu-grid {
  grid-template-columns: repeat(1, 1fr);
 }
}

/* ===================================================================== */
/* Lakehouse data dashboard (/) — fixed left sidebar + full-width content */
/* ===================================================================== */

/* Shell: 2-column grid (sidebar | content). Full viewport width — content
   no longer caps at --maxw so chart grids can breathe on wide displays. */
.dash-shell {
  display: grid;
  grid-template-columns: 0 minmax(0, 1fr);
  gap: 0;
  width: 100%;
  background: var(--bg);
  align-items: stretch;
}

/* ---------- Left sidebar ----------
   Sticky vertical menu. Compact density: narrower track, tighter row pitch,
   smaller icons — gives the dashboard content more room without losing
   legibility. */
.dash-sidebar {
  position: sticky;
  top: 52px;
  align-self: start;
  height: calc(100vh - 52px);
  display: flex;
  flex-direction: column;
  background: var(--bg-soft);
  border-right: 1px solid var(--line);
  padding: 0;
  overflow-y: auto;
  transition: top .25s ease, height .25s ease;
}
.is-scrolled .dash-sidebar { top: 44px; height: calc(100vh - 44px); }

.dash-sidebar__head {
  display: flex; align-items: center; gap: 8px;
  padding: 4px 6px 10px;
  border-bottom: 1px solid var(--line);
  margin-bottom: 8px;
}
.dash-sidebar__icon {
  width: 28px; height: 28px; flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--primary); color: #fff;
  font-size: 16px;
}
.dash-sidebar__titles { display: flex; flex-direction: column; line-height: 1.1; flex: 1; min-width: 0; }
.dash-sidebar__eyebrow {
  font-size: 9px; font-weight: 700; letter-spacing: .12em; text-transform: uppercase;
  color: var(--ink-soft);
}
.dash-sidebar__label { font-size: 13px; font-weight: 700; color: var(--ink); }
.dash-sidebar__close {
  display: none; background: none; border: none; cursor: pointer; padding: 2px;
  color: var(--ink-soft);
}
.dash-sidebar__close:hover { color: var(--ink); }

/* ---------- Sidebar navigation ---------- */
.dash-side-nav {
  display: flex;
  flex-direction: column;
  gap: 2px;
  flex: 1;
  min-height: 0;
}

/* Collapsible group (Akademik): header button toggles the items list. */
.dash-menu-group {
  display: flex; flex-direction: column;
}
.dash-menu-group__head {
  display: inline-flex; align-items: center; gap: 10px;
  width: 100%;
  padding: 7px 10px;
  background: none; border: none; cursor: pointer;
  font: 600 12px 'Roboto', sans-serif; color: var(--ink);
  letter-spacing: .02em;
  text-align: left;
  border-radius: 2px;
  transition: background .15s ease, color .15s ease;
}
.dash-menu-group__head:hover { background: rgba(245,158,11,.08); }
.dash-menu-group__icon {
  font-size: 17px; color: var(--primary-dark); flex: none;
}
.dash-menu-group__label { flex: 1; }
.dash-menu-group__caret {
  font-size: 17px; color: var(--ink-soft); flex: none;
  transition: transform .25s ease;
}
.dash-menu-group:not(.is-open) .dash-menu-group__caret { transform: rotate(-90deg); }
/* Dropdown items — vertical "trunk" line on the left so the children read as
   a tree branching from the parent group. Each child has a dot sitting on
   the trunk with a short horizontal connector — see .dash-menu-item below. */
.dash-menu-group__items {
  list-style: none; padding: 4px 0 6px 0; margin: 0;
  display: flex; flex-direction: column; gap: 2px;
  overflow: hidden;
  max-height: 600px;
  position: relative;
  transition: max-height .25s ease, opacity .2s ease;
}
.dash-menu-group__items::before {
  content: '';
  position: absolute;
  left: 17px; top: 6px; bottom: 6px;
  width: 1px;
  background: var(--line);
}
.dash-menu-group:not(.is-open) .dash-menu-group__items {
  max-height: 0; opacity: 0; padding: 0;
}

/* Leaf menu item — child of a group OR a top-level standalone (Keuangan etc). */
.dash-menu-item {
  display: inline-flex; align-items: center; gap: 8px;
  width: 100%;
  padding: 6px 10px 6px 30px;
  background: none; border: none; cursor: pointer;
  font: 500 12px 'Roboto', sans-serif; color: var(--ink-soft);
  border-left: 2px solid transparent;
  border-radius: 0;
  text-align: left;
  position: relative;
  transition: background .15s ease, color .15s ease, border-color .15s ease;
}
/* Horizontal connector — short stub running from the dot toward the item
   label, so each child reads like a branch off the trunk. Hidden on
   top-level items (which sit outside any group container). */
.dash-menu-item::before {
  content: '';
  position: absolute;
  left: 22px; top: 50%;
  width: 5px; height: 1px;
  background: var(--line);
  transform: translateY(-50%);
  transition: background .15s ease;
}
.dash-menu-item--top::before { display: none; }
.dash-menu-item__dot {
  position: absolute; left: 13px; top: 50%;
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--bg);
  border: 1.5px solid var(--line);
  transform: translateY(-50%);
  box-sizing: border-box;
  transition: background .15s ease, border-color .15s ease, transform .15s ease;
}
.dash-menu-item__icon { font-size: 16px; color: inherit; }
.dash-menu-item__label { flex: 1; }
.dash-menu-item:hover { background: rgba(245,158,11,.08); color: var(--ink); }
.dash-menu-item:hover .dash-menu-item__dot {
  background: var(--primary); border-color: var(--primary);
}
.dash-menu-item:hover::before { background: var(--primary); }

/* Active — modern flat treatment. Sharp edges (no border-radius), a 3px
   primary accent bar on the left, a solid primary-tinted background, and a
   thin primary marker on the right edge so the active item is obvious even
   at a glance. Children also get a filled primary dot with a halo on the
   trunk. */
.dash-menu-item.is-active {
  background: rgba(245,158,11,.12);
  color: var(--primary-dark);
  border-left-color: var(--primary);
  font-weight: 700;
}
.dash-menu-item.is-active::after {
  content: '';
  position: absolute;
  right: 0; top: 4px; bottom: 4px;
  width: 2px;
  background: var(--primary);
}
.dash-menu-item.is-active::before { background: var(--primary); }
.dash-menu-item.is-active .dash-menu-item__dot {
  background: var(--primary);
  border-color: var(--primary);
  box-shadow: 0 0 0 3px rgba(245,158,11,.18);
}

/* Top-level standalone (no parent group) — bigger icon, no tree decorations. */
.dash-menu-item--top {
  padding: 8px 10px;
  font-size: 12px; font-weight: 600; color: var(--ink);
}
.dash-menu-item--top .dash-menu-item__dot { display: none; }
.dash-menu-item--top .dash-menu-item__icon {
  font-size: 17px; color: var(--primary-dark);
}
.dash-menu-item--top.is-active .dash-menu-item__icon { color: var(--primary-dark); }

/* ---------- Content column ---------- */
.dash-content {
  min-width: 0;
  padding: 6px 20px 0px;
  background: var(--bg);
}

/* Back to onboarding portal — a bare arrow that sits beside the dashboard
   title, reading as part of the heading rather than a detached button. */
.dash-back {
  display: inline-flex; /* tampil di desktop; disembunyikan di drawer mobile (≤960px) */
  align-items: center; justify-content: center;
  flex: none; width: 30px; height: 30px; border-radius: 50%;
  color: var(--ink-soft); text-decoration: none; cursor: pointer;
  transition: background .15s, color .15s;
}
.dash-back:hover { background: var(--bg-blue); color: var(--primary-dark); }
.dash-back .material-symbols-rounded { font-size: 20px; }

/* Mobile sidebar toggle (shown only when sidebar collapses to drawer). */
.dash-sidebar-toggle {
  display: none;
  align-items: center; gap: 6px;
  background: var(--surface); border: 1px solid var(--line); cursor: pointer;
  padding: 8px 12px;
  font: 600 12px 'Roboto', sans-serif; color: var(--ink);
  margin-bottom: 14px;
}
.dash-sidebar-toggle:hover { border-color: var(--primary); color: var(--primary-dark); }
.dash-sidebar-toggle .material-symbols-rounded { font-size: 20px; }

.dash-tabpanel.is-hidden { display: none; }

/* Empty-state panel for tabs without data yet (Keuangan, Perencanaan). */
.dash-empty {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  text-align: center;
  padding: 80px 24px;
  background: var(--bg-soft);
  border: 1px dashed var(--line);
  min-height: 360px;
}
.dash-empty__icon {
  font-size: 64px;
  color: var(--primary);
  background: var(--surface);
  width: 96px; height: 96px;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--line);
  margin-bottom: 20px;
  padding: 12px
}
.dash-empty__title {
  margin: 0 0 8px; font-size: 22px; font-weight: 700; color: var(--ink);
}
.dash-empty__desc {
  margin: 0; max-width: 420px; font-size: 14px; line-height: 1.5; color: var(--ink-soft);
}
.dash-empty__badge {
  margin-top: 18px; padding: 5px 12px;
  font-size: 11px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
  background: var(--primary); color: #fff;
  border-radius: 2px;
}

/* SDG Relative Activity Index radar (Dampak tab). Renderer is D3; it sizes
   the SVG against viewport height each draw, so the host only needs a
   conservative floor before the first ResizeObserver tick. The clamp scales
   up on tall screens so the polygon fills available space. */
.chart-card--radar [data-sdg-radar-viz] {
  width: 100%;
  min-height: clamp(520px, 78vh, 880px);
  display: flex; flex-direction: column; align-items: stretch;
}
.sdg-radar-legend {
  justify-content: center;
  gap: 18px;
  margin: 4px 0 10px;
  font-size: 12px;
}

/* SDG Output vs FWCI diverging bar (Dampak tab). Pyramid bar membutuhkan
   lebar horizontal sebesar mungkin — span seluruh kolom grid di desktop
   supaya kedua sisi bar punya ruang ekstra (dan label tengah tidak berdesakan
   dengan bar). Min-height tetap viewport-aware. */
.chart-card--diverging {
  grid-column: 1 / -1;
}
.chart-card--diverging [data-sdg-pub-viz] {
  width: 100%;
  min-height: clamp(620px, 82vh, 980px);
  display: flex; flex-direction: column; align-items: stretch;
}
.sdg-pub-legend {
  justify-content: center;
  gap: 14px 18px;
  margin: 4px 0 10px;
  font-size: 12px;
}

/* International collaboration footprint (Internasionalisasi tab). Kartu span
   seluruh kolom grid supaya layout kiri-kanan (peta dunia + tren stacked area)
   punya area horizontal yang cukup; di mobile turun ke 1 kolom otomatis.
   Tinggi override default 365px karena KPI strip + split-panel butuh ruang
   lebih; viewport-aware clamp menjaga layout tetap fit di monitor berbeda. */
.chart-card--collab {
  grid-column: 1 / -1;
  height: auto;
  /* Layout 3 panel tertumpuk + KPI 2×2 + ranking 2-kolom — konten yang ada
     sendiri sudah cukup tinggi (peta + ranking 2-col + area chart). Tidak
     perlu floor besar; biar tinggi mengikuti konten supaya tidak ada ruang
     kosong tersisa di bawah. */
  min-height: 480px;
}
.chart-card--collab [data-articles-by-country-viz] {
  width: 100%; min-height: 340px;
  display: flex; flex-direction: column; align-items: stretch;
  gap: 10px;
}
/* 3-baris tertumpuk: Peta → Ranking → Tren. Sebelumnya peta+ranking sejajar
   pada baris pertama dan area di baris kedua, tapi peta yang sempit (½ lebar
   kartu) sulit dibaca pada negara kecil dan ranking jadi sangat tinggi karena
   12 item bertumpuk vertikal. Dengan semua panel full-width: peta bisa
   melebar, ranking dimekarkan ke 2 kolom (6+6), area chart tetap punya
   tempat. */
.collab-split {
  display: grid;
  grid-template-columns: 1fr;
  grid-template-areas:
    "map"
    "rank"
    "area";
  gap: 12px;
  margin-top: 4px;
}
.collab-split__panel--map  { grid-area: map; }
.collab-split__panel--rank { grid-area: rank; }
.collab-split__panel--area { grid-area: area; }
.collab-split__panel {
  background: #fffdf7;
  border: 1px solid var(--line);
  padding: 10px 12px;
  display: flex; flex-direction: column;
  gap: 6px;
  min-width: 0;
}
.collab-split__head {
  display: flex; align-items: flex-start; gap: 8px;
  padding-bottom: 4px;
  border-bottom: 1px solid var(--line);
}
.collab-split__head .material-symbols-rounded,
.collab-split__head svg {
  font-size: 16px !important;
  color: var(--primary-dark);
  width: 16px; height: 16px; flex-shrink: 0; margin-top: 1px;
}
.collab-split__title {
  margin: 0; font-size: 12.5px; font-weight: 700; color: var(--ink); line-height: 1.2;
}
.collab-split__sub {
  margin: 1px 0 0; font-size: 10.5px; color: var(--ink-soft); line-height: 1.35;
}
.collab-area-host { width: 100%; flex: 1; min-height: 220px; }
.collab-area-host svg { display: block; width: 100%; height: auto; }
/* Saat legend & map viz dipakai di dalam panel split (bukan edge-to-edge card),
   buang padding kiri-kanan yang tadinya untuk break-out 16px. */
.collab-split__panel .collab-geo__legend { padding: 0; }
.collab-split__panel .collab-geo__viz { background: #fff; }

/* Ranking panel — daftar Top 12 negara mitra dengan bar proporsional.
   Tiap baris: posisi · label · bar · nilai (angka + persen total).
   Bar di-tint dengan warna stacked-area-nya supaya cross-reference dengan
   chart tren mudah (Tiongkok di area chart = warna sama di ranking).
   Sekarang panel full-width — dipecah 2 kolom (6+6) supaya tidak menumpuk
   12 baris vertikal yang bikin kartu jangkung. Di <760px turun ke 1 kolom. */
.collab-rank {
  list-style: none; margin: 0; padding: 0;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 4px 16px;
}
@media (max-width: 760px) {
  .collab-rank { grid-template-columns: 1fr; }
}
.collab-rank__row {
  --c: var(--primary);
  display: grid;
  grid-template-columns: 22px minmax(0, 1fr) minmax(60px, 2fr) auto;
  align-items: center;
  gap: 8px;
  padding: 4px 6px;
  border-radius: 3px;
  cursor: default;
  font-size: 12px;
  transition: background .12s ease;
}
.collab-rank__row:hover { background: var(--bg-soft); }
.collab-rank__pos {
  font-weight: 700; font-size: 11px; color: var(--c);
  text-align: right;
}
.collab-rank__label {
  font-weight: 600; color: var(--ink);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.collab-rank__bar {
  display: block;
  height: 8px; background: #f6e9c8; border-radius: 4px; overflow: hidden;
}
.collab-rank__fill {
  display: block; height: 100%; background: var(--c);
  border-radius: 4px;
  transition: width .35s ease;
}
.collab-rank__val {
  font-weight: 700; color: var(--ink); white-space: nowrap;
  display: inline-flex; align-items: baseline; gap: 4px;
}
.collab-rank__val small {
  font-weight: 500; font-size: 10px; color: var(--ink-soft);
}
.collab-rank__row {
  cursor: pointer;
}
.collab-rank__row.is-active {
  background: #fff7e6;
  outline: 1px solid #e8d093;
}

/* Inline country-detail panel — replaces the pop-up modal. Lives below the
   stacked-area panel in .collab-split (full row). Header shows the active
   country (color-coded CC chip + name + rank/share). The KPI grid mirrors
   the prior modal's 6 stat cards, followed by the per-year bar chart and a
   collapsible raw-data table. Click a country in the map or in the Top
   Negara Mitra list to update this panel in place. */
.collab-split {
  grid-template-areas: "map";
}
/* Layout #tab-internasionalisasi — override default .dash-grid 3-kolom
   menjadi 2-kolom dengan posisi eksplisit per panel sehingga DOM order
   (chart-card → rank → area → detail dari setupArticlesByCountry) tetap
   bisa direnderkan dengan urutan visual berbeda: peta full-row di atas,
   rank|area 2 kolom di tengah, detail full-row paling akhir. */
#tab-internasionalisasi {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}
#tab-internasionalisasi > .chart-card--collab {
  /* chart-card--collab default `grid-column: 1 / -1` (full-row) tetap
     dipertahankan — peta butuh lebar penuh agar negara-negara kecil tetap
     terbaca. Pin ke baris 1 supaya tidak ke-shuffle oleh auto-flow. */
  grid-column: 1 / -1;
  grid-row: 1;
}
#tab-internasionalisasi > .collab-split__panel--rank {
  grid-column: 1 / 2;
  grid-row: 2;
}
#tab-internasionalisasi > .collab-split__panel--area {
  grid-column: 2 / 3;
  grid-row: 2;
}
#tab-internasionalisasi > .collab-split__panel--detail {
  /* Paling akhir — full-row di bawah rank/area supaya tabel + chart bar per
     tahun punya ruang horizontal yang cukup tanpa ter-squeeze ke 1/2 lebar. */
  grid-column: 1 / -1;
  grid-row: 3;
}
#tab-internasionalisasi > .collab-split__panel--rank,
#tab-internasionalisasi > .collab-split__panel--area,
#tab-internasionalisasi > .collab-split__panel--detail {
  min-width: 0;
  min-height: 280px;
}
/* Top Negara Mitra di kolom sempit (1/2 lebar): paksa 1-kolom internal supaya
   label tidak ter-truncate. */
#tab-internasionalisasi > .collab-split__panel--rank .collab-rank {
  grid-template-columns: 1fr;
}
@media (max-width: 980px) {
  /* Di tablet (.dash-grid 2-col default): biarkan auto-flow agar tinggi tidak
     buang ruang. Detail tetap di paling akhir karena dia di-append terakhir
     ke outerGrid di setupArticlesByCountry. */
  #tab-internasionalisasi > .chart-card--collab,
  #tab-internasionalisasi > .collab-split__panel--rank,
  #tab-internasionalisasi > .collab-split__panel--area,
  #tab-internasionalisasi > .collab-split__panel--detail {
    grid-column: 1 / -1;
    grid-row: auto;
  }
  #tab-internasionalisasi > .collab-split__panel--rank,
  #tab-internasionalisasi > .collab-split__panel--area {
    grid-column: span 1;
  }
}
@media (max-width: 640px) {
  /* Mobile — single column, stack vertikal sesuai DOM order. */
  #tab-internasionalisasi { grid-template-columns: 1fr; }
  #tab-internasionalisasi > .collab-split__panel--rank,
  #tab-internasionalisasi > .collab-split__panel--area {
    grid-column: 1 / -1;
  }
}
.collab-detail__cc {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 28px; height: 18px; padding: 0 6px;
  background: var(--primary);
  color: #fff; font-weight: 700; font-size: 10.5px;
  letter-spacing: .02em; border-radius: 3px;
  margin-right: 6px;
  vertical-align: 1px;
}
.collab-detail__kpi {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px;
  margin: 6px 0 4px;
}
@media (max-width: 760px) {
  .collab-detail__kpi { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 460px) {
  .collab-detail__kpi { grid-template-columns: 1fr; }
}
.collab-detail__kpi-card {
  --c: var(--primary);
  display: flex; flex-direction: column;
  padding: 8px 10px;
  background: var(--bg-soft);
  border: 1px solid var(--line);
  border-left: 3px solid var(--c);
  min-width: 0;
}
.collab-detail__kpi-label {
  font-size: 10px; font-weight: 600; color: var(--ink-soft);
  letter-spacing: .02em; text-transform: uppercase;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.collab-detail__kpi-value {
  font-size: 16px; font-weight: 700; color: var(--ink);
  margin-top: 2px; line-height: 1.2;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.collab-detail__kpi-value small {
  font-size: 11px; font-weight: 600; color: var(--ink-soft); margin-left: 4px;
}
.collab-detail__kpi-sub {
  font-size: 10px; color: var(--ink-soft); margin-top: 2px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.collab-detail__section { display: flex; flex-direction: column; gap: 4px; margin-top: 4px; }
.collab-detail__section-head {
  font-size: 11px; font-weight: 700; color: var(--ink-soft);
  text-transform: uppercase; letter-spacing: .04em;
}
.collab-detail__chart {
  background: #fff; border: 1px solid var(--line); padding: 6px 8px;
  min-height: 220px;
}
.collab-detail__chart svg { display: block; width: 100%; height: auto; }
.collab-detail__details { margin-top: 4px; border: 1px solid var(--line); background: var(--surface); }
.collab-detail__details summary {
  list-style: none; cursor: pointer; padding: 7px 10px;
  font-size: 12px; font-weight: 600; color: var(--ink);
  position: relative; padding-left: 22px;
}
.collab-detail__details summary::-webkit-details-marker { display: none; }
.collab-detail__details summary::before {
  content: '▸'; position: absolute; left: 8px; top: 50%;
  transform: translateY(-50%) rotate(0); transition: transform .15s ease;
  color: var(--ink-soft); font-size: 11px;
}
.collab-detail__details[open] summary::before { transform: translateY(-50%) rotate(90deg); }
.collab-detail__details summary:hover { background: var(--bg-soft); }
.collab-detail__table-wrap { max-height: 280px; overflow: auto; background: var(--surface); }

/* KPI strip — 4 angka ringkas (total intl publikasi, jumlah mitra, mitra
   terbesar, snapshot tahun terbaru). Dipaksa 2×2 supaya label panjang
   ("Mitra terbesar" = nama negara) dan nilai punya cukup lebar dan tidak
   bertabrakan dengan label/sub di kolom sebelahnya. Di mobile tetap 2×2
   (turun jadi 1 kolom di layar sangat sempit). */
/* Default hidden di grid card supaya area chart tetap ringkas; KPI strip
   hanya dimunculkan saat card di-zoom ke modal (.dash-zoom) di mana
   ruang lebih lega untuk menampilkan ringkasan angka. */
.collab-kpi { display: none; }
.dash-zoom .collab-kpi {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
  margin: 2px 0 10px;
}
.collab-kpi__card {
  display: flex; flex-direction: column;
  padding: 9px 12px;
  background: var(--bg-soft);
  border: 1px solid var(--line);
  border-left: 3px solid var(--primary);
  min-width: 0;
}
.collab-kpi__label {
  font-size: 10.5px; font-weight: 600; color: var(--ink-soft);
  letter-spacing: .02em; text-transform: uppercase;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.collab-kpi__value {
  font-size: 18px; font-weight: 700; color: var(--ink);
  margin-top: 2px; line-height: 1.2;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.collab-kpi__sub {
  font-size: 11px; color: var(--ink-soft);
  margin-top: 2px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.collab-legend {
  justify-content: center;
  gap: 3px 8px;
  margin: 1px 0 3px;
  font-size: 9.5px;
  color: var(--ink-soft);
}
.collab-legend .chart-legend__item { padding: 0 2px; line-height: 1.3; }
.collab-legend .chart-legend__item i { width: 7px; height: 7px; margin-right: 4px; }
@media (max-width: 520px) {
  .dash-zoom .collab-kpi { grid-template-columns: 1fr; }
}

/* International collaboration geochart — choropleth world map shown
   above the stacked-area on the Internasionalisasi tab. Runs flush to
   the card edges so the world reads at full card width. */
.collab-geo {
  display: flex; flex-direction: column;
  gap: 4px;
  /* Break out of the card's inner padding (.chart-card__body default
     padding) so the map sits edge-to-edge against the card border. */
  margin: 4px -16px 8px;
}
.collab-geo__head {
  display: flex; align-items: flex-start; gap: 8px;
  padding: 0 16px;
}
.collab-geo__head .material-symbols-rounded,
.collab-geo__head svg {
  font-size: 16px !important;
  color: var(--primary-dark);
  width: 16px; height: 16px; flex-shrink: 0; margin-top: 1px;
}
.collab-geo__title {
  margin: 0; font-size: 12.5px; font-weight: 700; color: var(--ink); line-height: 1.2;
}
.collab-geo__sub {
  margin: 1px 0 0; font-size: 10.5px; color: var(--ink-soft); line-height: 1.35;
}
.collab-geo__viz {
  width: 100%;
  background: #fff;
  display: block;
}
.collab-geo__viz svg { display: block; width: 100%; height: auto; }
.collab-geo__svg path {
  cursor: pointer; transition: fill .15s ease, stroke .15s ease;
}
.collab-geo__svg path:hover {
  stroke: #1f1407; stroke-width: 0.9;
}
.collab-geo__legend {
  display: flex; align-items: center; flex-wrap: wrap;
  gap: 4px 12px;
  padding: 0 16px;
  font-size: 10.5px; color: var(--ink-soft);
}
.collab-geo__legend-cap {
  flex: 1; min-width: 160px;
}
.collab-geo__legend-nd {
  display: inline-flex; align-items: center; gap: 6px;
}
.collab-geo__legend-nd i {
  width: 12px; height: 8px; display: inline-block;
}
.collab-geo__error {
  padding: 36px 18px;
  text-align: center;
  font-size: 11.5px; color: var(--ink-soft); font-style: italic;
  background: #fffdf7;
}

/* ---- Country detail modal — Peta Kolaborasi Internasional ---------------
   Opens on map-country click (and on ranking-row click). Shows headline
   KPIs, a per-year bar chart, and a collapsible year/count table for the
   selected partner country. Mirrors the iku-modal pattern but uses the
   amber/orange UNSRI palette so the surface ties visually to the parent
   chart. */
.collab-modal {
  position: fixed; inset: 0;
  display: flex; align-items: center; justify-content: center;
  /* Above the zoom modal (1500), tooltip (1500), and any sticky chrome —
     so clicking a country on the world map always brings this modal to the
     top, even when it overlaps the chart zoom view or the snackbar. */
  z-index: 9999;
  opacity: 0;
  transition: opacity .18s ease;
  pointer-events: none;
}
.collab-modal.is-open { opacity: 1; pointer-events: auto; }
.collab-modal[hidden] { display: none; }
.collab-modal__backdrop {
  position: absolute; inset: 0;
  background: rgba(15, 23, 42, .55);
  backdrop-filter: blur(2px);
}
.collab-modal__shell {
  position: relative;
  background: var(--surface);
  border: 1px solid var(--line);
  width: min(820px, 94vw);
  max-height: 88vh;
  display: flex; flex-direction: column;
  box-shadow: 0 24px 60px -20px rgba(0,0,0,.4);
  transform: translateY(8px);
  transition: transform .18s ease;
}
.collab-modal.is-open .collab-modal__shell { transform: translateY(0); }
.collab-modal__head {
  padding: 16px 56px 14px 18px;
  border-bottom: 1px solid var(--line);
  background: linear-gradient(180deg, #fffdf7 0%, var(--surface) 100%);
}
.collab-modal__head-row {
  display: flex; align-items: center; gap: 12px;
}
.collab-modal__cc {
  font-size: 14px; font-weight: 800; letter-spacing: .04em;
  color: #fff; background: var(--c, var(--primary-dark));
  padding: 6px 10px; border-radius: 4px;
  flex-shrink: 0;
}
.collab-modal__title-wrap { min-width: 0; }
.collab-modal__title {
  margin: 0; font-size: 17px; font-weight: 700; color: var(--ink);
  line-height: 1.25;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.collab-modal__sub {
  margin: 2px 0 0; font-size: 11.5px; color: var(--ink-soft); line-height: 1.4;
}
.collab-modal__close {
  position: absolute; top: 10px; right: 10px;
  width: 32px; height: 32px;
  border: 1px solid var(--line);
  background: var(--surface);
  display: inline-flex; align-items: center; justify-content: center;
  cursor: pointer;
  color: var(--ink-soft);
  transition: background .15s ease, color .15s ease;
}
.collab-modal__close:hover { background: var(--bg-soft); color: var(--ink); }
.collab-modal__close .material-symbols-rounded { font-size: 18px; }
.collab-modal__body {
  flex: 1;
  overflow: auto;
  padding: 16px 18px 20px;
  display: flex; flex-direction: column; gap: 14px;
}

/* KPI grid — 3 kolom di desktop (turun ke 2 lalu 1 di sempit). Border kiri
   menonjolkan accent dari series-color negara (atau fallback amber). */
.collab-modal__kpi-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px;
}
@media (max-width: 640px) {
  .collab-modal__kpi-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 420px) {
  .collab-modal__kpi-grid { grid-template-columns: 1fr; }
}
.collab-modal__kpi {
  display: flex; flex-direction: column;
  padding: 9px 12px;
  background: var(--bg-soft);
  border: 1px solid var(--line);
  border-left: 3px solid var(--c, var(--primary));
  min-width: 0;
}
.collab-modal__kpi-label {
  font-size: 10.5px; font-weight: 600; color: var(--ink-soft);
  letter-spacing: .02em; text-transform: uppercase;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.collab-modal__kpi-value {
  font-size: 18px; font-weight: 700; color: var(--ink);
  margin-top: 2px; line-height: 1.2;
}
.collab-modal__kpi-value small {
  font-size: 11px; font-weight: 500; color: var(--ink-soft); margin-left: 4px;
}
.collab-modal__kpi-sub {
  font-size: 11px; color: var(--ink-soft);
  margin-top: 2px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

.collab-modal__section { display: flex; flex-direction: column; gap: 6px; }
.collab-modal__section-head {
  font-size: 11px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
  color: var(--ink-soft);
}
.collab-modal__chart {
  width: 100%;
  min-height: 200px;
  background: #fffdf7;
  border: 1px solid var(--line);
  padding: 8px;
}
.collab-modal__chart svg { display: block; width: 100%; height: auto; }
.collab-modal__empty {
  padding: 32px 12px;
  text-align: center; font-size: 11.5px; color: var(--ink-soft); font-style: italic;
}

.collab-modal__details {
  border: 1px solid var(--line);
  background: var(--bg-soft);
}
.collab-modal__details summary {
  padding: 8px 12px;
  cursor: pointer;
  font-size: 12px; font-weight: 600; color: var(--ink);
  user-select: none;
  list-style: none;
}
.collab-modal__details summary::-webkit-details-marker { display: none; }
.collab-modal__details summary::before {
  content: '▸';
  display: inline-block;
  margin-right: 6px;
  color: var(--ink-soft);
  transition: transform .15s ease;
}
.collab-modal__details[open] summary::before { transform: rotate(90deg); }
.collab-modal__details summary:hover { background: var(--surface); }
.collab-modal__table-wrap { max-height: 260px; overflow: auto; background: var(--surface); }
.collab-modal__table {
  width: 100%;
  border-collapse: separate; border-spacing: 0;
  font-size: 12.5px; color: var(--ink);
}
.collab-modal__table thead th {
  position: sticky; top: 0; z-index: 1;
  background: var(--bg-soft);
  color: var(--ink-soft);
  font-weight: 700; letter-spacing: .02em; text-transform: uppercase;
  font-size: 10.5px;
  padding: 8px 12px;
  border-bottom: 1px solid var(--line);
  white-space: nowrap;
  text-align: left;
}
.collab-modal__table tbody td {
  padding: 6px 12px;
  border-bottom: 1px solid var(--line);
  line-height: 1.35;
  white-space: nowrap;
}
.collab-modal__table tbody tr:last-child td { border-bottom: 0; }
.collab-modal__table tbody tr:hover { background: var(--bg-soft); }

/* Rekap Penelitian per sumber dana (Riset & Inovasi tab) — single chart card
   with: KPI strip → combined legend → combo (stacked bars + line) → bottom
   panel pair (donut + horizontal-bar ranking). Always full width — the host
   itself drives the inner layout. */
.chart-card--riset [data-riset-penelitian-viz] {
  width: 100%;
  /* KPI strip (~80px) + combo (340) + donut/rank row (300) + gaps → ~740px.
     Use clamp so very tall screens get more room without forcing tiny ones
     beyond the floor. */
  min-height: clamp(740px, 78vh, 960px);
  display: flex; flex-direction: column; align-items: stretch;
  gap: 8px;
}
/* Full-page mode — saat kartu Rekap berdiri sendiri di pagination halaman 1,
   stretch ke tinggi viewport (sama mekanika dengan kartu table) supaya semua
   panel internal terlihat tanpa scroll. Span seluruh kolom grid juga. */
.chart-card--riset.chart-card--page-fill {
  height: calc(100vh - 200px);
  min-height: 620px;
  grid-column: 1 / -1;
}
.chart-card--riset.chart-card--page-fill [data-riset-penelitian-viz] {
  height: 100%;
}
.riset-kpi {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 8px;
  margin: 2px 0 4px;
}
.riset-kpi__card {
  display: flex; flex-direction: column;
  padding: 8px 10px;
  background: var(--bg-soft);
  border: 1px solid var(--line);
  border-left: 3px solid var(--primary);
}
.riset-kpi__label {
  font-size: 10px; font-weight: 600; color: var(--ink-soft);
  letter-spacing: .02em; text-transform: uppercase;
}
.riset-kpi__value {
  font-size: 10px; font-weight: 700; color: var(--ink);
  margin-top: 2px; line-height: 1.2;
}
.riset-kpi__sub {
  font-size: 10.5px; color: var(--ink-soft);
  margin-top: 2px;
}
@media (max-width: 760px) {
  .riset-kpi { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* Plot Riset & Inovasi — combo grouped-bar (dana, axis kiri) + 2 line series
   (jumlah penelitian, axis kanan) per tahun. Ukurannya MATCH dengan kartu
   lain di halaman Pendanaan: tidak override grid-column (jadi span 1 dari
   .chart-card--full) dan tidak override height (jadi 365px dari
   .chart-card:not(.metric)). KPI strip dikompres jadi 2 baris karena lebar
   1-kolom (~300px). ECharts combo otomatis menyusut via ResizeObserver. */
.chart-card--plotriset [data-plot-riset-inovasi-viz] {
  width: 100%; height: 100%; min-height: 0;
  display: flex; flex-direction: column; align-items: stretch;
  gap: 6px;
}
.chart-card--plotriset .plotriset-kpi {
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 4px;
}
.chart-card--plotriset .plotriset-kpi__item { padding: 4px 8px; }
.chart-card--plotriset .plotriset-kpi__item b { font-size: 11px; }
.chart-card--plotriset .plotriset-kpi__label { font-size: 9px; }
.plotriset-chart { width: 100%; flex: 1; min-height: 0; display: block; }
.plotriset-chart svg { display: block; width: 100%; height: auto; }
.plotriset-legend2 {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 6px 24px;
  padding: 6px 4px 0;
  font-size: 11px;
  color: #3d2f12;
}
.plotriset-legend2__item {
  display: inline-flex; align-items: center; gap: 8px;
  white-space: nowrap;
}
.plotriset-legend2__sw {
  width: 14px; height: 10px; display: inline-block;
}
.plotriset-legend2__line {
  position: relative;
  width: 22px; height: 2px;
  background: var(--c);
  display: inline-block;
}
.plotriset-legend2__line::after {
  content: '';
  position: absolute;
  top: -3px; left: 7px;
  width: 8px; height: 8px;
  background: var(--c);
  border: 1.5px solid #fff;
  border-radius: 50%;
}
@media (max-width: 760px) {
  .plotriset-legend2 { grid-template-columns: 1fr; }
}
.plotriset-kpi {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 8px;
  margin: 2px 0 4px;
}
.plotriset-kpi__item {
  --c: var(--primary);
  display: flex; flex-direction: column;
  padding: 8px 10px;
  background: var(--bg-soft);
  border: 1px solid var(--line);
  border-left: 3px solid var(--c);
  font-size: 10px;
}
.plotriset-kpi__label {
  font-size: 10px; font-weight: 600; color: var(--ink-soft);
  letter-spacing: .02em; text-transform: uppercase;
}
.plotriset-kpi__item b {
  font-size: 10px; font-weight: 700; color: var(--ink);
  margin-top: 2px; line-height: 1.2;
}
.plotriset-legend {
  justify-content: center;
  gap: 8px 16px;
  font-size: 12px;
}
@media (max-width: 960px) {
  .plotriset-kpi { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (max-width: 560px) {
  .plotriset-kpi { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

.riset-legend {
  justify-content: center;
  gap: 8px 16px;
  margin: 2px 0 4px;
  font-size: 11.5px;
  flex-wrap: wrap;
}
.riset-legend__line {
  display: inline-flex; align-items: center;
  width: 22px; height: 10px;
  background: transparent !important;
  border: none !important;
}

.riset-combo {
  width: 100%;
  background: #fffdf7;
  border: 1px solid var(--line);
  padding: 4px 0 2px;
}
.riset-combo svg { display: block; width: 100%; height: auto; }
.riset-grid line { stroke: #f0e3c8; }

.riset-bottom {
  display: grid;
  grid-template-columns: minmax(260px, 1fr) 1.4fr;
  gap: 10px;
  margin-top: 4px;
}
.riset-bottom__panel {
  background: var(--bg-soft);
  border: 1px solid var(--line);
  padding: 10px 12px;
  display: flex; flex-direction: column; gap: 4px;
}
.riset-bottom__title {
  margin: 0; font-size: 12.5px; font-weight: 700; color: var(--ink); line-height: 1.2;
}
.riset-bottom__sub {
  margin: 0; font-size: 10.5px; color: var(--ink-soft); line-height: 1.4;
}
.riset-donut, .riset-rank { width: 100%; margin-top: 4px; }
.riset-donut svg, .riset-rank svg { display: block; width: 100%; height: auto; }
.riset-rank__bar { transition: filter .15s ease; cursor: pointer; }
.riset-rank__bar:hover { filter: brightness(1.08); }
@media (max-width: 860px) {
  .riset-bottom { grid-template-columns: 1fr; }
}

/* ============================================================
   Keuangan / Penerimaan — single unified page (Keuangan tab).
   Sections are NOT wrapped in chart cards; they share a common
   surface so the page reads as one cohesive financial brief.
   ============================================================ */
.dash-page {
  background: var(--surface);
  border: 1px solid var(--line);
  padding: 14px 16px;
  display: flex; flex-direction: column; gap: 4px;
}
.dash-page__head {
  display: flex; align-items: center; gap: 10px;
  padding-bottom: 8px; margin-bottom: 8px;
  border-bottom: 1px solid var(--line);
}
.dash-page__icon {
  flex: none; width: 30px; height: 30px;
  display: inline-flex; align-items: center; justify-content: center;
  color: #fff;
  padding: 6px;
}
.dash-page__icon .material-symbols-rounded { font-size: 16px; }
.dash-page__title {
  margin: 0; font-size: 15px; font-weight: 700; color: var(--ink);
  letter-spacing: -.01em; line-height: 1.2;
}
.dash-page__desc {
  margin: 2px 0 0; font-size: 11.5px; color: var(--ink-soft); line-height: 1.35;
}

/* Login gate — gated modules (Keuangan, Perencanaan) render their full layout
   as a teaser, but the data is blurred and a gradient scrim + lock prompt sits
   on top until the visitor signs in. The page header stays readable (it isn't
   blurred and the scrim is transparent at the top), so users still see which
   module they're looking at. See partials/loginGate.hbs. */
.dash-page--locked {
  position: relative;
  overflow: hidden;
  min-height: 360px;
}
.dash-page--locked > *:not(.dash-page__head):not(.login-gate) {
  filter: blur(7px);
  pointer-events: none;
  user-select: none;
}
.login-gate {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  z-index: 4;
  background: linear-gradient(180deg,
    transparent 0%,
    var(--surface-translucent) 36%,
    var(--surface-translucent-strong) 100%);
}
.login-gate__panel {
  display: flex; flex-direction: column; align-items: center; text-align: center;
  gap: 8px;
  max-width: 360px;
  padding: 22px 24px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 0;
  box-shadow: 0 16px 40px rgba(0,0,0,.18);
}
.login-gate__icon {
  flex: none; width: 46px; height: 46px;
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--ink);
  margin-bottom: 2px;
}
.login-gate__icon.material-symbols-rounded { font-size: 24px; }
.login-gate__title {
  margin: 0; font-size: 15px; font-weight: 700; color: var(--ink);
}
.login-gate__desc {
  margin: 0; font-size: 12.5px; color: var(--ink-soft); line-height: 1.45;
}
.login-gate__btn {
  display: inline-flex; align-items: center; gap: 6px;
  margin-top: 6px; padding: 8px 18px;
  font-size: 13px; font-weight: 600; text-decoration: none;
  color: var(--ink);
  background: var(--accent);
  border-radius: 999px;
  transition: filter .15s ease, transform .15s ease;
}
.login-gate__btn:hover:not([disabled]) { filter: brightness(.95); transform: translateY(-1px); }
.login-gate__btn[disabled] {
  background: var(--line);
  color: var(--ink-soft);
  cursor: not-allowed;
  opacity: .8;
}
.login-gate__btn .material-symbols-rounded { font-size: 18px; }

.keu-page {
  display: flex; flex-direction: column; gap: 10px;
}
.keu-page__body {
  display: flex; flex-direction: column; gap: 14px;
}

/* Year filter — compact pill bar above the page body. Shared between every
   Keuangan submenu (Penerimaan, Realisasi Anggaran, …) so the picker
   placement + chrome is consistent across the whole module. */
.keu-filter {
  display: flex; align-items: center; flex-wrap: wrap;
  gap: 4px 6px;
  padding: 4px 8px;
  background: var(--bg-soft);
  border: 1px solid var(--line);
}
.keu-filter__label {
  font-size: 10.5px; font-weight: 700; color: var(--ink-soft);
  letter-spacing: .05em; text-transform: uppercase;
  margin-right: 2px;
}
.keu-filter__pill {
  appearance: none;
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--ink);
  font-size: 12px; font-weight: 600;
  padding: 3px 10px;
  cursor: pointer;
  border-radius: 999px;
  line-height: 1.4;
  transition: background .15s ease, color .15s ease, border-color .15s ease;
}
.keu-filter__pill:hover { border-color: var(--primary); color: var(--primary-dark); }
.keu-filter__pill.is-active {
  background: var(--primary);
  color: #fff;
  border-color: var(--primary);
}
.keu-filter__pill[data-empty="true"] {
  color: var(--ink-soft);
  font-weight: 500;
  font-style: italic;
}
.keu-filter__pill[data-empty="true"].is-active {
  background: #94a3b8;
  color: #fff;
  border-color: #94a3b8;
  font-style: normal;
}

/* In-progress empty state — shown when the picked year has no data yet. */
.keu-empty {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  text-align: center;
  padding: 36px 20px;
  background: var(--bg-soft);
  border: 1px dashed var(--line);
  min-height: 220px;
  gap: 6px;
}
.keu-empty__icon {
  font-size: 38px; color: var(--primary);
  background: var(--surface);
  width: 60px; height: 60px;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--line);
  margin-bottom: 4px;
}
.keu-empty__title {
  margin: 0; font-size: 15px; font-weight: 700; color: var(--ink);
}
.keu-empty__desc {
  margin: 0; max-width: 460px; font-size: 12px; line-height: 1.5; color: var(--ink-soft);
}
.keu-empty__badge {
  margin-top: 6px; padding: 3px 10px;
  font-size: 10px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
  background: var(--primary); color: #fff;
}

/* Perencanaan — blok historis tahun arsip (mis. 2025). Hero-style card,
   bukan empty/alert state, untuk menonjolkan satu angka capaian saja. */
.per-historis {
  position: relative;
  background:
    radial-gradient(120% 80% at 0% 0%, rgba(29, 78, 216, .07), transparent 55%),
    linear-gradient(180deg, var(--surface), var(--bg-soft));
  border: 1px solid var(--line);
  border-left: 1px solid var(--primary);
  padding: 24px 28px 22px;
  display: flex; flex-direction: column; gap: 12px;
  overflow: hidden;
}
.per-historis::before {
  content: '';
  position: absolute; top: -60px; right: -60px;
  width: 220px; height: 220px;
  background: radial-gradient(circle, rgba(29, 78, 216, .08), transparent 70%);
  pointer-events: none;
}
.per-historis__chip {
  align-self: flex-start;
  display: inline-flex; align-items: center; gap: 6px;
  padding: 4px 10px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 999px;
  font-size: 11px; font-weight: 700;
  color: var(--primary-dark);
  letter-spacing: .04em; text-transform: uppercase;
}
.per-historis__chip .material-symbols-rounded {
  font-size: 14px !important;
}
.per-historis__title {
  margin: 0;
  font-size: 22px; font-weight: 800; letter-spacing: -.01em;
  color: var(--ink);
  line-height: 1.2;
}
.per-historis__lede {
  margin: 0; max-width: 720px;
  font-size: 13px; line-height: 1.55; color: var(--ink-soft);
}
.per-historis__totalbox {
  margin-top: 6px;
  display: flex; flex-direction: column; gap: 2px;
  padding: 18px 20px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-top: 0;
  align-self: stretch;
}
.per-historis__totallbl {
  font-size: 11px; font-weight: 700;
  letter-spacing: .08em; text-transform: uppercase;
  color: var(--ink-soft);
}
.per-historis__totalval {
  font-size: 34px; font-weight: 800; letter-spacing: -.015em;
  color: var(--primary-dark);
  font-variant-numeric: tabular-nums;
  line-height: 1.15;
  word-break: break-word;
}
.per-historis__totalsub {
  font-size: 12px; color: var(--ink-soft);
}
.per-historis__meta {
  margin-top: 4px;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 10px;
}
@media (max-width: 760px) {
  .per-historis__meta { grid-template-columns: 1fr; }
  .per-historis__totalval { font-size: 26px; }
  .per-historis { padding: 18px 18px 16px; }
}
.per-historis__metaitem {
  display: flex; align-items: flex-start; gap: 10px;
  padding: 10px 12px;
  background: var(--surface);
  border: 1px solid var(--line);
  text-align: left;
}
.per-historis__metaitem--link {
  cursor: pointer;
  font: inherit; color: inherit;
  appearance: none;
  transition: background .15s ease, border-color .15s ease,
              transform .15s ease, box-shadow .15s ease;
}
.per-historis__metaitem--link:hover,
.per-historis__metaitem--link:focus-visible {
  background: var(--surface);
  border-color: var(--primary);
  box-shadow: 0 4px 14px rgba(29, 78, 216, .14);
  transform: translateY(-1px);
  outline: none;
}
.per-historis__metaitem--link:hover .material-symbols-rounded,
.per-historis__metaitem--link:focus-visible .material-symbols-rounded {
  transform: translateX(2px);
}
.per-historis__metaitem--link .material-symbols-rounded {
  transition: transform .15s ease;
}
.per-historis__metaitem--link:active {
  transform: translateY(0);
  box-shadow: 0 1px 4px rgba(29, 78, 216, .12);
}
.per-historis__metaitem .material-symbols-rounded {
  font-size: 20px !important;
  color: var(--primary);
  margin-top: 1px;
}
.per-historis__metaitem > div {
  display: flex; flex-direction: column; gap: 1px;
  min-width: 0;
}
.per-historis__metaitem b {
  font-size: 11px; font-weight: 700;
  color: var(--ink);
  letter-spacing: .04em; text-transform: uppercase;
}
.per-historis__metaitem span {
  font-size: 12px; color: var(--ink-soft); line-height: 1.4;
}

/* Headline KPI strip — same row, no card chrome between tiles. */
.keu-kpi {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 8px;
}
.keu-kpi__card {
  padding: 8px 12px;
  background: var(--bg-soft);
  border: 1px solid var(--line);
  border-left: 3px solid var(--primary);
  display: flex; flex-direction: column;
  position: relative;
}
.keu-kpi__card--lead { border-left-color: #a16207; background: #fff7e0; }
.keu-kpi__card--pos { border-left-color: #16a34a; }
.keu-kpi__card--neg { border-left-color: #b91c1c; }
/* Optional watermark icon in the top-right corner. Cards without an icon
   span are unaffected — used by the Realisasi Anggaran KPI strip. */
.keu-kpi__icon {
  position: absolute; top: 8px; right: 10px;
  font-size: 18px;
  color: var(--primary); opacity: .55;
  pointer-events: none;
}
.keu-kpi__card--lead .keu-kpi__icon { color: #a16207; opacity: .75; }
.keu-kpi__card--pos  .keu-kpi__icon { color: #16a34a; opacity: .7; }
.keu-kpi__card--neg  .keu-kpi__icon { color: #b91c1c; opacity: .7; }
.keu-kpi__card:has(.keu-kpi__icon) { padding-right: 36px; }
.keu-kpi__label {
  font-size: 10.5px; font-weight: 600; color: var(--ink-soft);
  letter-spacing: .02em; text-transform: uppercase;
}
.keu-kpi__value {
  font-size: 18px; font-weight: 700; color: var(--ink);
  margin-top: 1px; line-height: 1.2;
}
.keu-kpi__sub {
  font-size: 11px; color: var(--ink-soft); margin-top: 1px;
}

/* Sections — no surrounding card; only a section heading separates them. */
.keu-section {
  display: flex; flex-direction: column; gap: 6px;
  padding-top: 6px;
  border-top: 1px dashed var(--line);
}
.keu-section__head {
  margin: 0; font-size: 13.5px; font-weight: 700;
  color: var(--ink); letter-spacing: -.005em;
  display: inline-flex; align-items: center; gap: 6px;
  line-height: 1.25;
}
.keu-section__head--sub { font-size: 12.5px; }
.keu-section__icon {
  font-size: 16px; color: #a16207;
  background: #fff7e0;
  width: 24px; height: 24px;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid #f5e3b2; border-radius: 5px;
  flex-shrink: 0;
}
.keu-section__sub {
  margin: 0; font-size: 11.5px; color: var(--ink-soft); line-height: 1.4;
}
.keu-section__total {
  margin: 2px 0 0; font-size: 11.5px; color: var(--ink-soft);
}
.keu-section__note {
  margin: 4px 0 0; font-size: 11px; color: var(--ink-soft); font-style: italic;
}
.keu-legend {
  justify-content: flex-start;
  gap: 4px 14px; margin: 0 0 2px; font-size: 11.5px;
}
.keu-viz {
  width: 100%; min-height: 60px;
}

/* ----------------------------------------------------------------------- */
/* Alumni Tracer Study — overview KPI strip (reuses .keu-kpi) + a responsive */
/* 2-column card grid. Rendered by setupAlumniTracer in dashboard.js.        */
/* ----------------------------------------------------------------------- */
.altr { display: flex; flex-direction: column; gap: 14px; }
.altr-kpi { margin-bottom: 2px; }
.altr-grid {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px;
}
.altr-card {
  display: flex; flex-direction: column; gap: 8px;
  padding: 12px 14px; min-width: 0;
  background: var(--surface); border: 1px solid var(--line); border-radius: 8px;
}
.altr-card--full { grid-column: 1 / -1; }
.altr-card__head { display: flex; align-items: flex-start; gap: 8px; }
.altr-card__icon {
  font-size: 18px; color: #0e7490; background: #e0f2fe;
  width: 26px; height: 26px; border: 1px solid #bae6fd; border-radius: 6px;
  flex-shrink: 0; display: inline-flex; align-items: center; justify-content: center;
}
.altr-card__title { margin: 0; font-size: 13px; font-weight: 700; color: var(--ink); line-height: 1.25; }
.altr-card__sub { margin: 1px 0 0; font-size: 11px; color: var(--ink-soft); line-height: 1.35; }
.altr-viz { width: 100%; min-height: 60px; }
.altr-viz .tick text { fill: var(--ink-soft); }
.altr-note { font-size: 12.5px; color: var(--ink-soft); padding: 16px 2px; }
.altr-note code { font-size: 11.5px; background: var(--bg-soft); padding: 1px 5px; border-radius: 4px; }
/* Faculty ranking table */
.altr-table { width: 100%; border-collapse: collapse; font-size: 12px; }
.altr-table th, .altr-table td {
  padding: 6px 8px; border-bottom: 1px solid var(--line);
  text-align: left; white-space: nowrap;
}
.altr-table th {
  font-size: 10.5px; text-transform: uppercase; letter-spacing: .02em;
  color: var(--ink-soft); font-weight: 700;
}
.altr-table td.altr-num, .altr-table th.altr-num { text-align: right; }
.altr-table__rank { width: 28px; color: var(--ink-soft); font-weight: 700; text-align: center; }
.altr-table tbody tr:hover { background: var(--bg-soft); }
@media (max-width: 720px) {
  .altr-grid { grid-template-columns: minmax(0, 1fr); }
  .altr-card--full { grid-column: auto; }
  .altr-table { font-size: 11px; }
}

/* Pengesahan flow — Saldo Awal → Pendapatan → Belanja → Saldo Akhir.
   Reused by the Realisasi Anggaran page to show the year-end ledger as a
   single horizontal flow strip. Wraps on narrow screens. */
.keu-flow {
  display: flex; flex-wrap: wrap; align-items: stretch; gap: 6px 8px;
}
.keu-flow__step {
  display: flex; align-items: center; gap: 8px;
  padding: 6px 10px;
  background: var(--bg-soft);
  border: 1px solid var(--line);
  border-left: 3px solid #a16207;
  flex: 1 1 160px; min-width: 160px;
}
.keu-flow__label {
  display: block;
  font-size: 10px; font-weight: 600; color: var(--ink-soft);
  letter-spacing: .02em; text-transform: uppercase;
}
.keu-flow__value {
  display: block; font-size: 14px; font-weight: 700; color: var(--ink);
  line-height: 1.2;
}
.keu-flow__arrow {
  align-self: center; color: var(--ink-soft); font-size: 16px;
}
@media (max-width: 600px) {
  .keu-flow__arrow { display: none; }
}

/* Realisasi Anggaran — per-sumber-dana summary chip row.
   One chip per kode sumber dana (002/003/004/005), color-coded via --c. */
.rea-sumber {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
  gap: 6px;
  margin: 2px 0 4px;
}
.rea-sumber__card {
  padding: 7px 10px;
  background: var(--bg-soft);
  border: 1px solid var(--line);
  border-left: 3px solid var(--c, var(--primary));
  display: flex; flex-direction: column; gap: 1px;
}
.rea-sumber__head {
  display: flex; align-items: center; gap: 6px;
}
.rea-sumber__icon {
  font-size: 14px; color: var(--c, var(--primary));
  width: 22px; height: 22px;
  background: color-mix(in srgb, var(--c, var(--primary)) 14%, white);
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid color-mix(in srgb, var(--c, var(--primary)) 28%, white);
  border-radius: 5px;
  flex-shrink: 0;
}
.rea-sumber__kode {
  font-size: 10.5px; font-weight: 700; color: var(--c, var(--primary));
  letter-spacing: .04em;
}
.rea-sumber__sumber {
  font-size: 11.5px; font-weight: 600; color: var(--ink);
}
.rea-sumber__value {
  font-size: 14.5px; font-weight: 700; color: var(--ink); line-height: 1.2;
}
.rea-sumber__sub {
  font-size: 11px; color: var(--ink-soft);
}

/* Rincian Belanja — detail table per Sumber Dana × Kelompok Biaya.
   Baris kepala (rib-detail__group) gelap dengan accent border-left
   warna sumber dana, baris detail terang. Kolom Serapan menampilkan
   mini-bar persentase berwarna sesuai band serapan. */
.rib-detail {
  width: 100%;
  overflow-x: auto;
  border: 1px solid var(--line);
  background: var(--surface);
}
.rib-detail__table {
  width: 100%;
  border-collapse: collapse;
  font-size: 12.5px;
}
.rib-detail__table thead th {
  background: var(--bg-soft);
  color: var(--ink-soft);
  font-size: 11px; font-weight: 700;
  letter-spacing: .04em; text-transform: uppercase;
  padding: 8px 10px;
  text-align: left;
  border-bottom: 1px solid var(--line);
  white-space: nowrap;
}
.rib-detail__table td {
  padding: 7px 10px;
  border-bottom: 1px solid var(--line);
  vertical-align: middle;
  color: var(--ink);
}
.rib-detail__table tbody tr:last-child td { border-bottom: 0; }
.rib-detail__col-kode { width: 88px; font-family: 'JetBrains Mono', ui-monospace, monospace; font-size: 11.5px; }
.rib-detail__num { text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; }
.rib-detail__serapan { width: 180px; }
.rib-detail__bar {
  position: relative;
  height: 18px;
  background: #f3f4f6;
  border-radius: 3px;
  overflow: hidden;
}
.rib-detail__bar-fill {
  position: absolute; inset: 0 auto 0 0;
  background: var(--primary);
  opacity: .25;
}
.rib-detail__bar-text {
  position: relative; z-index: 1;
  display: block;
  text-align: right;
  padding: 0 6px;
  line-height: 18px;
  font-size: 11px; font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.rib-detail__group td {
  background: #fff7e0;
  border-left: 3px solid var(--c, var(--primary));
}
.rib-detail__group td:first-child { border-left-width: 3px; }
.rib-detail__kode-pill {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--c, var(--primary));
  color: #fff;
  font-size: 10.5px; font-weight: 700;
  letter-spacing: .04em;
}
.rib-detail__row td:first-child { padding-left: 24px; color: var(--ink-soft); }
.rib-detail__total td {
  background: var(--bg-soft);
  border-top: 2px solid var(--line);
  font-size: 13px;
}

/* Drill-down zone — two columns on desktop, stacked on small screens. */
.keu-drilldown {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 20px 24px;
  padding-top: 8px;
  border-top: 1px dashed var(--line);
}
.keu-drilldown__col {
  display: flex; flex-direction: column; gap: 6px;
}
@media (max-width: 900px) {
  .keu-kpi { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .keu-drilldown { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 560px) {
  .dash-page { padding: 16px; }
  .keu-kpi { grid-template-columns: minmax(0, 1fr); }
}

/* Chart grid pagination — controls injected by dashboard.js below the grid.
   Cards on inactive pages get `.is-hidden` so only one page is visible. */
/* !important is necessary — the flex layout rule below
   (.chart-card:not(.chart-card--metric)) has equal specificity and would
   otherwise override this with display: flex, leaving paginated cards
   visible and stacking onto every page. */
.chart-card.is-hidden { display: none !important; }
.dash-pager {
  display: flex; align-items: center; justify-content: center; gap: 14px;
  margin: 16px 0 8px;
  font-size: 13px; color: var(--ink-soft);
}
.dash-pager__info { min-width: 140px; text-align: center; font-weight: 600; color: var(--ink); }
.dash-pager__btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px; padding: 0;
  background: var(--surface); color: var(--ink-soft);
  border: 1px solid var(--line); border-radius: 2px; cursor: pointer;
  transition: color .15s ease, border-color .15s ease, background .15s ease;
}
.dash-pager__btn:hover:not(:disabled) {
  color: var(--primary-dark); border-color: var(--primary); background: var(--bg-soft);
}
.dash-pager__btn:disabled { opacity: .4; cursor: default; }
.dash-pager__btn .material-symbols-rounded { font-size: 20px; }

/* Header variant — sits to the right of the domain title (always visible). */
.dash-pager--header {
  margin: 0 0 0 auto;     /* push to the far right of the domain header */
  gap: 8px;
  font-size: 12px;
}
.dash-pager--header .dash-pager__info { min-width: 110px; font-size: 12px; }
.dash-pager--header .dash-pager__btn { width: 28px; height: 28px; }
.dash-pager--header .dash-pager__btn .material-symbols-rounded { font-size: 18px; }
@media (max-width: 560px) {
  .dash-pager--header .dash-pager__info { display: none; }
}

/* Labeled (sub-menu) pagination — used on the Riset & Inovasi tab.
   The info slot turns into a horizontal pill strip when pages carry
   `data-page-label`. Each pill jumps directly to its page; chevrons remain
   as a secondary affordance. */
.dash-pager__info--tabs {
  min-width: 0;
  display: flex; flex-wrap: wrap; gap: 6px; align-items: center; justify-content: center;
}
.dash-pager__tab {
  appearance: none;
  border: 1px solid var(--line); background: var(--surface); color: var(--ink-soft);
  padding: 5px 12px; border-radius: 16px;
  font-size: 12px; font-weight: 600; line-height: 1;
  cursor: pointer; white-space: nowrap;
  transition: color .15s ease, background .15s ease, border-color .15s ease;
}
.dash-pager__tab:hover { background: var(--bg-soft); color: var(--primary-dark); border-color: var(--primary); }
.dash-pager__tab.is-active {
  background: var(--primary); color: #fff; border-color: var(--primary);
  box-shadow: 0 2px 6px rgba(234, 88, 12, .25);
}
.dash-pager--header .dash-pager__tab { padding: 4px 10px; font-size: 11px; }
@media (max-width: 560px) {
  .dash-pager--header .dash-pager__info--tabs { display: flex; }
  .dash-pager--header .dash-pager__tab { padding: 3px 8px; font-size: 10px; }
}
/* Toolbar above the content panel — compact single-line strip with title +
   live/mock badge + refresh button. Title and subtitle sit inline so the
   header stays short and the data starts higher in the viewport. */
.dash-toolbar {
  display: flex; align-items: center; justify-content: space-between;
  gap: 8px; flex-wrap: wrap; margin-bottom: 8px;
  border-bottom: 1px solid var(--line); padding-bottom: 6px;
}
.dash-toolbar__lead {
  display: flex; align-items: center; gap: 8px; min-width: 0; flex: 1 1 auto;
}
.dash-toolbar__titles {
  display: flex; align-items: baseline; gap: 8px; min-width: 0; flex-wrap: wrap;
}
.dash-title { margin: 0; font-size: 15px; font-weight: 700; color: var(--ink); letter-spacing: -.01em; line-height: 1.2; }
.dash-subtitle {
  margin: 0; font-size: 11px; color: var(--ink-soft); line-height: 1.25;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  max-width: 60ch;
}
.dash-source {
  display: inline-flex; align-items: center; gap: 3px;
  font-size: 10px; font-weight: 600; padding: 2px 6px; border-radius: 2px;
  white-space: nowrap;
}
.dash-source .material-symbols-rounded { font-size: 12px; }
.dash-source--live { background: #e6f4ea; color: #2e7d32; }
.dash-source--mock { background: var(--bg-blue); color: var(--primary-dark); }

/* Domain section — one bordered container holds the domain header, the
   compact KPI strip, and the 3-column chart grid as a single visual unit. */
.dash-domain {
  margin-bottom: 18px;
  scroll-margin-top: 120px;
  background: var(--surface);
  border: 1px solid var(--line);
  padding: 12px 14px 10px;
}
.dash-domain__head {
  display: flex; align-items: center; gap: 10px;
  margin: 0 0 8px;
  padding-bottom: 6px;
  border-bottom: 1px dashed var(--line);
}
.dash-domain__icon {
  width: 28px; height: 28px; border-radius: 2px; color: #fff;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 16px;
  padding: 4px;
}
.dash-domain__title { margin: 0; font-size: 14px; font-weight: 700; color: var(--ink); letter-spacing: -.01em; line-height: 1.2; }
.dash-domain__desc { margin: 1px 0 0; font-size: 11.5px; color: var(--ink-soft); line-height: 1.25; }

/* Group sibling tabs — horizontal strip below the domain title that mirrors the
   sidebar group's children (e.g. Dosen / Tenaga Kependidikan). Reuses the amber
   primary accent so the active tab matches the sidebar's active leaf. */
.dash-domain-tabs {
  display: flex; flex-wrap: wrap; gap: 6px;
  margin: 0 0 14px;
  border-bottom: 1px solid var(--line);
  padding-bottom: 0;
}
.dash-domain-tab {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 7px 12px;
  background: none; border: none; cursor: pointer;
  font: 600 12px 'Roboto', sans-serif; color: var(--ink-soft);
  border-bottom: 2px solid transparent;
  margin-bottom: -1px; /* overlap the strip border so the active underline meets it */
  transition: color .15s ease, border-color .15s ease, background .15s ease;
}
.dash-domain-tab__icon { font-size: 16px; color: inherit; }
.dash-domain-tab:hover { color: var(--ink); background: rgba(245,158,11,.08); }
.dash-domain-tab.is-active {
  color: var(--primary-dark);
  border-bottom-color: var(--primary);
}

/* KPI metric strip — sits inside the domain container. Tiles are compact and
   pack tightly so they read as a header strip above the chart grid. */
.dash-metrics {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 8px;
  margin-bottom: 14px;
}
.dash-metrics:empty { display: none; }
.dash-metrics:empty + .dash-grid { /* no metrics → no extra spacing */ }

/* Chart grid — strict 3-column layout inside the domain container. */
.dash-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 14px;
  /* `dense` backfills the gap a wide (span-2) card leaves at a row break with a
     later single-column card, so the grid never has holes. */
  grid-auto-flow: row dense;
}
.dash-grid:empty { display: none; }

/* All charts render in a strict 3-column grid — wide/full/page-fill modifiers
   are kept on the markup for potential future use but no longer change layout.
   Every card occupies exactly one column track at every breakpoint. */
.chart-card--wide,
.chart-card--full,
.chart-card--page-fill { grid-column: span 1; }
/* Tables are the one exception: a 9-column resume needs the full grid row to
   stay readable. Span all 3 tracks on desktop / 2 on tablet / 1 on mobile. */
.chart-card--table { grid-column: 1 / -1; }
/* Generic placeholder-label charts (mock "Kategori A/B/C…") drift to the end
   of their grid track so real data shows first on any mixed page. The pager
   itself also moves them to the last page — this only handles the boundary
   page where real + placeholder cards may be visible together. */
.chart-card--generic { order: 1; }
@media (max-width: 980px) {
  .dash-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 640px) {
  .dash-grid { grid-template-columns: 1fr; }
}

/* Uniform card size — every non-metric chart card is 365px tall so the grid
   reads as a calm matrix instead of a ragged staircase. The card is a flex
   column: head is fixed, body + viz fill the remaining space. min-height: 0
   on the flex children unlocks shrinking so dense charts (heatmaps, grouped
   bars) fit the viewport rather than pushing the card taller. Overflow is
   hidden in the grid — the zoom modal is the place to inspect dense detail. */
.chart-card:not(.chart-card--metric) {
  height: 365px;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
/* Tables fill the viewport so the resume can be scanned without scrolling the
   whole page. Offset accounts for the sticky appbar (~45px), the dash toolbar
   (~38px), the domain header (~58px), and the pager + margins (~40px). The
   inner `.dash-table__wrap` scrolls so dense tables stay self-contained. */
.chart-card.chart-card--table {
  height: calc(100vh - 200px);
  min-height: 480px;
}
.chart-card:not(.chart-card--metric) .chart-card__head { flex: none; }
.chart-card:not(.chart-card--metric) .chart-card__body {
  margin-top: 10px;
  flex: 1; min-height: 0;
  display: flex; flex-direction: column;
}
.chart-card:not(.chart-card--metric) .chart-card__viz {
  flex: 1; min-height: 0;
}

/* Borderless cards: the domain container provides the outer frame, so each
   card is flat and separated only by the grid gap. A faint surface tint helps
   the eye group title + viz without drawing a line around every widget. */
.chart-card {
  border: 1px solid transparent;
  background: var(--bg-soft);
  box-shadow: none;
  transition: background-color .15s ease, border-color .15s ease;
}
.chart-card:hover {
  box-shadow: none;
  background: var(--surface);
  border-color: var(--line);
}

/* Chart card badge + states (extends the existing .chart-card) */
.chart-card__titles { min-width: 0; flex: 1 1 auto; }
.chart-card__title {
  font-size: 14px; font-weight: 700; color: var(--ink);
  line-height: 1.25; letter-spacing: -.005em;
}
.chart-card__desc {
  margin: 2px 0 0; font-size: 11.5px; color: var(--ink-soft);
  line-height: 1.35;
}
.chart-card__badge {
  flex: none; font-size: 10px; font-weight: 700; letter-spacing: .04em;
  text-transform: uppercase; color: var(--ink-soft);
  background: transparent; padding: 3px 0; border-radius: 0;
}
.chart-card__body { margin-top: 6px; }

/* ----------------------------------------------------------------------- */
/* Loading skeletons — disabled per user request. Cards render empty during */
/* the brief fetch window rather than showing shimmer placeholders. The     */
/* JS still injects the skeleton DOM (kept for forward-compat); CSS just    */
/* keeps it invisible. !important because some places set the skeleton via  */
/* innerHTML inside elements that may inherit display from flex layouts.    */
/* ----------------------------------------------------------------------- */
.chart-card__skeleton { display: none !important; }
.chart-card__skeleton {
  position: relative;
  border-radius: var(--radius);
  background: var(--bg-soft);
  overflow: hidden;
  color: rgba(245,158,11,.22); /* skeleton-tone — flows into SVG via currentColor */
}
.chart-card__skeleton::after {
  content: '';
  position: absolute; inset: 0;
  background: rgba(255,255,255,.18);
  pointer-events: none;
}
[data-theme="dark"] .chart-card__skeleton {
  background: rgba(245,158,11,.06);
  color: rgba(251,191,36,.18);
}
[data-theme="dark"] .chart-card__skeleton::after {
  background: rgba(251,191,36,.04);
}

/* Number-shaped block for KPI metric tiles. Kept short — these cards are
   compact, so a tall skeleton would dwarf the live value. */
.chart-card__skeleton--metric { height: 24px; max-width: 70%; margin: 2px 0; }

/* Viz skeleton — full chart height, hosts the inline SVG shape. */
.chart-card__skeleton--viz { height: 180px; display: block; padding: 12px; }
.chart-card__skeleton--viz svg {
  width: 100%; height: 100%; display: block;
  fill: currentColor; color: inherit;
}

@keyframes dash-shimmer {
  0% { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}
@media (prefers-reduced-motion: reduce) {
  .chart-card__skeleton::after { animation: none; opacity: .5; }
}
.chart-card__error {
  display: flex; align-items: center; justify-content: center; gap: 8px;
  height: 180px; color: #b91c1c; font-size: 13px;
}

/* Metric tile (rendered into a metric-type chart card) */
/* Ultra-compact KPI cards inside the unified domain container. Designed to
   sit as a header strip above the chart grid — short, narrow, and many per
   row without towering the section. */
.chart-card--metric {
  padding: 8px 10px;
  background: var(--surface);
  border: 1px solid var(--line);
  position: relative;
  min-height: 0;
}
.chart-card--metric:hover { background: var(--surface); border-color: #e3d2ab; }
.chart-card--metric .chart-card__head { margin-bottom: 0; align-items: center; }
.chart-card--metric .chart-card__title {
  font-size: 10.5px; font-weight: 600; color: var(--ink-soft);
  text-transform: uppercase; letter-spacing: .03em;
  line-height: 1.2;
  /* Truncate long KPI labels — full text shows in the tooltip / zoom view. */
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
}
.chart-card--metric .chart-card__desc { display: none; }   /* label above already says it */
.chart-card--metric .chart-card__badge { display: none; }  /* type badge is noise on a number */
.chart-card--metric .chart-card__body { margin-top: 4px; }
.chart-card--metric .chart-card__viz { height: auto; min-height: 0; }
.chart-card--metric .chart-card__skeleton--metric { height: 18px; max-width: 60%; }
.metric-tile { display: flex; flex-direction: column; gap: 0; }
.metric-tile__value {
  font-size: 18px; font-weight: 700; line-height: 1.1; color: var(--accent-deep);
  letter-spacing: -.01em;
}
.metric-tile__label { display: none; } /* title in the card head carries the label */

/* KPI icon (metric cards): small, tinted, anchored to the card's top-right
   corner. `color` is set inline per domain and flows into the SVG stroke. */
.chart-card__icon {
  position: absolute; right: 8px; top: 8px;
  display: inline-flex; align-items: center; justify-content: center;
  opacity: .65; pointer-events: none;
}
.chart-card__icon .hicon { width: 14px; height: 14px; display: block; }

/* Responsive: tighten layout on tablet/mobile */
@media (max-width: 1280px) {
  .dash-shell { grid-template-columns: 232px minmax(0, 1fr); }
  .dash-content { padding: 12px 16px 32px; }
}
@media (max-width: 960px) {
  /* Sidebar collapses to a slide-in drawer; menu toggle appears in content. */
  .dash-shell { grid-template-columns: 1fr; }
  .dash-sidebar {
    position: fixed; top: 0; left: 0; bottom: 0; height: 100vh;
    width: 280px; max-width: 86vw;
    z-index: 1200;
    transform: translateX(-100%);
    transition: transform .25s ease;
    box-shadow: 0 12px 32px rgba(43,33,16,.18);
    border-right: 1px solid var(--line);
  }
  .dash-sidebar.is-open { transform: translateX(0); }
  .dash-sidebar__close { display: inline-flex; }
  .dash-sidebar-toggle { display: none; } /* tombol Menu disembunyikan di mobile */
  .dash-back { display: none; } /* back-to-portal hanya muncul di desktop */
  .dash-content { padding: 10px 12px 32px; }
  .dash-domain { padding: 10px 10px 8px; }
}
@media (max-width: 560px) {
  .dash-title { font-size: 16px; }
  .dash-empty { padding: 56px 16px; min-height: 280px; }
  .dash-empty__icon { width: 76px; height: 76px; font-size: 48px; }
  .dash-metrics { gap: 6px; }
}

/* Backdrop for the mobile drawer (created by JS when sidebar opens). */
.dash-sidebar-backdrop {
  position: fixed; inset: 0; z-index: 1190;
  background: rgba(43,33,16,.45);
  opacity: 0; visibility: hidden;
  transition: opacity .2s ease, visibility .2s;
}
.dash-sidebar-backdrop.is-open { opacity: 1; visibility: visible; }

/* Dashboard toolbar actions + refresh button */
.dash-toolbar__actions { display: inline-flex; align-items: center; gap: 8px; }
.dash-refresh {
  display: inline-flex; align-items: center; gap: 4px; cursor: pointer; border: none;
  font-size: 12px; padding: 5px 10px;
}
.dash-refresh .material-symbols-rounded { font-size: 15px; }
.dash-refresh:disabled { opacity: .7; cursor: default; }
.dash-refresh.is-loading .material-symbols-rounded { animation: dash-spin .8s linear infinite; }
@keyframes dash-spin { to { transform: rotate(360deg); } }

/* Back-to-top button — hidden until scrolled, fades in bottom-right. */
.to-top {
  position: fixed; right: 24px; bottom: 24px; z-index: 1300;
  width: 44px; height: 44px; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--primary); color: #fff;
  border: none; border-radius: 2px; cursor: pointer;
  box-shadow: var(--shadow-2);
  opacity: 0; visibility: hidden; transform: translateY(8px);
  transition: opacity .2s ease, transform .2s ease, visibility .2s, background .2s;
}
.to-top:hover { background: var(--primary-dark); }
.to-top.is-visible { opacity: 1; visibility: visible; transform: translateY(0); }
.to-top .material-symbols-rounded { font-size: 22px; }
@media (max-width: 560px) { .to-top { right: 16px; bottom: 16px; } }

/* ===================================================================== */
/* Sidebar search — filters menu items + dashboard charts in real time.   */
/* ===================================================================== */
.dash-search {
  position: relative;
  margin: 2px 2px 8px;
}
.dash-search__icon {
  position: absolute; left: 8px; top: 50%; transform: translateY(-50%);
  font-size: 15px; color: var(--ink-soft); pointer-events: none;
}
.dash-search__input {
  width: 100%;
  padding: 7px 28px 7px 28px;
  background: var(--surface);
  border: 1px solid var(--line); border-radius: 2px;
  color: var(--ink);
  font: 500 12px 'Roboto', sans-serif;
  outline: none;
  transition: border-color .15s ease, box-shadow .15s ease;
  -webkit-appearance: none; appearance: none;
}
.dash-search__input::placeholder { color: var(--ink-soft); opacity: .8; }
/* Strip the browser's native clear button — the custom .dash-search__clear
   below is the only ✕ users should see. */
.dash-search__input::-webkit-search-cancel-button,
.dash-search__input::-webkit-search-decoration { -webkit-appearance: none; appearance: none; display: none; }
.dash-search__input::-ms-clear { display: none; width: 0; height: 0; }
.dash-search__input::-ms-reveal { display: none; width: 0; height: 0; }
.dash-search__input:focus {
  border-color: var(--primary);
  box-shadow: 0 0 0 3px rgba(245,158,11,.18);
}
.dash-search__clear {
  position: absolute; right: 4px; top: 50%; transform: translateY(-50%);
  display: none; align-items: center; justify-content: center;
  width: 18px; height: 18px; padding: 0;
  background: none; border: none; cursor: pointer;
  color: var(--ink-soft); border-radius: 2px;
}
.dash-search__clear:hover { color: var(--primary-dark); background: var(--bg-soft); }
.dash-search__clear .material-symbols-rounded { font-size: 16px; }
.dash-search.has-value .dash-search__clear { display: inline-flex; }

.dash-search__results {
  position: absolute; top: calc(100% + 4px); left: 0; right: 0; z-index: 30;
  max-height: 360px; overflow-y: auto;
  background: var(--surface);
  border: 1px solid var(--line);
  box-shadow: var(--shadow-2);
  display: none;
}
.dash-search.is-open .dash-search__results { display: block; }
.dash-search__group {
  padding: 6px 12px 4px;
  font-size: 10px; font-weight: 700; letter-spacing: .12em; text-transform: uppercase;
  color: var(--ink-soft);
  background: var(--bg-soft);
  border-bottom: 1px solid var(--line);
}
.dash-search__item {
  display: flex; align-items: center; gap: 10px;
  width: 100%; padding: 8px 12px;
  background: none; border: none; cursor: pointer;
  text-align: left;
  color: var(--ink);
  font: 500 13px 'Roboto', sans-serif;
  border-bottom: 1px solid var(--line);
  transition: background .12s ease;
}
.dash-search__item:hover, .dash-search__item.is-focused {
  background: var(--bg-soft); color: var(--primary-dark);
}
.dash-search__item:last-child { border-bottom: none; }
.dash-search__item-icon { font-size: 18px; color: var(--primary-dark); flex: none; }
.dash-search__item-text { flex: 1; min-width: 0; }
.dash-search__item-title { display: block; line-height: 1.2; }
.dash-search__item-sub {
  display: block; font-size: 10.5px; color: var(--ink-soft); margin-top: 2px;
}
.dash-search__item-meta {
  flex: none; font-size: 10px; font-weight: 700;
  color: var(--ink-soft); text-transform: uppercase; letter-spacing: .04em;
}
.dash-search__empty {
  padding: 16px 14px; font-size: 12.5px; color: var(--ink-soft); text-align: center;
}
mark.dash-search__hit {
  background: rgba(245,158,11,.22); color: inherit; padding: 0 1px;
}

/* When the search briefly highlights a card after navigating to it. */
.chart-card.is-search-flash {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
  animation: dash-flash 1.6s ease-out 1 forwards;
}
@keyframes dash-flash {
  0% { box-shadow: 0 0 0 0 rgba(245,158,11,.55); }
  70% { box-shadow: 0 0 0 14px rgba(245,158,11,0); }
  100% { outline-color: transparent; box-shadow: none; }
}

/* ===================================================================== */
/* Per-card zoom button + modal                                          */
/* ===================================================================== */
.chart-card__head-actions {
  display: inline-flex; align-items: center; gap: 6px; flex: none;
}
/* Zoom button is always visible at a soft opacity, then lifts on hover/focus.
   This signals every card is zoomable without waiting for hover. */
.chart-card__zoom {
  display: inline-flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; padding: 0;
  background: none; border: 1px solid transparent; border-radius: 2px;
  cursor: pointer; color: var(--ink-soft);
  opacity: .55;
  transition: opacity .15s ease, color .15s ease,
              background .15s ease, border-color .15s ease;
}
.chart-card:hover .chart-card__zoom,
.chart-card:focus-within .chart-card__zoom { opacity: 1; }
.chart-card__zoom:hover {
  color: var(--primary-dark); background: var(--surface); border-color: var(--line);
}
.chart-card__zoom .material-symbols-rounded { font-size: 16px; }

/* Make the whole non-metric card feel clickable — a subtle cursor hint and
   a soft lift on hover backs up the zoom button affordance. */
.chart-card:not(.chart-card--metric) { cursor: zoom-in; }
.chart-card:not(.chart-card--metric):hover { background: var(--surface); }

.dash-zoom {
  position: fixed; inset: 0; z-index: 1500;
  display: flex; align-items: center; justify-content: center;
  padding: 24px;
}
.dash-zoom[hidden] { display: none; }
.dash-zoom__backdrop {
  position: absolute; inset: 0;
  background: rgba(20,15,8,.72);
  backdrop-filter: blur(3px);
}
/* Fixed-size shell that fills the viewport — modal never grows past the
   screen and never spawns an outer scrollbar. Children manage their own
   overflow inside this bounding box. */
.dash-zoom__shell {
  position: relative;
  display: flex; flex-direction: column;
  width: min(100%, 1200px);
  height: min(820px, calc(100vh - 48px));
  max-height: calc(100vh - 48px);
  background: var(--surface);
  color: var(--ink);
  border: 1px solid var(--line);
  box-shadow: 0 24px 60px rgba(0,0,0,.4);
  animation: dash-zoom-in .2s ease-out;
  overflow: hidden;
}
/* Tables have many columns and need horizontal room. When a table card is
   zoomed, stretch the shell to ~5/6 of the viewport (≈83vw) and drop the
   side info panel so every column can be read without horizontal scroll on
   typical laptop screens. */
.dash-zoom[data-chart-type="table"] .dash-zoom__shell {
  width: min(100%, 83vw);
  height: calc(100vh - 48px);
}
.dash-zoom[data-chart-type="table"] .dash-zoom__layout {
  grid-template-columns: minmax(0, 1fr);
}
.dash-zoom[data-chart-type="table"] .dash-zoom__info { display: none; }

/* Self-rendered rich widgets (Rekap Penelitian, Plot Riset & Inovasi) — they
   already pack KPI strips + multiple sub-panels into one card, so they need
   the full modal width and the info panel suppressed. The shell expands to
   ~92vw with full viewport height so the rekap's combo + donut + ranking
   panels all render at usable sizes. */
.dash-zoom[data-chart-type^="self-"] .dash-zoom__shell {
  width: min(100%, 92vw);
  height: calc(100vh - 32px);
  max-height: calc(100vh - 32px);
}
.dash-zoom[data-chart-type^="self-"] .dash-zoom__layout {
  grid-template-columns: minmax(0, 1fr);
}
.dash-zoom[data-chart-type^="self-"] .dash-zoom__info { display: none; }
.dash-zoom[data-chart-type^="self-"] .dash-zoom__body .chart-card {
  overflow: auto;     /* let the rich widget scroll internally if needed */
}
/* The viz host inside Rekap is tall (KPI + combo + donut + ranking); allow
   it to expand to its natural height instead of being clipped by the flex
   container. */
.dash-zoom[data-chart-type^="self-"] .dash-zoom__body .chart-card__viz {
  overflow: visible;
  flex: 0 0 auto;
}
.dash-zoom[data-chart-type="self-risetPenelitian"] [data-riset-penelitian-viz] {
  min-height: calc(100vh - 200px);
}
.dash-zoom[data-chart-type="self-plotRisetInovasi"] [data-plot-riset-inovasi-viz] {
  min-height: calc(100vh - 240px);
}
@keyframes dash-zoom-in {
  from { opacity: 0; transform: scale(.98); }
  to   { opacity: 1; transform: scale(1); }
}
.dash-zoom__head {
  display: flex; align-items: center; justify-content: space-between; gap: 14px;
  padding: 12px 18px;
  border-bottom: 1px solid var(--line);
  background: var(--bg-soft);
}
.dash-zoom__title { margin: 0; font-size: 16px; font-weight: 700; color: var(--ink); letter-spacing: -.01em; }
.dash-zoom__close {
  display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; padding: 0;
  background: var(--surface); border: 1px solid var(--line); cursor: pointer;
  color: var(--ink-soft); border-radius: 2px;
  transition: color .15s ease, background .15s ease;
}
.dash-zoom__close:hover { color: var(--primary-dark); background: var(--bg-soft); }
.dash-zoom__close .material-symbols-rounded { font-size: 20px; }
.dash-zoom__body {
  padding: 16px;
  flex: 1; min-height: 0;
  overflow: hidden;            /* no outer scrollbar — children scroll instead */
  background: var(--surface);
}
/* Single-column layout: the chart claims the full modal body width so it
   has the maximum room to breathe. The side info panel is appended by JS
   but hidden here — keep the JS untouched while the chart takes the room. */
.dash-zoom__layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 16px;
  height: 100%;
  min-height: 0;
  align-items: stretch;
}
.dash-zoom__info { display: none; }
/* The cloned card becomes a flex column so its viz can claim the leftover
   space below the head + legend, instead of demanding a fixed min-height. */
.dash-zoom__body .chart-card {
  display: flex; flex-direction: column;
  height: 100%; min-height: 0;
  box-shadow: none; border: 1px solid var(--line); background: var(--surface);
  cursor: default; padding: 16px;
  overflow: hidden;
}
.dash-zoom__body .chart-card:hover { background: var(--surface); border-color: var(--line); }
.dash-zoom__body .chart-card__zoom { display: none; }
.dash-zoom__body .chart-card__head { flex: none; }
.dash-zoom__body .chart-card__title { font-size: 17px; }
.dash-zoom__body .chart-card__desc { font-size: 13px; margin-top: 4px; }
.dash-zoom__body .chart-card__body {
  flex: 1; min-height: 0;
  display: flex; flex-direction: column;
  margin-top: 8px;
}
/* Viz expands to fill the card body, but if its intrinsic content is taller
   (e.g. a heatmap with many golongan rows), it scrolls internally — never
   the modal. min-height: 0 unlocks the flex child shrink. */
.dash-zoom__body .chart-card__viz {
  flex: 1; min-height: 0;
  overflow: auto;
}
.dash-zoom__body .chart-card canvas {
  width: 100% !important;
  height: 100% !important;
}

/* ---- Bigger, clearer legend inside the zoom modal ----
   Legend is rendered before the SVG by some widgets; we pull it out of the
   flex column flow as a fixed-height block so it never overlaps the chart. */
.dash-zoom__body .chart-legend {
  flex: none;
  gap: 6px 14px;
  margin: 6px 0 8px;
  padding: 8px 10px;
  background: var(--bg-soft);
  border: 1px solid var(--line);
  max-height: 25%;
  overflow: auto;
}
.dash-zoom__body .chart-legend__item {
  font-size: 12.5px; font-weight: 500; color: var(--ink);
  gap: 8px;
}
.dash-zoom__body .chart-legend__item i {
  width: 13px; height: 13px;
  box-shadow: 0 0 0 1px rgba(0,0,0,.08) inset;
}

/* ---- Info side panel ----
   Pinned to the body height, scrolls internally if its own content overflows
   (e.g. on small viewports). Never causes the modal to scroll. */
.dash-zoom__info {
  display: flex; flex-direction: column; gap: 12px;
  padding: 14px;
  background: var(--bg-soft);
  border: 1px solid var(--line);
  font-size: 13px;
  min-height: 0; max-height: 100%;
  overflow: auto;
}
.dash-zoom__desc {
  margin: 0; font-size: 13px; line-height: 1.5; color: var(--ink);
}
.dash-zoom__chips {
  display: flex; flex-wrap: wrap; gap: 6px;
  padding-bottom: 12px;
  border-bottom: 1px dashed var(--line);
}
.dash-zoom__chip {
  --chip-accent: var(--primary);
  display: inline-flex; align-items: center; gap: 8px;
  padding: 4px 8px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-left: 3px solid var(--chip-accent);
  min-width: 60px;
}
.dash-zoom__chip-icon {
  font-size: 18px; line-height: 1; color: var(--chip-accent);
  flex: 0 0 auto;
}
.dash-zoom__chip-text {
  display: inline-flex; flex-direction: column; min-width: 0;
}
.dash-zoom__chip-label {
  font-size: 9.5px; font-weight: 700; letter-spacing: .05em;
  color: var(--ink-soft); text-transform: uppercase;
}
.dash-zoom__chip-value {
  font-size: 12.5px; font-weight: 600; color: var(--ink);
  text-transform: capitalize;
}
.dash-zoom__stats {
  display: flex; flex-direction: column; gap: 8px;
  margin: 0;
}
.dash-zoom__stat {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 10px;
  padding-bottom: 6px;
  border-bottom: 1px dashed var(--line);
}
.dash-zoom__stat:last-child { border-bottom: none; padding-bottom: 0; }
.dash-zoom__stat dt {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 11.5px; font-weight: 600; color: var(--ink-soft);
  text-transform: uppercase; letter-spacing: .03em;
  flex: 0 0 auto;
}
.dash-zoom__stat-icon {
  font-size: 15px; line-height: 1; color: var(--primary);
  flex: 0 0 auto;
}
.dash-zoom__stat dd {
  margin: 0; font-size: 13px; color: var(--ink); text-align: right;
  font-variant-numeric: tabular-nums;
  min-width: 0;
}
.dash-zoom__stat dd b {
  font-size: 15px; font-weight: 700; color: var(--accent-deep);
}
.dash-zoom__stat-tag {
  display: inline-block; margin-left: 4px;
  font-size: 10.5px; font-weight: 600; color: var(--ink-soft);
  background: var(--bg-soft); border: 1px solid var(--line);
  padding: 1px 6px;
}
.dash-zoom__stat.is-placeholder dt {
  font-weight: 500; text-transform: none; letter-spacing: 0;
  color: var(--ink-soft); font-style: italic;
}

/* AI analysis section — sits below the stats. Hidden by default; the
   frontend only reveals it (via .is-ready) once real analysis text arrives.
   Skeleton/loading/error states stay invisible to the user so the modal
   looks identical to the pre-AI design while data is being fetched. */
.dash-zoom__ai { display: none; }
.dash-zoom__ai.is-ready {
  display: flex; flex-direction: column; gap: 8px;
  padding: 12px;
  border: 1px solid var(--line);
  border-left: 3px solid var(--primary);
  background: var(--bg-soft);
}
.dash-zoom__ai-head {
  display: flex; align-items: center; gap: 8px;
}
.dash-zoom__ai-icon { font-size: 18px; color: var(--primary-dark); flex: none; }
.dash-zoom__ai-title {
  font-size: 12.5px; font-weight: 700; letter-spacing: .04em;
  text-transform: uppercase; color: var(--ink);
}
.dash-zoom__ai-provider {
  font-size: 10.5px; color: var(--ink-soft);
  text-transform: lowercase; letter-spacing: .02em;
  margin-left: auto;
}
.dash-zoom__ai-refresh {
  flex: none;
  border: 1px solid var(--line); background: var(--surface); color: var(--ink-soft);
  width: 24px; height: 24px;
  display: inline-flex; align-items: center; justify-content: center;
  cursor: pointer;
  transition: color .15s ease, background .15s ease, border-color .15s ease;
}
.dash-zoom__ai-refresh:hover {
  color: var(--primary-dark); background: var(--bg-blue); border-color: var(--primary);
}
.dash-zoom__ai-refresh .material-symbols-rounded { font-size: 16px; }
.dash-zoom__ai-body { font-size: 13px; line-height: 1.55; color: var(--ink); }
.dash-zoom__ai-text { margin: 0; white-space: pre-wrap; }
.dash-zoom__ai-hint {
  margin: 0; font-size: 12px; color: var(--ink-soft); line-height: 1.5;
}
.dash-zoom__ai-hint code {
  font-size: 11px; padding: 1px 5px;
  background: var(--surface); border: 1px solid var(--line);
  font-family: ui-monospace, Menlo, Consolas, monospace;
}
@media (max-width: 900px) {
  /* Narrow viewports: stack the info panel under the chart but keep both
     inside the same fixed-height body. The chart takes 65%, info takes 35%
     and scrolls internally — modal still fills the screen without scrolling. */
  .dash-zoom__layout {
    grid-template-columns: 1fr;
    grid-template-rows: minmax(0, 1fr) minmax(0, auto);
  }
  .dash-zoom__info { max-height: 35vh; }
}
@media (max-width: 600px) {
  .dash-zoom { padding: 12px; }
  .dash-zoom__shell { height: calc(100vh - 24px); max-height: calc(100vh - 24px); }
  .dash-zoom__body { padding: 12px; }
  .dash-zoom__body .chart-card { padding: 12px; }
  .dash-zoom__layout { gap: 12px; }
}

/* ===================================================================== */
/* Legal pages — Kebijakan Privasi & Ketentuan Layanan                    */
/* Layout: warm hero band → 2-column body (sticky TOC + readable column). */
/* ===================================================================== */
.legal {
  background: var(--bg);
  color: var(--ink);
}
.legal__hero {
  background: var(--bg-hero);
  border-bottom: 1px solid var(--line);
  padding: 56px 24px 40px;
}
.legal__hero-inner {
  max-width: 980px; margin-inline: auto;
}
.legal__eyebrow {
  display: inline-block;
  font-size: 11px; font-weight: 700; letter-spacing: .14em; text-transform: uppercase;
  color: var(--primary-dark); background: rgba(245,158,11,.15);
  padding: 4px 10px; border-radius: 2px;
  margin-bottom: 14px;
}
.legal__title {
  margin: 0 0 14px;
  font-size: clamp(28px, 4vw, 40px);
  font-weight: 800; letter-spacing: -.01em;
  color: var(--ink);
}
.legal__lede {
  margin: 0 0 18px;
  font-size: 16px; line-height: 1.65; color: var(--ink-soft);
  max-width: 760px;
}
.legal__meta {
  margin: 12px 0 0;
  display: flex; flex-wrap: wrap; gap: 6px 22px;
  font-size: 12.5px; color: var(--ink-soft);
}
.legal__meta strong { color: var(--ink); font-weight: 600; }

.legal__layout {
  display: grid;
  grid-template-columns: 260px minmax(0, 1fr);
  gap: 40px;
  max-width: 1180px;
  margin: 0 auto;
  padding: 40px 24px 64px;
  align-items: flex-start;
}

/* Sticky table of contents */
.legal__toc {
  position: sticky; top: 88px;
  background: var(--surface);
  border: 1px solid var(--line);
  padding: 18px 18px 14px;
  font-size: 13px;
  max-height: calc(100vh - 110px);
  overflow-y: auto;
}
.legal__toc-head {
  display: block;
  font-size: 11px; font-weight: 700; letter-spacing: .12em; text-transform: uppercase;
  color: var(--ink-soft);
  padding-bottom: 8px; margin-bottom: 8px;
  border-bottom: 1px solid var(--line);
}
.legal__toc ol {
  list-style: none; padding: 0; margin: 0;
  display: flex; flex-direction: column; gap: 2px;
}
.legal__toc a {
  display: block;
  padding: 5px 10px;
  border-left: 2px solid transparent;
  color: var(--ink-soft);
  border-radius: 0 2px 2px 0;
  transition: color .15s ease, background .15s ease, border-color .15s ease;
}
.legal__toc a:hover,
.legal__toc a.is-active {
  color: var(--primary-dark);
  background: var(--bg-soft);
  border-left-color: var(--primary);
}

/* Long-form content column */
.legal__content {
  font-size: 15px; line-height: 1.72; color: var(--ink);
  max-width: 760px;
}
.legal__content section { scroll-margin-top: 88px; padding-bottom: 6px; }
.legal__content section + section {
  margin-top: 28px; padding-top: 28px; border-top: 1px solid var(--line);
}
.legal__content h2 {
  margin: 0 0 14px;
  font-size: 22px; font-weight: 700; color: var(--ink);
  letter-spacing: -.005em;
}
.legal__content h3 {
  margin: 22px 0 8px;
  font-size: 15px; font-weight: 700; color: var(--ink);
}
.legal__content p { margin: 0 0 12px; }
.legal__content ul,
.legal__content ol {
  margin: 0 0 14px;
  padding-left: 22px;
}
.legal__content li { margin-bottom: 6px; }
.legal__content a {
  color: var(--primary-dark);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 2px;
}
.legal__content a:hover { color: var(--accent-deep); }

.legal__terms { display: grid; grid-template-columns: max-content 1fr; gap: 6px 18px; margin: 0; }
.legal__terms dt {
  font-weight: 700; color: var(--ink);
  padding-top: 2px;
  white-space: nowrap;
}
.legal__terms dd { margin: 0; padding-bottom: 6px; color: var(--ink-soft); }

.legal__note {
  background: var(--bg-soft);
  border-left: 3px solid var(--primary);
  padding: 12px 16px;
  font-size: 14px; color: var(--ink);
  margin: 14px 0 18px;
}
.legal__contact {
  background: var(--bg-soft);
  border: 1px solid var(--line);
  padding: 14px 16px;
  font-style: normal; line-height: 1.7;
  margin: 8px 0 14px;
}
.legal__sign {
  margin-top: 36px; padding-top: 18px;
  border-top: 1px dashed var(--line);
  font-size: 14px; color: var(--ink-soft);
  text-align: right;
}
.legal__sign strong { color: var(--ink); }

/* Responsive — TOC collapses below the content on tablet/mobile */
@media (max-width: 900px) {
  .legal__layout {
    grid-template-columns: 1fr;
    gap: 24px; padding: 24px 16px 48px;
  }
  .legal__toc {
    position: static;
    max-height: none;
    order: 2;
  }
  .legal__content { order: 1; max-width: 100%; }
  .legal__hero { padding: 36px 16px 28px; }
}
@media (max-width: 560px) {
  .legal__terms { grid-template-columns: 1fr; gap: 2px 0; }
  .legal__terms dd { padding-bottom: 12px; }
}

/* Respect users who prefer reduced motion — disable the scroll-shrink anims. */
@media (prefers-reduced-motion: reduce) {
  .appbar, .appbar__inner, .dash-sidebar,
  .dash-menu-group__items, .dash-menu-group__caret,
  .brand__logo-img { transition: none !important; }
  .dash-zoom__shell, .chart-card.is-search-flash { animation: none !important; }
}

/* ----------------------------------------------------------------------- */
/* Dashboard HTML table (chart type "table") — used by IKU Resume to show   */
/* every indikator with target / realisasi / capaian / status in one view. */
/* ----------------------------------------------------------------------- */
.dash-table__wrap {
  width: 100%; height: 100%;
  overflow: auto;
  border: 1px solid var(--line);
  border-radius: 10px;
  background: var(--surface);
}
.dash-table {
  width: 100%;
  border-collapse: separate; border-spacing: 0;
  font-size: 12.5px; color: var(--ink);
}
.dash-table thead th {
  position: sticky; top: 0; z-index: 1;
  background: var(--bg-soft);
  color: var(--ink-soft);
  font-weight: 700; letter-spacing: .02em; text-transform: uppercase;
  font-size: 10.5px;
  padding: 10px 12px;
  border-bottom: 1px solid var(--line);
  white-space: nowrap;
}
.dash-table tbody td {
  padding: 9px 12px;
  border-bottom: 1px solid var(--line);
  vertical-align: top;
  line-height: 1.35;
}
.dash-table tbody tr:last-child td { border-bottom: 0; }
.dash-table tbody tr:hover { background: var(--bg-soft); }

.dash-table__muted { color: var(--ink-soft); opacity: .55; }

.dash-table__link {
  color: #0f766e;
  font-weight: 600;
  text-decoration: none;
  border-bottom: 1px dashed currentColor;
}
.dash-table__link:hover { color: #134e4a; border-bottom-style: solid; }
[data-theme="dark"] .dash-table__link { color: #5eead4; }
[data-theme="dark"] .dash-table__link:hover { color: #99f6e4; }

.dash-table__chip {
  display: inline-block;
  padding: 2px 10px;
  border-radius: 999px;
  font-size: 11px; font-weight: 700;
  color: #fff;
  background: var(--c, #64748b);
  border: 1px solid var(--c, #64748b);
}
/* Sasaran rendered as plain colored text (no block) — same vocabulary as
   the IKU highlight cards above where Talenta/Inovasi/etc carry only color,
   not a filled box. */
.dash-table__sasaran {
  font-weight: 700;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .03em;
  white-space: nowrap;
}

.dash-table__status {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 11px; font-weight: 600;
  background: rgba(148, 163, 184, .18);
  color: #475569;
  border: 1px solid rgba(148, 163, 184, .35);
}
.dash-table__status--tercapai {
  background: rgba(15, 118, 110, .14);
  color: #0f766e;
  border-color: rgba(15, 118, 110, .35);
}
.dash-table__status--melampaui_target {
  background: rgba(21, 128, 61, .14);
  color: #15803d;
  border-color: rgba(21, 128, 61, .35);
}
.dash-table__status--belum_tercapai {
  background: rgba(220, 38, 38, .12);
  color: #b91c1c;
  border-color: rgba(220, 38, 38, .35);
}
.dash-table__status--tidak_dinilai {
  background: rgba(148, 163, 184, .18);
  color: #64748b;
  border-color: rgba(148, 163, 184, .35);
}

[data-theme="dark"] .dash-table__status--tercapai      { color: #5eead4; }
[data-theme="dark"] .dash-table__status--melampaui_target { color: #86efac; }
[data-theme="dark"] .dash-table__status--belum_tercapai { color: #fca5a5; }
[data-theme="dark"] .dash-table__status--tidak_dinilai { color: #cbd5e1; }

.dash-table__progress {
  position: relative;
  display: block;
  width: 100%;
  height: 18px;
  background: color-mix(in srgb, var(--ink-soft) 12%, transparent);
  border-radius: 9px;
  overflow: hidden;
  border: 1px solid var(--line);
}
.dash-table__progress-fill {
  position: absolute;
  top: 0; bottom: 0; left: 0;
  border-radius: 9px 0 0 9px;
  transition: width .4s ease;
}
.dash-table__progress-label {
  position: relative;
  z-index: 0;
  display: block;
  text-align: center;
  font-size: 10.5px;
  font-weight: 700;
  line-height: 16px;
  color: var(--ink);
  text-shadow: 0 0 2px var(--surface);
}
.dash-table__progress--low  .dash-table__progress-fill { background: #fca5a5; }
.dash-table__progress--mid  .dash-table__progress-fill { background: #fbbf24; }
.dash-table__progress--good .dash-table__progress-fill { background: #34d399; }
.dash-table__progress--over .dash-table__progress-fill { background: #0d9488; }

[data-theme="dark"] .dash-table__progress--low  .dash-table__progress-fill { background: #b91c1c; }
[data-theme="dark"] .dash-table__progress--mid  .dash-table__progress-fill { background: #b45309; }
[data-theme="dark"] .dash-table__progress--good .dash-table__progress-fill { background: #15803d; }
[data-theme="dark"] .dash-table__progress--over .dash-table__progress-fill { background: #115e59; }

.dash-table td[data-col="kodeIku"] {
  background: color-mix(in srgb, #0f766e 8%, transparent);
  font-weight: 700;
  color: #0f766e;
}
.dash-table th[data-col="kodeIku"] {
  background: color-mix(in srgb, #0f766e 14%, var(--bg-soft));
  color: #0f766e;
}
[data-theme="dark"] .dash-table td[data-col="kodeIku"] {
  background: color-mix(in srgb, #5eead4 12%, transparent);
  color: #5eead4;
}
[data-theme="dark"] .dash-table th[data-col="kodeIku"] {
  background: color-mix(in srgb, #5eead4 18%, var(--bg-soft));
  color: #5eead4;
}

/* IKU highlights — 11 IKU cards (kode + sasaran + judul induk) shown at the
   very top of the IKU tab, above the resume table. Color tone per card is
   driven by --c/--bg/--bd CSS vars set inline (Wajib teal, Pilihan amber). */
.iku-highlights {
  margin: 0 0 14px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.iku-highlights__legend {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  font-size: 11px;
  color: var(--ink-soft);
}
.iku-highlights__legend-item {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 2px 8px;
  border-radius: 0;
  background: var(--bg);
  border: 1px solid var(--bd);
  color: var(--c);
  font-weight: 600;
}
.iku-highlights__legend-swatch {
  width: 8px; height: 8px;
  border-radius: 0;
  background: var(--c);
}
.iku-highlights__grid {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: 6px;
}
@media (max-width: 1024px) {
  .iku-highlights__grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (max-width: 600px) {
  .iku-highlights__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
.iku-card {
  position: relative;
  background: var(--bg);
  border: 1px solid var(--bd);
  border-left: 3px solid var(--sasaran, var(--c));
  border-radius: 0;
  padding: 6px 9px;
  display: flex;
  flex-direction: column;
  gap: 3px;
  transition: transform .15s ease, box-shadow .15s ease;
}
.iku-card:hover {
  transform: translateY(-1px);
  box-shadow: 0 4px 10px -6px color-mix(in srgb, var(--c) 35%, transparent);
}
.iku-card__head {
  display: flex;
  align-items: center;
  gap: 6px;
}
.iku-card__kode {
  font-weight: 700;
  font-size: 12px;
  color: var(--c);
  letter-spacing: .02em;
  white-space: nowrap;
}
.iku-card__sasaran {
  flex: 1;
  margin: 0;
  font-size: 9.5px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .03em;
  color: var(--sasaran, var(--ink-soft));
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.iku-card__badge {
  font-size: 8.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .04em;
  padding: 1px 5px;
  border-radius: 0;
  background: var(--c);
  color: #fff;
  white-space: nowrap;
}
[data-theme="dark"] .iku-card {
  background: color-mix(in srgb, var(--c) 14%, var(--surface));
  border-color: color-mix(in srgb, var(--c) 35%, transparent);
}
[data-theme="dark"] .iku-highlights__legend-item {
  background: color-mix(in srgb, var(--c) 18%, var(--surface));
}

.iku-card { cursor: pointer; outline: none; }
.iku-card:focus-visible {
  box-shadow: 0 0 0 2px var(--surface), 0 0 0 4px var(--c);
}

/* IKU detail modal — opens on iku-card click with full indikator breakdown. */
.iku-modal {
  position: fixed; inset: 0;
  display: flex; align-items: center; justify-content: center;
  z-index: 200;
  opacity: 0;
  transition: opacity .18s ease;
  pointer-events: none;
}
.iku-modal.is-open { opacity: 1; pointer-events: auto; }
.iku-modal[hidden] { display: none; }
.iku-modal__backdrop {
  position: absolute; inset: 0;
  background: rgba(15, 23, 42, .55);
  backdrop-filter: blur(2px);
}
.iku-modal__shell {
  position: relative;
  background: var(--surface);
  border: 1px solid var(--line);
  width: min(880px, 92vw);
  max-height: 86vh;
  display: flex; flex-direction: column;
  box-shadow: 0 24px 60px -20px rgba(0,0,0,.4);
  transform: translateY(8px);
  transition: transform .18s ease;
}
.iku-modal.is-open .iku-modal__shell { transform: translateY(0); }
.iku-modal__head {
  padding: 16px 56px 14px 18px;
  border-bottom: 1px solid var(--line);
}
.iku-modal__head-row {
  display: flex; align-items: center; flex-wrap: wrap; gap: 8px;
}
.iku-modal__kode {
  font-size: 16px; font-weight: 800; letter-spacing: .02em;
  color: var(--c);
}
.iku-modal__sasaran {
  font-size: 11px; font-weight: 700;
  text-transform: uppercase; letter-spacing: .04em;
  color: var(--c);
}
.iku-modal__badge {
  font-size: 9.5px; font-weight: 700;
  text-transform: uppercase; letter-spacing: .04em;
  color: #fff; background: var(--c);
  padding: 3px 8px;
}
.iku-modal__judul {
  margin: 8px 0 0;
  font-size: 13px; line-height: 1.4;
  color: var(--ink);
}
.iku-modal__close {
  position: absolute; top: 10px; right: 10px;
  width: 32px; height: 32px;
  border: 1px solid var(--line);
  background: var(--surface);
  display: inline-flex; align-items: center; justify-content: center;
  cursor: pointer;
  color: var(--ink-soft);
  transition: background .15s ease, color .15s ease;
}
.iku-modal__close:hover { background: var(--bg-soft); color: var(--ink); }
.iku-modal__close .material-symbols-rounded { font-size: 18px; }
.iku-modal__body {
  flex: 1;
  overflow: auto;
  padding: 0;
}
.iku-modal__table-wrap { width: 100%; }
.iku-modal__table {
  width: 100%;
  border-collapse: separate; border-spacing: 0;
  font-size: 12.5px; color: var(--ink);
}
.iku-modal__table thead th {
  position: sticky; top: 0; z-index: 1;
  background: var(--bg-soft);
  color: var(--ink-soft);
  font-weight: 700; letter-spacing: .02em; text-transform: uppercase;
  font-size: 10.5px;
  padding: 10px 14px;
  border-bottom: 1px solid var(--line);
  white-space: nowrap;
  text-align: left;
}
.iku-modal__table tbody td {
  padding: 9px 14px;
  border-bottom: 1px solid var(--line);
  vertical-align: top;
  line-height: 1.35;
}
.iku-modal__table tbody tr:last-child td { border-bottom: 0; }
.iku-modal__row--sub td:first-child {
  padding-left: 28px;
  color: var(--ink-soft);
  font-size: 12px;
}
.iku-modal__indent { color: var(--ink-soft); margin-right: 2px; }

body.modal-open { overflow: hidden; }

/* ----------------------------------------------------------------------- */
/* Perencanaan & Pengembangan — kaskade dokumen strategis + analisis RAB.   */
/* Reuses keu-* page chrome (.keu-page / .keu-kpi / .keu-section / .keu-viz)*/
/* and adds per-* styles for the specifics of this dashboard.               */
/* ----------------------------------------------------------------------- */
.per-page .keu-kpi {
  grid-template-columns: repeat(5, minmax(0, 1fr));
}
@media (max-width: 1100px) {
  .per-page .keu-kpi { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (max-width: 720px) {
  .per-page .keu-kpi { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* Tone perencanaan KPI strip to teal (sibling of finance's amber). */
.per-page .keu-kpi__card--lead {
  border-left-color: #0f766e; background: #ecfeff;
}
.per-page .keu-kpi__card--lead .keu-kpi__icon { color: #0f766e; }
.per-page .keu-section__icon {
  color: #0f766e; background: #ecfeff; border-color: #99f6e4;
}

/* ---- (2) Cascade — vertical rail of strategic docs ---------------------- */
.per-cascade {
  display: flex; flex-direction: column;
  gap: 0;
}
.per-cascade__card {
  display: grid;
  grid-template-columns: 64px 1fr;
  gap: 14px;
  padding: 14px 16px 18px;
  background: var(--bg-soft);
  border: 1px solid var(--line);
  border-left: 4px solid var(--ac, #0f766e);
  position: relative;
}
.per-cascade__card + .per-cascade__card { margin-top: 6px; }
.per-cascade__rail {
  display: flex; flex-direction: column; align-items: center; gap: 6px;
  position: relative;
}
.per-cascade__lvl {
  font-size: 10px; font-weight: 700; letter-spacing: .06em;
  color: var(--ac, #0f766e);
  background: #fff; border: 1px solid var(--ac, #0f766e);
  padding: 2px 6px; border-radius: 999px;
}
.per-cascade__icon {
  font-size: 28px;
  width: 48px; height: 48px;
  display: inline-flex; align-items: center; justify-content: center;
  background: #fff; border: 1px solid var(--line);
  color: var(--ac, #0f766e);
  border-radius: 6px;
}
.per-cascade__line {
  position: absolute;
  left: 50%; top: 78px; bottom: -22px;
  width: 2px;
  background: linear-gradient(to bottom, var(--ac, #0f766e) 0%, var(--ac, #0f766e) 60%, transparent 100%);
  opacity: .35;
  transform: translateX(-50%);
}
.per-cascade__body { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.per-cascade__head {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
  font-size: 11.5px; color: var(--ink-soft);
}
.per-cascade__tier {
  font-weight: 700; font-size: 11px; letter-spacing: .06em; text-transform: uppercase;
  color: var(--ac, #0f766e);
  background: rgba(255,255,255,.7); border: 1px solid var(--ac, #0f766e);
  padding: 2px 8px; border-radius: 3px;
}
.per-cascade__kode { font-weight: 600; color: var(--ink); }
.per-cascade__periode { margin-left: auto; font-style: italic; }
.per-cascade__judul { margin: 2px 0 0; font-size: 14.5px; font-weight: 700; color: var(--ink); }
.per-cascade__pilar { margin: 2px 0 0; font-size: 12.5px; color: var(--ink); }
.per-cascade__capaian { margin: 0; font-size: 12px; color: var(--ink-soft); line-height: 1.5; }
.per-cascade__foot {
  margin-top: 4px; padding-top: 6px; border-top: 1px dashed var(--line);
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 11px; color: var(--ink-soft);
}
.per-cascade__foot .material-symbols-rounded { font-size: 14px; }

/* ---- (3) Sasaran Strategis — clickable filter cards --------------------- */
.per-ss {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 12px;
}
@media (max-width: 1100px) { .per-ss { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 720px)  { .per-ss { grid-template-columns: 1fr; } }

.per-ss__card {
  display: flex; flex-direction: column; gap: 6px;
  padding: 14px 14px 12px;
  background: var(--bg-soft);
  border: 1px solid var(--line);
  border-top: 3px solid var(--ac, #0f766e);
  cursor: pointer;
  transition: transform .12s ease, box-shadow .12s ease, border-color .12s ease;
}
.per-ss__card:hover { transform: translateY(-1px); box-shadow: 0 4px 14px rgba(15,23,42,.06); }
.per-ss__card.is-active {
  background: #fff;
  border-color: var(--ac, #0f766e);
  box-shadow: 0 0 0 2px rgba(15,118,110,.18);
}
.per-ss__card:focus-visible { outline: 2px solid var(--ac, #0f766e); outline-offset: 2px; }

.per-ss__head { display: flex; align-items: center; gap: 8px; }
.per-ss__icon {
  font-size: 22px; color: var(--ac, #0f766e);
  background: #fff; border: 1px solid var(--line);
  width: 32px; height: 32px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 6px;
}
.per-ss__kode {
  font-size: 12px; font-weight: 700; color: var(--ac, #0f766e);
  background: #fff; border: 1px solid var(--ac, #0f766e);
  padding: 2px 8px; border-radius: 999px;
}
.per-ss__meta {
  margin-left: auto; font-size: 11px; color: var(--ink-soft);
}
.per-ss__label { margin: 4px 0 0; font-size: 13.5px; font-weight: 700; color: var(--ink); line-height: 1.35; }
.per-ss__tujuan { margin: 0; font-size: 11.5px; color: var(--ink-soft); line-height: 1.45; }

.per-ss__progress { margin-top: 6px; }
.per-ss__progress-track {
  width: 100%; height: 7px;
  background: var(--surface); border: 1px solid var(--line);
  overflow: hidden;
}
.per-ss__progress-fill {
  display: block; height: 100%;
  background: linear-gradient(90deg, var(--ac, #0f766e), color-mix(in srgb, var(--ac, #0f766e) 50%, white));
}
.per-ss__progress-meta {
  display: flex; justify-content: space-between; align-items: center;
  margin-top: 3px; font-size: 11px; color: var(--ink-soft);
}
.per-ss__progress-meta b { color: var(--ink); font-size: 12px; }

.per-ss__stats {
  margin: 6px 0 0; padding: 8px 0 0;
  border-top: 1px dashed var(--line);
  display: grid; grid-template-columns: 1fr 1fr; gap: 6px 12px;
}
.per-ss__stats > div { display: flex; flex-direction: column; }
.per-ss__stats dt {
  font-size: 10.5px; letter-spacing: .04em; text-transform: uppercase;
  color: var(--ink-soft);
}
.per-ss__stats dd { margin: 0; font-size: 12.5px; font-weight: 600; color: var(--ink); }
.per-ss__target { font-weight: 500 !important; font-size: 11.5px !important; color: var(--ink-soft) !important; line-height: 1.45; }

/* ---- (4) IKU table — bullet bars --------------------------------------- */
.per-iku__legend { margin: 0 0 8px; }
.per-iku__grid { display: grid; gap: 0; font-size: 12.5px; }
.per-iku__row {
  display: grid;
  grid-template-columns: 80px 2.4fr 70px 130px 130px 1.6fr 110px;
  gap: 8px;
  padding: 9px 8px;
  align-items: center;
  border-bottom: 1px solid var(--line);
}
.per-iku__row--head {
  background: var(--bg-soft);
  font-size: 11px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
  color: var(--ink-soft);
  border-bottom: 2px solid var(--line);
  position: sticky; top: 0; z-index: 1;
}
.per-iku__row.is-dimmed { opacity: .25; }
.per-iku__num { text-align: right; font-variant-numeric: tabular-nums; }
.per-iku__chip {
  display: inline-block; font-size: 11px; font-weight: 700;
  padding: 2px 6px; border-radius: 3px;
  background: #ecfeff; color: #0f766e; border: 1px solid #99f6e4;
}
.per-iku__bullet {
  position: relative;
  display: block; width: 100%; height: 16px;
  background: var(--surface); border: 1px solid var(--line);
}
.per-iku__bullet-target,
.per-iku__bullet-real {
  position: absolute; top: 0; left: 0; height: 100%;
  display: block;
}
.per-iku__bullet-target { opacity: .55; }
.per-iku__bullet-real   { height: 60%; top: 20%; opacity: .95; }
.per-iku__bullet-text {
  position: absolute; right: 6px; top: 50%; transform: translateY(-50%);
  font-size: 11px; font-weight: 700;
  text-shadow: 0 0 2px #fff, 0 0 2px #fff;
}
.per-iku__predikat {
  display: inline-block; font-size: 11px; font-weight: 700;
  padding: 2px 8px; border-radius: 999px;
}
.per-iku__predikat[data-pred="Sangat Baik"] { background: #dcfce7; color: #166534; border: 1px solid #86efac; }
.per-iku__predikat[data-pred="Baik"]        { background: #ecfccb; color: #3f6212; border: 1px solid #bef264; }
.per-iku__predikat[data-pred="Cukup"]       { background: #fef3c7; color: #92400e; border: 1px solid #fcd34d; }
.per-iku__predikat[data-pred="Kurang"]      { background: #fee2e2; color: #991b1b; border: 1px solid #fca5a5; }

@media (max-width: 980px) {
  .per-iku__row {
    grid-template-columns: 70px 1fr 60px 1fr 1fr 1fr 90px;
    font-size: 11.5px;
  }
}

/* ---- (5) Aktivitas — sortable-style table ------------------------------ */
.per-akt__table-wrap { width: 100%; overflow-x: auto; }
.per-akt__table {
  width: 100%; border-collapse: collapse; font-size: 12.5px;
}
.per-akt__table thead th {
  position: sticky; top: 0; background: var(--bg-soft);
  font-size: 11px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
  color: var(--ink-soft);
  padding: 8px 10px;
  border-bottom: 2px solid var(--line);
  text-align: left;
}
.per-akt__table tbody td {
  padding: 8px 10px;
  border-bottom: 1px solid var(--line);
  vertical-align: middle;
}
.per-akt__table tbody tr.is-dimmed { opacity: .25; }
.per-akt__num { text-align: right; font-variant-numeric: tabular-nums; }
.per-akt__serapan { min-width: 150px; }
.per-akt__bar {
  position: relative; width: 100%; height: 16px;
  background: var(--surface); border: 1px solid var(--line);
}
.per-akt__bar-fill {
  position: absolute; top: 0; left: 0; height: 100%; display: block; opacity: .75;
}
.per-akt__bar-text {
  position: absolute; right: 6px; top: 50%; transform: translateY(-50%);
  font-size: 11px; font-weight: 700;
  text-shadow: 0 0 2px #fff, 0 0 2px #fff;
}
.per-akt__status {
  display: inline-block; font-size: 11px; font-weight: 700;
  padding: 2px 8px; border-radius: 999px;
}
.per-akt__status[data-status="on-track"] { background: #dcfce7; color: #166534; border: 1px solid #86efac; }
.per-akt__status[data-status="behind"]   { background: #fef3c7; color: #92400e; border: 1px solid #fcd34d; }
.per-akt__status[data-status="selesai"]  { background: #dbeafe; color: #1e3a8a; border: 1px solid #93c5fd; }
.per-akt__total td { border-top: 2px solid var(--line); background: var(--bg-soft); }


/* ============================================================
   Perencanaan — hierarchy-band layout (mirrors the reference
   dashboard_dokumen_strategis_ptnbh.html). Theme adapted to the
   UNSRI warm amber palette using existing dash-page/keu-* tokens.
   ============================================================ */

/* Hierarchy navigation strip (4 nodes since RPJMN was dropped). Buttons
   share a border so the band reads as one continuous bar; active node gets
   a bottom accent. */
.per-band {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 0;
  border: 1px solid var(--line);
  background: var(--surface);
  overflow: hidden;
}
/* Year filter at the very top of the Perencanaan page — mirrors keuangan
   filter visuals (.keu-filter), with a small top gap so it sits flush below
   the page title block. */
.per-filter { margin: 4px 0 8px; }
.per-page__body { display: flex; flex-direction: column; gap: 8px; }
.per-band__node {
  appearance: none;
  background: var(--surface);
  border: 0;
  border-right: 1px solid var(--line);
  padding: 10px 8px 12px;
  display: flex; flex-direction: column; align-items: center; gap: 3px;
  cursor: pointer;
  text-align: center;
  transition: background .15s ease, border-color .15s ease;
}
.per-band__node:last-child { border-right: 0; }
.per-band__node:hover { background: var(--bg-soft); }
.per-band__node.is-active {
  background: var(--bg-soft);
  border-bottom: 3px solid var(--primary);
  padding-bottom: 9px;
}
.per-band__icon {
  font-size: 18px !important;
  color: var(--ink-soft);
}
.per-band__node.is-active .per-band__icon { color: var(--primary-dark); }
.per-band__name {
  font-size: 11.5px; font-weight: 600; color: var(--ink);
}
.per-band__span {
  font-size: 10px; color: var(--ink-soft);
}
.per-band__count {
  margin-top: 3px; padding: 1px 8px;
  font-size: 10px; font-weight: 600;
  background: var(--bg-soft);
  color: var(--ink-soft);
  border-radius: 10px;
}
.per-band__node.is-active .per-band__count {
  background: #fff7e0;
  color: var(--primary-dark);
}
@media (max-width: 760px) {
  .per-band { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .per-band__node { border-bottom: 1px solid var(--line); }
}

/* Single-panel container — only one panel is live at a time. */
.per-panels { display: block; }
.per-panel { display: block; }
.per-panel__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 10px;
}
.per-panel__grid--full { grid-template-columns: minmax(0, 1fr); }
@media (max-width: 900px) {
  .per-panel__grid { grid-template-columns: minmax(0, 1fr); }
}

/* Card chrome inside each panel — flatter than the dashboard chart-card. */
.per-card {
  background: var(--surface);
  border: 1px solid var(--line);
  padding: 12px 14px;
  display: flex; flex-direction: column; gap: 8px;
  min-width: 0;
}
.per-card__hd {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: 2px;
}
.per-card__title {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 12.5px; font-weight: 700; color: var(--ink);
}
.per-card__title .material-symbols-rounded,
.per-card__title svg {
  font-size: 14px !important;
  color: var(--primary-dark);
  width: 14px; height: 14px;
}
.per-card__divider {
  height: 1px; background: var(--line); margin: 4px 0;
}
.per-card__hint {
  font-size: 10.5px; font-weight: 600; color: var(--ink-soft);
  letter-spacing: .04em; text-transform: uppercase;
}
.per-card__txt {
  margin: 0; font-size: 12px; color: var(--ink); line-height: 1.5;
}
.per-card__txt--muted { color: var(--ink-soft); }

/* Document list — one row per dokumen item with status badge. */
.per-doclist {
  list-style: none; margin: 0; padding: 0;
  display: flex; flex-direction: column; gap: 6px;
}
.per-doclist--inset { margin-top: 6px; padding-top: 6px; border-top: 1px dashed var(--line); }
.per-doc-row {
  display: flex; align-items: center; gap: 8px;
  padding: 7px 9px;
  background: var(--bg-soft);
  border: 1px solid var(--line);
  border-left: 3px solid var(--primary);
}
.per-doc-icon {
  font-size: 14px !important;
  color: var(--ink-soft);
  flex-shrink: 0;
}
.per-doc-body { flex: 1; min-width: 0; }
.per-doc-name {
  font-size: 12px; font-weight: 600; color: var(--ink);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.per-doc-sub {
  font-size: 10.5px; color: var(--ink-soft); margin-top: 1px;
}
.per-doc-badge {
  font-size: 9.5px; font-weight: 700; padding: 2px 8px;
  border-radius: 10px; letter-spacing: .04em; text-transform: uppercase;
  flex-shrink: 0;
}
.per-doc-badge--aktif { background: #dcfce7; color: #166534; border: 1px solid #86efac; }

/* Bullets list (pilar utama / sasaran list). */
.per-bullets {
  list-style: none; margin: 0; padding: 0;
  display: flex; flex-direction: column; gap: 4px;
  font-size: 12px; color: var(--ink); line-height: 1.45;
}
.per-bullets li {
  display: flex; align-items: center; gap: 8px;
}
.per-bullets--ss li { gap: 6px; }
.per-bullets__lbl { color: var(--ink); }
.per-dot {
  width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0;
}

/* Progress rows — single horizontal track with width-driven fill. */
.per-prog {
  display: flex; flex-direction: column; gap: 8px;
}
.per-prog__row { display: flex; flex-direction: column; gap: 3px; }
.per-prog__hd {
  display: flex; justify-content: space-between; align-items: baseline;
  font-size: 11.5px; color: var(--ink);
  gap: 8px;
}
.per-prog__hd > span {
  flex: 1; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.per-prog__pct {
  font-weight: 700; font-size: 11.5px; flex-shrink: 0;
  font-variant-numeric: tabular-nums;
}
.per-prog__pct[data-tone="good"] { color: #15803d; }
.per-prog__pct[data-tone="warn"] { color: #b45309; }
.per-prog__pct[data-tone="bad"]  { color: #b91c1c; }
.per-prog__pct[data-tone="mute"] { color: var(--ink-soft); }
.per-prog__bar {
  height: 6px;
  background: var(--bg-soft);
  border-radius: 3px;
  overflow: hidden;
}
.per-prog__fill {
  display: block; height: 100%;
  background: var(--primary);
  border-radius: 3px;
  transition: width .35s ease;
}

/* Mini KPI tiles inside a panel (3-tile, 4-tile variants). */
.per-mini {
  display: grid;
  gap: 6px;
  margin: 2px 0;
}
.per-mini--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.per-mini--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
@media (max-width: 560px) {
  .per-mini--3, .per-mini--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
.per-mini__tile {
  padding: 8px 10px;
  background: var(--bg-soft);
  border-radius: 6px;
  border: 1px solid var(--line);
}
.per-mini__tile--good { background: #ecfccb; border-color: #bef264; }
.per-mini__tile--warn { background: #fef3c7; border-color: #fcd34d; }
.per-mini__tile--bad  { background: #fee2e2; border-color: #fca5a5; }
.per-mini__val {
  font-size: 17px; font-weight: 700; color: var(--ink);
  line-height: 1.2;
}
.per-mini__lbl {
  font-size: 10px; color: var(--ink-soft);
  margin-top: 1px; letter-spacing: .02em;
}
.per-mini__tile--good .per-mini__val { color: #166534; }
.per-mini__tile--warn .per-mini__val { color: #92400e; }
.per-mini__tile--bad  .per-mini__val { color: #991b1b; }

/* Compact tables (Target Kinerja + Aktivitas). */
.per-table-wrap {
  width: 100%; overflow-x: auto;
  border: 1px solid var(--line);
  background: var(--surface);
}
.per-table {
  width: 100%; border-collapse: collapse;
  font-size: 11.5px;
}
.per-table thead th {
  background: var(--bg-soft);
  color: var(--ink-soft);
  font-size: 10.5px; font-weight: 700;
  letter-spacing: .04em; text-transform: uppercase;
  padding: 6px 8px;
  text-align: left;
  border-bottom: 1px solid var(--line);
  white-space: nowrap;
}
.per-table tbody td {
  padding: 6px 8px;
  border-bottom: 1px solid var(--line);
  vertical-align: middle;
  color: var(--ink);
}
.per-table tbody tr:last-child td { border-bottom: 0; }
.per-table tbody tr:hover td { background: var(--bg-soft); }
.per-table__num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.per-table__num b[data-tone="good"] { color: #15803d; }
.per-table__num b[data-tone="warn"] { color: #b45309; }
.per-table__num b[data-tone="bad"]  { color: #b91c1c; }
.per-table__num b[data-tone="mute"] { color: var(--ink-soft); }
.per-table tbody tr.per-table__total td {
  background: var(--bg-soft);
  border-top: 2px solid var(--line);
  border-bottom: 0;
  font-weight: 600;
  color: var(--ink);
}
.per-table tbody tr.per-table__total:hover td { background: var(--bg-soft); }

/* Chip used inside table cells (Sasaran code). */
.per-chip {
  display: inline-block;
  font-size: 10px; font-weight: 700;
  padding: 1px 7px;
  background: var(--bg-soft);
  border: 1px solid var(--line);
  border-radius: 8px;
  color: var(--ink);
  letter-spacing: .04em;
}

/* Status badge (predikat / status aktivitas) — tones map to data-tone. */
.per-status {
  display: inline-block;
  font-size: 10px; font-weight: 700;
  padding: 2px 8px;
  border-radius: 10px;
  letter-spacing: .03em;
}
.per-status[data-tone="good"] { background: #dcfce7; color: #166534; border: 1px solid #86efac; }
.per-status[data-tone="warn"] { background: #fef3c7; color: #92400e; border: 1px solid #fcd34d; }
.per-status[data-tone="bad"]  { background: #fee2e2; color: #991b1b; border: 1px solid #fca5a5; }
.per-status[data-tone="done"] { background: #dbeafe; color: #1e3a8a; border: 1px solid #93c5fd; }
.per-status[data-tone="mute"] { background: var(--bg-soft); color: var(--ink-soft); border: 1px solid var(--line); }

/* Empty-state line shown when a tier has no dokumen rows. */
.per-empty {
  padding: 12px;
  font-size: 11.5px;
  color: var(--ink-soft);
  text-align: center;
  background: var(--bg-soft);
  border: 1px dashed var(--line);
}

/* Bottom alignment band — horizontal flow tying the 6 tiers together. */
.per-align {
  background: var(--bg-soft);
  border: 1px solid var(--line);
  padding: 10px 14px;
  display: flex; flex-direction: column; gap: 8px;
  margin-top: 4px;
}
.per-align__title {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 11.5px; font-weight: 700; color: var(--ink);
}
.per-align__title .material-symbols-rounded,
.per-align__title svg {
  font-size: 14px !important;
  color: var(--primary-dark);
  width: 14px; height: 14px;
}
.per-align__flow {
  display: flex; align-items: center; gap: 0;
  overflow-x: auto;
  padding-bottom: 2px;
}
.per-align__node {
  background: var(--surface);
  border: 1px solid var(--line);
  border-left-width: 3px;
  border-radius: 6px;
  padding: 6px 11px;
  font-size: 10.5px;
  white-space: nowrap;
  flex-shrink: 0;
  text-align: center;
}
.per-align__node b {
  display: block; font-size: 11.5px; font-weight: 700;
  color: var(--ink); margin-bottom: 1px;
}
.per-align__node span { color: var(--ink-soft); }
.per-align__arrow {
  font-size: 16px !important;
  color: var(--ink-soft);
  padding: 0 4px;
  flex-shrink: 0;
}

/* ============================================================================
   Onboarding portal (served at /) — landing page body (views/onboarding.hbs),
   rendered inside layouts/main.hbs so it shares the navbar + footer with the
   dashboard. A grid of domain "doorways"; cooler, rounded aesthetic distinct
   from the squared amber report theme, per-card accent via --onb-color. Local
   theme vars switch under [data-theme="dark"] to follow the global preference.
   ============================================================================ */
.onb-page {
  --onb-bg-a: #fbffff;          /* page background */
  --onb-bg-b: #fbffff;          /* page background */
  --onb-surface: #ffffff;       /* card surface */
  --onb-title: #1e293b;         /* hero title */
  --onb-text: #475569;          /* hero subtitle / label */
  --onb-muted: #64748b;         /* hero desc */
  --onb-line: #e7ecf5;          /* card hairline */
  --onb-shadow: 0 8px 24px rgba(15, 23, 42, .08);
  --onb-shadow-hover: 0 16px 40px rgba(15, 23, 42, .14);
  position: relative;
  /* Clip the decorative blobs (the wave bleeds past the right edge) so they
     never trigger a horizontal scrollbar. overflow-x: clip leaves the vertical
     axis untouched (unlike `hidden`, which can force overflow-y: auto). */
  overflow-x: clip;
  min-height: 70vh;
  padding: clamp(10px, 3vw, 36px) clamp(10px, 5vw, 40px) 64px;
  background: linear-gradient(180deg, var(--onb-bg-a) 0%, var(--onb-bg-b) 60%);
  color: var(--onb-text);
}
[data-theme="dark"] .onb-page {
  --onb-bg-a: #0f1722;
  --onb-bg-b: #131c29;
  --onb-surface: #1a2433;
  --onb-title: #f1f5f9;
  --onb-text: #cbd5e1;
  --onb-muted: #94a3b8;
  --onb-line: #273346;
  --onb-shadow: 0 8px 24px rgba(0, 0, 0, .35);
  --onb-shadow-hover: 0 16px 40px rgba(0, 0, 0, .5);
}

.onb-decor { position: absolute; pointer-events: none; z-index: 0; }
.onb-decor--dots {
  top: 56px; left: clamp(12px, 4vw, 60px); width: 140px; height: 120px;
  background-image: radial-gradient(currentColor 2px, transparent 2px);
  background-size: 20px 20px;
  color: rgba(37, 99, 235, .14);
  -webkit-mask-image: linear-gradient(135deg, #000, transparent 75%);
          mask-image: linear-gradient(135deg, #000, transparent 75%);
}
.onb-decor--wave {
  top: 0; right: clamp(-40px, -2vw, 0px); width: 360px; height: 320px;
  background: radial-gradient(circle at 70% 30%, rgba(59, 130, 246, .10), transparent 60%);
  border-radius: 50%;
}

/* Hero kept deliberately compact — the cards are the focal point. */
.onb-hero { position: relative; z-index: 1; text-align: center; margin-bottom: clamp(24px, 4vw, 36px); }
.onb-hero__title {
  margin: 0;
  font-size: clamp(24px, 3.4vw, 34px);
  font-weight: 700;
  color: var(--onb-title);
  letter-spacing: -.5px;
}
.onb-hero__subtitle {
  margin: 6px 0 0;
  font-size: clamp(14px, 1.8vw, 17px);
  font-weight: 400;
  color: var(--onb-text);
}
.onb-hero__desc {
  margin: 10px auto 0;
  max-width: 520px;
  font-size: 13px;
  line-height: 1.55;
  color: var(--onb-muted);
}

/* Card grid — centered flex so an incomplete final row (e.g. 3 of 5) sits
   centered instead of left-aligned. Cards keep a fixed-ish size via flex-basis
   + max-width; flex-wrap handles responsiveness. */
.onb-grid {
  position: relative;
  z-index: 1;
  /* Sized so six cards (basis 180 + max 200 + gap 24) fill one row on desktop;
     fewer fit as the viewport narrows, with a centered partial last row. */
  max-width: 1320px;
  margin: 0 auto;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: clamp(16px, 2vw, 24px);
}
.onb-card {
  flex: 1 1 180px;
  max-width: 200px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 18px;
  padding: 36px 16px;
  min-height: 180px;
  background: var(--onb-surface);
  border: 1px solid var(--onb-line);
  border-radius: 8px;
  box-shadow: var(--onb-shadow);
  text-decoration: none;
  transition: transform .18s ease, box-shadow .18s ease, border-color .18s ease;
}
.onb-card:hover,
.onb-card:focus-visible {
  box-shadow: var(--onb-shadow-hover);
  border-color: color-mix(in srgb, var(--onb-color) 40%, var(--onb-line));
  outline: none;
}
.onb-card__icon {
  display: grid;
  place-items: center;
  width: 84px;
  height: 84px;
  border-radius: 50%;
  background: color-mix(in srgb, var(--onb-color) 14%, var(--onb-surface));
  color: var(--onb-color);
  transition: background .18s ease;
}
.onb-card__icon .material-symbols-rounded,
.onb-card__icon svg { width: 36px; height: 36px; }
.onb-card__icon svg { stroke-width: 2; }
.onb-card__label {
  font-size: 16px;
  font-weight: 600;
  color: var(--onb-title);
  text-align: center;
}

/* Tighten the card size a touch on phones so two still fit per row. */
@media (max-width: 420px) { .onb-card { flex-basis: 140px; min-height: 150px; padding: 24px 12px; } }

/* ---------------------------------------------------------------------------
   Onboarding "data sedang diproses" dialog — centered, closeable modal popped
   by cards flagged `inProgress` (see onbInProgressDialog in public/js/main.js).
   --------------------------------------------------------------------------- */
.onb-alert {
  position: fixed;
  inset: 0;
  z-index: 9999;
  display: grid;
  place-items: center;
  padding: 24px;
  opacity: 0;
  transition: opacity .2s ease;
}
.onb-alert.is-open { opacity: 1; }
.onb-alert__backdrop {
  position: absolute;
  inset: 0;
  background: rgba(15, 23, 42, .55);
  backdrop-filter: blur(2px);
}
.onb-alert__shell {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 12px;
  width: min(420px, 100%);
  padding: 32px 28px;
  background: var(--onb-surface, #fff);
  border: 1px solid var(--onb-line, #e2e8f0);
  border-radius: 16px;
  box-shadow: 0 24px 60px rgba(15, 23, 42, .3);
  transform: translateY(12px) scale(.98);
  transition: transform .2s ease;
}
.onb-alert.is-open .onb-alert__shell { transform: none; }
.onb-alert__icon {
  display: grid;
  place-items: center;
  width: 64px;
  height: 64px;
  border-radius: 50%;
  background: color-mix(in srgb, #f59e0b 16%, var(--onb-surface, #fff));
  color: #f59e0b;
}
.onb-alert__icon .material-symbols-rounded,
.onb-alert__icon svg { width: 30px; height: 30px; }
.onb-alert__title { margin: 0; font-size: 19px; font-weight: 700; color: var(--onb-title, #0f172a); }
.onb-alert__desc { margin: 0; max-width: 320px; font-size: 14px; line-height: 1.55; color: var(--text-muted, #64748b); }
.onb-alert__btn {
  margin-top: 8px;
  padding: 10px 28px;
  font-size: 14px;
  font-weight: 600;
  color: #fff;
  background: #f59e0b;
  border: none;
  border-radius: 8px;
  cursor: pointer;
  transition: background .18s ease;
}
.onb-alert__btn:hover { background: #d97706; }
